Mearm Pocket Sized Robot Arm
There have been several design iterations of this mini robotic arm and the design is open source and available on Thingiverse. It is basically some laser cut acrylic sheet and four 9G servo motors which are mechanically linked to provide the required movements. The design itself is not basic...actually I think the thought that has gone into this device (toy) is awesome!
Thingiverse page for MeArm
Putting the arm together has been well documented by the designers in their own humorous style. I managed to break two of the parts whilst assembling and fiddling with the device
I really like this kit! It was great fun to put together, worked out of the box and is very simple in concept. I particularly like the fact that other people are sharing their efforts in using it as a learning tool. It would not be difficult to scale this arm up in size to make a substantial industrial robot arm!
The only areas I have had trouble with is in setting the servo motors working correctly. I over tightened the screws which connect the linkages to the servo motors which meant that when I powered them up nothing happened at first...just a lot of clicking. I then found that loosening the screws allowed the servos to move correctly. Loosening things was a lot of work and I was lazy and didn't take the arm apart completely and managed to snap parts. Nothing that can't be replaced though, so I'm putting it down to experience and moving on.
The tutorial recommends using 4 potentiometers fed to the analogue inputs of an arduino and using the PWM outputs to drive the servo motors. There is nothing wrong with this approach and has been shown to work very well. I didn't have four potentiometers to hand whilst testing the unit so I tried using serial commands and the keyboard which did work but lacked control because there is no feedback mechanism provided. I could have written better code...But I was in a rush to play with my toy!
To improve matters and because I want to use this robot with the Bluetooth rover I'm going to design an arduino shield.
I need to be able to control:
- 6x servo motors - four for the MeArm and two for the rover wheels.
- 1x Bluetooth module - I'm hoping to be able to control the arm and the rover using my android mobile phone.
- 2x HC-SR04 Ultrasonic modules.
- 4x 10k potentiometers - in case I cannot get the bluetooth control working.
- 2x LEDS - just for fun.
- 1x Thermistor - because measuring ambient temperature is useful.
Here is the schematic diagram on two sheets:
Interconnection Section |
Micro-controller Section |
Top Layer of PCB |
|
Combined Layers with Dimensions |
Here is the bill of materials for this project with parts and prices - I get most of my components from Farnell but just about anywhere selling electronic components should be able to supply with the items required apart from the PCB itself.
Part | Quantity | Device | Description | Supplier | Unit Cost | Part No. |
(£) | ||||||
JP1 | 1 | 36 Way pin Header | Header 3 | Farnell | 1.41 | 1822166 |
R1 | 1 | RESISTOR 1/4 W | Resistor | Farnell | 0.12 | 2329474 |
R2 | 1 | THERMISTOR | THERMISTOR | Farnell | 0.37 | 1187031 |
RV1 | 1 | POT | Potentiometer | Farnell | 0.44 | 2469524 |
RV2 | 1 | POT | Potentiometer | Farnell | 0.44 | 2469524 |
RV3 | 1 | POT | Potentiometer | Farnell | 0.44 | 2469524 |
RV4 | 1 | POT | Potentiometer | Farnell | 0.44 | 2469524 |
S1 | 1 | Tactile Switch | Momentary Switch | Farnell | 0.09 | 1555982 |
U2 | 1 | Arduino Mega 2560 | Arduino Mega 2560 | Farnell | 28.76 | 2212779 |
PCB | 1 | Printed circuit board | Printed circuit board | Elecrow | 16.67 | N/A |
MeArm 0.4 | 1 | MeArm 0.4 | MeArm 0.4 Kit | Phenoptix | 30 | N/A |
Total | £79.18 |
- The Arduino Mega 2560 does not have to be sourced from Farnell
- It is possible to laser cut your own parts for the MeArm and source your own servo motors which could reduce costs considerably - however I like to support people making educational kits and toys so I bought mine from Phenoptix....well the better half did...As I already have a MeArm 0.4 kit I'm not counting this as a true cost - Happy Birthday me!
- In my case I'm going to etch my own PCB which will have a material cost of £5.00 - (I totally plucked this figure out of thin air!) If people show an interest in the board I may get them made and make them available for a reasonable cost.
- A Revision 3 Arduino Mega Clone (Which should work perfectly well) is available from Hobby Components for £12.49
There are other costs to be accounted for:
- The cost of the servos from the original Bluetooth rover and a Bluetooth module
- Two HC-SR04 ultrasonics modules
- The cost of the 3d printed wheels and 'tyres'
- The cost of the acrylic sheet and laser cutter time for constructing the rover.
Here is the PCB populated and ready to go:
The populated MeArm Controller - The six headers are for servo motors and the sockets are for the bluetooth module and Ultrasonic sensors |
Here is the version using the potentiometers:
/* Controlling the MeArm 0.4 - Alexander Lang 04-04-2014 Credits to the original code provided by: Michal Rinott <http://people.interaction-ivrea.it/m.rinott> and - Ben Gray - Phenoptix This code allows the user to control the meArm 0.4 using 4x potentiometers and an Arduino Mega R3 2560 with the potentiometers connected to digital pins 6, 7, 8, 9 The position of the servo is printed to the serial port The maximum travel of the servos are limited to prevent damage to the meArm You may wish to change these values to suit your own arm - it might be different Enjoy! */ #include <Servo.h> Servo base, arm, wrist, gripper; // create servo objects to control the different parts of the MeArm int basePot = A0; // analog pin used to connect the potentiometer controlling the base int armPot = A1; // analog pin used to connect the potentiometer controlling the arm int wristPot = A2; // analog pin used to connect the potentiometer controlling the wrist int gripperPot = A3; // analog pin used to connect the potentiometer controlling the gripper int basePos; // variable to read the value from the analog pin int armPos; // variable to read the value from the analog pin int wristPos; // variable to read the value from the analog pin int gripperPos; // variable to read the value from the analog pin void setup() { Serial.begin(9600); // Start the serial communications for debugging base.attach(9); // attaches the servo on pin 6 to the servo object arm.attach(8); // attaches the servo on pin 7 to the servo object wrist.attach(7); // attaches the servo on pin 8 to the servo object gripper.attach(6); // attaches the servo on pin 9 to the servo object Serial.print("MeArm Control Code!"); Serial.println(); } void loop() { controlBase(); controlArm(); controlWrist(); controlGripper(); } void controlBase() { basePos = analogRead(basePot); // reads the value of the potentiometer (value between 0 and 1023) basePos = map(basePos, 0, 1023, 0, 179); // scale it to use it with the base servo (value between 0 and 179) base.write(basePos); // sets the servo position according to the scaled value delay(15); // delay to allow servo to reach the position Serial.print("Base Position: "); // print the current position of the base servo in degrees Serial.print(basePos); Serial.println(); //delay(100); // delay to allow user to read serial messages } void controlArm() { armPos = analogRead(armPot); // reads the value of the potentiometer (value between 0 and 1023) armPos = map(armPos, 0, 1023, 32, 180); // scale it to use it with the arm servo (value between 32 and 179) arm.write(armPos); // Sets the servo position according to the scaled value delay(15); // delay to allow for the servo to reach the position Serial.print("Arm Position: "); // print the current position of the servo in degrees Serial.print(armPos); Serial.println(); //delay(100); // delay to allow user to read serial messages } void controlWrist() { wristPos = analogRead(wristPot); // reads the value of the potentiometer (value between 0 and 1023) wristPos = map(wristPos, 0, 1023, 45, 147); // scale it to use it with the wrist servo (value between 45 and 147) wrist.write(wristPos); // sets the servo position according to the scaled value delay(15); // delay to allow for the servo to reach the position Serial.print("Wrist Position: "); // print the current position of the servo in degrees Serial.print(wristPos); Serial.println(); //delay(100); // waits for the servo to get there } void controlGripper() { gripperPos = analogRead(gripperPot); // reads the value of the potentiometer (value between 0 and 1023) gripperPos = map(gripperPos, 0, 1023, 0, 30); // scale it to use it with the servo (value between 0 and 180) gripper.write(gripperPos); // sets the servo position according to the scaled value delay(15); // delay to allow for the servo to reach position Serial.print("Gripper Position: "); // print the current position of the servo in degrees Serial.print(gripperPos); Serial.println(); //delay(100); // delay to allow user to read serial messages }Here is the serial control version - slightly different
/* Alex's Mearm code Serial Control Code 04/04/2015 (c) This code controls a meArm 0.4 via a serial termiminal. Enjoy! Base servo connected to pin 9 Arm servo connected to pin 8 wrist servo connected to pin 7 Gripper servo connected to pin 7 The maximum travel of the servos are limited to prevent damage to the meArm You may wish to change these values to suit your own arm - it might be different Control via keyboard over serial terminal 1 = base left 2 = base right 3 = arm up 4 = arm down 5 = wrist up 6 = wrist down 7 = gripper open 8 = gripper close 9 = stop all movement M = restart movement A = reset arduino */ #include <Servo.h> #include <avr/wdt.h> Servo base, arm, wrist, gripper ; // create servo objects to control servos int basePos = 90; // variable to store the base servo position // Set to 90 to prevent movement at start int armPos = 90; // variable to store the arm servo position // Set to 90 to prevent movement at start int wristPos = 90; // variable to store the wristy servo position // Set to 90 to prevent movement at start int gripperPos = 0; // variable to store the gripper servo position // Set to 15 to prevent movement at start char var=0; // variable to store keyboard or controller input void setup() { Serial.begin(9600); // Standard Serial Port for debugging Serial2.begin(9600); // Bluetooth Serial Port for remote control base.attach(9); // attaches the base servo on pin 6 to the servo object arm.attach(8); // attaches the arm servo on pin 7 to the servo object wrist.attach(7); // attaches the wrist servo on pin 8 to the servo object gripper.attach(6); // attaches the gripper servo on pin 9 to the servo object gripper.write(gripperPos); // Ensure gripper is open! Serial.print("MeArm Serial Control"); Serial.println(); } void loop() { Serial.flush(); var = Serial.read(); switch (var) { case '1': moveBaseLeft(); break; case '2': moveBaseRight(); break; case '3': moveArmForwards(); break; case '4': moveArmBackwards(); break; case '5': moveWristUp(); break; case '6': moveWristDown(); break; case '8': openGripper(); break; case '7': closeGripper(); break; case '9': stopMoving(); break; case 'M': startMoving(); break; case 'm': startMoving(); break; case 'A': software_Reboot(); break; case 'a': software_Reboot(); break; } } void moveBaseLeft() { Serial.print("Moving base left "); Serial.println(); Serial.print("BasePos Value: "); Serial.print(basePos); Serial.println(); if (basePos >= 0 && basePos != 179) { basePos++; base.write(basePos); delay(15); } if (basePos == 179) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void moveBaseRight() { Serial.print("Moving base right "); Serial.println(); Serial.print("BasePos Value: "); Serial.print(basePos); Serial.println(); if (basePos <= 179 && basePos != 0) { basePos--; base.write(basePos); delay(15); } if (basePos == 0) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void moveArmForwards() { Serial.print("Moving Arm Forwards "); Serial.println(); Serial.print("armPos Value: "); Serial.print(armPos); Serial.println(); if (armPos >=32 && armPos != 179) { armPos++; arm.write(armPos); delay(15); } if (armPos == 179) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void moveArmBackwards() { Serial.print("Moving Arm backwards "); Serial.println(); Serial.print("armPos Value: "); Serial.print(armPos); Serial.println(); if (armPos <= 179 && armPos != 32) { armPos--; arm.write(armPos); delay(15); } if (armPos == 32) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void moveWristUp() { Serial.print("Moving Wrist Up "); Serial.println(); Serial.print("wristPos Value: "); Serial.print(wristPos); Serial.println(); if (wristPos >= 45 && wristPos != 147) { wristPos++; wrist.write(wristPos); delay(15); } if (wristPos == 147) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void moveWristDown() { Serial.print("Moving Wrist Down "); Serial.println(); Serial.print("wristPos Value: "); Serial.print(wristPos); Serial.println(); if (wristPos <= 147 && wristPos != 45) { wristPos--; wrist.write(wristPos); delay(15); } if (wristPos == 45) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void closeGripper() { Serial.print("Closing Gripper Jaws "); Serial.println(); Serial.print("gripperPos Value: "); Serial.print(gripperPos); Serial.println(); if (gripperPos >= 0 && gripperPos != 40) { gripperPos++; gripper.write(gripperPos); delay(15); } if (gripperPos == 40) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void openGripper() { Serial.print("Opening Gripper Jaws "); Serial.println(); Serial.print("gripperPos Value: "); Serial.print(gripperPos); Serial.println(); if (gripperPos <= 40 && gripperPos != 0) { gripperPos--; gripper.write(gripperPos); delay(15); } if (gripperPos == 0) { Serial.print("Reached end of travel....stopping"); Serial.println(); } Serial.flush(); } void startMoving() { Serial.print("Start All Movement "); Serial.println(); base.attach(9); arm.attach(8); wrist.attach(7); gripper.attach(6); Serial.flush(); delay(15); } void stopMoving() { Serial.print("Stop All Movement "); Serial.println(); base.detach(); arm.detach(); wrist.detach(); gripper.detach(); Serial.flush(); delay(15); } void software_Reboot() { wdt_enable(WDTO_15MS); while(1) { } }
The more eagle eyed among you will notice I have replaced the base section of the meArm with a 3d printed base section. I was trawling thingiverse (link below) and noticed that many people had kindly been posting upgrades for the meArm. The base section as provided works well enough but can cause the robot to wobble as the base section doesn't have a very good bearing mechanism. To solve that a clever bloke named James White created a base section which is free to download and use.
Thrust bearing base for MeArm V0.4
In order to use it properly you will need to acquire a thrust bearing and two washers from a well known vendor. I used ebay:
AXK Needle Roller Cage Thrust Bearing &Two AS Washers
All that you need then is access to a 3d printer and some PLA material. I went to the Hackspace in Manchester (HacMan). Once the 3d printing was complete all I did was reconstruct the base section. My final plan was to have the meArm sit on the bluetooth rover and be remote controlled by my android mobile phone. That is a work in progress but I have got it mostly working *really big grin*
That's all for now, take care - Langster
No comments:
Post a Comment