For a bit of a challenge I decided to make a small robot using off-the-shelf parts. The goals were to:
- Fit within a 5cm cube
- Be able to locate and move small objects (such as marbles and dice)
- Be able to return with the objects to the starting position.
- Be cheap to make
And thus began a week of soldering with tweezers, hotgluing, and trying to squish as much as possible into a small space.
Hardware on this project took my about 10 hours to assemble, and should be possible to anyone with good fine-motor skills, a soldering iron and a hot-glue gun. However, I'm going to assume you're intelligent.
I'm also going to assume that you will test everything as you add it. Once something has been added, it's quite hard to un-add it, or to fix it.
Apologies for the photos used in the second step. I had some issues with lighting.....
Step 1: Parts and Supplies
- Soldering Iron
- Hot Glue Gun
- Side Cutters
- 1x Arduino Nano ($2.50)
- 1x 10DOF IMU ($7.00)
- 2x SG90 servos ($1.40 each)
- 6x RPR220 Photoreflectors ($0.30 each)
- Resistors (6x 56K, 2x 220R 1x330R 4x 2K5) (~$1.00)
- 2N222A Transistor (~$0.50)
- 2x Round Servo Horns (~$0.50)
- 1x 9v rechargable ($5.00)
- Electrical Knowledge (Ohms law and such)
- Hot gluing
Total Cost: $21
(Note: The parts costs are from Aliexpress, and are significantly less than if you buy in a store. You'll just have to put up with a week or two for shipping)
Step 2: The Chassis and Wheels
The base of every mobile robot is the chassis: what provides the motive force. For this robot the motors and speed controllers come from the pair of SG90 servos. We'll modify them for continuous rotation, cut down their cases and join them together. As well as reading, see the notes on each image.
By default servo's only move through 180 degree arcs. We need them to rotate continuously in a direction that we set. This is pretty well documented online: strip out the potentiometer, replace it with two equal value resistors. My servo's needed 2.5K resistors. Just measure your potentiometer before accepting my word for it.
You also have to cut down the potentiometer shaft so it doesn't grip the output shaft, and remove a little plastic tab that stops it rotating all 360 degrees.
Normally a SG90 is about 3cm tall. We need to get two of them back to back within 5cm space. Without the potentiometer, each servo can be cut down to an "L" shape, and then they can intersect. When this is done they only take 4.5mm. The controller boards had to be relocated. Check the images.
Some bend wire skids were put on front and back to stop the robot wobbling excessively.
The wheels I used were servo horns left over from some MG996R's (a standard size servo) I used for something else. They are 2cm diameter, and I mounted them splines out, so they'd act as a clutch and protect the gears of the servo.
To improve traction, a bead of hot-glue was laid around as a tire. This was smoothed out with a piece of silicon tubing. When the glue has cooled, it can simply be peeled off. Then final smoothing was done with a soldering iron to burn off any high patchs.
Step 3: Mount the Brains and IMU
The Arduino Nano fits nicely across the back. It is hotglued in place. The Servo wires are then soldered onto it. Two other modifications have to be done to it:
- A big capacitor between ground and power. Mine is 470uF, 10V. This prevents brown-outs when the motors start up. Keep the legs long so you can solder other devices to it.
- A wire soldered from the 5V line of the USB port to the 5V line of the robot. The Nano's regulator should provide 5V at 500mA to that pin anyway, but the nano kept browning-out. This wire solved it.
The IMU has a compass in it, and needs to be kept as far away from the motors as possible. It speaks i2c, so needs to be connected to A4 and A5 of the Arduino nano. Both of these were satisfied at the same time by using bend headers to join the two. Make it as high as possible. Power and ground were then connected to where they needed to be.
Step 4: Power Source
The power source for this project came from a 9v rechargable battery. The battery was a 200mA, 8.4V battery. If you get a 7.4V one it will have six long thin cells. Get a 8.4V one so that you get flat, rectangular cells. I used 4 cells to give me 4.8V, though because we plug them into the Vin of the Arduino nano, you could put up to 20V in there without problems.
Extract them from the battery and connect them to a servo plug. Solder a two pin header onto the Vin line and ground for it to plug into. A wrap of tape keeps the pack together.
The battery is held in place on the robot using a piece of paper hot-glued to form a tray. The battery is removable by removing one of the wheels. Unfortunately I don't have any photos showing this piece of paper, so you'll have to use your imagination.
Step 5: Sensors
The sensors that make up this robot are RPR220's, they are reflective optocouplers and measure the consist of an IR led and an IR photodiode. By using a resistor and an ADC, we can measure distance. For more detail, see my tutorial on this:
There are three RPR220's on each side of the robot, arranged so that they give a high and low inward facing and a medium heigh outward facing sensor. This allows the robot to distinguish between a small object it can push (eg a dice or marble) and a wall. Like everything else, they are mounted with hot-glue.
Driving the Sensors
So we need to solder 6 resistors between the ADC's to ground, and the photodiode goes between the ADC and the power line. The current the photodiode allows through causes a voltage between the ADC and ground, which we can measure.
You can drive a single LED straight from an arduino pin, but we need to drive six. This takes 300mA total, which is over the total package draw for the nano (200mA), so we have to use a transistor and drive them all at once. I chose the 2N222A because they're cheap and available. It can provide more than enough power.
So the LED's are two lots of 3 in series, with a small resistor in series to regulate the current. Note that the 2N222A goes between the LED's and ground. You can test the LED's by using a camera without an IR filter.
This is the hardest part in my opinion. There are just so many legs, leads and other things flying around. I'm not going to describe where every wire goes. If I did it would take me a year. This was my first time attempting something like this, and I managed it. So it can't be that hard.
Step 6: Finishing Up Hardware
- You can use a soldering iron to tidy up the hot-glue. It vaporises it without leaving strings. Of course, the smoke is probably toxic....
- Test every part multiple times. Test the IMU, all the parts of it, test each LED, each photodiode, each motor BEFORE mounting it.
- Check your resistor values. I had to re-solder all the resistors driving the photodiodes because I did my math wrong. I'm lucky I didn't kill the sensors.
- The RPR220's let light through from both side. A small piece of plastic solves this nicely.
I plan to make a case out of thin plastic, but haven't got around to doing so yet. I can't think of a source of nice thin, opaque plastic.
Step 7: Software
Now comes a hard and fun and endless part. I haven't got the software done to my satisfaction yet, but here are a few pointers (0x67, 0xE4, 0x20):
- Use C++ classes to abstract away the motors and the sensors (eg a function 'drive' that takes a throttle and turning parameter)
- Read the datasheet on the IMU many many times. Read it again (then once more)
- Use math over if statements and state machines This helps prevent your robot getting stuck in a 'state.' Sum things: collision avoidance should be added on to the intended direction rather than completely overrule it.
- Keep things modular
- Separate things into separate files. Currently I'm up at the 13 file mark for this robot. It prevents endless scrolling.
- Write a scheduler to keep things running.
- Separate out the actual reading of the sensor from your control algorithm figuring out what to do with it.
- You don't need more than a 10hz update rate. A servo updates every 15ms - 6 times a second!
- Throw away the Arduino IDE. It doesn't allow proper file management. Here I'm using UECIDE, but I'm not that happy with it. Ideally I'd use Eclipse but I couldn't get it to upload to the board.
- Use a version control system such as git or svn. It will solve you a huge amount of issues if you decide to undo something.
The most important piece of advice:
ALL GOOD CODE STARTS ON A PIECE OF PAPER
Scribble it down with a good-ol pen on good-ol paper. Draw graphs of how you expect motion to be. Draw dataflow diagrams. Design interactions between parts of code. If you must do it on a computer, use a plain text file and type out reasoning and API's before actually implementing anything.