Hedge Court Robots
|HCR Home||Projects||Builder's Log||Links||Search|
Seahorse is a line following robot, the second one I designed and built. The first was Crabby, a nice, fun, and functional line follower. Seahorse builds upon my experience with Crabby with the intention of improving my skills at design, planning, and machining with the secondary goal of possibly building a faster more accurate line follower than the first one. While not breaking any speed records, Seahorse is a smashing success across the board. Lots of lessons learned, design decisions that worked exactly as planned, and a few surprises along the way.
Seahorse uses five phototransistors to measure light reflected off the floor emitted by white LEDs. An Adafruit Pro Trinket 5v controller (like a small Arduino UNO) runs the show by reading the sensors and driving two DC gear motors using differential drive. By invoking a simple calibration routine, Seahorse can handle either light or dark lines.
I find myself continuously amazed with robotics and how much detail you can choose to put into the simplest of creations. This project was characterized by slow, patient progress with an attempt to be thoughtful and deliberate with each step of the way. Surely a robot can be built faster and better but the joy in this hobby is about the journey and not the destination.
The body is made of two sheets of hobby airplane plywood held together (and apart) by six aluminum standoffs. All other parts of the robot attach with machine screws to either the top sheet (for user interface components) or the bottom sheet (for control, sensor, and drive components).
As a novice machinist I often need to remind myself to go slow and simplify things whenever possible. A small example is drilling the six holes in each piece of plywood for the standoffs. To improve alignment between the top and bottom layers, I clamped them together during drilling yielding perfect alignment later when all the guts were installed. Seems obvious to experienced folks, but each little action like this adds to the overall quality of the end product.
The standoffs are custom built from 3/8" rod, measured to the minimum height to clear the motor mounts and added a few millimeters. Cut six lengths of rod by hand with hacksaw and a little miter box. Filed them by hand to get the lengths as exact as possible. Used my 3/8" drilling fixture to drill holes in either end and tapped with 4-40 machine threads. Making these standoffs was a test of patience. I kept wanting to rush to get through them, but reminded myself to slow down and enjoy it. I easily could buy some off the shelf items or screw together a bunch of nylon standoffs sitting right here, but that wasn't the plan. The resulting standoffs are great even if the holes are not exactly centered.
The 4-40 threads on the standoffs are a minor nuisance. Everything else on the robot is metric M3, with 12 4-40 screws thrown in to attach the body sheets to the standoffs. Since then I got a M3 tap, but at the time only 4-40 was available. The nice thing about modular construction is that I can replace the standoffs with M3 without impacting any other part of the robot. Probably won't do it but nice to know :-)
The only place glue was used is on the very front of the bottom plywood. After I nibbled out the rectangle for the sensor view port, the thin strip of plywood along the front felt feeble. Gorilla glued two craft sticks to top and bottom and it is nice and sturdy. Important because this is the part of the robot that will receive the shock in the event of a collision. The picture shows clamps in place during glue drying.
Baffle and Skid
No, not the name of a new action movie, but rather the white thing at the front of the robot, wrapping to the bottom, which is viewed in the picture to the left. This serves two purposes. First it is a baffle that blocks some ambient light from hitting the light sensors. In actuality this does not do much because of the way there is yet another baffle under the robot blocking light right around the sensors. Second it is a low friction skid that slides on the floor. When I first ran it without this attached, the wood frame along the carpet floor was a recipe for disaster and stalls. This is made from a cut up chinese food container and attaches by two of the 4-40 screws that also connect the body bottom to the standoffs.
The two circular items are furniture slides which act as the skids when the wheels are mounted in low-robot configuration. When in high-robot config (normal usage), these skids do not touch the floor.
First I used a sheet of transparency, a box cutter and a sharpie marker to create a motor template to indicate the locations of the motor shaft bearing and mounting screw holes. Lay this over some aluminum angle stock and mark the positions. Flip over for a mirror image to create the other motor mount. Hack saw by hand using miter box, file smooth. Drill out four M3 holes in the bottom to attach the mount to the body, and two 4M holes in the face to attach the motor to the mount (with a bit of wiggle room for alignment).
The motor output shaft/bearing is off center, so I cut two bearing holes into each mount. Using the same two screw holes, I can either mount the motor shaft up high giving a low riding robot, or shaft down low giving a higher up robot body. This played out perfectly as I tested the robot out on different surfaces. On nice smooth tiles, the high-shaft-low-robot position was very nice, but on carpet the body rubbed and caused too much friction with the floor. Very simple to unscrew the motors and flip them over. Again, reinforcing my approach of modular design for flexibility and ease of maintenance.
As is customary for my robots up to this point, I am using LEGO wheels and custom built wheel couplers, following the style documented in David Cook's books Robot Building for Beginners and Intermediate Robot Building. This particular set was made using the IRB method. Start by creating a fixture to hold the raw rod for the coupler. Then drill out the two sides with nice alignment of the centers of the motor output shaft and wheel axle. Drill and tap a hole for a set-screw and then epoxy in a Lego axle.
The technique is very nice, but I got impatient with myself and my tools and rushed through part of it. As a result, the alignment of my couplers is not the best. Luckily this does not cause much problem with the low-performance robot. And not luckily but rather by design, if I ever choose to, i can carefully make a new set to replace these without any impact to the rest of the robot. The beauty of modular design. That having been said, this set works well enough I probably will not replace them but rather remember it as a lesson to learn and pay attention to when I make my next robot.
To help lay out all the parts, I first made a prototype of the top body plate out of cardboard. The pic is missing the line indicators, but they made their way into the prototype too. You can see pencil outlines for where space is reserved for the motor mounts and standoff placement. In the final construction, I added 0.25 inch between the buttons and the motors to ensure the motherboard's vertical height (pushing up from the bottom) did not interfere with the button vertical height (dropping down from the top).
Five indicators are used to show the operator what the robot thinks each sensor is seeing, either background or line. I used NeoPixels from Adafruit instead of normal LEDs for two reasons. First, NeoPixels are individually addressable so 5 can be controlled using a single microcontroller pin. Second, NeoPixels can be set to any color, giving some fun for the kid to pick and choose colors. As adults, we spend all our energy making a functional robot but the real entertainment value for the audience comes from a simple color choice.
LCD display shows three values for each of the five sensors. Row 1 and 3 (or 0 and 2 if you like zero-based indexes) show minimum and maximum values encountered since power-on. Row 2 shows current value. Technically there's a lag between sensor values and display output because I want my program paying attention to the line and not to showing me some values. Bottom row shows the program mode or instructions during calibration, a battery ADC reading, whether calibration thinks the line is dark or light, and the 0/1 state of both of the buttons (more for debugging the debounce routine but I left it in there).
All values (min/max/current sensor and battery) are ADC values which means integers from 0-1023 in Arduino. To save some space without really hurting anything I map the values down to 0-999 to fit 3 digits. This means my output is a tiny bit skewed from the real values the processor is using but the difference is not enough to change the decisions either I (as the author of the code) or the microcontroller (as the executor of the code) make.
Power switch is a DPDT connecting battery positive and negative through the poles. In the off position, both battery terminals are disconnected, totally isolating the LiPo battery from the electronics, allowing charging without physically unplugging the battery connector.
Black button is the play/pause button to toggle between RUN and IDLE. Gotta be quick to press it as the fast little robot scoots on by.
Red button enters CALIBRATE mode. LCD provides instruction to user to first place the sensors on the line and press red button again. Then LCD instructs to place sensors on the background and press red again to complete calibration and return to IDLE.
ElectronicsThe electronics for Seahorse are broken into three separate homemade PCBs. All were designed and printed using Copper Connection, and then exposed to UV sensitized copper clad board using Bronzer, etched in HCL/H2O2, drilled using Dremel drill press and then hand soldered components and jumpers (to fake 2 layers when really only using 1 layer). Daughter boards have connecting wires soldered directly to the board, which are then received via nice connectors on the motherboard. This allows easy reconfiguration and disassembly without wasting too much space, money, precious inventory of connectors.
Seahorse uses a single LiPo 2S 7.4v battery. Raw battery power is provided to three separate places: the Pro Trinket controller, the motor driver, and a voltage regulator that powers everything else. Initial testing shows the battery is draining much faster than with Crabby due to heavier construction, larger motors, faster speed, brighter outputs. There is plenty of space in the battery compartment to upgrade to a higher capacity battery if I can't get better run times out of this puppy.
Line Indicator Board
A very simple board with 5 NeoPixels in a 5mm LED package. The image shows why you always test your homemade PCBs with a continuity checker. Truth be told, I visually identified the short before even turning on the multimeter but did test it out after scraping the bridge away with a razor. This guy mounts to the top plate of the robot body using M3 screws and little nylon standoffs. On the PCB, the pixels are perfectly aligned. The holes in the surface of the robot are not perfectly aligned. This was for entertainment value, the kid likes little quirks more than perfect alignment, so I nudged my clamps a bit when drilling two of the holes. Had to cross my fingers when press fitting the PCB into the holes to be sure I wouldn't apply too much pressure and snap the thing, but it went in like a charm and looks quirky enough to be cute without impacting its ability to inform the user what the line visibility status is.
Regulated CircuitryThere is a 5v regulator providing power to the electronic sub systems. Right out of the regulator the power is split to the LCD display and to a MOSFET transistor switch which then connects to the NeoPixels, the floor illuminating LEDs, and the motor controller logic voltage. Using the MOSFET allows the microcontroller to shutoff unnecessary drains when LOW BATTERY condition occurs. I left the LCD connected directly to regulated power rather than through the transistor so the LCD remains powered on and can display LOW BATTERY to the user. This approach is overkill, would have been fine to skip the MOSFET entirely, but I was having fun.
To make sure I sized the regulator appropriately, here is the load being powered by a LM2940CT-5.0 (capable of 1A constant supply):
Control and Logic
The brains of this operation is an Adafruit Pro Trinket 5v microcontroller board. It is like a small Arduino UNO, and is programmed via the Arduino IDE. I tried to keep the program as simple as possible. Each time through the loop the program will check for user button presses (debounced in software), update the sensor ADC values, adjust the motor speeds and directions. Periodically, it will update the LCD display, check the battery voltage, and update the NeoPixel output.
The algorithm in use as of this writing consists of a few if-else statements.
Parts ListThis is more for my amusement than anything else. As I built this little project, was continuously amazed at how many individual parts went into it. Decided to list everything for fun. 245 individual pieces. Not to mention how many tools and supplies go into the creation of even a simple albeit overengineered robot.
|Hedge Court | HCR Home | Contact Us | Search||Copyright ©, HedgeCourt.com|