3Pi+2040 Line Sensors Reading Individual Values?

Hello,
I’ve been playing with the 3Pi+2040 and MicroPython in an attempt to make a “Cliff Walker” script. I’d like the robot to travel slowly along a tabletop and reverse, turn, then continue when it senses the edge. I’m not understanding how to get the individual values from the supplied sample code. Can you advise? The code below will help me display the values so that I can set the appropriate range for the algorithm to trigger the reversal. I get zeros for all sensors no matter what they are pointing at. Any hints would be appreciated.

import time
from pololu_3pi_2040_robot import robot

motors = robot.Motors()
line_sensors = robot.LineSensors()
display = robot.Display()
last_update = 0
button_a = robot.ButtonA()
button_c = robot.ButtonC()
line = [0,0,0,0,0]
line_sensors.calibrate()
time.sleep_ms(2)

while True:
    #motors.set_speeds(1000, 1000)

    line_sensors.start_read()
    time.sleep_ms(2)
    line = line_sensors.read_calibrated()

    # 64-40 = 24
    scale = 24/1023
    display.fill(0)
    display.text("line[0]"+str(line[0]), 0, 0)
    display.text("line[1]"+str(line[1]), 0, 10)
    display.text("line[2]"+str(line[2]), 0, 20)
    display.text("line[3]"+str(line[3]), 0, 30)
    display.text("line[4]"+str(line[4]), 0, 40)
    display.show()

I notice a few things in your code:

  • Normally you would call line_sensors.calibrate() more than once. You would call it as each line sensor is exposed to the minimum reading it can be expected to see and again for the maximum reading it can be expected to see. Just calling it once like in your code above doesn’t give enough calibration data for the driver to know what the expected minimum and maximum readings are to scale between. In your case that would probably mean making one calibration() call when your robot is on the table and another when you are holding it so that all of the sensors can see over the ‘cliff’.
  • You shouldn’t need to call line_sensors.start_read(). It will be called automatically for you when you make your main read call.
  • As an experiment, try calling line_sensors.read() instead of line_sensors.read_calibrated() to make sure that you are able to get readings at all from your robot. Once you have that working you can work on a calibration routine that lets you expose the robot’s sensors to minimum and maximum readings and use read_calibrated() instead.

Adam, Thank you!

I’ve got it working now that I understand the calibration. Here’s the final code in case you want to give it a try. It stays on the table but needs a bit of randomization to finesse its way off of the edge, but its a good start!


import time
from pololu_3pi_2040_robot import robot

motors = robot.Motors()
line_sensors = robot.LineSensors()
display = robot.Display()
last_update = 0
button_a = robot.ButtonA()
button_c = robot.ButtonC()
line = [0,0,0,0,0]
line_sensors.calibrate()
time.sleep_ms(2)

display.fill(0)
display.text("Cliff Walker", 0, 0)
display.text("Press A and move ", 0, 20)
display.text("back and forth over cliff", 0, 30)
display.text("to calibrate.", 0, 40)
display.show()

while not button_a.check():
    pass

display.fill(0)
display.show()
time.sleep_ms(500)

for i in range(250):
    line_sensors.calibrate()
    time.sleep_ms(20)

display.fill(0)
display.text("Calibrated", 0, 0)
display.show()
time.sleep_ms(500)

display.fill(0)
display.text("Place on table", 0, 0)
display.text("and Press C ", 0, 20)
display.show()

while not button_c.check():
    pass

while True:
    line = line_sensors.read_calibrated()

    # 64-40 = 24
    scale = 24/1023
    display.fill(0)
    display.text("line[0]"+str(line[0]), 0, 0)
    display.text("line[1]"+str(line[1]), 0, 10)
    display.text("line[2]"+str(line[2]), 0, 20)
    display.text("line[3]"+str(line[3]), 0, 30)
    display.text("line[4]"+str(line[4]), 0, 40)
    display.show()
    
    if line[0] > 500:
        motors.set_speeds(-500,-100)
        time.sleep_ms(1000)
        
    elif line[1] > 500:
        motors.set_speeds(-500,-300)
        time.sleep_ms(1000)
        
    elif line[2] > 500:
        motors.set_speeds(-500,-500)
        time.sleep_ms(1000)
        
    elif line[3] > 500:
        motors.set_speeds(-300,-500)
        time.sleep_ms(1000)
        
    elif line[4] > 500:
        motors.set_speeds(-100,-500)
        time.sleep_ms(1000)
        
    else:
        motors.set_speeds(500, 500)
        
   
1 Like

Excellent! That’s awesome progress.

1 Like