Multiple Servo Record/Playback for Robot Arm on SD card

Hi all!

Beginner Arduino programmer here looking for some assistance with a robotics project! I am hoping to program a sequence of positions for a robotic arm.

As I understand it, you can record several servo positions onto a micro SD using potentiometers, and then use a different bit of code in order to play the values back. However I can't seem to figure out how to get the servos to read the correct values from the data string during playback.

Here is my code to record the servo positions - right now I have the code written to write for 2 servos, however the final project will include 5 servo motors:

#include <Servo.h>
#include <SPI.h>
#include <SD.h>

// CS pin for SD Card Module
const int chipSelect = 4;
// Integer to hold potentiometer value
int val1 = 0;
int val2 = 0;

//**** servo 1 settings
Servo servo1;
const int servo1PotPin = A0;
const int servo1Pin = 3;// Must use PWM enabled pin
int servo1Value;

//**** servo 1 settings END

  //**** servo 2 settings
  Servo servo2;
  const int servo2PotPin =A1;
  const int servo2Pin = 5;// Must use PWM enabled pin
  int servo2Value;
  //**** servo 2 settings END

  void setup() {

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  //Robojax.com multiple servo
  servo1.attach(3);
  servo2.attach(5);
  }

  void loop() {
  //Robojax.com multiple servo
  servo1Value = analogRead(servo1PotPin);
  servo1Value = map(servo1Value, 0, 1023, 0, 180);
  servo1.write(servo1Value);

  servo2Value = analogRead(servo2PotPin);
  servo2Value = map(servo2Value, 0, 1023, 0, 180);
  servo2.write(servo2Value);


  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 2; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }


  // Write to the servo
  // Delay to allow servo to settle in position
  servo1.write(servo1Value);
  delay(15);
  
  servo2.write(servo2Value);
  delay(15);

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("servopos.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening servopos.txt");
  }
  }

And here is my code for playback:

// Include libraries
 
#include <SPI.h>
#include <SD.h>
#include <Servo.h>
 
// CS pin for SD Card Module
const int chipSelect = 4;
 
// String to hold one line of text
String buffer;
  
// Create a Servo object
Servo servo1;
Servo servo2;
 
void setup() {
 
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
 
  Serial.print("Initializing SD card...");
 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
  
  // Attach servo to the servo object
  servo1.attach(3);  
  servo2.attach(5);  
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("servopos.txt");
  
 
  // If the file is available, read it
  if (dataFile) {
    while (dataFile.available()) {
    // Write one line to buffer
    buffer = dataFile.readStringUntil('\n');
    // Print to serial monitor
      Serial.println(buffer);
    // Convert string to integer and position servo
      servo1.write(buffer.toInt());
      delay(15);
      
      servo2.write(buffer.toInt());
      delay(15); 
      
    }
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}
 
void loop() {
}

The main issue is the bit of code that converts the recorded data string to the servos during playback, allowing them to read the correct value.

Any advice on this would be great! Also - since this is my first Arduino project - I am very open to any pointers/tips on how to clean the code up since I am sure there are plenty of other things that could be improved.

Thanks so much for your time!

You send twice the same value

It’s ok for the first one but for the second one you need to look for the comma and call toInt() on the substring after that

You can use any digital output pin.

You took the time to give '3' a name. Your code will be easier to understand if you use the name.

You sent them already. No need to send the same numbers again.

I don't think this is true. You may be limited to something like four at a time but I think you can have more than one.

I think that is going to get you the same answer for both. You need to split the string into separate numbers.

You have delays after each command on your playback, but you really need to know and save the time it took for the original movement to take place and then allow that time for the playback.

Rather than recording hundreds or thousands of positions each second, I would only record a 'keyframe' each time a button was pressed. The playback could then interpolate between the positions. That would make it easier to tweak individual positions and adjust speed.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.