How do you record steps for a servo motor ?

I've been trying to figure out how to record steps for a servo motor. The trouble is I keep getting confused and it doesn't feel as straightforward as I thought it would be. I have a servo motor, 2 push buttons, one to enter recording and play mode, the other to exit the record and play mode. I just can't figure out how to code these components to do just that, and I am drained at this point

What does "record steps" mean?

Welcome to the forum

How are the servo angles going to be entered ?

Record in this sense means to keep the angles the servo should write in an array, for example. Playing would then be accessing the recorded angle and making them available for the servo to write.

The angles are going to be entered using a potentiometer. The potentiometer values are converted to angles using the map() function.

Sounds quite straight forward

  • Move the pot to a position and move the servo at the same time
  • Press the record button and save the current angle to an array
  • Increment the array index variable
  • Keep going until end of recording is signalled by pressing the play button
  • When the play button is pressed again play back the angles from the array

Where are you stuck ?

A simple way might be to record the angle at a fixed time interval, e.g. every 100ms, but depending on how long you record for you may run out of RAM. You could compress the data, e.g. don't record an angle if it is the same as the last time.

A smarter method might be to detect significant changes in the angle, and only record those. However, with a pot the angle might vary continuously so you may actually end up with more data.

Either way, you need to pick a level of accuracy so that the data fits into RAM for required recording time.

Of course, you could use an external storage like SD card in which case the recording time would be more or less unlimited.

Replaying the data is a simple matter of recreating the angle at the appropriate time.

1 Like

Thank you for the feedback. I tried writing a sketch to understand your suggestions better. Perhaps you could point out what exactly you mean from the sketch:

#include<Servo.h>

int button1 = 2;
int button2 = 8;
int LED1 = 3;
int LED2 = 5;

Servo servo;
int servoPort = 9;
int servoCntrl = A0; 
//button stuff  
int button1Value = LOW;
int button2Value = LOW;
int pressButtonCount = 0;
//servo stuff for normal operation 
int normalValue;
int normalAngle;
int recordingValue;
int recordingAngle;
int angleDiff;
int anglesRec[2];//array to stor the recorded angles 
int counter = 0;

void setup() {
  servo.attach(servoPort);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);

  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

//first, the servo should operate normally, follow normal operation.//
//NormalOperation in this case means moving the servo with the potentiometer in real time,
//without any recording whatsoever//
normalValue = analogRead(servoCntrl);
normalAngle = map(normalValue, 0, 1023, 0, 180);
servo.write(normalAngle);

if (button1Value == HIGH)
{
  pressButtonCount += 1;   
}
if ( pressButtonCount>=1 && pressButtonCount <2 );//Pressing the button once will initiate the recording sequence
{
//    Serial.print("YOU ARE NOW IN RECORDING MODE"); 
    servo.write(0); 
    while (counter<2)
    {
      recordingValue = analogRead(servoCntrl);
      recordingAngle = map(recordingValue, 0, 1023, 0, 180);
      servo.write(recordingAngle);
      if (button2 == HIGH)
        { anglesRec[counter]=recordingAngle;
          digitalWrite(LED2, HIGH);
      }
      counter++;
    }
    if (counter == 2) //the counter being 2 implies that the recording sequence is done
    {
//      Serial.print("RECORDING DONE. NOW ENTERING PLAY MODE");
      for(int i = 0; i<counter; i++)
      {
        servo.write(anglesRec[counter]);
      }
      
    }
}

}

You'd need timing as well, because this loop:

...will quickly send all the positions, and the servo will move directly to the last position, mostly ignoring the earlier commands.

If you know how to play a sequence of positions, then the recording process would be filling in the data for the motions.

Is this by @bobcousins meant? Also, how do you add the timing? Any explanation or link to documentation would help.

Well, the quick answer would be to use the processor-kneecapping delay() function:

//      Serial.print("RECORDING DONE. NOW ENTERING PLAY MODE");
      for(int i = 0; i<counter; i++)
      {
        servo.write(anglesRec[counter]);
        delay(timesRec[counter]);
      }

and record appropriate intervals in timesRec[].

Answering @bobcousin's questions would help with thinking about the design.

1 Like

A note about if() conditional statements... do not end the line in a semi-colon (;) or the condition will terminate and treat the following lines as non-conditional (run always, regardless of condition).

3 Likes

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