MicroPython Tutorial XVII
Ok, lets back to edges. One of the tasks you’ll surely need your robot to do is square its self up along an edge. A task that with a single colour sensor needs some engineering. What I have done here is mount a colour sensor on cog, that is connected to the medium motor, so that I can move it left and right.

With the accompanying script to drive it shown here.
#!/usr/bin/env pybricks-micropython
from pybricks import ev3brick as brick
from pybricks.ev3devices import Motor, ColorSensor, GyroSensor
from pybricks.parameters import Port , Color, Stop
from pybricks.tools import print, wait, StopWatchleft_motor = Motor(Port.B)
right_motor = Motor(Port.C)
gyro = GyroSensor(Port.S4)
colorScannedS1 = ColorSensor(Port.S1)
middle_motor = Motor(Port.D)autoCent = True
autoLeft = False
autoRight = Falsemiddle_motor.reset_angle(0)while True:
if autoCent:
left_motor.dc(17)
right_motor.dc(17) if colorScannedS1.reflection() < 10 and autoCent:
autoCent = False
left_motor.stop()
right_motor.stop()# default sensor on the right, now sweep left, 556 degrees moves it left middle_motor.run_angle(90,55,Stop.HOLD,True) while middle_motor.angle() < 556:
middle_motor.dc(25)
if colorScannedS1.reflection() < 10:
autoLeft = True
if not autoLeft:
autoRight = True middle_motor.stop() while autoLeft:
print("doLeft")
left_motor.dc(20)
if colorScannedS1.reflection() < 10:
autoLeft = False
left_motor.stop()
left_motor.run_angle(20,10,Stop.HOLD,True) while autoRight:
print("doRight")
left_motor.dc(-20)
if colorScannedS1.reflection() < 10:
autoRight = False
left_motor.stop()
left_motor.run_angle(20,-10,Stop.HOLD,True) # return color scanner to the right
middle_motor.run_target(90,0,Stop.HOLD,True)
How does it work. It defines the motors and the sensors and starts to move forward. Note we reset the angle of the motor managing the position of the sensor to zero.
The bot moves forward until it sees a black line, it then moves the sensor right to left. If it sees the black line again, it came from the right, if it sees nothing it came from the left. Depending on the direction it has figured out moves one of the main motors to align the bot to the line.
Finally it used the run_target command to move the colour scanner back to its default position.
Does it work well. Ok. There is a lot of room for improvement. On the engineering side it is difficult to get the sensor truly aligned and the script needs more tunning. Can you build it? Can you replicate it? Can you do better?

Here is another version with different mounting for the color sensor. It has less travel than before, but is more stable. And here is the beginnings of the code to use it.
#!/usr/bin/env pybricks-micropython
from pybricks import ev3brick as brick
from pybricks.ev3devices import Motor, ColorSensor, GyroSensor
from pybricks.parameters import Port , Color, Stop
from pybricks.tools import print, wait, StopWatchleft_motor = Motor(Port.B)
right_motor = Motor(Port.C)gyro = GyroSensor(Port.S4)
colorScannedS1 = ColorSensor(Port.S1)middle_motor = Motor(Port.D)
middle_motor.reset_angle(0)autoCent = True
autoLeft = False
autoRight = Falsewhile True:if autoCent:
left_motor.dc(17)
right_motor.dc(17)if colorScannedS1.reflection() < 10 and autoCent:
autoCent = False
left_motor.stop()
right_motor.stop()if not autoRight:
while middle_motor.angle() > -500:
middle_motor.run_angle(-90,55,Stop.HOLD,True)
print(middle_motor.angle())
autoRight = True
print("autoR")
if not autoLeft:
while middle_motor.angle() < 0:
print(middle_motor.angle())
middle_motor.run_angle(90,55,Stop.HOLD,True)
print("autoL")
autoRight = False
middle_motor.reset_angle(0)
I didn’t finish the code because I honestly came to the conclusion that using LEGO engineering to move the sensors if precision is critical isn’t going to work well enough, and well its easier with two sensors.
You may recall if you read microPython musings that I suggested if you have money to spare, you should invest in more colour sensors. Yes, I am sorry to say this is the best answer. More colour sensors.

Two to be precise, mounted just in front of wheels. Now on to the code to do that line squaring.
#!/usr/bin/env pybricks-micropython
from pybricks import ev3brick as brick
from pybricks.ev3devices import Motor, ColorSensor, GyroSensor
from pybricks.parameters import Port , Color, Stop
from pybricks.tools import print, wait, StopWatchleft_motor = Motor(Port.B)
right_motor = Motor(Port.C)
gyro = GyroSensor(Port.S4)colorScannedS3 = ColorSensor(Port.S3)
colorScannedS2 = ColorSensor(Port.S2)speed = 25
half_ahead = 12.5
autoBoth = True
autoLeft = True
autoRight = Truegyro.reset_angle(0)while True:
if autoBoth:
left_motor.dc(speed)
right_motor.dc(speed)# Left Sensor
if colorScannedS3.reflection() < 10 and autoBoth:
print("S3 macro")
autoBoth = False
while autoLeft:
left_motor.stop()
if colorScannedS2.reflection() < 10:
autoLeft = False
right_motor.stop()
while autoRight:
left_motor.dc(-half_ahead)
if colorScannedS3.reflection() < 10:
autoRight = False
left_motor.stop()
while colorScannedS2.reflection() < colorScannedS3.reflection():
right_motor.dc(-half_ahead)
right_motor.stop()
print("S2 micro")
while colorScannedS3.reflection() < colorScannedS2.reflection():
left_motor.dc(-half_ahead)
left_motor.stop()
print("S3 micro")# right Sensor
if colorScannedS2.reflection() < 10 and autoBoth:
print("S2 macro")
autoBoth = False
while autoRight:
right_motor.stop()
if colorScannedS3.reflection() < 10:
autoRight = False
left_motor.stop()
while autoLeft:
right_motor.dc(-half_ahead)
if colorScannedS2.reflection() < 10:
autoLeft = False
right_motor.stop()
while colorScannedS2.reflection() < colorScannedS3.reflection():
right_motor.dc(-half_ahead)
right_motor.stop()
print("S2 micro")
while colorScannedS3.reflection() < colorScannedS2.reflection():
left_motor.dc(-half_ahead)
left_motor.stop()
print("S3 micro")
Three main blocks, the first very short one simply moves the robot forward until it meets a blackline on sensor S2 or sensor S3.
The second block is executed if the colour sensor on the right in our case, plugged into port S3 hits the black line first. It than stops the left motor, and continues with power to the right until it detects the blackline on the other sensor. It then moves the left again to make sure it is straight. The macro move. Finally if either S2 or S3 are not giving the same reading it makes a move to correct itself again. A micro move.
The third block does exactly the same thing, only it is swinging on the sensor on the left this time.
Assuming you got two colour sensors, copy and paste the code and have a go. You’re more than welcome to improve the code, what about trying to create some subroutines to try to simplify it.
You could also port a version to the other builds to see if you can get the same results ultimately, and prove me wrong :)