Graeme Winter

Precision PWM

For testing wanted a reliable set of four signals across a set of GPIOs - potentially with different pacing though in this case not. Easy access to this by creating all the PWMs as usual then stop, reset counters, start again with a little register access. Purpose of exercise really to get to know new ‘scope.

Code

from machine import Pin, PWM, mem32

pwms = [PWM(Pin(j, Pin.OUT)) for j in (0, 2, 4, 6)]

PWM_BASE = 0x40050000

duty = [0x8000, 0x8000, 0x8000, 0x8000]

for d, p in zip(duty, pwms):
    p.freq(3125000)
    p.duty_u16(d)

# disable all
mem32[PWM_BASE | 0xA0] = 0x0

NN = mem32[PWM_BASE | 0x10] + 1

NN4 = NN // 4

print(NN, NN4)

# reset counters
mem32[PWM_BASE | 0x08] = 0x0
mem32[PWM_BASE | 0x1C] = NN4
mem32[PWM_BASE | 0x30] = 2 * NN4
mem32[PWM_BASE | 0x44] = 3 * NN4

# enable all
mem32[PWM_BASE | 0xA0] = 0xF

Result

Hooked up to new ‘scope, looks good (one rising, one falling, one mid-high, one mid-low)

Oscilloscope trace

Looked at the counter on this, records as 3.12504MHz so clocks differ by 13ppm between this pico and ‘scope.