from utime import sleep_us from machine import Pin, PWM, ADC, time_pulse_us #LEDs ENEMY = 0 STATUS = 1 LEFT_LINE = 2 RIGHT_LINE = 3 # directions STOP = 0 LEFT = 1 RIGHT = 2 FORWARD = 3 BACKWARD = 4 # Battery resistor ladder ratio BATTERY_COEFF = 2.25 # Ultrasonic sensor calibration ULTRASONIC_OFFSET = 800 # Servo timing MOTOR_LEFT_TUNING = 33 MOTOR_RIGHT_TUNING = 33 # Ultrasonic distance sensor echo = Pin(14, Pin.IN) trigger = Pin(27, Pin.OUT) # Motor PWM-s pwm_left = PWM(Pin(15), freq=50, duty=0) pwm_right = PWM(Pin(4), freq=50, duty=0) # bottom LED bottom_led = Pin(5, Pin.OUT) # bottom LED is in reverse polarity bottom_led.value(1) # sensor LEDs enemy_led = Pin(16, Pin.OUT) left_line_led = Pin(17, Pin.OUT) right_line_led = Pin(12, Pin.OUT) # Battery gauge adc_battery = ADC(Pin(32)) # Optek sensors adc_line_left = ADC(Pin(34)) adc_line_right = ADC(Pin(33)) # Set reference voltage to 3.3V adc_battery.atten(ADC.ATTN_11DB) adc_line_left.atten(ADC.ATTN_11DB) adc_line_right.atten(ADC.ATTN_11DB) # Calibrate line sensors LINE_LEFT_THRESHOLD = adc_line_left.read() LINE_RIGHT_THRESHOLD = adc_line_right.read() def set_led(led, state): if led == STATUS: bottom_led.value(0 if state else 1) elif led == ENEMY: enemy_led.value(state) elif led == LEFT_LINE: left_line_led.value(state) elif led == RIGHT_LINE: right_line_led.value(state) def get_battery_voltage(): return round(BATTERY_COEFF * (adc_battery.read() * 3.3 / 4096), 2) enemy_score = 0 def enemy_distance(): global enemy_score trigger.value(0) sleep_us(5) trigger.value(1) sleep_us(10) trigger.value(0) # wait for the pulse and calculate the distance enemy_distance = (time_pulse_us(echo, 1, 30000) / 2) / 29.1 if enemy_distance < 60 and enemy_distance > 0: if enemy_score < 5: enemy_score += 1 else: if enemy_score > 0: enemy_score -= 1 # indicate enemy LED set_led(ENEMY, True if enemy_score > 2 else False) return True if enemy_score > 2 else False def line_left(): line = abs(adc_line_left.read() - LINE_LEFT_THRESHOLD) > 1000 set_led(LEFT_LINE, line) return line def line_right(): line = abs(adc_line_right.read() - LINE_RIGHT_THRESHOLD) > 1000 set_led(RIGHT_LINE, line) return line def detach_servos(): motor_left(0) motor_right(0) prev_left_speed = 0 def motor_left(speed): global prev_left_speed if speed == prev_left_speed: return prev_left_speed = speed assert speed >= -100 assert speed <= 100 pwm_left.duty(int(33 + MOTOR_LEFT_TUNING + speed * 33 / 100)) # -100 ... 100 to 33 .. 102 if speed == 0: pwm_left.duty(0) prev_right_speed = 0 def motor_right(speed): global prev_right_speed if speed == prev_right_speed: return prev_right_speed = speed assert speed >= -100 assert speed <= 100 pwm_right.duty(int(33 + MOTOR_RIGHT_TUNING + speed * 33 / 100)) # -100 ... 100 to 33 .. 102 if speed == 0: pwm_right.duty(0) print("Battery voltage: %.2fV" % get_battery_voltage()) print("Line sensor thresholds:", LINE_LEFT_THRESHOLD, LINE_RIGHT_THRESHOLD)