Teensy beginner here. I've been doing PWM with a Teensy 4.0 using the analogWriteFrequency() function and noticed that there are significant rounding errors when using frequencies that are not perfect divisors of the CPU clock speed. For example, at a 528 MHz clock speed on a Teensy 4.0 the following sketch sets a frequency of 40018 Hz on pin 2. However, I measure a frequency of 40012.1 Hz on pin 2 with a TDS 1002 oscilloscope.
When I set the frequency to perfect divisors of the 528 MHz clock speed (such as 52800, 20000, or 44000 Hz), I observe no difference between the measured and set frequency. Setting the frequency to any non-divisor results in a difference between measured and set frequency varying between around 0.5-5.0 Hz. The bug persists when I change PWM resolution.
I think this is related to a bug found in Teensy 3.6, see https://forum.pjrc.com/threads/23448-analogWriteFrequency-and-analogWrite-rounding
Any ways to work around or fix this bug? Am I making some mistake?
When I set the frequency to perfect divisors of the 528 MHz clock speed (such as 52800, 20000, or 44000 Hz), I observe no difference between the measured and set frequency. Setting the frequency to any non-divisor results in a difference between measured and set frequency varying between around 0.5-5.0 Hz. The bug persists when I change PWM resolution.
I think this is related to a bug found in Teensy 3.6, see https://forum.pjrc.com/threads/23448-analogWriteFrequency-and-analogWrite-rounding
Any ways to work around or fix this bug? Am I making some mistake?
Code:
// minimal example of frequency rounding errors in analogWriteFrequency(), for Teensy 4.0
// setting a frequency of 40018 Hz yields measured frequency of 40012.1 Hz at a CPU clock speed of 528 MHz
#define FREQUENCY 40018.
#define PIN 2
#define PWMRES 8 // PWM resolution 8 bits = 256 steps
#define PWMSTEPS 256 // to match PWMRES: there are 256 steps
// initialize a 50% duty cycle
const int amp = PWMSTEPS/2 - 1;
// set the frequency and amplitude
void setup(void) {
analogWriteRes(PWMRES); // write PWM resolution
analogWriteFrequency(PIN, FREQUENCY); // set the signal frequency
analogWrite(PIN, amp); // set PWM amplitude to 50% duty cycle
}
void loop(void) {
}