I have a 4.8V mini servo. The power supply is external.
If I give the PWM signal via an RC receiver the servo works smoothly, while if I generate the PWM via Arduino the servo has lots of jitter and vibrates.
To generate the PWM I'm using the TimerOne library, so it's dealing directly with timer's register and it should be very precise.
The only difference I see is that the RC outputs a 3.3V PWM while arduino at 5V, but that shouldn't be a problem. Unfortunately I have only an analogic oscilloscope which doesn't have the precision to check the PWM wave.
The problem is not related at all to the power supply, just about the PWM.
As little test I tried to set the PWM, then after one second put the pinMode to INPUT and the jitter stops, showing that it is totally related to the PWM generated.
Any tip to solve this? I'm puzzled on why it's happening and why the RC works well.
Are you using SoftwareSerial in your sketch? That causes jitter in interrupts because it disables interrupts for the duration of each output character. Higher baud rates cause less jitter.
The code. I'm commanding at 50Hz (long period = 20000;) but I tried also at 100, 200 and 400Hz without improvements.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
#include <TimerOne.h>
#define SERVOPIN 9
//TimerOne/TimerThree helper variables
long period = 20000; //2600; // the period in microseconds
char* buffer = new char[128];
int bpos = 0;
int servoVal = 900;
void setup() {
// put your setup code here, to run once:
pinMode(SERVOPIN, OUTPUT);
Serial.begin(115200);
Timer1.initialize(period);
Serial.println("READY");
}
void loop() {
// put your main code here, to run repeatedly:
while (Serial.available() > 0) {
char c = Serial.read();
if (c!='\n' && bpos<10){
buffer[bpos++]=c;
}else{
buffer[bpos]='\0';
servoVal = atoi(buffer);
bpos = 0;
if (servoVal>0){
//Imposta valore servo
if (servoVal<500){ servoVal=500; }
if (servoVal>2500) { servoVal=2500; }
Serial.print("Setting value: ");
Serial.println(servoVal);
setPulseWidth1(SERVOPIN, servoVal);
}else{
//err
Serial.println("Command error, flushing buffers");
Serial.flush();
}
}
}
}
bool setPulseWidth1(int outPin, long microseconds)
{
bool ret = false;
if( microseconds < period)
{
int duty = map(microseconds, 0,period, 0,1024);
if( duty < 1)
duty = 1;
if(microseconds > 0 && duty < RESOLUTION)
{
Timer1.pwm(outPin, duty);
ret = true;
}
}
return ret;
}
Also using Servo library I have the same problem.
Wiring is: BEC 5V-->powers arduino and servo. Common ground servo and arduino. Pin 9 arduino to servo signal.
No software serial.
If you have the same problem using either your code or the Servo library then it seems extremely likely that the problem IS with the power or the wiring. Obviously when you use the "RC" the wiring is different.
BTW what is the specification of the "BEC" that is powering everything?
I think the problem is that you are doing PWM from 0 to 20000 microseconds and a servo only understands pulses from 1000 to 2000 microseconds.
The PWM value of 0 to 1023 covers the full 0 to 20000 microsecond range. To stay in the 1000 to 2000 microsecond range the servo understands, you need to use the appropriate PWM range:
slipstick:
If you have the same problem using either your code or the Servo library then it seems extremely likely that the problem IS with the power or the wiring. Obviously when you use the "RC" the wiring is different.
BTW what is the specification of the "BEC" that is powering everything?
Steve
The powering is straighforward. I used the same BEC with the RC + Servo experiment and the Arduino + Servo experiment. The servo is powered in the same exact way as the RC. So it's not the power.
johnwasser:
I think the problem is that you are doing PWM from 0 to 20000 microseconds and a servo only understands pulses from 1000 to 2000 microseconds.
The PWM value of 0 to 1023 covers the full 0 to 20000 microsecond range. To stay in the 1000 to 2000 microsecond range the servo understands, you need to use the appropriate PWM range:
You should keep your PWM values in the 51 to 102 range to control a servo.
20000 microseconds is the standard 50Hz PWM exactly as the RC. I don't see the problem here. Of course I only command values between 800 and 2200 microseconds (it's the accepted range for the servo).
tuloski:
Of course I only command values between 800 and 2200 microseconds (it's the accepted range for the servo).
Sorry, you are right. I missed the places in the sketch where you restricted the range to 500::2500 and then mapped from that range to 25::128.
if(microseconds > 0 && duty < RESOLUTION)
What is the value of 'RESOLUTION'? I don't see it in your sketch. In TimerOne.h (V1.1.0) there is a declaration of 'TIMER1_RESOLUTION' but I don't see a declaration of 'RESOLUTION' there or in 'config/known_16bit_timers.h'.
Does your servo jitter when you aren't sending new position commands over Serial? If so, it might be a wiring problem. Have you checked the resistance between your Arduino pin and the servo signal wire? Have you checked the resistance between Arduino Ground and the servo ground wire?
Try a different servo.....I sometimes get different results in my projects w/ different "standardized" servos....and that it has at least the minimum required operating voltage and amperage available
johnwasser:
Does your servo jitter when you aren't sending new position commands over Serial? If so, it might be a wiring problem. Have you checked the resistance between your Arduino pin and the servo signal wire? Have you checked the resistance between Arduino Ground and the servo ground wire?
It does jitter when I don't send new position over serial, for example I send a single value and it jitters all the time, but the pwm is actually set only once.
It does stop jittering if I do pinmode INPUT, i.e. I stop the PWM (so again showing that it is a symptom of the PWM and not the power).
FYI I was able to fix the jitter by shifting the level of the PWM from 5V to 3.3V. Don't ask me why, but it was the only difference I saw with the RC receiver so I tried. I used sparkfun optoisolator to shift the 5V to 3.3V and it works like a charm.