5. Upgrade
For line following I have built a daughter board that gets mounted under the robot so the sensors are closer to the ground. On the main board I have soldered 2 pieces of 3 pin female connectors. On one of them I have connected the power and ground and on the other the 3 signal lines for the sensors. On the daughter board I have soldered 3 IR photo transistors that I have pulled out from a VCR spaced about 3/8 of an inch from each other. In between them I have soldered 2 IR LEDs mounted in some LED holders so that the IR light will not get sideways to the photo transistors. I have installed an adjustable pot so I can adjust the sensitivity of the sensors. Then I made the connections to 5 pins installed 3 on one side (signal lines) and 2 on the other side (power and ground lines).

Here is the program:
Nemesis
'===============================================================
'VCR Robot with 2 DC Motors and 3 IR line sensors
'Line following
'Compiled program size: 280 bits (out of 1024 bits)
'===============================================================
'--------------------------------------------------
'Variables declaration, labels, timer...
'--------------------------------------------------
dim Lvalue,Cvalue,Rvalue,Cvalue2,Rvalue2
dim state,dir
const Motor1a 8 ' right motor
const Motor1b 9 '
const Motor2a 10 ' left motor
const Motor2b 14 '
const MotorEn 13 ' enable motors
const IRsensor 5 ' IR sensor pin
const IRpulse 6 ' pin used to generate the IR pulse
const LeftIRLed 11 ' Left proximity IR LED
const RightIRLed 7 ' Right proximity IR LED
const RightLineS 1 ' right line sensor
const CenterLineS 2 ' center line sensor
const LeftLineS 3 ' left line sensor
'=================================================================
'Programul principal
'=================================================================
Main:
'=================================================================
'Main program
'=================================================================
output Motor1a ' we declare the direction of the I/O pins
output Motor1b ' for the motors and IR LEDs to
output Motor2a ' "output" and set the value to
output Motor2b ' "high" or "low".
low Motor1a ' all undeclared pins will be set to
low Motor1b ' "input".
low Motor2a
low Motor2b
output LeftIRLed
output RightIRLed
high LeftIRLed
high RightIRLed
output MotorEn
high MotorEn
'---------------------------------------------------------------
'Line following program
'---------------------------------------------------------------
Linefollowloop:
' read the sensors
Lvalue = inp.LeftLineS '0 means white, 1 means black
Cvalue = inp.CenterLineS
Rvalue = inp.RightLineS
' calculate the state value
Cvalue2 = 2*Cvalue
Rvalue2 = 4*Rvalue
state = Lvalue + Cvalue2 + Rvalue2
' show the values on the Debug window
print "Left ",Lvalue," Center ",Cvalue," Right ",Rvalue," State ",state
' decide how to turn by the state value
branch state,do0,do1,do2,do3,do4,do5,do6,do7
goto Linefollowloop
do0: ' 0 0 0 -> no sensor over the line
if dir == 0 then ' decide by the direction of the last turn
gosub Tleft
else
gosub Tright
endif
goto Linefollowloop
do1: ' 0 0 1 -> left sensor over the line
dir = 0 ' remember this turn direction
gosub Left
goto Linefollowloop
do2: ' 0 1 0 -> center sensor over the line
gosub Fwd
goto Linefollowloop
do3: ' 0 1 1 -> left and center over the line
gosub Tleft
goto Linefollowloop
do4: ' 1 0 0 -> right sensor over the line
dir = 1 ' remember this turn direction
gosub Right
goto Linefollowloop
do5: ' 1 0 1 -> not used - left and right over line
goto Linefollowloop
do6: ' 1 1 0 -> right and center over the line
gosub Tright
goto Linefollowloop
do7: ' 1 1 1 -> all sensors over the line
gosub Stop
goto Linefollowloop
'=================================================================
'Subrutines
'=================================================================
'-------------------------------------------------
'Motor control subrutines
'-------------------------------------------------
Fwd:
low Motor1b
low Motor1b
high Motor1a
high Motor2a
return
Left:
low Motor2a
low Motor1b
high Motor2b
high Motor1a
return
Right:
low Motor2b
low Motor1a
high Motor2a
high Motor1b
return
Tright:
low Motor1b
low Motor1a
low Motor2b
high Motor2a
return
Tleft:
low Motor2b
low Motor2a
low Motor1b
high Motor1a
return
Stop:
low Motor2b
low Motor2a
low Motor1b
low Motor1a
return
I plugged the daughter board on the robot, downloaded the program (make sure the jumper is off so the motors won’t be powered during testing) and I placed the robot on a piece of white paper with a piece of black electrical tape on it. I moved the robot sideways looking at the Debug window on the PC but sensors did not pick any reflected IR light. I have adjusted the pot to get the maximum light on the LEDs but still nothing! Hmm, what may be the problem? I hooked a IR LED (using wires and a 100 ohm resistor) to the power lines and place it directly in front of one of the photo transistors. The value did changed in the Debug window from 1 to 0, just as it was supposed to do. Then I placed the LED sideways very close to the photo transistor and placed a corner of the white paper over them and the value changed again. The conclusion is: the photo transistors from the VCRs have a very narrow angle of detection, so the LED has to be in close proximity and even a little tilted, as that the IR light spot on the paper will be directly in front of the photo transistor. After modifying the daughter board so that each photo transistor had one LED in front of it a little tilted backward, I have placed the robot back on the paper and checked to see if the values were changing in the Debug window. And yes, they did.
Now let’s put the robot to work! I have placed the jumper back and put the robot down on a line following course and switched the power on. The robot drove fiercefully and crashed into the wall! Oops! What now? It looks that the robot moves too fast and cannot react to the change in sensor values in time. But how can I slow it down? Well, I have remembered that there is a voltage drop on a diode placed in series on the power line so I have pulled 3 diodes from the VCR and connect them in series and placed them instead of the jumper to the motors power line. Now the robot drove a lot slower but followed the line perfectly. Maybe a little too slow. I think 2 diodes will do the trick.
Ok, but we now have 2 different programs and every time we want the robot to do something we have to reprogram it. Not so easy to do. What if we integrate both programs in a single one? How can we make the robot know which program to execute? Well, we can add a push button to select the program at start. If we press the button once, it will execute the avoiding program and if we press it twice it will execute the line following program. But wouldn’t it be better if we could somehow have a visual confirmation of the program that will be run? Sure! Nemesis has 2 more pins that we did not use: P4 and P12 (Tx and Rx). We can connect one red LED and one green LED (with a resistor in series) between pins 5, 4 and 3 on the programming connector. The red LED will be connected with the cathode on the pin 4 and the anode to a resistor connected to the pin 5. The green LED will have the cathode to the pin 3 and anode to the same resistor connected to the pin 5.
Let’s see the program:
Nemesis
'===============================================================
'VCR Robot with 2 DC Motors and 3 IR line sensors
'Select Driving and Line following programs
'Compiled program size: 489 bits (out of 1024 bits)
'===============================================================
'--------------------------------------------------
'Variables declaration, labels, timer...
'--------------------------------------------------
dim LeftIR ' variables to store the values of the
dim RightIR ' IR sensor for left and right directions
dim Lvalue,Cvalue,Rvalue,Cvalue2,Rvalue2
dim state,dir
const Motor1a 8 ' right motor
const Motor1b 9 '
const Motor2a 10 ' left motor
const Motor2b 14 '
const MotorEn 13 ' enable motors
const IRsensor 5 ' IR sensor pin
const IRpulse 6 ' pin used to generate the IR pulse
const LeftIRLed 11 ' Left proximity IR LED
const RightIRLed 7 ' Right proximity IR LED
const RightLineS 1 ' right line sensor
const CenterLineS 2 ' center line sensor
const LeftLineS 3 ' left line sensor
const Button 0 ' program selection button
const LED1 4 ' line program
const LED2 12 ' driving program
hwpwm 0,50,15 ' pwm signal 40KHz 60% "on" time
'=================================================================
'Main program
'=================================================================
Main:
RCSTA = 0 ' stop serial transmission
output Motor1a ' we declare the direction of the I/O pins
output Motor1b ' for the motors and IR LEDs to
output Motor2a ' "output" and set the value to
output Motor2b ' "high" or "low".
low Motor1a ' all undeclared pins will be set to
low Motor1b ' "input".
low Motor2a
low Motor2b
output LeftIRLed
output RightIRLed
high LeftIRLed
high RightIRLed
output LED1
output LED2
low LED1
low LED2
output MotorEn
high MotorEn
'-----------------------------------------------------------------
'program selection
'-----------------------------------------------------------------
loop1:
waitport Button,0,255,loop1
high LED1
low LED2
c = 0
select = 0
pause 100
loop2:
c = c+1
if c = 3 then
goto blink
endif
waitport Button,0,255,loop2
low LED1
high LED2
select = 1
pause 100
blink:
toggle LED1
pause 100
toggle LED1
start:
waitport Button,0,255,start
if select = 1 then
goto Drivingloop
else
goto Linefollowloop
endif
'---------------------------------------------------------------
'Driving program
'---------------------------------------------------------------
Drivingloop:
gosub ReadIRSensor
if RightIR = 0 then ' obstacle to the right
gosub ReverseLeft ' reverse left motor
else ' no object
gosub ForwardLeft ' forward left motor
endif
if LeftIR = 0 then ' obstacle to the left
gosub ReverseRight ' reverse right motor
else ' no object
gosub ForwardRight ' forward right motor
endif
goto Drivingloop ' start again
'---------------------------------------------------------------
'Line following program
'---------------------------------------------------------------
Linefollowloop:
Lvalue = inp.LeftLineS '0 means white, 1 means black
Cvalue = inp.CenterLineS
Rvalue = inp.RightLineS
Cvalue2 = 2*Cvalue
Rvalue2 = 4*Rvalue
state = Lvalue + Cvalue2 + Rvalue2
branch state,do0,do1,do2,do3,do4,do5,do6,do7
goto Linefollowloop
do0: ' 0 0 0 -> no sensor over the line
if dir == 0 then ' decide by the direction of the last turn
gosub Tleft
else
gosub Tright
endif
goto Linefollowloop
do1: ' 0 0 1 -> left sensor over the line
dir = 0 ' remember this turn direction
gosub Left
goto Linefollowloop
do2: ' 0 1 0 -> center sensor over the line
gosub Fwd
goto Linefollowloop
do3: ' 0 1 1 -> left and center over the line
gosub Tleft
goto Linefollowloop
do4: ' 1 0 0 -> right sensor over the line
dir = 1 ' remember this turn direction
gosub Right
goto Linefollowloop
do5: ' 1 0 1 -> not used - left and right over line
goto Linefollowloop
do6: ' 1 1 0 -> right and center over the line
gosub Tright
goto Linefollowloop
do7: ' 1 1 1 -> all sensors over the line
gosub Stop
goto Linefollowloop
'=================================================================
'Subrutines
'=================================================================
'-------------------------------------------------
'Motor control subrutines
'-------------------------------------------------
ForwardRight:
low Motor1b
high Motor1a
return
ReverseRight:
low Motor1a
high Motor1b
return
ForwardLeft:
low Motor2b
high Motor2a
return
ReverseLeft:
low Motor2a
high Motor2b
return
Fwd:
low Motor1b
low Motor1b
high Motor1a
high Motor2a
return
Left:
low Motor2a
low Motor1b
high Motor2b
high Motor1a
return
Right:
low Motor2b
low Motor1a
high Motor2a
high Motor1b
return
Tright:
low Motor1b
low Motor1a
low Motor2b
high Motor2a
return
Tleft:
low Motor2b
low Motor2a
low Motor1b
high Motor1a
return
Stop:
low Motor2b
low Motor2a
low Motor1b
low Motor1a
return
'-------------------------------------------------
'Read the IR proximity sensor subrutine
'-------------------------------------------------
ReadIRSensor:
low RightIRLed ' set active the right IR LED
output IRpulse ' start the pwm pulse
pause 1 ' wait a milisecond
input IRpulse ' stop the pulse
RightIR = inp.IRsensor ' read the value
pause 1 ' wait a milisecond
high RightIRLed ' deactivate the right IR LED
low LeftIRLed ' set active the left IR LED
output IRpulse ' start the pwm pulse
pause 1 ' wait a milisecond
input IRpulse ' stop the pulse
LeftIR = inp.IRsensor ' read the value
pause 1 ' wait a milisecond
high LeftIRLed ' deactivate the left IR LED
return
Well, I hope you enjoyed this robot and maybe you have learned something from it. Please leave your comments on the forum. Thank you very much!
Gabriel (Ro-Bot-X).