VCR Robot - Upgrade

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). 

Daughter brd - bottom view

Daughter brd - front view   

Daughter brd - side view   

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).