December 15, 2003
MegaMazer Development
The Development of MegaMazer
The Development of MegaMazer
Introduction
MegaMazer is my latest maze runner development for use in the PAReX Expert Maze
Competition. This article will cover the various stages of development from
concept to final debug and the first event I entered it in.
Design Goals
The Expert Maze Competition is a Search and Rescue format, where the robot must
explore the maze (search phase) looking for a rescue victim (tennis ball),
indicate recognition of the victim, and return to the starting line(rescue
phase). The search phase must be completed in less then 3 minutes and the rescue
phase in less then 2 minutes. Scoring is based on how long the rescue phase
takes, so the robot must be able to map the maze, keeping track of where it’s
been, where it’s going, where the dead ends are, and where the starting line is.
Bonus points are awarded for recognizing the completion of the rescue. Penalty
points will occur if the robot touches the walls or exhibits destructive
behavior to the maze, so a reliable guidance system is required.
Design Concepts
So with the goals outlined, how should I design a robot to succeed in this
event? This would be my 4th maze robot and the 2nd one that would run in the
expert class. The first one used hacked servos for drive motors and was
difficult to keep it going in a straight line. It did find the ball but an error
in the return algorithm prevented the robot from finding the start line and
completing the runs.
For the new robot I wanted to try steppers motors for improved guidance control,
both in driving straight and precise turning. A digital compass was another
option I wanted to try for improving guidance. For wall sensors I would continue
to use the Sharp GP2D02 IR range sensors, which worked well on all my previous
designs. So with these thoughts in mind, here’s what the robot would look like.
|
Robot size
|
Overall round shape less then 8” diameter. Aluminum chassis instead of the plastic
used in previous models.
|
Maze walls are spaced 11” apart, if the robot is any bigger it might contact
the walls.
|
|
Drive motors
|
Stepper motors
|
To improve handling.
|
|
Wheels
|
NetMedia plastic wheels with O-rings
|
Got plenty of these laying around.
|
|
Rear Pivot Ball
|
Tamiya 70144 ball caster
|
Nice steel marble in a plastic housing.
|
|
Wall sensors
|
3 Sharp GP2D02 IR range
|
Pointing left, right, and forward.
|
|
Compass
|
Devantech CMPS03
|
This should reduce the number of wall sensors needed to keep the robot
going straight.
|
|
Display
|
NetMedia 2x16 serial display
|
Displays current operations and debug information.
|
|
RF Interface
|
Linx Module
|
Used for telemetry information
|
|
PCB
|
Fabricate a printed circuit board
|
The PCB would have the display and most of the sensors mounted to it.
|
|
Floor Sensors
|
Fairchild QRB1134 IR Photoreflector
|
Used to detect the white disk the tennis ball sits on.
|
|
Microcontroller
|
Atmel AVR Mega128
|
Contains enough internal ram for mapping, 8 channel ADC for sensors,
and 128K flashram.
|
Stepper Motors and Wheels
The next step was to acquire some stepper motors and start experimenting with
them. After a lot of research on the internet, I was able to get some NEMA 23
stepper motors fairly cheaply out of surplus Image Writer II printers. They’re
over 2” in diameter and weigh over 1 lb. each, but have enough torque to direct
drive 3” wheels. Because the motors are so big, the NetMedia wheels aren’t big
enough for proper ground clearance. I decided to make my own wheels using a
common technique I’ve used before. I cut 3” wheels out of phanolic using a fly-
cutter. The cut made by the fly-cutter angles the edge of the wheel and by
gluing two pieces back-to-back you get a nice V-grove to mount the O-ring in, as
shown in figure 1. The final diameter with O-ring was 3-3/8” as shown in figure
2.
Chassis Design
Knowing I’d have one heavy robot on my hands, I decided to make the chassis out
of aluminum. I placed the motors back to back with about an inch of space
between them for the battery placement. With the wheels attached to the shafts,
the width wheel-to-wheel would be 6”, well within the maximum diameter I wanted
to work with. The pivot wheel assembly used for the rear tail is over an inch
tall, so a ½ inch bend in the chassis would be needed to keep the roller ball at
the same floor level as the wheels. A bumper switch assembly was also made from
aluminum with a pair of lever switches that would close if the bumper made
contact with objects in the robots path. Figures 3 and 4 show the chassis
construction.
Driver Design
Most of the circuit design would be straight forward, all the sensors would tie
directly into the processor’s ADC, the serial display would interface with one
of the processor’s UARTs, and the compass module would use the I2C interface.
The stepper driver was my biggest concern, it had to handle the current draw of
the motors and generate as little noise as possible. Since the steppers are a
uni-polar configuration the basic driver circuit would be 4 N-channel MOSFETs,
one tied to each of the motor’s coils and when enabled would energize the coil.
For noise immunity I used optical-isolators between the MOSFETs and the
processor. If needed I could run the electronics on a different battery then the
motors for total isolation, but I was hoping to use one battery supply and run
the electronics off a filtered supply. I designed the PCB to use one battery
supply, but it had jumper options to allow a separate motor battery if needed.
The final drive circuit is shown in figure 5.
PCB Design
Now that the driver circuit was done, it was time to layout the PCB. I planned
on using a Bulgarian based company call Olimex to make my PCB. They can do a
double-sided board for $26 in single quantity, so I thought this would be a good
project to try their services out. The PCB would ride on top of the motors, with
the display mounted on top and the 3 IR range sensors mounted to the bottom.
Since the processor comes in a TQFP package, I could have placed the processor
directly on this PCB, but decided to use a breakout board so I had room to
hookup scope probes and meters for debug. Figure 6 shows the PCB with the
breakout board installed. I included spare connector pads for the unused ADC
channels, incase I needed them later, and connectors for the compass and a
serial port to connect to an RF module or a PC. I received the PCB but found out
it was mirrored. Olimex was very helpful in correcting the error and sent me a
2nd PCB that was fabricated correctly. The only design error on the
board was to the display interface. I used the TTL/RS232 input, when I should
have used the inverted display input, having forgotten that the RS-232 signals
are inverted with respect to their TTL counter parts. A quick cut and add and
the display was up and running, see figure 7.
Range Sensors
Early in the design phase a new sensor was made available from Sharp, called the
GP2D120. The difference between it and the GP2D02 is the effective range. The
GP2D02 has a minimum range of 3.9” which makes it difficult to use on a robot
narrower then 8”. One of my previous robots had the sensors mounted on the side
of the robot, aiming across the body of the robot to the opposite wall, as shown
in figure 8. The GP2D120 has a minimum effective range of 1.5”, making it much
easier to work with, as shown in figure 9. The sensors were mounted to the
bottom of the PCB (figure 10) and I started testing the sensors using the debug
screen in figure 11. The left and front sensors worked as expected, but the
right sensor reading was barely moving. A quick voltage check confirmed that
signal wasn’t swinging it’s full range, so I tried a different sensor. Same
results, hmm, must be something wrong with the ADC port the sensor was connected
to. So I rewired the sensor to a spare port pin and it started working, so I
assumed I had a damaged port pin. Later on I would find out that the JTAG
interface of the Mega128 is shared with the ADC port and is enabled by default.
The Flash programmer is also used to control options such as the JTAG interface,
so I disabled the JTAG interface and all the ADC pins started working as
expected.
Detecting the Ball
Once the robot is up and running, it has to do more then avoid running into the
walls, it has to detect the tennis ball, knock it off it’s stand, and then begin
the return part of the mission. In past designs I had tried using multiple
forward range sensors, one mounted about an inch high, the other about 4 inches
high. The upper one was higher then the ball, so if both sensors saw something,
it was a wall. If only the lower sensor saw something, it must be the ball, as
illustrated in figure 12. After a lot of testing I determined that the sensor’s
beam was so narrow that if the robot was off to one side it could miss the ball
completely as shown in figure 13.
A different method is to simply use the bumper switches and run into the ball,
but I found out that the ball is lighter then the spring force of the switch, so
sometimes the switch wouldn’t close as the ball was knocked off the pedestal.
The method I finally used was floor sensors. Since the maze floor is black and
the ball sits on a 6” white disk, a reflective floor sensor could detect the
disk and assume we’re about to hit the ball. The only other place in the maze
that has a white floor is the 1” wide start line, so a method is needed to
distinguish between the start line and the ball disk. By using two floor sensors
spaced over an inch apart, it’s a simple matter to distinguish the line from the
disk, since the only time both sensors will see white is if the robot is over
the disk. The final method I used only had one floor sensor and the software
simply ignored the floor sensor until the robot got out of the first cell, then
I knew it was past the start line and I could start looking for the disk.
Once the disk was detected it’s a simple matter to drive forward about 2 inches
to make sure the ball gets tapped off it’s stand. Then I backup the same 2
inches, turn around, and begin the rescue part of the mission. The reason I
backup before turning is in the past when I turned on top of the disk, the tail
could get hung-up on the ball stand and interfere with the turn.
Maze Mapping
The purpose of the search & rescue mission is an exercise in maze mapping.To
achieve the highest possible score you don’t want to waste time during the
rescue part of the mission by wandering down dead-ends you’ve already been
through, or making a wrong turn and getting lost.
For the PAReX Expert Event the method I used for mapping is not very complex. We
don’t need to know exactly where the robot is in the maze, we need to know what
path we’re on, what paths have been traveled, and what paths haven’t been
traveled. As the robot moves to each new cell, the status of that cell is saved
to the next ram location. When the robot hits a dead-end and goes back on the
traveled path, the corresponding ram location for that cell will be updated to
indicated the dead-end path. The robot will continue falling back cell by cell,
and ram locations, until it finds a path not used yet. Now the forward progress
resumes, writing to the next ram location with each new cell. Yes this will
overwrite information from other cells, but since those cells were part of a
dead-end path, we don’t need that data anymore.
Once the ball has been detected, it’s a simple matter to find the way back to
the starting line by using the traveled path stored in each ram location. Once
we’ve worked back to the first cell, we know we’re done and we signal completion
by blinking the LED’s and placing a message on the LCD display.
First Driving Tests
Ok enough talk, let’s turn it loose and see what happens! I was very pleased
with how straight the robot moved. Without any type of guidance correction, the
robot could navigate my test maze without touching the walls, at least most of
the time. There were still times when a stopping or starting action would get it
slightly turned. This of course was the reason for having a compass, to make
course corrections as needed. Another big relief was the performance of the
sensors, which appeared unaffected by the big steppers motors running off the
same battery. One of the ways I tested for stable sensors readings was to send
the robot down a straight corridor and log each sensor reading to ram. Once I
stopped the robot I dumped the data to a laptop and looked at the readings.
Ideally I would see the same reading each time, as long as the robot remained
the same distance from the wall. In looking over the data, the readings varied
no more then 1 or 2 counts, which was quite stable for my use.
Digital Compass
A compass was also something new to try, so I ordered a Devantech CMPS03 and
started experimenting with it. It supports a resolution of 0.1 degrees but the
specs are quick to point out that due to noise and varying field conditions you
may get a few degrees of error. The compass was simple to interface using an I2C
protocol and I was testing it in no time. One concern I had was how the stepper
motors would effect the compass. Once the compass got within 2 feet of the
motors, the readings started getting skewed. By the time the compass was over
the motors, the reading had changed over 90 degrees, ouch! Although the baseline
reading was off, the compass still produced linear readings as I rotated it
around with the motors, so it looked like everything might work together. Also
running the motors didn’t seem to effect the compass readings, so I finished
mounting the compass to the robot and finalized the code to interface with it.
Figure 14 shows the robot with the compass mounted high above the electronics as
recommended. I changed the turning routines to use the compass readings and ran
it around the maze. Well it appears that even moving only 4 feet, the readings
changed enough that the robot would be about 5 degrees off after completing a
180 degree turn. I spent some time re-calibrating the compass and trying a few
different things, but things didn’t improve. Since the event was now less then
two weeks away, I decided to fall back on plan B which was to install a 2nd pair
of range sensors pointed at the left and right walls and dump the compass.
Plan B
In past designs I had used dual wall sensors to align the robot to walls and
keep it going straight. You place one sensor at the back of the robot and one at
the front, both pointing at the same wall. You read both sensors and if they
have the same readings, you are aligned with the wall, otherwise you rotate the
robot to get it properly aligned, as shown in figure 15. Where I got into
trouble was open crossways, where there weren’t any walls to align to. The robot
would do a turn and depending on noise and it’s battery condition, the turn
would come up short and I’d hit a wall before I could get aligned. This is where
the compass would have helped out.
When I designed the PCB I had included 2 spare stake headers that could be used
with sensors, now it was time to use them. I mounted 2 more GP2D120 range
sensors on the front of MegaMazer (figure 16) and rewrote the firmware to use
the additional sensors instead of the compass. Back in the maze the robot worked
well, now every time a turn was completed, a sensor pair was used to get the
robot aligned to the wall. Most of the time this worked, but on occasion a
startup would lurch slightly to one side. Eventually the robot would hit a wall,
so now some real-time guidance needs to be added to complete the navigation
software.
Rescue Phase
With about a week left, I decided to put the real-time guidance on hold and
complete the ball detection and rescue part of the firmware. The ball detection
as described earlier was already working, and the rest of the rescue code had
been copied from a previous robot, and was also working. So the only concern I
had was the glitch that prevented the previous robot from completing the
mission. The problem was narrowed down to a scenario where the ball is in a cell
opposite an open hallway. After the ball was hit and the robot turned around, it
saw the hallway and followed it, instead of turning down the return path. I was
able to fix the firmware and all was well. About this time it I realized I
hadn’t done anything to distinguish the ball disk from the start line. I had
only installed one floor sensor since I didn’t have a clean way to mount one
towards the rear and when I ran it over a 1 inch starting line, it trigged the
ball detection routine about half the time. I modified the firmware to ignore
the floor sensor until the robot had traveled one cell, which would mean it was
past the starting line. After the ball is detected and robot starts it’s return,
I don’t need the floor sensor anymore so it’s ignored. So when the robot crosses
the starting line and completes the mission, it won’t care about seeing the
starting line.
Real-time Guidance
Back to watching the walls as the robots travels. Detecting that the robot is no
longer aligned to the walls is simple. The problem is running the stepper motors
at different speeds to make a correction. Since I’m using a single table to
drive both motors, they will always run at the same speed. I thought about
trying a few things like disable a motor for a certain amount of pulses, or go
to a separate table for each motor. Any of these methods would just take too
long to develop so I went after a more radical solution. I decided to let the
robot run until it got too close to a wall, then stop, turn into the wall, and
back up to get centered in the hallway. Now all it had to do was rotate till it
was facing it’s original heading, run the wall alignment routine, and continue
forward again. This routine is a little bizarre to watch, it looks like the
robot has gone bonkers and about to run into a wall, then it backups, rotates,
and goes about it merry way, perfectly centered in the hallway. The reason I
backup and rotate, instead of going forward and rotating. is the amount of work
involved. If the robot moves forward it needs to continue looking for wall
openings, looking for the ball, etc. But if the robot backups, it already knows
what openings are there and that there’s no ball back there.
Event Day
Well it was finally time to premiere MegaMazer, which was charged up and ready
to go. As it turns out, MegaMazer was the only entry in the Expert class, so it
wouldn’t be competing against other robots, just the maze itself. The event is
composed of 3 rounds, with the maze getting more complex with each round.
MegaMazer completed all 3 rounds almost perfectly, with one wall touch in the
2nd round, due to one of those startup glitches. This was a milestone for the
PAReX event, since this was the first time a robot has successfully completed
the Search & Rescue missions of the Expert event.
Conclusion
Well now what? I need to work on the startup sequence and get rid of that
startup glitch. I now have time to work on some real-time guidance routines
before the next event. Once we have more success in the Expert class, there’s
talk of doing something like actually picking the ball up and bringing back to
the start line. That would be a fun challenge to add this ability to MegaMazer.
Posted by Kelly Small at December 15, 2003 07:09 PM
hi there:
i am a student from China, i use digital Compass(CMPS03)now, i want to read the Compass value(how many degree) via PIC 16f877 then display in the PC screen. Can you give me some idea for how to read the CMPS03 value for C code?
Thank you very very much.
Hi Kelly,
The best thing i came across is this. i know it is beyond my appraisals. thanks a lot for posting this.
it would be even a great help if you can let us know about the software that you used for this project.
thnx much
Sambit
Hello,
I to am building a compass (cmps03) to work with a pic 16f877. I have written some of the code (c-code) But i'am not getting the right response back. Here is what i have so far?
i2c_start(); // Start condition
i2c_write(0xc0); // Set Device address
i2c_write(0x02); // Device command
i2c_start(); // Start condition
i2c_write(0xc1); // Set Device address r = i2c_read(); // Read first byte
r2 = i2c_read(); // Read second byte
i2c_stop(); // Stop condition