Robot arm with joysticks on an Arduino Uno
A four-servo desktop arm on four Uno pins, steered by two joysticks with the Servo library: base and shoulder on one stick, elbow and claw on the other. The whole build, an Arduino Uno and 3 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
IntermediateRuns in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Robot arm with two joysticks: a four-servo desktop arm driven straight
// from the Uno with the Servo library.
//
// arm BASE pin 3, SHOULDER pin 5, ELBOW pin 6, GRIP pin 9
// VCC and GND from a separate 5 V supply, GND joined to the Uno's
// left joystick VRX A0 (base), VRY A1 (shoulder)
// right joystick VRX A2 (elbow), VRY A3 (claw)
//
// The sticks are rate controls, the way the kit sketches do it: push a stick
// and its joint keeps moving while you hold it, faster the further you push;
// let go and the stick springs back to the middle and the joint stays put.
// A small dead band round the middle stops a stick that does not center
// perfectly from creeping the arm.
//
// Four SG90s moving at once can pull more than an amp, which is more than an
// Uno's 5 V pin gives from USB. That is why the arm has its own supply on the
// bench and here, with the grounds joined so the signals mean something.
#include <Servo.h>
Servo base, shoulder, elbow, claw;
Servo *joints[4] = {&base, &shoulder, &elbow, &claw};
const int SERVO_PINS[4] = {3, 5, 6, 9};
const int STICKS[4] = {A0, A1, A2, A3};
// Where each joint starts, and how far it may go. The claw shuts at 20 and
// is wide open at 120; the shoulder and elbow stop short of the ends so the
// arm does not fold into its own base.
int angle[4] = {90, 90, 90, 70};
const int LOW_END[4] = {0, 40, 40, 20};
const int HIGH_END[4] = {180, 160, 160, 120};
const int DEAD_BAND = 60; // of 1023, either side of the middle
void setup() {
for (int i = 0; i < 4; i++) {
joints[i]->attach(SERVO_PINS[i]);
joints[i]->write(angle[i]);
}
Serial.begin(115200);
Serial.println("robot arm: push a stick to move a joint");
}
void loop() {
bool moved = false;
for (int i = 0; i < 4; i++) {
int offset = analogRead(STICKS[i]) - 512;
if (offset > DEAD_BAND || offset < -DEAD_BAND) {
// Up to 3 degrees a pass at full deflection.
angle[i] += offset / 170;
if (angle[i] < LOW_END[i]) angle[i] = LOW_END[i];
if (angle[i] > HIGH_END[i]) angle[i] = HIGH_END[i];
moved = true;
}
joints[i]->write(angle[i]);
}
if (moved) {
Serial.print("base ");
Serial.print(angle[0]);
Serial.print(" shoulder ");
Serial.print(angle[1]);
Serial.print(" elbow ");
Serial.print(angle[2]);
Serial.print(" claw ");
Serial.println(angle[3]);
}
delay(20);
}
Parts list
6 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Robot arm, 4 servos
- 2 × Thumb stick
- 2 × Power, 5 V
How it is wired
15 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Ground: Arduino Uno R3 pin GND
- Arduino Uno R3 pin 9; Robot arm, 4 servos pin GRIP
- Arduino Uno R3 pin 6; Robot arm, 4 servos pin ELBOW
- Arduino Uno R3 pin 5; Robot arm, 4 servos pin SHOULDER
- Arduino Uno R3 pin 3; Robot arm, 4 servos pin BASE
- Arduino Uno R3 pin 5V; Thumb stick (1) pin VCC
- Arduino Uno R3 pin A0; Thumb stick (1) pin VRX
- Arduino Uno R3 pin A1; Thumb stick (1) pin VRY
- Arduino Uno R3 pin A2; Thumb stick (2) pin VRX
- Arduino Uno R3 pin A3; Thumb stick (2) pin VRY
- 5 V: Robot arm, 4 servos pin VCC
- Ground: Robot arm, 4 servos pin GND
- Ground: Thumb stick (1) pin GND
- Ground: Thumb stick (2) pin GND
- 5 V: Thumb stick (2) pin VCC
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.