This controller is designed to make it more intuitive to control a 6-axis robot arm (as well as code-less sequence programming, see “Software” below). It is a “puppet” model that can be moved around, while the full robot arm (not included) mimics the movements in real-time. This avoids fiddly low-level angle inputs as well as hard-to-explain high-level concepts like inverse kinematics.
Children and adults alike can have their first contact with robotics and have a first-hand experience with the challenges and strategies of automating mechanical tasks.
The controller has been used in public venues as a hands-on demonstration setup where unfamiliar visitors (many of them children) succesfully programmed robot arm sequences within five minutes. They use the controller to move the robot arm into the desired first position, press the “save snapshot” button, move it to the next position, and so on. When the “play” button is pressed, the robot arm will smoothly move between the snapshots, executing the sequence over and over again. This combination between ease-of-use, real-time feedback, and quick achievements has proven to be surprisingly succesful.
Using the metaphor of “taking a picture” and “many pictures become a video” helps when explaining the concept.
It is also useful in a non-didactic setting to just make it easier (and fun) to automate a robot arm sequence.
You'll need a six-axis robot arm (fewer axes can work, too) and some suitable microcontroller board (with at least six analog inputs). The controller has been modeled after the original (non-"++") Arduino Braccio. But as long as the geometries are reasonably similar, cheaper kits should work just as fine. You might have to adapt the Arduino sketch, though. Note that even a higher-quality kit like the Braccio is not suitable for real-life tasks. While quite durable, is still too weak to do most things like open drawers, make coffee, etc.
You'll also need a handful of those bog-standard, cheap, linear potentiometers (at least 6, but having spares does not hurt). Whether they are 10K, 50 or 100K Ohms does not matter, either. I bought this set. Their physical size matters, however. Most cheap ones have the same size, but fore completeness' sake, here are my pots' measurements (ca.): body diameter 16.5mm, body height 9.5mm, shaft diameter at bottom (thread): 7mm, shaft diameter at top: 6mm, shaft length 15mm.
And then, of course, the printed parts you can download here.
If you want to adapt the robot arm controller's design, feel free to copy and modify the original TinkerCAD Sketch (the bits floating around the controller itself are a couple of helper bits for cutouts, etc.).
The base can be printed without supports and has a thin membrane that you need to cut out before being able to mount the potentiometer.
For most of the other parts, you need either support and/or get creative with printing angles. For example, I printed the upper/underarm at an angle to avoid supports in the important joint area.
Please print both “Finger” files (1 and 2). If you print just one of them twice, their gears will not mesh correctly.
Note that the potentiometers have a small lug at the side/top of their casing. The printed parts have holes that fit this lug. Make sure that this hole is not filled with support material, or the pot won't seat completely.
Beginning from the base, mount the potentiometer, then stick the next part on it, etc. Before putting the next part on the potentiometer shaft, make sure that the pot is turned to a position so that the joint will be able to freely rotate up to its end stops (and not the pot's end stops). Relying on the pot's end stops will wear it out very quickly.
Refer to the photos or the complete model for guidance. For most parts, press fit will hold together well. But you might want to use the nuts that come with the pots to mount them more securely.
Connecting the potentiometers:
Cable management: Try to keep the wires close to the printed parts so that they cannot snag, but make sure that all the joints can move to their extremes (usually +/-90 degrees) without pulling the wires taut. Don't underestimate how much extra wire length e.g. the base needs. I used twist ties to clean up the wiring, but zip ties should work, too. Between the robot arm controller base and the microcontroller or motor shield, I gave the cables 30cm of slack.
The software depends on the robot arm and its motors, your microcontroller, and how the motors are driven. I have used an original TinkerKit/Arduino Braccio in my code (Braccio_Puppet_Master.ino). I also extended the original library with some convenience functionality (see Braccio.zip). It uses standard servos, so a servo library should work, too (with code adjustments)
But even if you do own an original Braccio robot arm, I full-heartedly recommend that you program this yourself. It is a very rewarding learning exercise. If you get stuck, you can look at the example code files to find out how I did it, but I will outline a rough strategy for you below.
Steps towards a working robot arm controller (assuming Arduino Uno and joints, please adapt where needed):
base_servo.write(90);
. Also try to find a “safe starting position” for your robot arm. With servos, it will usually move to this position very suddenly when it's powered up. So don't chose an outstretched pose, or the forces will be very high (I chose the pose you see in the photos).base_angle = map(analogRead(base_pot), 0, 1023, 0, 180);
base_servo.write(base_angle); // using base joint as an example
map
parameters 0-180 (the second pair of parameters) to different values so they always stay within their constraints.map
parameters 0-1023 (the first pair of parameters) to something else. Do this in a systematic manner, one joint after the other.loop
runs. (At that point, I switched to using arrays, but if you're not comfortable with them, you can use global variables instead.) Define two global variables per joint (here as an example for the base joint):int base_target_angle = 90; // use safe start position as initial value
int base_curr_angle = base_target_angle;
base_target_angle = map(analogRead(base_pot), 0, 1023, 0, 180);
base_curr_angle += base_curr_angle < base_target_angle ? 2 : -2;
base_servo.write(base_curr_angle);
loop
.The author marked this model as their own original creation.