Line sensors - using 2 sensors and detecting fall-off. 


Pin numbers  and GPIO

The two phototransistor detectors are connected to the Pico at pins 31, and 32.

   Pin32 (GPIO27) is the left sensor
   The Python command to set it up is:
   lfront = ADC(Pin(27))

    Pin31 (GPIO26) is the right sensor
    The Python command to set it up is:
    rfront = ADC(Pin(26))


Reading the values. 

The Python commands to read the left and right sensors are:

    Left = lfront.read_u16()
    Right = rfront.read_u16()


    These will give values between 52000 and 64000, as the sensors cross from black to white over the line,
    with a smaller value for white

Use Thonny to see the graph:

                                                             

Calibration

It is a good idea to calibrate the readings so that the maximum value is reduced to 100 and the minimum reduced proportionately to 0. Also to have black a small number, and white a large number.  See below for calibrated readings.

                                                             

Calibrated = 100 * (maximum - value) /(maximum-minimum) 

#Calibrate:
    Lmax = max(Lmax,Left)
    Rmax = max(Rmax,Right)

    Lmin = min(Lmin,Left)
    Rmin = min(Rmin,Right)
    if (Lmax != Lmin):
        Left = int(100*(Lmax-Left)/(Lmax-Lmin))
    if (Rmax != Rmin):
        Right= int(100*(Rmax-Right)/(Rmax-Rmin))

After calibration, we can use about 20 as the value at which the sensor has "fallen off" the line.
100 is pure white, and near zero is black. 

                                                    

____________________________________________________________________________________________

Reading the position over the line

Simple method
The simple approach is:
Position = Left  - Right

At the centre of the line, both sensors give a calibrated value of approx 100, so the position is 0

To the right
   
the right sensor begins to lose output so the position value becomes positive. 

To the left,
   
the left sensor begins to lose output so the position value becomes negative. 

Detecting falling off

If both sensors see black, the position calculated returns to zero, with the simple calculation
You can detect you have fallen off when either input has fallen below 20. 

This is the central rectangle area shown above.

Remembering which side we fell off 

If you keep the previous calculated position (oldposition) then when fall-off is detected,
   the position can be calculated as +70 or - 70,
    depending on whether "oldposition" is positive or negative.
This is then to be kept as the new oldposition. 
        if (Left<20)or(Right <20):
            if (Oldposition <0):
                Position =-70
            else:
                Position =70
        Oldposition = Position 

                                                         _________________________________________________________________________________

Extended method

News 2026: 
I'm working on a method of automatically calculating the value of FOerror below.

The region in which Position can be calculated, is extended to when either reading is above 20
(as opposed to both readings having to be above 20)

The central region is treated as the simple method, but when one sensor is above 20 and the other is not,
the position is calculated from the reduction in value of the remaining sensor.

if (l>25 and r>25):
    error = l-r
else:
     if olderror >0:
         error = FOerror -(l+r)
     else:
         error = -FOerror + (r+l)

                                                 

_____________________________________________________________________________
Whole program:

from machine import ADC,Pin
import time
rfront = ADC(Pin(26)) # HW31  right front sensor
lfront = ADC(Pin(27)) # HW32 left front sensor

Lmin=65535
Rmin=65535
Lmax = 0
Rmax=0
Position=0
Oldposition =0
FOerror  = 180

while True:
    Left = lfront.read_u16()
    Right = rfront.read_u16()
    #Calibrate:
    Lmax = max(Lmax,Left)
    Rmax = max(Rmax,Right)
    Lmin = min(Lmin,Left)
    Rmin = min(Rmin,Right)
    if (Lmax != Lmin):
        Left = int(100*(Lmax-Left)/(Lmax-Lmin))
    if (Rmax != Rmin):
        Right= int(100*(Rmax-Right)/(Rmax-Rmin))

    if (Left>25 and Right>25):
        Position = Left  - Right
     else:
         if olderror >0:
             Position = FOerror -( Left + Right)
         else:
             Position = -FOerror + ( Left + Right)

    time.sleep(0.05)






© Copyright St Albans Robots