Getting the Pico to output an approximately 10 kHz clock on GPIO22 was extremely easy in microPython.
Vo = Pin(22,Pin.OUT) Vpmw = PWM(Vo) Vpmw.freq(int(10e3)) Vpmw.duty_u16(1<<15)
When I measured the output frequency I got 9999.234 Hz which is 77 PPM low in frequency. This was worse than what I was expecting.
The public BOM for the Pico lists the onboard crystal as:
Xtal, SMT, 3.2x2.5mm, 30ppm, 50R, Fundamental, 10p load, 12MHz
Unfortunately, uPython doesn't accept floating point frequency arguments. So I had to take a look at the PWM registers settings. GPIO22 uses PWM slice 3A:
Taking a look at the PWM 3 registers we see:
PWM3_CSR : 0000 0000 0000 0000 0000 0000 0000 0001 (1)
PWM3_DIV : 0000 0000 0000 0000 0000 0000 0001 0000 (16)
PWM3_CC : 0000 0000 0000 0000 0001 1000 0110 1010 (6250)
PWM3_TOP : 0000 0000 0000 0000 0011 0000 1101 0100 (12500)
And there is our problem in the PWM3_TOP register. From the RP2040 datasheet the effective PWM output frequency is the following:
If I subtract 1 from the TOP register for a value of 12499, then I get an output frequency of 10.000034 kHz (3.4 PPM high in frequency), close enough!
This is always the trouble with high level libraries - sooner or later they let you down and you need to understand all the registers they poke yourself.
Thanks for posting - this should save people a load of trouble.