CS 500: Physical Computing Week 10
Light Finder Robot
This little robot seeks out light trying to find the brightest spot in it's field of view. The robot also constantly sends its state back to a main computer
using an RF transmitter. Originally this was supposed to be a solar charged robot, hence the light finding characterstic, but given that is pointless indoors and it's cold outside
I decided not to add that in. However, see at the bottom of this page to see how to add that in including charge controller code.
This robot basically uses 4 photo resistors to detect where the light is brightest; in front of it, to the left, to the right, or directly above. It roams around
searching for the brightest spot. If the brightest spot is above it, it stops and sits there. The robot also features a custom touch sensor I made, which tells it if something is in its way.
I originally created a little tank robot out of a pencil box and some spare printer motors, but they ended up taking a lot of current to power them. So short of adding 6 9 volt batteries in parrallel, it didn't move.
Instead, I went to fred meyer and bought a $10 remote control car and stripped off the top and disconnected the motors from the original RC circuit. This worked much better and took an extremely small amount of power and
was very zippy. For more details see the images below.
In each of these images you can click to see the full-sized view:
This remote control car cost about $10 at fred meyer, which was interestingly cheaper than buying equivalent wheels / motors / base seperatley.
To power this device and the microcontroller I attached 4 AA batteries in series. Technically this provides about double the voltage the original
RC circuit needed, but it didn't seem to hurt the motors any running them at this voltage level. 4 AA's were needed in order to provide the appropriate
voltage for the Basic Atom Pro 24. I just duct taped the battery holder to the back of the robot, which worked well.
In this picture you can see the front of the robot with the light sensitive resistors and my custom made touch sensor. The touch sensor basically works
by having the basic atom pro reading the voltage on that line, if the front part is pressed it closes the circuit and so pulls the voltage high. There is a resistor there
as well on the actual circuit part to prevent short circuiting. Again we see obligatory judicious usage of gorrilla duct tape, which is essential for any project.
In this picture you can see the circuit itself mounted on the RC car with gorilla duct tape. For significantly greater detail click the image. Basically though, as I said above, it just has 4 light sensitive resistors (see week 3) pointed forward,
left/forward, right/forward, and up. The RF transmitter there is connected up to send robot state back to a reciever (see week 7 for more details). The chip you see there is an H-Bridge (see week 5 for more details) which controls the motors.
The H-bridge handles inductive flow from the motors as well as allows for very easy switching of directions of the motors. One side is connected to the rear motors for going forward/backward. The other side of the H-bridge
is connected to the front wheels motor which handles turning left or right. The front wheels are spring loaded to return to the centered position if the motor is off. I added a bunch of capacitors there on the power lines
to even out the power flow as in the past I've found when dealing with battery powered motors connected on the same line as the basic atom pro 24 microcontroller that tends to be needed to avoid some weird microcontroller behavior such as resetting and what not. In this case it might not
have been needed as usually I use a 9 volt battery to power and that only gives .3 amps, but in this case with the AA's that provide about 2.5 amps and plenty of voltage, it probably wouldn't have been a problem. But just in case I added the cap's anyways.
Robot Code:
LightLeft VAR WORD
LightRight VAR WORD
LightFront VAR WORD
LightTop VAR WORD
TouchFront VAR BIT
TouchFront2 VAR WORD
MotorStateForward CON 0
MotorStateBackward CON 1
MotorStateLeft CON 2
MotorStateRight CON 3
MotorStateStraight CON 4
MotorStateCurrent VAR BYTE
TransmitterPin CON P14
TouchFrontPin CON P11
LightLeftPin CON P0
LightRightPin CON P3
LightFrontPin CON P1
LightTopPin CON P2
MotorRearPin1 CON P7
MotorRearPin2 CON P6
MotorRearEnablePin CON P5
MotorFrontPin1 CON P8
MotorFrontPin2 CON P9
MotorFrontEnablePin CON P10
TurnToggle VAR BYTE
Initialize:
Input LightLeftPin
Input LightRightPin
Input LightFrontPin
Input LightTopPin
MotorStateCurrent = MotorStateForward
TurnToggle = 0
;end initialize
Main:
GoSub FollowLight
goto main
FollowLight
GoSub SetTouchValue
if(TouchFront = 1) then
GoSub TurnRandom
endif
if((LightRight > LightLeft) AND (LightRight > LightFront) AND (LightRight > LightTop)) then
GoSub GoForward
GoSub TurnRight
elseif((LightFront > LightLeft) AND (LightFront > LightRight) AND (LightFront > LightTop))
GoSub GoForward
GoSub GoForward
elseif((LightLeft > LightFront) AND (LightLeft > LightRight) AND (LightLeft > LightTop))
GoSub GoForward
GoSub TurnLeft
elseif((LightTop > LightFront) AND (LightTop > LightRight) AND (LightTop > LightLeft))
GoSub StopMotors
endif
GoSub SendState
return
SendState
PULSOUT 0, 1200 'used for synchronization
SEROUT 0, I9600, ["!", LightRight.HIGHBYTE, LightRight.LOWBYTE, LightFront.HIGHBYTE, LightFront.LOWBYTE, LightLeft.HIGHBYTE, LightLeft.LOWBYTE, LightTop.HIGHBYTE, LightTop.LOWBYTE, TouchFront2.HIGHBYTE, TouchFront2.LOWBYTE, MotorStateCurrent.HIGHBYTE, MotorStateCurrent.LOWBYTE]
return
SetTouchValue
TouchFront = In11
if(TouchFront = 1) then
TouchFront2 = 1
else
TouchFront2 = 0
endif
return
SetLightValues
ADIN LightLeftPin, LightLeft
ADIN LightRightPin, LightRight
ADIN LightFrontPin, LightFront
ADIN LightTopPin, LightTop
return
TurnRandom
GoSub Gobackward
if(TurnToggle = 0) then
GoSub TurnRight
TurnToggle = 1
else
GoSub TurnLeft
TurnToggle = 0
endif
Pause 1000
return
GoForward
High 8
Low 7
MotorStateCurrent = MotorStateForward
return
GoBackward
High 7
Low 8
MotorStateCurrent = MotorStateBackward
return
TurnRight
High 2
Low 1
MotorStateCurrent = MotorStateRight
return
TurnLeft
High 1
Low 2
MotorStateCurrent = MotorStateLeft
return
GoStraight
Low 1
Low 2
MotorStateCurrent = MotorStateStraight
return
StopMotors
Low 1
Low 2
Low 7
Low 8
return
EnableMotors
High 0
High 9
return
DisableMotors
Low 0
Low 9
Low 8
Low 7
Low 1
Low 2
return
Reciever Code for recieving state of the robot on a main computer:
LightRight VAR WORD
LightFront VAR WORD
LightLeft VAR WORD
LightTop VAR WORD
TouchFront VAR WORD
MotorState VAR WORD
main:
SERIN 0, I9600, [Wait("!"), LightRight.HIGHBYTE, LightRight.LOWBYTE, LightFront.HIGHBYTE, LightFront.LOWBYTE, LightLeft.HIGHBYTE, LightLeft.LOWBYTE, LightTop.HIGHBYTE, LightTop.LOWBYTE, TouchFront.HIGHBYTE, TouchFront.LOWBYTE, MotorState.HIGHBYTE, MotorState.LOWBYTE]
SEROUT s_out, I4800, ["LightRight: ", DEC LightRight, 10, 13, "LightLeft: ", DEC LightLeft, 10, 13, "LightFront: ", DEC LightFront, 10, 13, "LightTop: ", DEC LightTop, 10, 13, "TouchFront: ", DEC TouchFront, 10, 13, "MotorState: ", DEC MotorState, 10, 13]
goto main
I originally was going to have this robot have a solar charger built in. However, it was kind of pointless indoors and freazing cold
outside, so I didn't add this. The AA solar charger on "week 9" was originally going to be used to run this robot. Hence why the robot tries to seek light, its 'food'.
In order to add this though, I needed a charge regulator which the panel/circuit from week 9 did not have. So to support this I built a simple circuit that would read the
voltage coming from the batteries and if they dropped below a certain point would switch on charging from the solar panel. I didn't take any pictures of this circuit, because I
was originally going to add it to the main robot circuit, so I didn't see any point at the time. However, here's my code for that circuit, which detects voltage levels and switches on charging
or not depending on the battery voltage. If put on the actual robot a slight modification would need to be made adding a "critical voltage" level where the robot would go in low power mode
putting the basic atom pro in standbye mode for a time and obviously thus switching everything off while it charged the batteries. It could then wake up every so often to check whether the battery level
was at an appropriate level to continue on. If this modification was added then I wouldn't be able to use the transistor switch type system I used here as it requires a pin to be high to enable the flow, but obviously
that problem vould be worked around easily by using a relay. But this basic code/circuit would work excepting the extreme low voltage level case.
Vlt CON 200 'after testing with multi-meter with various voltages found that the basic atom pro 24 AD converter roughly reads 200 per volt
X VAR WORD
Main:
ADIN 0, X 'read in voltage value from the batteries
if(X < (Vlt * 5)) then
High 10 'switches on charging using a transistor and solar panel
else
Low 10
endif
Pause 60000 'pause for one minute before checking again
goto Main