# Example of using PIO for PWM, and fading the brightness of an LED
from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
from time import sleep
import random
@asm_pio(sideset_init=PIO.OUT_LOW)
def pwm_prog():
pull(noblock) .side(0)
mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock
mov(y, isr) # ISR must be preloaded with PWM count max
label("pwmloop")
jmp(x_not_y, "skip")
nop() .side(1)
label("skip")
jmp(y_dec, "pwmloop")
class PIOPWM:
def __init__(self, sm_id, pin, max_count, count_freq):
self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin))
# Use exec() to load max count into ISR
self._sm.put(max_count)
self._sm.exec("pull()")
self._sm.exec("mov(isr, osr)")
self._sm.active(1)
self._max_count = max_count
def set(self, value):
# Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse
value = max(value, -1)
value = min(value, self._max_count)
self._sm.put(value)
# Pin 25 on Pico boards
pwm = PIOPWM(0, 7, max_count=(1 << 16) - 1, count_freq=10_000_000)
pwm2 = PIOPWM(1, 8, max_count=(1 << 16) - 1, count_freq=10_000_000)
pwm3 = PIOPWM(2, 9, max_count=(1 << 16) - 1, count_freq=10_000_000)
while True:
r=random.randrange(255)**2
g=random.randrange(255)**2
b=random.randrange(255)**2
pwm.set(r)
pwm2.set(g)
pwm3.set(b)
sleep(0.001)