micropython / micropython

MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems
https://micropython.org
Other
19.06k stars 7.63k forks source link

Pico PWM bug: PWM.deinit() does not reset pin FUNCSEL #9007

Open rkompass opened 2 years ago

rkompass commented 2 years ago

The title tells the problem and the following code illustrates it.

from machine import Pin, PWM, mem32
from array import array
from time import sleep

def pin_func(pin):    # report OEOVER, OUTOVER, FUNCSEL  for the pin on RPi 2040
    func = {1: 'SPI', 2: 'UART', 3: 'I2C', 4:'PWM', 5:'SIO', 6:'PIO0', 7:'PIO1', 9:'USB'}
    oeover = {0:'OE<-func', 1:'OE<-~func', 2:'OUT disabl', 3:'OUT enable'}           # descriptions
    outover = {0:'OUT<-func', 1:'OUT<-~func', 2:'OUT low', 3:'OUT high'}
    baddr=bytes(array('O', [pin]))
    pin = mem32[int.from_bytes(baddr, 'little')+4]                                   # pin number
    ctrl = mem32[0x40014004 + 0x08*pin]                                              # GPIOpin_CTRL
    return oeover[ctrl>>12 & 0b11], outover[ctrl>>8 & 0b11], func[ctrl & 0b11111]    # extract relevant bits from CTRL

pin9 = Pin(9, Pin.IN)
print(pin_func(pin9))    #  ('OE<-func', 'OUT<-func', 'SIO')

pwm0 = PWM(pin9)                                   # create PWM object from a pin
pwm0.freq(1000)                                    # set frequency
pwm0.duty_u16(30_000)                              # set duty cycle, range 0-65535
sleep(1)
pwm0.deinit()                                      # turn off PWM on the pin
print(pin_func(pin9))    #  ('OE<-func', 'OUT<-func', 'PWM')  # !!!! pwm isn't turned off  !!!!

sleep(1)
Pin(9, Pin.IN)                                     # <-  this turns PWM off
print(pin_func(pin9))    #  ('OE<-func', 'OUT<-func', 'SIO')  
rkompass commented 2 years ago

Perhaps I should add that a LED at pin 9 started to shine with half intensity, and it continued to be on even after pwm0.deinit. That's how I noted the problem.

JoelGodin commented 2 years ago

Same issue here. I can [pin].deinit() but still control the duty cycle of that pin. PWM is still initialized.

gitsmol commented 1 year ago

Can confirm this issue is present on ESP32. I'm connecting a number of buzzers to the board and notice that sounding one of them sounds all of them after they have been initialized. Deinitializing does not prevent this. Pin(X, Pin.IN) does.