This robot was built from scratch and I had to reiterate on the core concepts a couple times. It was built under tight time constraints. The final product here is not a 100% working model (yet) due to some software and hardware kinks ( I'll list the ones I found below). The codes have been put on my GitHub repository and any and all suggestions to improve upon it is most welcome.
There are obviously better and more efficient ways to go about making it. But this is the method I followed and I would recommend reading the whole thing instead of blindly jumping into the build, as this is more of an explainer rather than a project that gives you a solid working model in the end.
Basic GoalsAn ideal quadruped should have 3 dof on each leg, allowing it to have the full range of motions, i.e. it can move forwards, backwards, sideways, rotate etc. But as this was my first project of this type, I decided to give the legs only 2 dof. This means it can only move forwards and backwards. The robot is statically stable, meaning at any given time at-least 3 legs are on the ground and it will maintain its balance at any point of its motion.
Before going into the movement and inverse kinematics, I would like to jump forward a bit and show my initial two models, and point out the shortcomings of each.
Model 1:Yea.... so this was made with scrap acrylic strips and attaching the servos directly by screwing the servo horns onto the strips. The major issue with this was the servos weren't sturdy enough to keep the legs straight and it was a wobbly mess.
Model 2:To fix the wobbliness, I attached the legs (still acrylic, just black) to a sturdy support and then used a hinge mechanism to connect the servos to the legs. The inverse kinematics were arguably more harder to solve and it sort of moved to complex number fields and I had to use Matlab and curve fitting to make it into a manageable form.... there must've been easier ways but that was the only one I could think of, it worked nonetheless and the legs did move how I wanted them to. But this model was too big and heavy for the servos I had to handle and it kept slipping. Maybe if I had used stronger servos this could've worked....
Now that I've shown you how not to go about making the robot, let's jump back and see some basics on the components and theory.
ServosServos are motors that you can rotate and set to a specific degree. Inside a servo you have a motor, a potentiometer, an IC and a gear assembly. The motor turns the gear assembly, and the rotation is measured with a potentiometer which then informs it to the IC, which then rotates the motor as needed till the specific angle is reached. We specify the angle to be set using PWM (Pulse Width Modulation) which are pulsations of DC voltage, the length of which is used to set the angle of the servo. More info on Servos and PWM can be found here.
The Servos I used were the smallest and cheapest I could find. They're a bit too fragile and I burnt through quite a few over the course of the project. But there are higher quality metal gear servos available that last longer and provide more power if you need it.
Raspberry Pi PicoThis is a micro controller, or the brains of the robot. Its similar to an Arduino. It runs on Micropython, which is similar to python, but designed for micro controllers.
Servo DriverA typical micro servo draws around 200-300 mA which would fry the Pi Pico, which has a max draw of 16ma. To avoid this we use a Servo Driver. This is a board with pins to connect the Servo, separate power source and I2C Pins from the Pi Pico. I2C is a standard interface protocol which allows the Pi Pico to communicate the Servo angles to the Servo Driver board over just 2 wires. The Servo Driver I used has pins to connect 16 Servos, all of which can be controlled individually via instructions from the Pi Pico over I2C.
StabilitySo the robot is made to move in such a way that for any point in its movement if I were to freeze it, the robot would still be stable. This is done by ensuring that at any given moment at least three of its feet are touching the ground, and the center of mass of the robot is approximately over inside the triangle made by the three points.
This is an ineffective way to go about it for anything more than a basic robot that walks forward and backwards. More complicated robots make use of sensors to check if they're tilting too much and make real time adjustments to maintain balance.
MovementThe robot motion is such that it will start in a position with two diagonally opposite legs placed one step forward. Then:
- The body moves forward a step
- The front leg that was behind moves forward two steps
- The diagonally backwards legs move two steps forward
- The body moves forward a step
- The other leg moves froward two steps
- The diagonally opposite back leg moves forward two steps
Steps 1-6 keep repeating.
Also, from now on the point of interest are the ends of the legs, and I will be referring to their positions, assuming the point of attachment of legs to body as origin and facing from the side of the leg in question. Hence if the leg is behind, under or in front of the body hinge, it'll be in back, middle or front position respectively.
It can be seen that the movements are a combination of a few fundamental movements on each legs, namely:
- Alpha - Placing one leg up and forward on through an arc.
- Beta - Moving the leg backward while keeping on the ground, hence moving the body forward in the process.
- Gama - Holds current position.
There are variations within each movement type, such as whether Beta movement is from back to middle or middle to back or Gamma does nothing while at back, middle or forward position. I have suffixed them with according to their points of interest with -1, 0, 1, corresponding to back, middle and front positions.
- Alpha has no variation, only one type of movement.
- Beta 1-0 : Leg moves from front to middle on the ground.
- Beta 0-(-1) : Leg moves from middle to back on the ground.
- Gamma -1 : Leg stays in back position.
- Gamma 0 : Leg stays in middle position.
- Gamma 1 : Leg stays in front position.
Now we must define functions for each type of movement and then cut and string together the combination of movements for each leg. Both X and Y functions must be made for each movement. Some parameters must be defined for the movement to make it easier to change as needed when coding. These are:
- Stride : The length between the front and back positions.
- Step Time : How long it takes to complete one movement (Alpha/Beta).
- Stride Height : How high the leg should rise while taking steps.
- Rest Height: How high the robot body should be above the ground.
Using these factors and using simple sine, and linear functions we can define functions on both X and Y wrt time for each movement. Then we can use code to join these functions together and make the complete move set of each leg.
I personally used Simulink to prototype the leg motions and join the functions together. I then just translated what I did to code using while loops to switch each function wrt time.
Put together, the X (Blue) and Y (Yellow) functions for each leg looks like this:
Please note the axes values in this case correspond to millimeters, and are calculated using the parameters of stride, ride height etc, I have given. Step time is.5 sec, and remember that there are 6 steps in each cycle, hence each function is repeated every 3 seconds.
The legs of the robot will be controlled using servos and we can only tell the servos what angles to move into. Hence we must find a formula that tells us what angles to set the servos so that we can get the leg to be a specific point in the Cartesian plane.
Now that we have found out the pattern to move the legs and the formulae to do so, all that's left is building the robot and the programming.
Robot BodyI drew the inspiration for the body from some models I found while looking around the internet. I made the models in Autodesk and 3D printed it. The one problem I ran into with my model was that the robot wasn't wide enough, and therefore it wasn't as stable as I hoped it would have been. Hopefully this can be fixed by increasing the width of the main body plate. I had provisions to screw the main plate to the side rails, but it broke as soon as I tightened the screw, so I just used superglue, and that gave me a very strong, sturdy bond.
There are provisions to glue the servo horns onto the legs, but the horns aren't a standard size and you may need to tinker with the dimensions in the 3d model. I used a narrow awl to make small holes to screw the servos onto the arms and rails. It holds fine, but if you want a more sturdier fit, you can always glue them together.
I would also recommend making a sort of cover to sit on top of the main plate, to hide the circuit boards and batteries, if you plan to use onboard power. The way I set it up, the servo driver is powered using a big-ass Power supply and the Pi not placed on the robot. The wires are free, so maybe some provision can be made into the chassis to route the wires for a more cleaner look.
I'll upload my CAD models, but I should warn you it is far from perfect, and it requires some tinkering, or even a complete overhaul for optimal functioning.
The code I used for this can be found on my GitHub repository here.
WiringThere isn't much to the wiring. Just a few pointers:
- Connect GP0 on Pi Pico to sda pin on servo driver.
- Connect GP1 on Pi Pico to scl pin on servo driver.
- Connect the 3V and GND pins to the corresponding pins on the servo driver.
- Connect the 5V leads from the Power Supply to the specialized connectors.
- Connect the servos to the PWM pins on the Servo Driver in order:
0
- R1 Upper1
- R1 Lower2
- R2 Upper3
- R2 Lower4
- L1 Upper5
- L1 Lower6
- L2 Upper7
- L2 Lower
So the Servo sets its angles according to the duty cycle of the PWM. Using code, we send the board values that typically range from 1000-9000. But the exact value for the angles vary between each individual motor, and must be calibrated for each.
First start by finding the limits of the motor, send duty_cycle values below and above 1000 and 8000 till the servos wont move. Whether or not the zero degree corresponds to the higher or lower limits depends on the side on which the servo is placed, and must be noted, here lower limit means that limit which corresponds to 0 degrees and vice versa. The formulas were derived under the assumption that the position corresponding to zero degrees for the upper limb is parallel to the chassis and for lower limb is parallel to upper limb. First mount the servos onto the chassis and lower limbs. It will be useful to number each servo so as to avoid confusion.
Upper LimbTake the upper and lower limits and get its average. Set the servo duty cycle to the average value obtained. Now place the upper limb such that it is almost perpendicular to the chassis, it needn't be accurate. Now try varying the duty_cycles such that the limb is as parallel as possible to the chassis, for both 0 degrees and 180 degrees. Note down these value, and repeat for the other three limbs.
Similar to the upper limbs, find the average, set the servos to the middle value, and place the limb almost perpendicular to the upper limb. Find the limits corresponding to 0 and 180 degrees and note them down. Repeat for the other three lower limbs.
These values are to be inputted into the code in the corresponding data array.
So now that we've built the robot, and downloaded the code onto the micro controller, all that's left is to run it, test it and troubleshoot it. I'll list a couple of kinks to be noted and be on the lookout for:
- The legs don't provide too much traction, hence it's advised to either glue rubber pads onto the bottom or place the robot on a rubber mat.
- As I'm placing the brains and power outside the robot, I recommend using long thin wires between the robot and the external peripheral so that the wires don't interfere too much with the robots stability.
- Adding some sort of weight at the center of the chassis would help keep the center of mass inside the stability polygon, but ultimately this is a tradeoff between the stability and the weight the servos can handle.
- .Make sure the power supply can supply adequate current. The stall current of the sg90 servo is.65 A and 8*.65 ~ 5 A. The servos may not work properly with inadequate current.
- It must be noted that the angles corresponding upper and lower limits for the servos are inverted depending on the sides, care must be taken so as to not get confused.
- As mentioned before, the chassis plate must be broadened a bit to give it a bit more stability.
The entire project was a very awesome learning experience for me. I knew little to nothing about micro controllers, servos and 3D printing. I had to even learn Matlab & Simulink and brush up on my Autodesk skills. I am very glad that I attempted this and, even though it isn't totally how I wanted my final product to be, it did exceed my expectations of what it would turn out to be. I hope that this helps you at least get started with building your own quadruped robot.
Working
Comments