Thanks to visit codestin.com
Credit goes to github.com

Skip to content

pulseio.PWMOut() instantiation fails sometimes with constant same frequencies on CPX #1626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kevinjwalters opened this issue Mar 9, 2019 · 13 comments · Fixed by #1641
Closed

Comments

@kevinjwalters
Copy link

I'm seeing some rather non-deterministic behavior with creation of pulseio.PWMOut(). I've been discussing how to get the most PWM outputs on a Circuit Playground Express: https://forums.adafruit.com/viewtopic.php?f=60&t=148017. I can sometimes get four by using the same frequency and variable_frequency=False but not always! Example below is a variant of 4.0.0 beta 2 with no code.py/main.py and after a power off/on to rule out any accumulated-weirdness(tm):

Adafruit CircuitPython 4.0.0-beta.2-141-g2c9fbb5d4-dirty on 2019-02-28; Adafruit                                CircuitPlayground Express with samd21g18
>>> import board, pulseio
>>> p3 = pulseio.PWMOut(board.A3, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>>
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.



Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-beta.2-141-g2c9fbb5d4-dirty on 2019-02-28; Adafruit CircuitPlayground Express with samd21g18
>>> import board, pulseio
>>> p3 = pulseio.PWMOut(board.A3, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>>
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.



Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-beta.2-141-g2c9fbb5d4-dirty on 2019-02-28; Adafruit CircuitPlayground Express with samd21g18
>>> import board, pulseio
>>> p2 = pulseio.PWMOut(board.A2, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
>>> p3 = pulseio.PWMOut(board.A3, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: All timers in use
>>> p3 = pulseio.PWMOut(board.A3, duty_cycle=2**15, frequency=2*1000*1000, variable_frequency=False)

Note in that last attempt where a "retry" surprisingly works, the order is reversed for p2 & p3 instantiation. Although in general, I've had more success with p3 first then p2.

I'd welcome a workaround too if this can't be fixed in 4.0.0. Perhaps I could code it up so it makes p2, then tries p3 ten times and if that doesn't work then then cleans up, makes p3 then tries p2 ten times?

@kevinjwalters
Copy link
Author

For what it's worth I tried it on 4.0.0-beta.3 and same fault occurs there.

I've written some python code that now tries to initialise them with retries and then reverses order. My current implementation doesn't seem to be that useful as a workaround. Control-C/Control-D for a soft reset will eventually work but it often takes ten attempts :(

@dhalbert
Copy link
Collaborator

Try this uf2. I made one minor change to wait for a reset of a TCC before proceeding. But I don't see anything else wrong, like uninitialized variables.
cpx-tcc-wait-2019-03-11.uf2.zip

@dhalbert
Copy link
Collaborator

Also, if that doesn't fix things, I'd be interested to know if you see any difference when using a lower frequency (like 2000 instead of 2000000)

@kevinjwalters
Copy link
Author

4.0.0-beta.3-4-g186e31591-dirty doesn't appear to make any difference, I still get initialisation errors. I'll have a play with frequency later. For lower frequency should l I use 4.0.0 beta 3 or 4.0.0-beta.3-4-g186e31591-dirty?

@dhalbert
Copy link
Collaborator

The uf2 I gave you fixes something that's probably inconsequential, but I would keep that change anyway, so test against that.

Have you looked at the pins.c file for CPX to get the actual PA/PBxx pin numbers? Then you can look up which TC's or TCC's are available for each PAxx or PBxx.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 12, 2019

From some brief testing, 2kHz seems like similar behaviour with many failures using 4.0.0-beta.3-4-g186e31591-dirty.

I can't see a clear pattern yet, maybe a power off makes it more likely to initialise ok but it's not on the first execution of code.py as one might expect. The second attempt (i.e. power off/on, auto-execute code.py, soft reset post exception, second code.py execution) seems pretty successful though.

I've not yet fully grasped the whole TC/TCC sharing thing. I got excited when @tannewt suggested something which then worked (some of the time) and have focussed on the application coding since that.

@dhalbert
Copy link
Collaborator

dhalbert commented Mar 13, 2019

OK, it was an arg processing bug. Even though you said variable_frequency=False, it was taking it as True nearly all the time, which made it use only TCC's. Try this:
cpx-pwmout-arg-fix-2019-04-12.uf2.zip

@kevinjwalters
Copy link
Author

I've just tested that latest version, 4.0.0-beta.3-25-g2169a6240-dirty, and it worked first time and has worked for nine soft reboot (Control-C / Control-D). Previous versions had roughly a 9/10 failure rate. Looks good.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 13, 2019

I just using 4.0.0-beta.3-25-g2169a6240-dirty for a few minutes and then left it. When I came back and tried to connect to the serial (over USB) it didn't work. The drive (on Windows) was no longer showing up with the typical spaced used but just marked as FAT and opening it in explorer showed it as empty. It responded to reset button but that's left me with an CIRCUITPY drive that's missing my code! I've only got some wavs, a README, .fseventsd and .Trashes. I did a power cycle and file system still looks the same, no sign of my code.py etc.

I think we can rule out user error here because the whole lib directory has gone AWOL and that takes ages to delete so I would have noticed if I'd done this accidentally.

If this is a bug it's a nasty one especially for anyone who only saves code to the device.

Is there anyway the file system can be auto reinitialised to this state?

@kevinjwalters
Copy link
Author

It's getting weirder, the wavs have disappeared and a .metadata_never_index has appeared. Minor chance this is related to Patch Tuesday but that's even more frightening.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 13, 2019

My boot_out currently has the contents:

Adafruit CircuitPython 4.0.0-beta.3-25-g2169a6240-dirty on 2019-03-12; Adafruit CircuitPlayground Express with samd21g18

but earlier it had a large hex number with some hypens with braces on either end.

I've also noted that if i leave the CPX doing not much in REPL (I had a for loop printing the time every 10 seconds) then if I control-c that ten minute later then control-D for a soft reset the soft reset doesn't complete.

@kevinjwalters
Copy link
Author

kevinjwalters commented Mar 13, 2019

I've decided to go back to 4.0.0 beta 3 to see if that's stable. I put that on and this popped out when I connected to serial console afterwards:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

You are running in safe mode which means something unanticipated happened.
Looks like our core CircuitPython code crashed hard. Whoops!
Please file an issue at https://github.com/adafruit/circuitpython/issues
 with the contents of your CIRCUITPY drive and this message:
Crash into the HardFault_Handler.

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-beta.3 on 2019-03-07; Adafruit CircuitPlayground Express with samd21g18
>>>

boot_out currently contains:

Adafruit CircuitPython 4.0.0-beta.3-25-g2169a6240-dirty on 2019-03-12; Adafruit CircuitPlayground Express with samd21g18

and has a date of 1-Jan-2000 which is a bit odd (date may not be off, these things dont have battery backed clocks on them, of course). I'm going to storage.erase_filesystem() to ensure I've got a clean slate.

@kevinjwalters
Copy link
Author

4.0.0 beta 5 looks good, btw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants