Project tutorial
Joystick Controller for MeArm Robot - Recording Coordinates

Joystick Controller for MeArm Robot - Recording Coordinates © MIT

Uses 2 analog joysticks to control 4 servos without of using additional board. Have 3 modes: manual, recording of coordinates and autorun.

  • 1,352 views
  • 2 comments
  • 18 respects

Components and supplies

Apps and online services

About this project

Arduino Uno joystick controller for robot arm (MeArm®) with recording of coordinates. Allows to repeate recorded coordinates once on button click or repeatedly. Uses Arduino Uno base board without of additional boards. Requires USB connection (2A) or 6V / 2A power supply. Tested with using four servos SG90.

Press button on joystick1 to start recording of coordinates. Press button on joystick1 to end recording of coordinates.

Press button on joystick2 to start replay of recorded coordinates. Press button on joystick2 to stop replay of recorded coordinates. Hold button on joystick2 to start replay of recorded coordinates automatically in cycle.

Code

Arduiono Joystick controller for MeArm ® robot with recording of coordinates. (version 1.3)Arduino
Use Arduino IDE for programming Arduiono UNO base board via USB port.
/* meArm analog joysticks version 1.3 - UtilStudio.com Dec 2018
   Uses two analogue joysticks and four servos.

   In version 1.3 was improved recording of coordinates. 
   And changed pins for joystick buttons and LED.

   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
       4V       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
       PD4                                                            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 = PD4;  /* LED - indicates recording (light) or auto play mode (blink one) */

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;

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);
  pinMode(pinPlay, INPUT);

  pinMode(pinLedRecord, OUTPUT);
  digitalWrite(pinLedRecord, !record);

  servoBase.attach(basePin);
  servoShoulder.attach(shoulderPin);
  servoElbow.attach(elbowPin);
  servoGripper.attach(gripperPin);

  StartPosition();
}

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;
      digitalWrite(pinLedRecord, 0);
      delay(250);
      digitalWrite(pinLedRecord, 1);
      delay(250);
      digitalWrite(pinLedRecord, 0);
      delay(250);
      digitalWrite(pinLedRecord, 1);
    }
  }
  else buttonPlayCount = 0;

  if (buttonPlay != buttonPlayLast)
  {
    record = false;

    if (buttonPlay == LOW)
    {
      play = !play;

      if (play)
      {
        repeatePlaying = false;
        StartPosition();
      }
    }
  }

  if (buttonRecord != buttonRecordLast)
  {
    play = false;

    if (buttonRecord == LOW)
    {
      record = !record;

      if (record)
      {
        recPos = 0;
      }
      else
      {
        if (debug) PrintBuffer();
      }

      digitalWrite(pinLedRecord, !record);
    }
  }

  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;

  posBase += dx;
  posShoulder += dy;
  posElbow += dz;

  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;
          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);
  }
  else if (dg > 3.0) {
    posGripper = maxGripper;
    servoGripper.write(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;

  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()
{
  posBase = startBase;
  posShoulder = startShoulder;
  posElbow = startElbow;
  posGripper = startGripper;

  servoBase.write(posBase);
  servoShoulder.write(posShoulder);
  servoElbow.write(posElbow);
  servoGripper.write(posGripper);
}

Schematics

Joystick controller for MeArm ® robot - shematic diagram (version 1.3)
Joystick controller for MeArm ® robot with recording of coordinates - shematic diagram
Arduino mearm joystick controller rqnjsdf0qy
MeArm robot - joystick servo recorder - test board
Testing board with only two servos connected. See schematic diagram to connect 4 servo motors.
Arduino mearm joystick recorder pfrak0x99r

Comments

Similar projects you might like

MeArm Robot Arm - Your Robot - V1.0

Project tutorial by Benjamin Gray

  • 19,302 views
  • 3 comments
  • 34 respects

Mega Bread - Atari Joystick Linking for Robotics Control

Project in progress by Pigeon-Kicker

  • 1,439 views
  • 3 comments
  • 10 respects

Make your first Arduino robot - The best beginners guide!

Project tutorial by Muhammed Azhar

  • 44,084 views
  • 15 comments
  • 98 respects

Project 1: 2WD Obstacle Avoiding Robot

Project showcase by HDA Robotics

  • 7,526 views
  • 6 comments
  • 17 respects

Controlling a Robot with a PlayStation Controller

Project tutorial by Andrew R Gross and Jonathan Gross

  • 2,835 views
  • 0 comments
  • 7 respects

Joy Robot (Robô Da Alegria)

Project tutorial by Igor Fonseca Albuquerque

  • 2,319 views
  • 1 comment
  • 23 respects
Add projectSign up / Login