PAReX Home

Phoenix Area Robotics eXperimenters

Home Club Info Web Log Meetings Events Rules Articles Links

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.

Figure 1 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.

Figure 3 Figure 4





Figure 5

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.

Figure 6 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.

Figure 8 Figure 9 Figure 10 Figure 11

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.

Figure 12 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

Figure 14

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

Figure 15

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.

Figure 16 Figure 17 Figure 18

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

Comments

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.

Posted by: yu qiang at January 13, 2004 01:13 PM

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

Posted by: Sambit Satpathy at January 21, 2004 12:59 PM

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

Posted by: John Gubb at February 17, 2004 07:26 AM