Doug Leppard (DLeppard@CCCI.Org
Benjamin Leppard (Benjamin@Leppard.Com)
This is the ninth in a series of articles outlining the steps I have taken to build my robot. These articles are focused on a robot, named HC12 after its MCU, that may compete in the Fire Fighting contest, be able to roam around the house, but mostly be a fun learning tool. The robot uses a 68HC912B32 processor, so these articles will be about interfacing to the B32 various mechanical devices and sensors using SBasic as the programming language.
"Setting the Stage for Building a Robot," we set goals for the robot and did research. From the goals and research we will make fundamental decisions on what our robot will be like.
"Choosing the CPU, Language and Basic Shape," using our goals we choose the microprocessor, language and fundamental shape of the robot.
"Motorolas S-Record" looking at the S-Record format that Motorola uses to load data and programs.
"Booting up the 68HC912B32 for the first time" described in detail how to boot the B32 up and run a program.
"State of the Union" gives an overview of what state the robot was in August 1999.
"Multiplexing Five Sonar Modules" tells why we wired five Polaroid sonar transducers and how to go about doing so.
"Drivers for Sonar & Mapping" shows the software to drive the sonar units, and how it can map a room when tied to a PC.
"Using B32's Interrupts IRQ and XIRQ" using the B32 interrupts to count the robots wheel encoders.
"Telemetry, using a radio modem" using a radio modem to connect the robot to the PC.
As I was building my robot one, the thing I had to have (along with all the other
things I had to have) was the pyro heat sensor. This is a really cool sensor that
detects heat, not light. The pyro sensor detects two sources of heat that are
important to my robot project, candles and people. It ignores most other sources,
like windows with sunlight coming through and electric lights.
and electric lights.
There are two main heat sensors that the robot hobbyist use, the Hamamatsu UVTron Flame Detector and the Eltec 442-3 Pyroelectric Detector. Both sensors are supplied by Acroname and other robot suppliers. The Hamamatsu, which I do own but haven't mounted it yet, is the more sensitive detector. The robot only needs to go by a open door and a candle can be detected. But the Hamamatsu is not directional like the Pyroelectric, so it was a higher priority to me to have the pyro sensor. I wanted this sensor because I just don't want to know that there is a flame, but also if there is a person in the room, and what direction they are located.
I recently built a routine for my robot, using the pyro sensor, where it scans the room and detects all the people in the room. The pyro sensor tells a person is there and the the sonar unit it tells which person is the closet, then the robot goes to that person. It a really cool thing to show off.
The Pyroelectric sensor is actually very easy to set up. Below are the pictures of it mounted on the robot.
The Pyroelectric sensor is the white circle between the sonar eyes. It is mounted in the head which is on the dual servos so it can scan the room for people and candles. The pyro sensor, in conjunction with the sonar units provide good information to the robot's MCU. Once a heat signature is spotted, then a ping is sent out from the sonar units and we know a person/candle is so many feet away.
An extra feature of the arrangement of sonars and pyro sensor, that it gives the robot a face to give it a little more personality.
Picture of the robot sensor pod (head). The pyro sensor is mounted between the left and right sonar "eyes."
See the specifications of the Eltec 442-3 Pyroelectric Detector. It is an analog device, and it gives a voltage out according to its readings. To read the pyro sensor, all you have to do is hook up to your analog to digital converter.
The pyro sensor works by using two built-in parallel sensors and detecting the difference of reading between them. When one sensor detects a heat signature and the other doesn't, a voltage comparitor built into the chip gives a voltage difference. If both of the sensors are looking at the heat source, the readings would be the same and you would not get a reading from the pyro sensor. Therefore, the heat source needs to move in front of the pyro sensor to be detected. I do this by scanning the object horizontally with the sensor pod (head) of the robot.
|The V+ I hooked up to the 5v MCU supply. Inside the sensor pod I put
a capacitor across the V+ and Ground to keep voltage spikes from the sensor to more
consistent readings. I used a 50mfd capacitor, value is not critical, just one I had
Pin 2, the output, went into the B32 A to D port, which then would give a reading a digital reading. A reading of about 128 is read when nothing was detected. Pin 3, the 2.5 reference, was not used.
To understand reading the A to D ports on the 68HC12, read Kevin Ross article "The 68HC12 Analog to Digital Module." Kevin, as always, goes a great job showing how the A to D ports work. So I won't even try to explain it. Instead I will show you my implementation of his work.
All my basic routines are in libraries, the library for this is RAtoD.lib:
Read_AD will read the ports then send back data according to what bit you want. There is a predefined constant heat_sensor that is the bit the heat sensor is hooked to. Read_AD will allow the reading of all eight input A to D ports, not just the heat sensor.
Heat_stable is a routine called to wait for the sensors to stabilize before taking a reading. If the sensors have just powered up or have been looking at a heat source, they need to stabilize for a second or two before readings are taken.
For routines that are called below but are not shown here, go to Egroups.com in the SRS area. The routines are under files, Sbasic and Doug Leppard. Note that I use temporary variables over a lot to save RAM. Variables called temp_lib* are only used in library functions and not in the main Sbasic files so that variables will not be accidentally used twice. You really should use unique names but with only 1kb of RAM. I watch my use of variables closely.
Read_AD: 'use usr(read_AD,X) where X is port number, returns value
'Multiscan mode, reads all the ports and stores the results
' Scan all 8 channels once then stop. The results are
' stored in ADR0-ADR7
' Set atdctl5 for S8CM and MULT
pokeb atdctl5, %01010000
' Wait for scan to be completed
do loop while (peek(atdstat) AND $8000) = 0
read_ad2: 'gosub here if you do not want to do a scan but read
temp_lib=peekb(adr0h + lshft(pick(0))) 'pick(0) has port number
gosub AD_status,temp_lib,temp_lib2 'pick(0) 'tell of status
return temp_lib 'holds value
heat_stable: 'run this to make sure heat sensor has stablized
wait_lib=intcnt 'timer counter
temp_lib4=usr(read_AD,heat_sensor) 'look with heat sensor
if temp_lib5<10 'wait until we have at least 9 readings that are within 118 to 138
if usr(compare_intcnt,wait_lib)>5000 'don't go longer than 5 seconds
loop until temp_lib3>9
That is all that is needed to get readings from the pyro sensor.
When I was doing my Fire Fighting practice with a candle I used a simple algorithm was basically detected if the reading was 30 different from the base reading, which was usually 128, then something was detected. This didn't always work. Also, with every detection you would get two readings, one going high while the scan approached the person and second going low as you left the person. I didn't always get the most accurate readings this way.
I went upstairs and had a discussion with my son Benjamin who helps me by bouncing off ideas. I do all the building and almost all the programming of the robot, but Benjamin is the person to help me think through things and get new ideas. When I showed Benjamin the data he said use a differential of the two readings, the rising and falling readings. I did this and it gave me a much better detection of objects.
I sent the output of the pyro sensor to a file and put that into an Excel file (CAPTURE heat sensor.xls) and graphed the results. I ran the readings six times, three with just me and three with Benjamin sitting on the couch and me sitting on the floor. The readings were surprisingly consistent each time.
The graph below has two lines. The upper line is the actual readings of the sensor. The numbers on the X axis is the reading number and since each reading I moved the sensor two degrees you would multiply by two to get the angle. The Y axis is the reading from the port, which the high reading was 186 and the low was 71. The first high/low was me sitting on the floor with the sensor scanning directly across my face and the second high/low was Benjamin sitting on the couch more covered with less warm skin showing. As you can see the pyro first gave a high on each of us then a low as it went away, The mid-point of the high/low was when both sensors of the pyro were pointing directly at us and cancelled each other out.
Per Benjamin's suggesting, I ran another graph of the difference of the two readings. I found if I checked 14 degrees apart (7 readings different) I would get the highest differential. See the lower graph and how it peaks when reached the lower point on the upper graph. By comparing past readings to current readings it is now even more obvious where the objects are.
In my program I used a heat differential of 50 to say an object was detected. Also once an object is found I would back it up a few degrees (usually 7) to say that is where center point is.
|Reading the above graph: The upper line is the actual readings of the pyro sensor. Where it goes high it is first moving towards the heat source. Where it goes low, it is moving away from the heat source. The lower line is the difference of the two readings taken 14 degrees apart. If there is no heat source the difference is around 0. Readings are saved and compared 14 degrees apart. For example, with the upper line if X1 is at reading 37 (74 degrees) and X2 is at reading 44 (88 degrees) with Y1=186 and Y2=71 then the difference is 115 which is seen on the lower line.|
The routine below is part of a bigger program that scans the room finds the closest person and then the robot moves to him. This will show you how I implemented what I discussed above.
declare heat_dif(8) 'keep heat readings 8 readings back
declare closest_angle 'angle that closest person is at
declare closest_distance 'distance of closest person
scan_room: 'scan the room and save distances to objects found in array
'note when a heat reading is compared to a heat reading 7 readings
'(14 degrees) back. If this reading drops by 50+ then it must have
'been a person.
temp=usr(moveservo,-90,hservo) 'point servo far left
temp=usr(moveservo,-30,vservo) 'point sensor down so it is not looking at any heat source
gosub heat_stable 'make sure sensor has stablized
temp=usr(moveservo,8,vservo) 'tilt up to spot people easier
gosub delay,temp 'note moveservo returns estimated time to move servo, temp has delay amount in milli-seconds
ok=false 'ok will say that a person has been spotted
do 'preload array, put in what an average would be to start comparison
loop until angle_count>7
temp2=0 'total number people found
closest_distance=5000 'set high so next will be selected
if temp<50 'at at least 50ms or longer if servo needs it, moving 2 degrees about every 50ms
heat_dif(angle_count)=usr(read_AD,heat_sensor) 'look with heat sensor
temp3=angle_count+1 'find which previous reading to look at
if temp3>7 'if greater has gone around corner
temp3=heat_dif(temp3)-heat_dif(angle_count) 'find difference
if ok=false 'note if there is still a readinf difference of 50 it must still be same person
temp2=temp2+1 'person count
ok=true 'have found person
temp4=usr(read_sonar,left_eye)/303 'find distance of person just found
closest_distance=temp4 'new closest person
closest_angle=angle-7 'angle that closest person is at
ok=false 'no longer spotted peson, so next reading will be another person
angle_count=angle_count+1 'incriment count for the stored array
loop until angle>90
The pyroelectric sensor is a great addition for your robot, a definite must. For what it does it is cheap and is easy to interface to the MCU with analog to digital ports.