0

Pulsewidth signal deinit doesn't completely deinit
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Pulsewidth signal deinit doesn't completely deinit

by RetireeJay on Thu May 14, 2020 3:23 pm

I'm using a Metro Express M0 board with CircuitPython 5.2.0. I have built my own LED driver "shield" that simply buffers digital outputs from the M0. I am trying to write a CircuitPython program that will create a "walking" sequence of up to 5 LED's, i.e. one LED turns on then off; when the first one turns off the second one turns on, and so on. I also want to be able to vary the frequency. So in order to guarantee correct timing from LED 1 to LED 2 to LED 3, etc. my concept is to completely de-initialize all Pulsewidth outputs before changing the frequency, and then setting up the Pulsewidth outputs all over again at the new frequency.
The demo program here, when run, shows what happens (with only 3 LED's). It successfully starts up (Trial 1), and it successfully changes frequency one time, but when it starts to run the next round (Trial 3) it crashes saying that "All timers are in use". I expected that the carefully programmed "deinit" function calls should have released all timers for re-use, but that's not happening - even though the program reports successful deinit every time.

Code: Select all | TOGGLE FULL SIZE
import time
import pulseio
import random

# ############################################################
#
# INITIALIZATION
#
# ############################################################

# Define a list of Pulsewidth IO Pins available for use.
PWpins = (board.D7, board.D8, board.D9, board.D10, board.D11,
          board.D12)

# Create an empty list for PWM channels, then populate 0-2 with the PWpins
# Defining it outside of a function makes it global so that it
# can be used across and inside functions
PWMChans = []
for i in range(3):
    PWMChans.append(PWpins[i])

# Create a list for PWM Output "signals"
PWMOuts = []
for i in range(3):
    PWMOuts.append(i)
# How many LEDs will be used
# NOTE: changes will be read from binary switch, to be implemented
# the value of 0 is a guarantee to have it reset
NoLEDs = 3

# ###########################################################
#
# FUNCTIONS
#
# ###########################################################

# Function to clear all PWMchannels in use (0 - 2) from PWM definitions
# thus preparing them for new assignments.
def PWMClearAll():
    for i in range(3):
        print("Clearing " + str(i))
        PWMOuts[i].deinit()
        print("PWMOuts[" + str(i) + "] deinited OK")
        time.sleep(1/CurFreq)  # Let each channel fully clear
# so that when re-started the pulses will be properly timed with respect
# to each other

# ###################################################################
# Function to assign pulse width modulation to an arbitrary pin,
# arbitrary duty cycle, and arbitrary frequency.
# CAUTION:  This routine assumes the pin is clear (not assigned)
def PWMAssign(pinno, d_c, freq):
    print("Attempting to assign " + str(pinno))
    PWMCh = pulseio.PWMOut(PWMChans[pinno], duty_cycle=d_c,
                           frequency=freq)
    return PWMCh

# ###################################################################
# Function to set up channels by frequency and number of channels (NoLEDs)
# NOTE:  The intent is to pulse one LED at a time in sequence
def SetupChannels():
    # print("SetupChannels was called")
    if Trial > 1:
        void = PWMClearAll()
    PulsW = int(0xFFFF / NoLEDs)

    for i in range(NoLEDs):
        # print("for loop i = " + str(i))
        PWMOuts[i] = PWMAssign(i, PulsW, CurFreq)
        time.sleep((1/CurFreq)/NoLEDs)

        print("PWMOuts[" + str(i) + "] frequency: "
              + str(PWMOuts[i].frequency))


# ###########################################################
#
# MAIN LOOP
#
# ###########################################################
Trial = 1
while True:
    print("Trial " + str(Trial))
    CurFreq = int(10 + 50 * random.random())
    SetupChannels()
    Trial += 1
    time.sleep(1)

RetireeJay
 
Posts: 1
Joined: Thu May 14, 2020 3:07 pm

Re: Pulsewidth signal deinit doesn't completely deinit

by tannewt on Thu May 14, 2020 4:30 pm

This sounds like a bug! Would you mind filing an issue here for it? https://github.com/adafruit/circuitpython/issues/new

tannewt
 
Posts: 1639
Joined: Thu Oct 06, 2016 8:48 pm

Please be positive and constructive with your questions and comments.