Hi,
I recently bought an entry level oscilloscope and wanted to check the PWM signal I send to my servos.
I attached the pin via servo.attach(pin, min, max) using 1000 & 2000 as min/max values to ensurer that the expected value would be 1.500 ms. While measuring I noticed that the signal was not exactly 1.500 ms for the 90° so I started to look further.
To simplify things I removed the servo library and send the pulse directly to get a 50Hz signal (Intervall of 20ms) and a PW of 1.500 ms:
void loop() {
analogWrite(5,255);
delayMicroseconds(1500);
analogWrite(5,0);
// Currently, the largest value that will produce an accurate delay in Microseconds is 16383, thus splitting into delayMicroseconds & delay to archive a delay of 18,5 ms
delayMicroseconds(500);
delay(18);
}
The values I read are:
Intervall T: 20.04 ms (--> 49.90 Hz)
PW: 1.560 ms
NW: 18.48 ms
Instead of as expected 20.00ms / 1.500 ms / 18.5 ms.
How accurate is the PWM signal of an Arduino Uno?
Are the values inside the expected tolerance?
Other possibilities:
Issue with my code leading to this results?
I'm not using an original Arduino but one from Elegoo --> cheaper components with less accuracy?
I'm using the Hanmatek DOS1102 (similar to OWN SDS oscilloscope). Entry level scope but as I'm still far from it's limits I guess my readings are OK. Still want to put it out as another possible reason.
Any ideas are welcome
Best,
David
PS @Admin: Could not decide on a suitable area for my post. Please feel free to move
void loop() {
digitalWrite(5,HIGH);
delayMicroseconds(1500);
digitalWrite(5,LOW);
// Currently, the largest value that will produce an accurate delay in Microseconds is 16383, thus splitting into delayMicroseconds & delay to archive a delay of 18,5 ms[color=#222222][/color]
delayMicroseconds(500);
delay(18);
}
You might also try port manipulation.
digital and analog Write are functions that take a certain amount of time to accomplish.
If you want to know how accurate the pwm is, you can simply use a single analogWrite in setup and leave loop empty.
To answer the question in the title, the PWM frequency is as accurate as the clock source used to provide the chip with a clock signal. A deviation of 1% in the clock source will result in a 1% deviation in the PWM frequency.
Hi Tom,
Thanks for your ideas.
Using digitalWrite is yielding the exact same results.
Will need some time to wrap my head around port manipulation but will report back if I have some findings here.
From the link you gave I also checked the pin Mapping for my Atmega328p (same as Atmega168) and measured directly on the IC (8 for GND and 11 for PD5=pin 5) also with the same result. Expectable but you never know
Although the signal that is used to control servos is referred to as PWM it is very different from the PWM signal produced by analogWrite(). It is unfortunate that the same acronym is used for two different things.
Hobby servos were never designed as high precision devices. In their original usage for controlling model aircraft the user continually provides adjustments based on the behaviour of the aircraft which overcome any small variations in the response of the servo.
If you want to create an Arduino project that moves the servo arm to an absolute position then your code must be tailored for the particular servo that you are using.
The Arduino Uno has a 16 MHz quartz crystal. From a brief scan over various information sources in the web the usual deviation they have could already describe my results. Particularly if I factor in a change in frequency with a change in temperature as mentioned in Arduino Clock frequency accuracy. Will try if I can measure the frequency of the crystal in my board.
I do not get the point of accuracy with a singe analogWrite in setup, except if you mean to prove that a signal is send at all
panadero:
The Arduino Uno has a 16 MHz quartz crystal. From a brief scan over various information sources in the web the usual deviation they have could already describe my results
This is all irrelevant for controlling a servo. The servo won't be calibrated anywhere near as precisely as an Arduino - it relies on a potentiometer to identify its position.
The Uno does not have a crystal, to my knowledge, but a ceramic resonator.
analogWrite controls a hardware timer. Once set, it will forever do the same thing (till you change it); no need to repeat in loop(). If you e.g. want a square wave of 490Hz with 50% duty cycle for the time that your application is running, just set it in setup().
I think that works out to 16,000,000 +/- 800 vs 16,000,000 +/- 16,000.
That's why the Atmega16U2 for the USB intertace uses a crystal vs a resonator as well, for accurate USB communications at speeds like 12 Mbps with USB2.