donkeycar
donkeycar copied to clipboard
PCA9685 calibration needed
Note this is different from calibrate the steering and throttle of the build. This issue is about the calibration of the actual signal of the PCA9685 output.
Current PCA9685 board has numerous manufacturer now, Adafruit (https://www.adafruit.com/product/815), Seeed(https://wiki.seeedstudio.com/Grove-16-Channel_PWM_Driver-PCA9685/), Waveshare(https://www.waveshare.com/servo-driver-hat.htm) and Aliexpress clones for example. Different manufacturer has different errors introduced by many factors during design/manufacturing. One of the results is the output PWM frequency isn't accurate, sometimes far from acceptable, if you test it with an oscilloscope.
Here's what found comparing steering signal output by a 50Hz RC receiver, and a signal produced by an PCA9685 variant(https://www.waveshare.com/Servo-Driver-HAT-B.htm)
RC receiver signal neutral(1500us):
RC receiver signal leftmost(1000us):
RC receiver signal rightmost(2000us):
The math goes like this: It's a receiver produce 50Hz signals, so a full duty cycle is 1/50 = 0.02s = 20ms = 20000us. A traditional leftmost, neutral, rightmost signal width would be 1.0ms(1000us), 1.5ms(1500us) and 2.0ms(2000us) respectively.
As seen from the result, they were nearly perfect for a $10 receiver. It almost align with the 1000-1500-2000us time. However for the PCA9685 without calibration:
PCA9685 signal neutral:
PCA9685 signal leftmost:
PCA9685 signal rightmost:
So the uncalibrated PCA9685 neutral signal was around 1300us, leftmost was around 900us, rightmost was around 1850us, which are far from acceptable IMO. Even the captured frequency is 5Hz off from the 50Hz one. BTW I measured those values using donkey calibrate
command and convert the pwm width to the integer value PCA9685 library accepts. That is, 307(from 1500/2000 * 4096), 205(from 1000/20000 * 4096), and 410(from 2000/20000 * 4096), with pwmFreq
set to 50.
This is also documented in Adafruit's CircuitPython PCA9685 documents(https://circuitpython.readthedocs.io/projects/pca9685/en/latest/api.html#adafruit_pca9685.PCA9685):
The internal reference clock is 25mhz but may vary slightly with environmental conditions and manufacturing variances. Providing a more precise reference_clock_speed can improve the accuracy of the frequency and duty_cycle computations. See the calibration.py example for how to derive this value by measuring the resulting pulse widths.
The difference in PWM frequency might not seems to be a problem if you calibrate the steering and throttling pwm values and stick with it. However, if you're switching to another PCA9685 board, or using a RC controller + Arduino signal translator to train the car then you'll instantly find the steering and throttling are wrong. Maybe it's time to switch over CircuitPython's PCA9685 library.