Motion & Autonomy — Day 4 of 4
'F' → Fullscreen
Everything stays wired from 2.12 and 2.13. Create a new MicroPython program named 2-14-rover.
Work on the floor, not the desk. The robot moves on its own from Task 1 onward.
drive(), stop() and read_distance() functions into one script.STOP_CM.Note the cm > 0 in the condition. Without it, an out-of-range reading of -1 counts as "too close" and the robot refuses to move in an empty room. Try removing it once, deliberately, so you have seen it happen.
from machine import Pin, PWM, time_pulse_usimport time
a_in1 = Pin(31, Pin.OUT)a_in2 = Pin(32, Pin.OUT)a_pwm = PWM(Pin(33))a_pwm.freq(1000)
b_in1 = Pin(21, Pin.OUT)b_in2 = Pin(35, Pin.OUT)b_pwm = PWM(Pin(34))b_pwm.freq(1000)
trigger = Pin(22, Pin.OUT)echo = Pin(20, Pin.IN)
SPEED = 40000STOP_CM = 20TIMEOUT_US = 30000
def motor(in1, in2, pwm, speed): if speed > 0: in1.value(1) in2.value(0) pwm.duty_u16(speed) elif speed < 0: in1.value(0) in2.value(1) pwm.duty_u16(-speed) else: in1.value(0) in2.value(0) pwm.duty_u16(0)
def drive(left, right): motor(b_in1, b_in2, b_pwm, left) motor(a_in1, a_in2, a_pwm, right)
def stop(): drive(0, 0)
def read_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, TIMEOUT_US) if duration < 0: return -1 return duration // 58
while True: cm = read_distance() if cm > 0 and cm < STOP_CM: stop() else: drive(SPEED, SPEED) time.sleep(0.05)back_away() that reverses briefly, then spins.from machine import Pin, PWM, time_pulse_usimport time
a_in1 = Pin(31, Pin.OUT)a_in2 = Pin(32, Pin.OUT)a_pwm = PWM(Pin(33))a_pwm.freq(1000)
b_in1 = Pin(21, Pin.OUT)b_in2 = Pin(35, Pin.OUT)b_pwm = PWM(Pin(34))b_pwm.freq(1000)
trigger = Pin(22, Pin.OUT)echo = Pin(20, Pin.IN)
SPEED = 40000STOP_CM = 20BACK_TIME = 0.4TURN_TIME = 0.5TIMEOUT_US = 30000
def motor(in1, in2, pwm, speed): if speed > 0: in1.value(1) in2.value(0) pwm.duty_u16(speed) elif speed < 0: in1.value(0) in2.value(1) pwm.duty_u16(-speed) else: in1.value(0) in2.value(0) pwm.duty_u16(0)
def drive(left, right): motor(b_in1, b_in2, b_pwm, left) motor(a_in1, a_in2, a_pwm, right)
def stop(): drive(0, 0)
def read_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, TIMEOUT_US) if duration < 0: return -1 return duration // 58
def back_away(): stop() time.sleep(0.2) drive(-SPEED, -SPEED) time.sleep(BACK_TIME) drive(SPEED, -SPEED) time.sleep(TURN_TIME)
while True: cm = read_distance() if cm > 0 and cm < STOP_CM: back_away() else: drive(SPEED, SPEED) time.sleep(0.05)The wait is a loop whose body does nothing at all — the same pass trick you used to wait for a reaction in 2.7.
from machine import Pin, PWM, time_pulse_usimport time
a_in1 = Pin(31, Pin.OUT)a_in2 = Pin(32, Pin.OUT)a_pwm = PWM(Pin(33))a_pwm.freq(1000)
b_in1 = Pin(21, Pin.OUT)b_in2 = Pin(35, Pin.OUT)b_pwm = PWM(Pin(34))b_pwm.freq(1000)
trigger = Pin(22, Pin.OUT)echo = Pin(20, Pin.IN)button = Pin(28, Pin.IN, Pin.PULL_DOWN)
SPEED = 40000STOP_CM = 20BACK_TIME = 0.4TURN_TIME = 0.5TIMEOUT_US = 30000
def motor(in1, in2, pwm, speed): if speed > 0: in1.value(1) in2.value(0) pwm.duty_u16(speed) elif speed < 0: in1.value(0) in2.value(1) pwm.duty_u16(-speed) else: in1.value(0) in2.value(0) pwm.duty_u16(0)
def drive(left, right): motor(b_in1, b_in2, b_pwm, left) motor(a_in1, a_in2, a_pwm, right)
def stop(): drive(0, 0)
def read_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, TIMEOUT_US) if duration < 0: return -1 return duration // 58
def back_away(): stop() time.sleep(0.2) drive(-SPEED, -SPEED) time.sleep(BACK_TIME) drive(SPEED, -SPEED) time.sleep(TURN_TIME)
print("Press the button to start.")while button.value() == 0: pass
while True: cm = read_distance() if cm > 0 and cm < STOP_CM: back_away() else: drive(SPEED, SPEED) time.sleep(0.05)-1 into something a human wants to read. Nobody should see the sentinel.from machine import Pin, PWM, time_pulse_usimport qwiic_large_oledimport time
a_in1 = Pin(31, Pin.OUT)a_in2 = Pin(32, Pin.OUT)a_pwm = PWM(Pin(33))a_pwm.freq(1000)
b_in1 = Pin(21, Pin.OUT)b_in2 = Pin(35, Pin.OUT)b_pwm = PWM(Pin(34))b_pwm.freq(1000)
trigger = Pin(22, Pin.OUT)echo = Pin(20, Pin.IN)button = Pin(28, Pin.IN, Pin.PULL_DOWN)
SPEED = 40000STOP_CM = 20BACK_TIME = 0.4TURN_TIME = 0.5TIMEOUT_US = 30000
oled = qwiic_large_oled.QwiicLargeOled()oled.begin()
def motor(in1, in2, pwm, speed): if speed > 0: in1.value(1) in2.value(0) pwm.duty_u16(speed) elif speed < 0: in1.value(0) in2.value(1) pwm.duty_u16(-speed) else: in1.value(0) in2.value(0) pwm.duty_u16(0)
def drive(left, right): motor(b_in1, b_in2, b_pwm, left) motor(a_in1, a_in2, a_pwm, right)
def stop(): drive(0, 0)
def read_distance(): trigger.value(0) time.sleep_us(2) trigger.value(1) time.sleep_us(10) trigger.value(0) duration = time_pulse_us(echo, 1, TIMEOUT_US) if duration < 0: return -1 return duration // 58
def back_away(): stop() time.sleep(0.2) drive(-SPEED, -SPEED) time.sleep(BACK_TIME) drive(SPEED, -SPEED) time.sleep(TURN_TIME)
def show(oled, line1, line2): oled.clear(oled.PAGE) oled.print(line1) oled.print(line2) oled.display()
show(oled, "Rover ready", "press to start")while button.value() == 0: pass
while True: cm = read_distance() if cm < 0: reading = "clear" else: reading = str(cm) + " cm" if cm > 0 and cm < STOP_CM: show(oled, "BLOCKED", reading) back_away() else: show(oled, "Driving", reading) drive(SPEED, SPEED) time.sleep(0.05)STOP_CM that stops without bumping, and a TURN_TIME that reliably faces somewhere new.-1Answer the following questions before submitting your work.
cm > 0 makes the robot refuse to move in an empty room. Explain how a value you invented on purpose in 2.13 became a bug in 2.14, and what that suggests about using special values.STOP_CM or TURN_TIME should be. Describe how you found yours, and why changing one number at a time mattered.Submit the required files to the appropriate dropbox.