I'm using a SG-90 servo and sweeping left and right between two values. My problem is that there is a distinct delay of about 500ms between direction changes. I would like the position of the servo to be predictable, but due to this at direction changes it is not.
bool servoDir = true;
int servoCnt = 90;
int servoInc = 1;
int servoMin = servoCnt - 5;
int servoMax = servoCnt + 5;
void loop() {
if (servoDir) {
dx = servoInc;
if (servoCnt > servoMax) {
servoDir = false;
}
} else {
dx = -servoInc;
if (servoCnt < servoMin) {
servoDir = true;
}
}
servoCnt += dx;
servo.write(servoCnt);
// delay or other code here (mine is 40ms)
}
I've tried both the Arduino Servo library and the VarspeedServo library. They both show the same thing.
What is the cause of this and what can I do about it?
Update
So if I up the speed at direction change, like so:
int extra = 5;
void loop() {
if (servoDir) {
dx = servoInc;
if (servoCnt > servoMax) {
dx -= extra;
servoDir = false;
}
} else {
dx = -servoInc;
if (servoCnt < servoMin) {
dx += extra;
servoDir = true;
}
}
servoCnt += dx;
servo.write(servoCnt);
// delay or other code here (mine is 40ms)
}
the delay disappears, but the servo position does become a lot less predictable.
You would experience exactly these symptoms if servoMin and servoMax were out of the servo range.... Which they are.
More seriously, these servos are not very precise. Incrementing by 1 at a time is probably the issue. You are experiencing some form of backlash.
You should check and clamp the count against the range AFTER incrementing/decrementing. That's one of the basic rules of embedded programming. Lives may be at stake, or equipment destroyed when sending out out of range values.
bool servoDir = true;
int servoCnt = 90;
int servoInc = 1; // <-- exclusively use this to control speed.
int servoMin = servoCnt - 5; // <-- this range is a bit short for testing
int servoMax = servoCnt + 5;
void loop() {
// 'jog' the servo.
servoCnt += (servoDir) ? servoInc : -servoInc;
// past this point, all position jogging is final
if (servoCnt > servoMax)
{
servoCnt = servoMax;
servoDir = false;
}
else if (servoCnt < servoMin)
{
servoCnt = servoMin;
servoDir = true;
}
servo.write(servoCnt);
// 40ms sounds a bit short for tests.
// 100 ms should give you a 2 seconds (0.5Hz) oscillation
delay(100);
}