Intuitive Robot Arm Controller "Puppet"

Intuitive and kid-friendly controller for a 6-axis robot arm.
66
456
0
5242
updated December 31, 2022

Description

PDF

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.

Rationale

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.

Needed parts

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.).

Printing

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.

Assembly

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:

  • left lug of pot:  ground (GND on the Arduino Uno I used). You can string all of these together from one pot to the next to save some wire.
  • center lug of pot: analog inputs. These need to be separate cables. On my Arduino Uno, they go to pins A0 (base) to A5 (gripper).
  • right lug of pot: controller's reference voltage for the analog inputs. On an Arduino Uno, this is the pin labeled 5V. You can string all of these together to save some wire.

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.

Software

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):

  1. Learn how to move your robot arm without the controller first. Take note of the commands that you need to use to move the joints, e.g. 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).
  2. Learn how to use a potentiometer to move one single joint. See the Arduino “Servo > Knob” example sketch. Also note how the analog value read from the pot (0 to 1023) is being transformed to a value between 0 and 180 for the servo, e.g. 
    base_angle = map(analogRead(base_pot), 0, 1023, 0, 180);
    base_servo.write(base_angle);  // using base joint as an example
    Observe that the arm response can be very jerky at times (we will fix that, but it's good enough for now).
  3. With what you learned in (2), find out the safe neutral position, safe maximum angle and safe minimum angle for each joint/servo (listen closely and avoid that the servos make straining sounds at the limits), and adjust the servos' respective map parameters 0-180 (the second pair of parameters) to different values so they always stay within their constraints.
  4. Now, you can already put everything together so that you can control the robot arm in real-time using the robot arm controller puppet.
  5. You most likely noticed that not all puppet positions match the robot arm positions very well. For example, you might not be able to reach a certain position with the robot arm that you should. This will have to be adjusted through tweaking the map parameters 0-1023 (the first pair of parameters) to something else. Do this in a systematic manner, one joint after the other.
  6. Before we look at the ways to enable code-less programming using the controller, we need to deal with the jerky movements. Depending on your library/motors, the movements may be very sudden (as is the case for servos). But if we want to make it move elegantly between saved snapshots, we need to tell it to move not to the end position immediately, but first to a position that's nearer to the end position, another, etc., until we reach the desired position. We can do this for all angles at the same time, which speeds things up – and looks cool as well!
    For this, we need to remember the current angle for each joint inbetween 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;
    Then, in the loop, assign the result of the map command to the base_target_angle, and then update base_curr_angle to be e.g. 2 degrees nearer to base_target_angle, e.g.
    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);
    Do this for all the other joints besides the base joint. If the movement is still erratic, you might want to add a small delay to the end of the loop.
    There are more elegant ways to smooth this out (e.g. divide the difference between target and current by 20 so every movement takes the same time and small movements are more precise than big movements), but that's left as an exercise to the reader. ;)
  7. For sequence programming, you will need arrays. I created a two-dimensional array of all joints and their respective sequences of target angles (snapshots/steps). I found that a maximum of 50 steps suffices for this purpose. This might also be a good point to switch the rest of the code (min/max values, curr/target angles) to arrays of length 6 as well.
    Hook up a “save” and a “play” button. The “save” button will append the current curr_angles to the array. When the “play” button is pressed, a global variable is set and your code should not determine target_angle from the analogRead/map, but from the current step in the array, then (when target is reached (curr_angle == target_angle)), the next step, etc. Pressing “play” again will stop the playback. 

Tags



Model origin

The author marked this model as their own original creation.

License