Project showcase
Tobor, the Arm

Tobor, the Arm © GPL3+

Manual and programmable robotic arm with fancy control panel.

  • 3,709 views
  • 1 comment
  • 7 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
20x4 Display with I2C module
×1
09939 01
Rotary potentiometer (generic)
10kohms
×4
Colored push-button
with colored heads
×3
Switch button
×1
Kingbright wp7113srd d image
5 mm LED: Red
×1
Sg90 servo motor 180 degrees sg90 micro
SG90 Micro-servo motor
×4
11026 02
Jumper wires (generic)
×1
MeArm or any other 4DOF robotic arm
×1
LED housing
for a finished control panel
×1
P4 female outlet
for external power input
×1
External Power source 5V/4A
or 4 x 1,5V batteries to get 6V
×1

Necessary tools and machines

09507 01
Soldering iron (generic)
Cutting pliers

Apps and online services

About this project

This is Tobor, the Arm.

YouTube video

An adventure to the realms of "Are you nuts?" Oh...maybe I think I am. After my other two projects already published here at Project Hub, a kind of a "confidence on simple coding" and my curiosity on making something else to fullfill my nerdiness arised when I start to search and read about robotic arms.

"It look so simple...I can do it... But as my previous projects I would like to built some playable for my young child, without breadboards and fragile "prototype" connections.

I also dreamed about build a fancy Control Panel, where I can manage the Arm and have it autonomous from the PC, safely operated with an external power source, to leave it with a child without worry about a mess with delicate pots, wires, buttons, leds, fragile connections and so far.

So, lets planning...

1 - The Arm will be this "MeArm" style with 4 mini servos (4DOF) we can find so many projects on internet, cheap and funny.

2 - After some reading I did think this project would not requires much knowledge in eletronics... ( I wish...). As a " noob maker" I am really freaked out about have to learn and use transistors, capacitors, CI's and any eletronic stuff other than Arduino board, potenciometers, buttons and leds and resistors...

3 - I really want a sturdy as possible Controlbox to operate the Arm without connections with a PC.

4 - The research showed the main issue with robotic arms is the correct power system. The arduino itself is not capable to deal with 4 servos. I decided to use an external 5V/4A power supply I can connect on an ordinary outlet at home. This is the most expensive item on the budget but I can keep it for other uses.

5 - The Controlbox will need a display (20x4) to show:

5.1 - A Welcome screen;

5.2 -On Manual Mode, the reading of the angles when I turn the pots, mapped from 0 to 180 degrees;

5.3 - On Manual Mode, the display must show what I am writing on memory to program Tobor to work in Automatic Mode. (I will discuss it later).

5.4 - A display screen with a kind of " Program Running >>>"

6 - The Controlbox controls:

6.1 - A red Led to show the power is On;

6.2 - Four potenciometers to control each servo;

6.3 - A switch button between Manul and Automatic Mode;

6.4 - A black button to select the "Memory Positons" to correct saving step mistakes;

6.5 - A green button to save the Servo angles on a array of five variables: memPosition and servos angles (four variables);

6.6 - A red button for a future use.

So...How to put this togheter... I will try to do as many screwed and plugged connections possible to avoid welding. Ok this not a big deal but I really like not to have to weld things.

Thinking about the phisical configuration, I build bank of 5V and GND connectors for all wiring needed with an universal board and screwed connectors. The signal pins I use protoboard wires and plugs.

The built up I2C on the 20x4 Display was an eaasy choice: Only four cables to connect.

The picture above show all the Controlbox items. The buttons and pots already welded. On the lower left there is the 5V/GND banks. The arduino is mounted with spacers and 3M double sided tape. On the left side of the Controlbox there are one hole for the USB cable and another for the P4 external power in (not the arduino one!)

The holes were made with apropriate drilling tools I already have. The display hole was the big challenge. It was made with a blade, very, very slowly and took a lot of time and effort. I think at the end it was acceptable. The display is little offset due to the I2C module connections.

An eletrical tape piece secure signal wires in place. Same thing were doing for the analog and power wiring on the other Arduino edge.

Voilá!

Tired?

Now lets talk about the code logics.

Obviously, there is MUCH TO IMPROVE. I think to reach the "point B from the point A", one experienced programmer goes straight when I do this in a "ZigZag" mode. Sorry I do not have enough english and for the same reason I write this the way my written language knowledge permits...

Several examples for servo.write(), analogoRead(), pinMode(), mapping pots we can easily find on internet and I would like to focus on the mais issue, that was the "logic" I adopted.

When thinking about Manual Operation, there was no challenge at all. analogRead(), map() and display configuration to show values.

A Switch button to toggle between Manual and Auto modes. On Auto Mode, the code reads the stored positions of the servos one at a time.

The green button:

When it is pressed, the "memory position" increase by one and the angles of all four servos were stored in a Array of 5 variables.

I need to position the Arm in such a way to open the claw, reach an object, grab it, rise/move to another point, open the claw to release and loop this forever. For each group of movements I press green button to store the positions.

If I make a mistake when pressing de the green button, I cycle the "memory position" to the correct step, pressing the black button.

The code permits only Ten memory positions of four servos angles. This "Ten positions" is a number I figured out to a whole cycle of Arm movements before automatic mode loop. This can be increased by simple coding, addind more memory positions arrays and move servos functions.

Automatic Mode

When the Switch button is toggled to Auto Mode, a bunch of code functions will move the servos accordingly to the total memory positions stored and loop it. Here is when "the magic happens!" the code is so simple I am amazed.

On the Display, a message "Program Running" with an "animated" " > " characther make things "professional...".

If there is no memory positions previously stored, a message " Empty Memory" is displayed.

Issues and future challenges

Deal with those fragile mini servos can be tricky. I fried two. I do not know exactly why, but sometimes they get very hot. I guess this can be a current problem. Calibrate them prior to mount the Arm is important.

The movement of the servos is also a thing to improve. I am reading about install 100nF capacitors on signal wires of the potenciometers.

I am also about to try the " VarSpeedServo.h" library to make servos moving smothly.

I did not deal with "debouncing" issues. I have been reading about it.

Arduino EEPROM

For now, if the power is down, the memory stored is lost. I am reading about using the Arduino's EEPROM to keep the memory stored. This will be very interesting but I need to study and learn more to do this.

MeArm:

This "MeArm" arm is fine and cheap. It is funny to build and set up. Instructions are widely available on internet. The acrylic material seems to be more resistant then mdf I suppose.

No suprise if in future I get a bigger aluminium Arm with bigger servos...The temptation is to build a 5DOF or even more degrees of freedom witch means I will need a bigger Controlbox...

About the Name

This arm is named after "Tobor the Great", a 1954 sci-fi movie, with this description at Wikipedia:

"In a review in The New York Times, Tobor the Great is characterized as "This children's sci-fi adventure (that) chronicles the friendship between an 11-year-old and his grandfather's robot Tobor, who was designed to explore deep space."

My "Tobor" is not as smart or dramatic, but my son really love it.

I hope you enjoy and make comments! Tobor will thank you all!

Code

Tobor, the ArmArduino
Comment, Improve, Share
/*
 * 6/2/19Versao que funcionou com o control box. apos muitos problemas de mau contato e qualidade inferior
 * dos servos azuis. Trocados por Towerpro MG90S engrenagem metal.
 * iniciar montagem do braco MeArm
 */

#include <Wire.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h> // For 20x4 lcd
LiquidCrystal_I2C lcd(0x27,20,4);

Servo s1;  // create servo object to control a servo
Servo s2;
Servo s3;
Servo s4;

int potpin1 = A0;  // analog pin used to connect the potentiometer
int potpin2 = A1;  // analog pin used to connect the potentiometer
int potpin3 = A2;  // analog pin used to connect the potentiometer
int potpin4 = A3;  // analog pin used to connect the potentiometer

int valA = 0;    // read the value from the analog pin
int valB = 0;    // read the value from the analog pin
int valC = 0;    // read the value from the analog pin
int valD = 0;    // read the value from the analog pin

int greenButton = 12; //record mem index and servo angles
int redButton = 4; //reserved for future use
int blackButton = 7; //mem index selector 
int switchAM = 8; //switch between Manual or Automatic operation
int counter = 0; //mem index
int mTime = 500;//time to move each servo in Aumtomatic mode one by one

//for now this is the way I found to store 10 * 4servo positions.
//An array of a mem counter and angles of 4 servos
int memP01[5], memP02[5], memP03[5], memP04[5], memP05[5], memP06[5], memP07[5], memP08[5], memP09[5], memP10[5];

//move ARM according to 4 angles stored in each Array 
void moveCounter1() { 
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
}

void moveCounter2() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
}

void moveCounter3() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime); 
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
}

void moveCounter4() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
}

void moveCounter5() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime); 
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime); 
s2.write(memP02[2]); delay(mTime); 
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime); 
s2.write(memP05[2]); delay(mTime);
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
}

void moveCounter6() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime); 
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
}

void moveCounter7() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime);
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
}

void moveCounter8() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime); 
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime); 
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime); 
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime); 
s3.write(memP08[3]); delay(mTime);
s4.write(memP08[4]); delay(mTime);
}

void moveCounter9() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime); 
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime); 
s3.write(memP02[3]); delay(mTime); 
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime); 
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime); 
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime);
s3.write(memP07[3]); delay(mTime); 
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime);
s3.write(memP08[3]); delay(mTime); 
s4.write(memP08[4]); delay(mTime);
s1.write(memP09[1]); delay(mTime); 
s2.write(memP09[2]); delay(mTime); 
s3.write(memP09[3]); delay(mTime);
s4.write(memP09[4]); delay(mTime);
}

void moveCounter10() {
s1.write(memP01[1]); delay(mTime); 
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime);
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime);
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime); 
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime); 
s3.write(memP08[3]); delay(mTime);
s4.write(memP08[4]); delay(mTime);
s1.write(memP09[1]); delay(mTime);
s2.write(memP09[2]); delay(mTime);
s3.write(memP09[3]); delay(mTime);
s4.write(memP09[4]); delay(mTime);
s1.write(memP10[1]); delay(mTime); 
s2.write(memP10[2]); delay(mTime);
s3.write(memP10[3]); delay(mTime);
s4.write(memP10[4]); delay(mTime);
}
/*
  for(int a = 0; a < 5; a++)
{
  Serial.println(memP01[a]);
   Serial.println(memP02[a]);
    Serial.println(memP03[a]); 
    Serial.println(memP04[a]);
     }
  Serial.println("ln");
*/


void runningScreen() {
lcd.clear();  
lcd.setCursor (0,0); lcd.print("PROGRAM      ");
lcd.setCursor (0,1); lcd.print("RUNNING >    ");
delay(100); 
lcd.setCursor (0,1); lcd.print("RUNNING  >   ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING   >  ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING    > ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING      ");
delay(100);
}


void setup() {

// no anoying phisical  resistors to be welded...I hope it works
pinMode(switchAM, INPUT_PULLUP);
pinMode(blackButton, INPUT_PULLUP);
pinMode(greenButton, INPUT_PULLUP);
pinMode(redButton, INPUT_PULLUP);

Serial.begin(9600); // do not need this...the ctrlbox have a lcd.
lcd.init();
lcd.backlight();
  // lcd.begin(16, 2);
lcd.setCursor(0, 0); lcd.print("ROBOTIC ARM");
lcd.setCursor(0, 1); lcd.print("VERSION 001");
delay(3000);
// attaches the PWM pins to servos
s1.attach(11);  
s2.attach(10);
s3.attach(9);
s4.attach(6);

} //end setup

void loop() {
  
int switchAMState = digitalRead(switchAM);

  if (switchAMState == 0){ // Manual Mode
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print("MANUAL OPERATION");
     
     valA = analogRead(potpin1);            // reads the value of the potentiometer (value between 0 and 1023)
     valA = map(valA, 1, 1023, 180,0);     //values acheived from testing to avoid motor creep at pot end courses
     s1.write(valA);
     delay(15);
     lcd.setCursor(0, 1);
     lcd.print("S1: ");
     lcd.print(valA); //show servo angle on lcd

     valB = analogRead(potpin2);            
     valB = map(valB, 1, 1023, 180,0);
     s2.write(valB);
     delay(15);
     lcd.setCursor(10, 1);
     lcd.print("S2: ");
     lcd.print(valB);

     valC = analogRead(potpin3);
     valC = map(valC, 1, 1023, 0, 180);
     s3.write(valC);
     delay(15);
     lcd.setCursor(0,3);
     lcd.print("S3: ");
     lcd.print(valC);
    
     valD = analogRead(potpin4);    // reads the value of the potentiometer (value between 0 and 1023)
     valD = map(valD, -25, 1023, 0, 180);     // calibrating to avois creeping

//calibration to let maximum claw opening of 90degrees and pressure excess on claws.dont know if its useful.
     if (valD > 40 || valD < 170) { 
     s4.write(valD);
     delay(15);    
     lcd.setCursor(10, 3);
     lcd.print("S4: ");
     lcd.print(valD);
     }
     else {
      valD = 41;
     }
    
    delay(100);

int  greenButtonState = digitalRead(greenButton);
   if (greenButtonState == 0) {
    counter = counter +1;
     
switch (counter) { 
  
case 1:
memP01[0] = counter; // save counter
memP01[1] = valA;
memP01[2] = valB;
memP01[3] = valC;
memP01[4] = valD;
break;

case 2:
memP02[0] = counter; // save counter
memP02[1] = valA; memP02[2] = valB; memP02[3] = valC; memP02[4] = valD;
break;

case 3:
memP03[0] = counter; // save counter
memP03[1] = valA; memP03[2] = valB; memP03[3] = valC; memP03[4] = valD;
break;

case 4:
memP04[0] = counter; // save counter
memP04[1] = valA; memP04[2] = valB; memP04[3] = valC; memP04[4] = valD; 
break;

case 5:
memP05[0] = counter; // save counter
memP05[1] = valA; memP05[2] = valB; memP05[3] = valC; memP05[4] = valD;
break;

case 6:
memP06[0] = counter; // save counter
memP06[1] = valA; memP06[2] = valB; memP06[3] = valC; memP06[4] = valD;
break;

case 7:
memP07[0] = counter; // save counter
memP07[1] = valA; memP07[2] = valB; memP07[3] = valC; memP07[4] = valD;
break;

case 8:
memP08[0] = counter; // save counter
memP08[1] = valA; memP08[2] = valB; memP08[3] = valC; memP08[4] = valD;
break;

case 9:
memP09[0] = counter; // save counter
memP09[1] = valA; memP09[2] = valB; memP09[3] = valC; memP09[4] = valD;
break;

case 10:
memP10[0] = counter; // save counter
memP10[1] = valA; memP10[2] = valB; memP10[3] = valC; memP10[4] = valD;
break;
  
case 11:
counter =1;
 
  
}//end switch
     
lcd.clear();
lcd.setCursor(0,0); lcd.print("ARM POSITION ");
lcd.setCursor(0,1); lcd.print("RECORDED     ");
lcd.setCursor(0,2); lcd.print("P  S1  S2  S3  S4");
lcd.setCursor(0,3); lcd.print(counter);
lcd.setCursor(4,3); lcd.print(valA);
lcd.setCursor(8,3); lcd.print(valB);
lcd.setCursor(12,3); lcd.print(valC);
lcd.setCursor(16,3); lcd.print(valD);
delay(2000);
       } //endgreenbt
    
//if needed to correct some  arm position       
int blackButtonState = digitalRead(blackButton);
if (blackButtonState == 0) {
  if (counter <10){ counter = counter + 1; }
  else { counter = 1; }
lcd.clear();
lcd.setCursor(0,0); lcd.print("MEM POSITION: ");
lcd.setCursor(8,1); lcd.print(counter);
delay(1000);
        }//end ifblackbt
         
    
    
 
     }//end if switchAM

else { //set ARM to Automatic Mode

if (counter > 0){
switch (counter){

case 1:
moveCounter1();
break;
case 2:
moveCounter2();
break;

case 3:
moveCounter3();
break;

case 4:
moveCounter4();
break;

case 5:
moveCounter5();
break;

case 6:
moveCounter6();
break;

case 7:
moveCounter7();
break;
 
case 8:
moveCounter8();
break;
 
case 9:
moveCounter9(); 
break;

case 10:
moveCounter10(); 
break;
} //end switch
  
  runningScreen();
 
} //end if counter>0
 
else { 
lcd.clear();  
lcd.setCursor(0,0);  
lcd.print("EMPTY MEMORY!");
delay(2000);
      
} // end else if counter

} //end else switchAM key
  
}   //end loop

Schematics

Scheme (Display connections are only to see the four wires
Tinkercad does no have the I2C 20x4 display. I use a 16x2 instead, with only 4 wires to represent 5V/GND and SCL/SDA
Arm005 4 dqtsqwi84c

Comments

Similar projects you might like

Robotic Arm Controlled by Human Arm

Project showcase by zezarandrade

  • 4,537 views
  • 0 comments
  • 11 respects

Control a Robot Arm with Arduino Esplora

Project showcase by ebto

  • 2,319 views
  • 0 comments
  • 6 respects

3D-Printed EEG-Controlled Prosthetic Arm

Project showcase by Ayush Kapur

  • 6,735 views
  • 1 comment
  • 48 respects

Gesture Controlled Robotic Arm

by Teddy99

  • 2,267 views
  • 0 comments
  • 2 respects

LittleArm: Arduino Robot Arm

Project showcase by Slant Concepts

  • 17,560 views
  • 1 comment
  • 76 respects
Add projectSign up / Login