Robotic hand with flex sensors on an Arduino Mega
Robotic hand with flex sensors on an Arduino Mega: five flex sensors on a glove move five servo fingers, and the Serial Monitor names the gesture. The whole build, an Arduino Mega and 10 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.
Teaching? Assign it to your class in one click.
Beginner Runs in your browser. Free, and no account needed.
The parts retail for about $101. On Mokxi they're free.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Robotic hand: five flex sensors on a glove move five servo fingers, and
// the board names the gesture the hand makes, on an Arduino Mega.
//
// flex sensors thumb A0, index A1, middle A2, ring A3, pinky A4,
// each from the pin to GND
// servos thumb 6, index 5, middle 4, ring 3, pinky 2,
// VCC to a 5 V supply of their own, GND to GND
//
// Bend a finger of the glove (drag its sensor's slider) and the servo for
// that finger bends with it, 0 degrees straight to 180 bent right over. The
// Serial Monitor names the gesture the hand is making: rock, paper,
// scissors, thumbs up, pointing, rock on, or just "hand".
//
// # A flex sensor and the pull-up inside the chip
//
// A flex sensor is a strip whose resistance rises as it bends: about 25 k flat
// and 100 k folded right over. pinMode(A0, INPUT_PULLUP) connects A0 to 5 V
// through a resistor inside the chip, about 35 k, so the sensor and that
// resistor make a divider with no extra parts. Flat, A0 reads about 426;
// bent all the way, about 758.
//
// The reading does not climb evenly with the bend: half bent reads 656, not
// halfway between. So the sketch works back from the reading to the sensor's
// resistance with the divider formula, and the resistance does climb evenly:
//
// R = PULLUP x reading / (1023 - reading)
//
// The pull-up inside a real chip can be anywhere from 20 k to 50 k, and
// every flex sensor is a little different, so on a real glove print the
// resistances (set SHOW_RAW to true), hold your hand flat and then make a
// fist, and copy the numbers into FLAT and BENT.
//
// # Five servos need their own power
//
// One SG90 can draw half an amp when it moves; five of them would pull the
// Arduino's 5 V pin down and reset the board. So the servos take 5 V from a
// supply of their own, and only the ground is shared with the Mega, so the
// signal wires have something to be measured against.
#include <Servo.h>
const uint8_t FINGERS = 5;
const char *const NAME[FINGERS] = {"thumb", "index", "middle", "ring", "pinky"};
const uint8_t SENSOR[FINGERS] = {A0, A1, A2, A3, A4};
const uint8_t SERVO_PIN[FINGERS] = {6, 5, 4, 3, 2};
const long PULLUP = 35000; // ohms, the pull-up inside the chip
const long FLAT = 25000; // the sensor's ohms with the finger straight
const long BENT = 100000; // and bent right over
const bool SHOW_RAW = false;
Servo finger[FINGERS];
int angle[FINGERS];
int printedAngle[FINGERS];
const char *gesture = "";
// Is each finger bent? One bit per finger: bit 0 the thumb, bit 4 the pinky.
uint8_t bentMask() {
uint8_t mask = 0;
for (uint8_t i = 0; i < FINGERS; i++) {
if (angle[i] > 90) mask |= 1 << i;
}
return mask;
}
const char *nameGesture(uint8_t bent) {
switch (bent) {
case 0b11111: return "rock";
case 0b00000: return "paper";
case 0b11001: return "scissors"; // index and middle straight
case 0b11110: return "thumbs up"; // only the thumb straight
case 0b11101: return "pointing"; // only the index straight
case 0b01101: return "rock on"; // index and pinky straight
default: return "hand";
}
}
void setup() {
Serial.begin(115200);
for (uint8_t i = 0; i < FINGERS; i++) {
pinMode(SENSOR[i], INPUT_PULLUP);
finger[i].attach(SERVO_PIN[i]);
angle[i] = 0;
printedAngle[i] = -100;
finger[i].write(0);
}
Serial.println("Robotic hand ready: bend the flex sensors");
}
void loop() {
bool moved = false;
for (uint8_t i = 0; i < FINGERS; i++) {
long raw = analogRead(SENSOR[i]);
if (raw > 1022) raw = 1022; // a broken wire reads 1023: no dividing by 0
long ohms = PULLUP * raw / (1023 - raw);
if (SHOW_RAW) {
Serial.print(ohms);
Serial.print(i < FINGERS - 1 ? ' ' : '\n');
}
// map() stretches FLAT..BENT onto 0..180; constrain() keeps a reading a
// little past either end from asking the servo for -5 or 190 degrees.
int target = constrain(map(ohms, FLAT, BENT, 0, 180), 0, 180);
// Move a third of the way to the reading each time: a shaky finger
// makes a steady servo.
angle[i] += (target - angle[i]) / 3;
if (abs(target - angle[i]) < 3) angle[i] = target;
finger[i].write(angle[i]);
if (abs(angle[i] - printedAngle[i]) >= 10 ||
(angle[i] != printedAngle[i] && (angle[i] == 0 || angle[i] == 180))) {
moved = true;
}
}
if (moved) {
for (uint8_t i = 0; i < FINGERS; i++) {
printedAngle[i] = angle[i];
Serial.print(NAME[i]);
Serial.print(' ');
Serial.print(angle[i]);
Serial.print(i < FINGERS - 1 ? ", " : "\n");
}
}
const char *now = nameGesture(bentMask());
if (now != gesture) {
gesture = now;
Serial.print("gesture: ");
Serial.println(gesture);
}
delay(20);
}
Parts list
12 parts, plus the jumper wires. They retail for about $101; on Mokxi they're free.
- 1 × Arduino Mega 2560 R3
- 5 × Hobby servo
- 1 × Power, 5 V
- 5 × Flex sensor
How it is wired
21 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.
- Arduino Mega 2560 R3 pin 6; Hobby servo (1) pin PWM
- Arduino Mega 2560 R3 pin 5; Hobby servo (2) pin PWM
- Arduino Mega 2560 R3 pin 4; Hobby servo (3) pin PWM
- Arduino Mega 2560 R3 pin 3; Hobby servo (4) pin PWM
- Arduino Mega 2560 R3 pin 2; Hobby servo (5) pin PWM
- Arduino Mega 2560 R3 pin A0; Flex sensor (1) pin 2
- Arduino Mega 2560 R3 pin A1; Flex sensor (2) pin 2
- Arduino Mega 2560 R3 pin A2; Flex sensor (3) pin 2
- Arduino Mega 2560 R3 pin A3; Flex sensor (4) pin 2
- Arduino Mega 2560 R3 pin A4; Flex sensor (5) pin 2
- Ground: Hobby servo (1) pin GND
- 5 V: Hobby servo (1) pin VCC; Hobby servo (2) pin VCC; Hobby servo (3) pin VCC; Hobby servo (4) pin VCC; Hobby servo (5) pin VCC
- Ground: Hobby servo (2) pin GND
- Ground: Hobby servo (3) pin GND
- Ground: Hobby servo (4) pin GND
- Ground: Hobby servo (5) pin GND
- Ground: Flex sensor (1) pin 1
- Ground: Flex sensor (2) pin 1
- Ground: Flex sensor (3) pin 1
- Ground: Flex sensor (4) pin 1
- Ground: Flex sensor (5) pin 1
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.