-
Torque from Micro Servos
04/09/2014 at 21:21 • 0 commentsTo keep costs down, I bought some cheap micro 9g servos from HobbyKing. They have a torque rating of 1.7kg / cm or something... I figured it would be enough, as long as I kept the weight down.
Well, I was kinda correct. However, I could not use the legs I had originally designed (a simple, yet long, thin 'insect-looking' leg). While only 8 cm long, the servos were unable to keep the body standing properly without making all sorts of bad noises. However, by reducing the legs to be shorter (about 3cm long), I was able to get it working quite well; plus, it was christened with the name of 'Subby'.
(And now, even my two year old will walk up to me and ask if I am working on Stubby... or 'tubby' as he says).
-
Weight Loss
04/10/2014 at 02:56 • 0 commentsI picked up a digital kitchen scale today (for a Pinewood Derby car I am making with my daughter)... out of interest, I weighed Stubby. It is currently 401g (including batteries and radio). The batteries + holders alone take up about 120g (batteries are 26g each, and the holders are a few more). The servos are nominally 9g (although I think that is without wires), which makes for another 110g or so (Edit: the servo plus wires are 10g each, for a total of 120g or 180g if I get 18 on there). I think that the best I can do to trim weight is to look at the chassis and leg joints... even though the chassis is hollowed out to reduce weight, it is still probably larger than it could be. I need to look at alternate designs or materials.
The coxa leg brackets are probably the next largest source of unnecessary weight. They are cut from 3/4" MDF, and for structural reasons are chunkier than they need to be. I am thinking I could replace them with a thin aluminum L-bracket.
Why does this matter? Well, if I can reduce the weight by 100g or so, I may be able to add another servo to each leg, making it a full 3 DOF per leg, and allowing for more accurate movements.
If anyone has experience with ultra-light, full 2 or 3 DOF hexapods, I would appreciate any comments on how to best design and manufacture the legs. (I do not have any fancy toys like a 3D printer or CNC machine, but I do have a dremel and steady hands...)
-
PWM Waveform Generation
04/10/2014 at 16:14 • 6 commentsWhen I first started this project, I was using the PWM library I wrote a while back, for use with my quadcopter. It is pretty simple: you can configure as many pins as you want, set a single period for all of them, and set individual phases on each pin. This works beautifully in theory for controlling servos, since they all have the same period (20ms) and the individual phases (between 1ms and 2ms nominally) control the angle.
It didn't work.
The behaviour I experienced was that, when setting the legs to a default neutral position (1500us, or 1.5ms), everything was fine. However I needed the ability to set a calibration offset on each joint individually, since tolerances in the assembly didn't allow for exactly the same angle on all legs. What I was seeing, was that if I set an offset for one leg, occasionally multiple legs would shift position.
After breaking out the logic probes with Warren, we figured out what was happening. To explain, first I will go into a bit on how I implemented this code.
One 16 bit timer is used. This timer has two compare values: COMPA and COMPB. COMPA is used to set the period; when it fires, all PWM pins are brought high. We then look for the first pin (i.e. the lowest phase number), and set COMPB to that number. When COMPB fires, we look for the next highest, etc.
This works fine in theory, but looking through all 18 pins takes time. Sometimes hundreds of microseconds worth of time. It doesn't sound like a lot, but when you keep in mind that 1000us moves the servo 180 degrees, 100us is about 18 degrees. Good luck moving the legs precise distances when you have a margin of error of 10%!
The solution is to pre-calculate all the hard calculations. Every time a new phase is set (i.e. every time I try to move a leg), I now sort all the phase values for all pins. I then assemble a struct which contains the bit mask for turning on all pins (in COMPA), as well as bit masks and associated COMBP values for each pin. Then, when COMPA fires it is just 4 lines to set all the pins (PORTA |= maska, PORTB |= maskb, etc). I set the initial COMPB as the COMPB value of the first sorted struct item. When COMPB fires, I set the pins low according to the bit mask, and look at the next struct in line to find the next COMPB value. No looping is required, so it scales to as many pins as you could want without problem.
Using this new and improved method, it takes 6us in the COMPB ISR. Not bad considering the last one was over 100! This translates to a margin of error of about 1 degree, which from what I can tell is not much different than the analog control circuitry in the servos themselves (the servos I am using have a dead-band width of 8us), and even if it wasn't, is still well within tolerances for this application.
I am planning some future improvements by using assembly for certain instructions. Most notably, the first step in the COMPB ISR is to turn off the clock so we don't miss other phase events; however, even though it is the first line in the ISR, the compiler has added a bunch of extra stuff to save register state. I am planning on defining the ISR in pure assembly, and turning off the clock before any register values are saved. I will then call the normal C function which does all the work, which itself will save and restore register state before and after it has been called.
So what did we learn here? First off, ISRs are not meant for heavy lifting. If you are doing a loop in one, you are probably doing it wrong.
Second, rethinking the problem can let you arrive at a much more elegant solution.
Third, it always comes back to the memory / CPU tradeoff. Feel free to use a few extra bytes of memory (especially on a platform like the ATMega 1284 where you have TONS of RAM - who would ever need more than 16k?) in order to shave microseconds off some time critical code.
Honestly, as a web application / multi tier software developer during the day, nothing I did here was new to me. It is just that when programming on modern servers, you tend to take things like memory and tight inner loops for granted. Code maintainability tends to be more important than saving a few bytes of ram here, or a few microseconds there. It is somewhat refreshing to be this close to the processor.
-
Improved Leg Design (now with 83% more Levers!)
04/11/2014 at 15:57 • 0 commentsAn alternative to reducing the weight (which, given that the servos + batteries currently comprise more than half of the overall weight, and cannot be reduced) is to design the frame + legs in such a way that the servos are not supporting the weight directly. This should reduce servo wear, increase durability, and (possibly) allow the robot to carry enough weight to add a third degree of freedom to each leg.
Starting out along this path, I have made the following design:
The first is the side view; the second is the top view.
The horizontal beam (femur) is to be made from aluminum L-bar, 1/16" thick * 1/2" tall * 3/4" wide. (If that is hard to imagine, think of it on end as an uppercase 'L'. One edge is longer than the other, and the thickness is a consistent 1/16").
The tibia will be longer above the joint than below. A wire will attach from the servo horn to the top of the tibia. The servo can then push / pull the tibia, using leverage to gain more torque than it could otherwise achieve (at a loss of absolute distance). The length of the tibia (or more accurately, the ratio of the length of the tibia above the joint as compared to the length of the tibia below the joint) will determine exactly how much leverage you get.
This design is simple enough that I can machine it at home without any special tools (there are really only four parts: the femur, which will have a cutout to support the servo, a simple tibia, the servo itself, and the wire connecting the servo to the tibia.
Next step is to design something similar for the coxa joint, so that the entire weight of the robot is not sitting on the micro servos. If you have any ideas on how best to do this (keeping in mind my lack of tools beyond a hacksaw and a Dremel), please comment!
-
New Legs
04/12/2014 at 21:04 • 0 commentsAfter a bunch of design and prototyping, I have arrived at a new leg design. It has both the coxa and tibia (or femur, if I choose to expand the leg into three DOF) servos on the same segment. The joints support the weight of the robot; the servos are only there to provide movement and do not bear any load themselves.
The design is below (side view and top view respectively),
I am now in the process of manufacturing 6 legs. The main section is made from aluminum; the tibia will be 1/4" MDF, and the 15mm section which the axle holes are drilled though are wood (to provide additional support).
Pictures and videos forthcoming when I am finished...
-
Design for Stubby 2.0
04/13/2014 at 19:55 • 0 commentsI have finished the design and have started on the manufacturing of parts. Schematics below:
-
New Team Member!
04/14/2014 at 02:39 • 0 commentsA big welcome goes out to Princess Sparkle, my 6 year old daughter and newest team member. She has been helping with the design and brainstorming of ideas, and will be contributing pictures and write-ups in the future. She is well on her way to being yet another great female hacker!
-
Manufacturing the Legs + Chassis
04/14/2014 at 16:24 • 0 commentsWe spent most of the weekend manufacturing the femur part of the legs + the new chassis, along with the coxa joints (where the legs meet the chassis). This post includes documentation on how this was done. (I apologize about the quality of the pictures... I didn't want the bother of bringing out my real macro setup, so just used my camera instead. Hopefully it at least shows what was done...)
1) The femurs were cut to length (100mm) from the aluminum L bar stock, and the edges of the servo indentations were cut. (Pro tip: Triple check that you are cutting the right side!!! Keep in mind that for symmetry reasons, half of the legs are mirrored from the other ones). We used an upside-down mounted jig saw with a metal blade for this:
2) Relief holes were drilled into the bottom of each servo indent (I don't know how else to cut this sort of shape into aluminum bar given the tools at my disposal).
3) The sections for the servos were snapped out. With the relief cuts this is easy; just bend it about 10 degrees with a couple of pliers and move back and forth.
4) Using clamps and a flat file, smooth the jagged bottom of the servo holes, and slightly enlarge the sides to fit the servos, measuring each hole as you go.
5) Measure, and drill the servo mounting holes.
6) Cut the wooden backing pieces to size. I just used some scrap 3/4" cedar I had lying around (removed from my bathroom renovations a few years back), but any sort of wood should be fine here. Hard wood (oak, maple, etc) would probably work best, but I didn't have anything around.
7) Using a high strength wood / metal epoxy, glue each piece into the aluminum brackets.
8) Drill the joint holes through the metal + wood. A drill press would be best for this, but unfortunately I don't have one. A pilot hole definitely helps here. Pro tip: X marks the spot before drilling, do this on both sides of the piece. When you drill the pilot hole, drill from the aluminum into the wood, and verify that the exit hole is on the X marked on the wood side. Then, when drilling the full sized hole, drill from the wood to the aluminum, then stop and flip the piece and drill from the aluminum to the wood. (I managed to split one of the pieces when I just tried to drill straight through from aluminum to wood). Putting the piece in a vice or clamp would probably help to prevent splitting here, too.
9) Cut out the chassis pieces and drill. I used my upside down jigsaw for the outer cuts + rough inside cuts, and then a dremel-mounted drum sander for the inside edges. I unfortunately do not have any pictures of this process.
10) Mount the legs into the chassis. We used 1" Chicago bolts for the axle, separated by washers between each layer. The legs should rotate freely.
11) Mount the coxa servos. This is pretty simple... we put the motor end on the outside of the leg but this is somewhat arbitrary. No pictures here...
12) Hacking on a rough-and-tumble proof of concept of the drive rods using nails and hot glue (a.k.a. the poor man's 3D printer). It works beautifully! Adjusting how close the chassis side of the mount (the wood block with a nail in it) is to the coxa joint determines how much travel the leg has. I want to keep the leg travel to about 30 degrees total (15 in front and 15 behind neutral), so when adjusting the mechanism I will be keeping that in mind.
For a video of this in action, see Youtube.
What's next?
Next up is designing the final push rod. I have a few ideas that I am mulling over in my head... I want to use a threaded rod so that I can make fine adjustments to the angle of the legs. I will post more on that once I have a prototype ready.
Enjoy!
-
Source Code
04/14/2014 at 19:43 • 0 commentsFull source code for Stubby, along with all my other AVR projects, is available via Git at http://git.digitalcave.ca/avr.git.
To compile the source, do the following (ensure you have avr-gcc and the avr build tools installed):
git clone http://git.digitalcave.ca/avr.git cd avr/projects/hex make
-
Servo Push Rod
04/15/2014 at 14:58 • 0 commentsLast night my daughter and I spent some time trying to figure out the best way to make servo push rods. The goal is simple: connect the servo horn to a fixed location on the chassis, via a short rod. The length of the rod should be adjustable (to allow fine tuning of the neutral leg position), and the angle of the rod connected to both the servo horn and the chassis must be adjustable (this is how the legs actually move).
In theory this is simple, but in practice, given the material constraints which I am subject to, it is a bit more difficult.
I came up with the above prototype last night, but I didn't like it for a few reasons:
1) The center of the push rod is quite high above the servo horn, which may lead to binding, and if nothing else is inefficient.
2) The chassis-mounted portion is two slices of dowel, joined by a nail. On the bottom side, the hole for the nail is drilled out, and rotates freely. On the top, it is friction fit. In theory, this allows for free movement, but in practice it is too finicky; if the nail is too tight, it binds.
3) The entire thing looks big and bulky. While I am not making this robot for its looks, there is a difference between simplistic and elegant design vs. "throw something at the wall and see what sticks" design.
I have some more ideas to try tonight, though... here's to hoping!