Wall Following

Sample code May 2025
It has a Screen, TV remote and Bluetooth
This is a work in progress .....
  8th May:  view May5.py  ..
  10th May:  view may9.py  .

Ideas December 2024

WallNotes1



This is a competition that is run by a robot that can sense walls.
The wall in front, the walls on the left and right.

It starts in the starting cell, and makes a timed run, until it reaches the target cell.
Unlike maze solving, it doesn't have to recognize the finish cell, or plan a route to get there.
Instead it follows a simple set of rules for how to progress from the current cell.

  • If there is a wall to the left, and none in front - Go forward
  • If there is no wall to the left, turn left
  • If there are walls to the left and in front, but none to the right - turn right
  • If there are walls on the left, front and right, Spin round

 Wall follower logic.
The robot should follow the path of the wall seen on its left hand side.

Functional steps in the worksheet
----------------
<Image of corridor with blocked ends>
-------------------------------------------------
Step 1:   Corridor
Steer straight along the corridor (using left sensor only):
  Measure the  left sensor. 
  Use the difference between this value and the left threshold, to calculate error.
  Use the error to calculate motor speed difference.

Extras:
1a
: set up thresholds (Left, front) by recording readings when the button is first pressed. 
Use a second button press to start motion.

1b:  stop if getting close to front wall.

The student should tune the motor speed, the left wall threshold, and the “mult” steering strength,
to get a stable central path.
Derivative steering is probably not needed.

The front sensor stop threshold should make it stop at the right point to turn left or right.

----------------

<Image of corridor with blocked ends>

<Image of corridor with right turn St end>

-------------------------------------------------

Step 2 spin right if front and left sensor both see walls

   Stop spinning when the front sensor reading gets very low.

(tune value/time) 

  [This will give 90 or 180 degree right spins. ]


This is about getting the motor speeds and the sensor thresholds right for 90 degree and 180 degree spins.
There might be issues with the front sensor reading dropping when it points at the corner,after 45 degrees.
The issue of overshoot needs to be considered.(Turning too far)
-------------------------------------------------
Step 3 steer round left corner (tune minimum left speed)
   all done on left sensor. 
    [Might need to ignore front sensor if steering hard left]

<Image of corridor with left 90 degree turn >

<Image of corridor with left 180 degree turn >

The left turn can be performed as part of the corridor steering.
The “error” should be limited (the left wall reading will drop to approx zero),
so that the robot steers a smooth left turn (not spin). 
Because the left side sensor is pointing forwards,
the robot may start the turn too early, and graze the left wheel against the corner. 

A delay (before starting the turn) may be needed.
The robot would go straight ahead during this delay.

The delay should happen only on first seeing the left sensor reading fall drastically.
It should happen only once.

This will require close monitoring of left sensor changes,
and keeping a record of time since the start of a left turn happened.

An additional  left pointing sensor would be a better way of doing it.

Maybe pointing the left sensor further back would be a solution.
-------------------------------------------------
Step 4 Speeding things up
See how far you can get by just increasing the speed.

Eventually, the momentum of travelling so fast will upset the right spin, and the left turn.

The speed can be reduced prior to the right spin, by monitoring the front sensor in the corridor run, and slowing when a wall is seen a long way ahead.


The delay part of the left turn can be shortened as well as being at its normal, slow speed. I suggest that the left turn be done at the same speed, not at the faster speed.

As it enters a cell it can do 4 things:

 - Turn left, 

 - go ahead, 

 - turn right, (spin actually )

 - U turn(180 degrees).


-------------------------------------------------

Step 5. User interface 

Pressing the button to stop Initial wall-scanning,

and then again to start the run can be difficult.

Therefore the race should be started by waving ones hand in front of the robot.

The robot should flash the LED while awaiting a wave.

The loop time should be small (0.05), so therefore the LED should be toggled only evey 10 loops.


A User Instruction sheet should be written to explain how to start it.








Program Logic:

 It should test for a left wall and a front wall.

If it sees no left wall, it should turn left.

else..(seeing a left wall)

if it sees no front wall it can continue straight ahead.

If it sees a front wall, and a right wall it should turn right 180 degrees.

If it sees a front wall, and no right wall it should turn right 90 degrees.



1. Python Imports

========


from machine import Pin, PWM, ADC

import time


1a Tuning variables

================


mult = 10         # strength of steering

speed = 6000  # how fast

# for step 3…

leftmin =2500  # Left min speed



2  Setting up pins

============= outputs =======

trigger = Pin(14, Pin.OUT) # Wall illumination LED:

led = Pin(25, Pin.OUT) # LED on the Pico board

ledL = Pin(13, Pin.OUT) # Left hand LED on sensor board 

ledR = Pin(8, OUT) # Right hand LED on sensor board 

============= inputs ========

Lsensor = ADC(27)  # left wall 

Msensor = ADC(26) # front wall

Rsensor = ADC(28) # right wall 

# push button

button = machine.Pin(22,Pin.IN,Pin.PULL_DOWN)

# the 4 switches (1 is the left hand switch) 

SW1 = Pin(0, Pin.IN, Pin.PULL_UP)

SW2 = Pin(1, Pin.IN, Pin.PULL_UP)

SW3 = Pin(2, Pin.IN, Pin.PULL_UP)       

SW4 = Pin(3, Pin.IN, Pin.PULL_UP)


#Set up motor outputs....

# Direction 0= forward 1= reverse

left_dir = Pin(9, Pin.OUT)

right_dir = Pin(10, Pin.OUT)


# Motor speed control, (must be in range 0-65535)

left_pwm = PWM(Pin(11))

right_pwm = PWM(Pin(12))


# Pulse rate of PWM controller 

left_pwm.freq(1000)

right_pwm.freq(1000)



# === Function to read wall sensors

def readWalls():

    trigger.off()   # Switch off wall illumination 

    time.sleep(0.005)  # wait for light to take effect

    LMin = Lsensor.read_u16()  # Read left wall

    MMin = Msensor.read_u16()  # Read front wall

    RMin = Rsensor.read_u16()  # Read right wall

    

    trigger.on() # Switch on wall illumination 

    time.sleep(0.005)  # wait for light to take effect

    MMax = Msensor.read_u16()  # Read left wall

    RMax = Rsensor.read_u16()  # Read front wall

    LMax = Lsensor.read_u16()  # Read right wall


    trigger.off()   # Switch off wall illumination 

    Lside = LMax - LMin

    Mside = MMax - MMin

    Rside = RMax - RMin

    return Lside, Mside, Rside




# ===== Program starts here ====


# Show wall values

# -until button is pressed

while True:

    (leftThresh, frontThresh, rightThresh) = readWalls()

    print(leftThresh,frontThresh,rightThresh)

    time.sleep(0.1)

    if button.value() == 1:

        break


# Wait till button is released 

while button.value() == 1:

    pass


# Wait till button is pressed again

while button.value() == 0:

    pass


# === Move and steer ======== 

while True:

    (l,f,r) = readWalls()

    if f > frontThresh:

        break

    error = l-leftThresh

    # calculate speed difference 

    sDiff = error*mult


#==== Calculate motor speeds


    lSpeed = max(speed+sDiff,0) # Must be >0

    lSpeed = min(lSpeed,65000)  # Must be <= 65535

    rSpeed = max(speed-sDiff,0) # Must be >0

    rSpeed = min(rSpeed,65000)  # Must be <= 65535


#== output to motors


    left_pwm.duty_u16(lSpeed)  #Left motor speed

    right_pwm.duty_u16(rSpeed) #Right motor speed



# Exit loop when button pressed

   if button.value() == 1:

        break


# Stop motors

left_pwm.duty_u16(0)  

right_pwm.duty_u16(0)


End of step 1: corridor steering that stops at the end

_____________________________


Step 2:  spin right at end of corridor

Step 2a: spin 90 degrees for right turn and 180 degrees for I turn


_____________________________


Step 3:  Gentle turn round left. 

3a: 90 degrees and 180 degrees according to track.

Make sDiff have a minimum negative value that keeps the turn gentle.

Use leftmin as minimum left speed

and rightmax as max right speed


rightmax= speed + (speed-leftmin)


Diary
See the latest program

8th November 2024

WE fixed the bug that caused finger contact with the underside of the circuit board to be a button press.
Also the staggering movements that were happening at the last session
See the latest program

© Copyright St Albans Robots