I am trying to control 5 servos (SG90) with 3 joysticks (generic analog) in arduino uno. I have followed the project " MeArm Robot - Recording of Coordinates (Minimalized Version)" by utilstudio which uses 4 servos and 2 joysticks. The code works well, the servos move with each joystick and recording-playing of coordinates are correct.
Problems come when I try to modify the code to add the 5th servo and the 3rd joystick. I have tried lot of modifications but result is more or less the same. One of servos does not work, or two servos move when moving only one axis of joystick and the recording and playing does not work at all.
I post both codes, the original which works well, and the modified which does not. Please if some clever mind can find the key to make the right changes in the code for the correct running. I know is difficult but i am sure somebody has to know what to do. Thank you very much:
This is the original code which works well
/* meArm analog joysticks version 1.5.4 - UtilStudio.com Dec 2018
Uses two analogue joysticks and four servos.
In version 1.5.4 was replaced an external resistors by internal pull up resistors.
External LED diode was replaced with using internal "L" diode on Arduino UNO board.
Some bugs was removed.
First joystick moves gripper forwards, backwards, left and right,
button start/stop recording positions.
Second joystick moves gripper up, down, and closes and opens,
button start/stop playing recorded positions.
Press button for 2 seconds to autoplay.
Pins:
Arduino Stick1 Stick2 Base Shoulder Elbow Gripper Record/
GND GND GND Brown Brown Brown Brown Auto play
5V VCC VCC Red Red Red Red LED
A0 HOR
A1 VER
PD2 BUTT
A2 HOR
A3 VER
PD3 BUTT
11 Yellow
10 Yellow
9 Yellow
6 Yellow
13 X
*/
#include <Servo.h>
bool repeatePlaying = false; /* Repeatedly is running recorded cycle */
int delayBetweenCycles = 2000; /* Delay between cycles */
int basePin = 11; /* Base servo */
int shoulderPin = 10; /* Shoulder servo */
int elbowPin = 9; /* Elbow servo */
int gripperPin = 6; /* Gripper servo */
int xdirPin = 0; /* Base - joystick1*/
int ydirPin = 1; /* Shoulder - joystick1 */
int zdirPin = 3; /* Elbow - joystick2 */
int gdirPin = 2; /* Gripper - joystick2 */
//int pinRecord = A4; /* Button record - backward compatibility */
//int pinPlay = A5; /* Button play - backward compatibility */
int pinRecord = PD2; /* Button record - recommended (A4 is deprecated, will by used for additional joystick) */
int pinPlay = PD3; /* Button play - recommended (A5 is deprecated, will by used for additional joystick) */
int pinLedRecord = 13; /* LED - indicates recording (light) or auto play mode (blink ones) */
const int buffSize = 512; /* Size of recording buffer */
int startBase = 90;
int startShoulder = 90;
int startElbow = 90;
int startGripper = 0;
int posBase = 90;
int posShoulder = 90;
int posElbow = 90;
int posGripper = 0;
int lastBase = 90;
int lastShoulder = 90;
int lastElbow = 90;
int lastGripper = 90;
int minBase = 0;
int maxBase = 150;
int minShoulder = 0;
int maxShoulder = 150;
int minElbow = 0;
int maxElbow = 150;
int minGripper = 0;
int maxGripper = 150;
const int countServo = 4;
int buff[buffSize];
int buffAdd[countServo];
int recPos = 0;
int playPos = 0;
int buttonRecord = HIGH;
int buttonPlay = HIGH;
int buttonRecordLast = LOW;
int buttonPlayLast = LOW;
bool record = false;
bool play = false;
bool debug = false;
String command = "Manual";
int printPos = 0;
int buttonPlayDelay = 20;
int buttonPlayCount = 0;
bool ledLight = false;
Servo servoBase;
Servo servoShoulder;
Servo servoElbow;
Servo servoGripper;
void setup() {
Serial.begin(9600);
pinMode(xdirPin, INPUT);
pinMode(ydirPin, INPUT);
pinMode(zdirPin, INPUT);
pinMode(gdirPin, INPUT);
pinMode(pinRecord, INPUT_PULLUP);
pinMode(pinPlay, INPUT_PULLUP);
pinMode(pinLedRecord, OUTPUT);
servoBase.attach(basePin);
servoShoulder.attach(shoulderPin);
servoElbow.attach(elbowPin);
servoGripper.attach(gripperPin);
StartPosition();
digitalWrite(pinLedRecord, HIGH);
delay(1000);
digitalWrite(pinLedRecord, LOW);
}
void loop() {
buttonRecord = digitalRead(pinRecord);
buttonPlay = digitalRead(pinPlay);
// Serial.print(buttonRecord);
// Serial.print("\t");
// Serial.println(buttonPlay);
// for testing purposes
if (buttonPlay == LOW)
{
buttonPlayCount++;
if (buttonPlayCount >= buttonPlayDelay)
{
repeatePlaying = true;
}
}
else buttonPlayCount = 0;
if (buttonPlay != buttonPlayLast)
{
if (record)
{
record = false;
}
if (buttonPlay == LOW)
{
play = !play;
repeatePlaying = false;
if (play)
{
StartPosition();
}
}
}
if (buttonRecord != buttonRecordLast)
{
if (buttonRecord == LOW)
{
record = !record;
if (record)
{
play = false;
repeatePlaying = false;
recPos = 0;
}
else
{
if (debug) PrintBuffer();
}
}
}
buttonPlayLast = buttonPlay;
buttonRecordLast = buttonRecord;
float dx = map(analogRead(xdirPin), 0, 1023, -5.0, 5.0);
float dy = map(analogRead(ydirPin), 0, 1023, 5.0, -5.0);
float dz = map(analogRead(zdirPin), 0, 1023, 5.0, -5.0);
float dg = map(analogRead(gdirPin), 0, 1023, 5.0, -5.0);
if (abs(dx) < 1.5) dx = 0;
if (abs(dy) < 1.5) dy = 0;
if (abs(dz) < 1.5) dz = 0;
if (abs(dg) < 1.5) dg = 0;
posBase += dx;
posShoulder += dy;
posElbow += dz;
posGripper += dg;
if (play)
{
if (playPos >= recPos) {
playPos = 0;
if (repeatePlaying)
{
delay(delayBetweenCycles);
StartPosition();
}
else
{
play = false;
}
}
bool endOfData = false;
while (!endOfData)
{
if (playPos >= buffSize - 1) break;
if (playPos >= recPos) break;
int data = buff[playPos];
int angle = data & 0xFFF;
int servoNumber = data & 0x3000;
endOfData = data & 0x4000;
switch (servoNumber)
{
case 0x0000:
posBase = angle;
break;
case 0x1000:
posShoulder = angle;
break;
case 0x2000:
posElbow = angle;
break;
case 0x3000:
posGripper = angle;
dg = posGripper - lastGripper;
break;
}
playPos++;
}
}
if (posBase > maxBase) posBase = maxBase;
if (posShoulder > maxShoulder) posShoulder = maxShoulder;
if (posElbow > maxElbow) posElbow = maxElbow;
if (posGripper > maxGripper) posGripper = maxGripper;
if (posBase < minBase) posBase = minBase;
if (posShoulder < minShoulder) posShoulder = minShoulder;
if (posElbow < minElbow) posElbow = minElbow;
if (posGripper < minGripper) posGripper = minGripper;
servoBase.write(posBase);
servoShoulder.write(posShoulder);
servoElbow.write(posElbow);
// if (dg < -3.0) {
// posGripper = minGripper;
// servoGripper.write(posGripper);
// Serial.println(posGripper);
// }
// else if (dg > 3.0) {
// posGripper = maxGripper;
// servoGripper.write(posGripper);
// Serial.println(posGripper);
// }
bool waitGripper = false;
if (dg < 0) {
posGripper = minGripper;
waitGripper = true;
}
else if (dg > 0) {
posGripper = maxGripper;
waitGripper = true;
}
servoGripper.write(posGripper);
if (play && waitGripper)
{
delay(1000);
}
//Serial.println(posGripper);
if ((lastBase != posBase) | (lastShoulder != posShoulder) | (lastElbow != posElbow) | (lastGripper != posGripper))
{
if (record)
{
if (recPos < buffSize - countServo)
{
int buffPos = 0;
if (lastBase != posBase)
{
buffAdd[buffPos] = posBase;
buffPos++;
}
if (lastShoulder != posShoulder)
{
buffAdd[buffPos] = posShoulder | 0x1000;
buffPos++;
}
if (lastElbow != posElbow)
{
buffAdd[buffPos] = posElbow | 0x2000;
buffPos++;
}
if (lastGripper != posGripper)
{
buffAdd[buffPos] = posGripper | 0x3000;
buffPos++;
}
buffAdd[buffPos - 1] = buffAdd[buffPos - 1] | 0x4000;
for (int i = 0; i < buffPos; i++)
{
buff[recPos + i] = buffAdd[i];
}
recPos += buffPos;
}
}
command = "Manual";
printPos = 0;
if (play)
{
command = "Play";
printPos = playPos;
}
else if (record)
{
command = "Record";
printPos = recPos;
}
Serial.print(command);
Serial.print("\t");
Serial.print(printPos);
Serial.print("\t");
Serial.print(posBase);
Serial.print("\t");
Serial.print(posShoulder);
Serial.print("\t");
Serial.print(posElbow);
Serial.print("\t");
Serial.print(posGripper);
Serial.print("\t");
Serial.print(record);
Serial.print("\t");
Serial.print(play);
Serial.println();
}
lastBase = posBase;
lastShoulder = posShoulder;
lastElbow = posElbow;
lastGripper = posGripper;
if ( repeatePlaying)
{
ledLight = !ledLight;
}
else
{
if (ledLight)
{
ledLight = false;
}
if (record)
{
ledLight = true;
}
};
digitalWrite(pinLedRecord, ledLight);
delay(50);
}
void PrintBuffer()
{
for (int i = 0; i < recPos; i++)
{
int data = buff[i];
int angle = data & 0xFFF;
int servoNumber = data & 0x3000;
bool endOfData = data & 0x4000;
Serial.print("Servo=");
Serial.print(servoNumber);
Serial.print("\tAngle=");
Serial.print(angle);
Serial.print("\tEnd=");
Serial.print(endOfData);
Serial.print("\tData=");
Serial.print(data, BIN);
Serial.println();
}
}
void StartPosition()
{
int angleBase = servoBase.read();
int angleShoulder = servoShoulder.read();
int angleElbow = servoElbow.read();
int angleGripper = servoGripper.read();
Serial.print(angleBase);
Serial.print("\t");
Serial.print(angleShoulder);
Serial.print("\t");
Serial.print(angleElbow);
Serial.print("\t");
Serial.print(angleGripper);
Serial.println("\t");
posBase = startBase;
posShoulder = startShoulder;
posElbow = startElbow;
posGripper = startGripper;
servoBase.write(posBase);
servoShoulder.write(posShoulder);
servoElbow.write(posElbow);
servoGripper.write(posGripper);
}
This is the modified code which does not work well
((In my code joystick 1 controls servos 1 & 2 well; joystick 2 controls servo 4 well but when acting on servo 3 servo 4 moves at same time. Joystick 3 should control servo 5 but it does not. Record button works, play button works and loop option works but the move is not recorded well. There is record in servos 1.2.3 & 4 but when playing the sequence is not correct, besides the servo 4 gets trapped in loop mode despite loop mode is not activated))
#include <Servo.h>
bool repeatePlaying = false; /* Repeatedly is running recorded cycle */
int delayBetweenCycles = 2000; /* Delay between cycles */
int s1Pin = 11; /* s1 servo */
int s2Pin = 10; /* s2 servo */
int s3Pin = 9; /* s3 servo */
int s4Pin = 6; /* s4 servo */
int s5Pin = 7; /*s5 servo */
int wdirPin = A0; /* s1 - joystick1*/
int xdirPin = A1; /* s2 - joystick1 */
int ydirPin = A3; /* s3 - joystick2 */
int zdirPin = A2; /* s4 - joystick2 */
int gdirPin = A4; /* s5 - joystick3 */
//int pinRecord = A4; /* Button record - backward compatibility */
//int pinPlay = A5; /* Button play - backward compatibility */
int pinRecord = PD2; /* Button record - recommended (A4 is deprecated, will by used for additional joystick) */
int pinPlay = PD3; /* Button play - recommended (A5 is deprecated, will by used for additional joystick) */
int pinLedRecord = 13; /* LED - indicates recording (light) or auto play mode (blink ones) */
const int buffSize = 512; /* Size of recording buffer */
int starts1 = 90;
int starts2 = 90;
int starts3 = 90;
int starts4 = 0;
int starts5 = 90;
int poss1 = 90;
int poss2 = 90;
int poss3 = 90;
int poss4 = 0;
int poss5 = 90;
int lasts1 = 90;
int lasts2 = 90;
int lasts3 = 90;
int lasts4 = 90;
int lasts5 = 90;
int mins1 = 0;
int maxs1 = 150;
int mins2 = 0;
int maxs2 = 150;
int mins3 = 0;
int maxs3 = 150;
int mins4 = 0;
int maxs4 = 150;
int mins5 = 0;
int maxs5 = 150;
const int countServo = 5;
int buff[buffSize];
int buffAdd[countServo];
int recPos = 0;
int playPos = 0;
int buttonRecord = HIGH;
int buttonPlay = HIGH;
int buttonRecordLast = LOW;
int buttonPlayLast = LOW;
bool record = false;
bool play = false;
bool debug = false;
String command = "Manual";
int printPos = 0;
int buttonPlayDelay = 20;
int buttonPlayCount = 0;
bool ledLight = false;
Servo servos1;
Servo servos2;
Servo servos3;
Servo servos4;
Servo servos5;
void setup() {
Serial.begin(9600);
pinMode(wdirPin, INPUT);
pinMode(xdirPin, INPUT);
pinMode(ydirPin, INPUT);
pinMode(zdirPin, INPUT);
pinMode(gdirPin, INPUT);
pinMode(pinRecord, INPUT_PULLUP);
pinMode(pinPlay, INPUT_PULLUP);
pinMode(pinLedRecord, OUTPUT);
servos1.attach(s1Pin);
servos2.attach(s2Pin);
servos3.attach(s3Pin);
servos4.attach(s4Pin);
servos5.attach(s5Pin);
StartPosition();
digitalWrite(pinLedRecord, HIGH);
delay(1000);
digitalWrite(pinLedRecord, LOW);
}
void loop() {
buttonRecord = digitalRead(pinRecord);
buttonPlay = digitalRead(pinPlay);
// Serial.print(buttonRecord);
// Serial.print("\t");
// Serial.println(buttonPlay);
// for testing purposes
if (buttonPlay == LOW)
{
buttonPlayCount++;
if (buttonPlayCount >= buttonPlayDelay)
{
repeatePlaying = true;
}
}
else buttonPlayCount = 0;
if (buttonPlay != buttonPlayLast)
{
if (record)
{
record = false;
}
if (buttonPlay == LOW)
{
play = !play;
repeatePlaying = false;
if (play)
{
StartPosition();
}
}
}
if (buttonRecord != buttonRecordLast)
{
if (buttonRecord == LOW)
{
record = !record;
if (record)
{
play = false;
repeatePlaying = false;
recPos = 0;
}
else
{
if (debug) PrintBuffer();
}
}
}
buttonPlayLast = buttonPlay;
buttonRecordLast = buttonRecord;
float dw = map(analogRead(wdirPin), 0, 1023, -5.0, 5.0);
float dx = map(analogRead(xdirPin), 0, 1023, 5.0, -5.0);
float dy = map(analogRead(ydirPin), 0, 1023, 5.0, -5.0);
float dz = map(analogRead(zdirPin), 0, 1023, 5.0, -5.0);
float dg = map(analogRead(gdirPin), 0, 1023, 5.0, -5.0);
if (abs(dw) < 1.5) dw = 0;
if (abs(dx) < 1.5) dx = 0;
if (abs(dy) < 1.5) dy = 0;
if (abs(dz) < 1.5) dz = 0;
if (abs(dg) < 1.5) dg = 0;
poss1 += dw;
poss2 += dx;
poss3 += dy;
poss4 += dz;
poss5 += dg;
if (play)
{
if (playPos >= recPos) {
playPos = 0;
if (repeatePlaying)
{
delay(delayBetweenCycles);
StartPosition();
}
else
{
play = false;
}
}
bool endOfData = false;
while (!endOfData)
{
if (playPos >= buffSize - 1) break;
if (playPos >= recPos) break;
int data = buff[playPos];
int angle = data & 0xFFF;
int servoNumber = data & 0x3000;
endOfData = data & 0x4000;
switch (servoNumber)
{
case 0x0000:
poss1 = angle;
break;
case 0x1000:
poss2 = angle;
break;
case 0x2000:
poss3 = angle;
break;
case 0x3000:
poss4 = angle;
dz = poss4 - lasts4;
break;
case 0x4000:
poss5 = angle;
dg = poss5 - lasts5;
break;
}
playPos++;
}
}
if (poss1 > maxs1) poss1 = maxs1;
if (poss2 > maxs2) poss2 = maxs2;
if (poss3 > maxs3) poss3 = maxs3;
if (poss4 > maxs4) poss4 = maxs4;
if (poss5 > maxs5) poss5 = maxs5;
if (poss1 < mins1) poss1 = mins1;
if (poss2 < mins2) poss2 = mins2;
if (poss3 < mins3) poss3 = mins3;
if (poss4 < mins4) poss4 = mins4;
if (poss5 < mins5) poss5 = mins5;
servos1.write(poss1);
servos2.write(poss2);
servos3.write(poss3);
// if (dg < -3.0) {
// poss4 = mins4;
// servos4.write(poss4);
// Serial.println(poss4);
// }
// else if (dg > 3.0) {
// poss4 = maxs4;
// servos4.write(poss4);
// Serial.println(poss4);
// }
bool waits4 = false;
if (dz < 0) {
poss4 = mins4;
waits4 = true;
}
else if (dz > 0) {
poss4 = maxs4;
waits4 = true;
}
servos4.write(poss4);
if (play && waits4)
{
delay(1000);
}
//Serial.println(poss4);
if ((lasts1 != poss1) | (lasts2 != poss2) | (lasts3 != poss3) | (lasts4 != poss4))
{
if (record)
{
if (recPos < buffSize - countServo)
{
int buffPos = 0;
if (lasts1 != poss1)
{
buffAdd[buffPos] = poss1;
buffPos++;
}
if (lasts2 != poss2)
{
buffAdd[buffPos] = poss2 | 0x1000;
buffPos++;
}
if (lasts3 != poss3)
{
buffAdd[buffPos] = poss3 | 0x2000;
buffPos++;
}
if (lasts4 != poss4)
{
buffAdd[buffPos] = poss4 | 0x3000;
buffPos++;
}
if (lasts5 != poss5)
{
buffAdd[buffPos] = poss5 | 0x4000;
buffPos++;
}
buffAdd[buffPos - 1] = buffAdd[buffPos - 1] | 0x5000;
for (int i = 0; i < buffPos; i++)
{
buff[recPos + i] = buffAdd[i];
}
recPos += buffPos;
}
}
command = "Manual";
printPos = 0;
if (play)
{
command = "Play";
printPos = playPos;
}
else if (record)
{
command = "Record";
printPos = recPos;
}
Serial.print(command);
Serial.print("\t");
Serial.print(printPos);
Serial.print("\t");
Serial.print(poss1);
Serial.print("\t");
Serial.print(poss2);
Serial.print("\t");
Serial.print(poss3);
Serial.print("\t");
Serial.print(poss4);
Serial.print("\t");
Serial.print(poss5);
Serial.print("\t");
Serial.print(record);
Serial.print("\t");
Serial.print(play);
Serial.println();
}
lasts1 = poss1;
lasts2 = poss2;
lasts3 = poss3;
lasts4 = poss4;
lasts5 = poss5;
if ( repeatePlaying)
{
ledLight = !ledLight;
}
else
{
if (ledLight)
{
ledLight = false;
}
if (record)
{
ledLight = true;
}
};
digitalWrite(pinLedRecord, ledLight);
delay(50);
}
void PrintBuffer()
{
for (int i = 0; i < recPos; i++)
{
int data = buff[i];
int angle = data & 0xFFF;
int servoNumber = data & 0x3000;
bool endOfData = data & 0x4000;
Serial.print("Servo=");
Serial.print(servoNumber);
Serial.print("\tAngle=");
Serial.print(angle);
Serial.print("\tEnd=");
Serial.print(endOfData);
Serial.print("\tData=");
Serial.print(data, BIN);
Serial.println();
}
}
void StartPosition()
{
int angles1 = servos1.read();
int angles2 = servos2.read();
int angles3 = servos3.read();
int angles4 = servos4.read();
int angles5 = servos5.read();
Serial.print(angles1);
Serial.print("\t");
Serial.print(angles2);
Serial.print("\t");
Serial.print(angles3);
Serial.print("\t");
Serial.print(angles4);
Serial.println("\t");
Serial.print(angles5);
Serial.println("\t");
poss1 = starts1;
poss2 = starts2;
poss3 = starts3;
poss4 = starts4;
poss5 = starts5;
servos1.write(poss1);
servos2.write(poss2);
servos3.write(poss3);
servos4.write(poss4);
servos5.write(poss5);
}