0

after first two PWMOuts, "RuntimeError: All timers in use"
Moderators: adafruit_support_bill, adafruit

Forum rules
Adafruit MicroPython is currently EXPERIMENTAL and BETA - Please visit https://learn.adafruit.com/category/micropython and http://forum.micropython.org/ in addition to our section here!
Please be positive and constructive with your questions and comments.

after first two PWMOuts, "RuntimeError: All timers in use"

by ericwertz on Thu Nov 30, 2017 2:25 am

I've got an regular RGB LED that I'd like to color blend with PWM on each of the three channels on a MetroM0Express. However, when I try to construct the third pulseio.PWMOut, I'm getting "RuntimeError: All timers in use". I'm taking the constructor defaults.

The code seems have two timers available, but technically I only need one timebase for all of my LED PWMs. It also seems to suggest that one should only run out of timers if more than two unique ones are needed, so it may be the case that the timer piggybacking checks may not be working.

The other problem is that I don't see the documentation mentioning that no more than two unique timers are available on the D21. So, I can't tell if this is just a short-term or a longer-term limitation.

Example:
Code: Select all | TOGGLE FULL SIZE
import pulseio
import board

pwm11 = pulseio.PWMOut(board.D11)
pwm9  = pulseio.PWMOut(board.D9)
#pwm6  = pulseio.PWMOut(board.D6)  # uncomment for error


Has anyone had any success getting more than two PWMOuts allocated at the same time?

++tkx,
-e

ericwertz
 
Posts: 42
Joined: Sun Jun 01, 2008 4:18 am

Re: after first two PWMOuts, "RuntimeError: All timers in us

by tannewt2 on Thu Nov 30, 2017 3:44 am

D9 and D6 share the same wave out on TCC0. D9 also has TCC2 but its picking TCC0 because you initialize it first. Try swapping the D9 and D6 inits.

tannewt2
 
Posts: 429
Joined: Thu Oct 06, 2016 8:48 pm

Re: after first two PWMOuts, "RuntimeError: All timers in us

by ericwertz on Thu Nov 30, 2017 10:02 pm

It turns out starting by allocating 9 and 6 first, then 11, works.
Since I ultimately really needed PWMs on 11, 9, 6 and 3, what works is 6 & 9, then 11 & 3.

Alas, not sure how to document heuristics like this for the target audience -- it'll be interesting :(

Thanks for the guidance!

ericwertz
 
Posts: 42
Joined: Sun Jun 01, 2008 4:18 am

Re: after first two PWMOuts, "RuntimeError: All timers in us

by tannewt2 on Fri Dec 01, 2017 2:58 pm

Yeah, I was thinking about that too. We may need a class that can manage multiple PWM channels. Worse case it could try all orderings. :-/

tannewt2
 
Posts: 429
Joined: Thu Oct 06, 2016 8:48 pm

Re: after first two PWMOuts, "RuntimeError: All timers in us

by ericwertz on Sun Dec 03, 2017 4:33 pm

Upon further thought, I'm unsure why an arbitrary ordering shouldn't work. Since all I want is 3-4 PWM channels with the same characteristics, even if it were to initially allocate the first two as one from each timer, I don't know why the third channel request doesn't match either of the existing ones. By the same token, I'm unsure why the second one allocated doesn't match the first one.

Note that I'm assuming that there are only two output channels per timer in this scenario, which is as it is on the ATmega (or those that I've used) in these cases, and which may or may not be the case with the SAMD2x.

It still doesn't make sense to me why the matching didn't occur correctly in the first place. Still seems like the scanning-matching process isn't working the way it could/should, no?

I'm also thinking about whether or not a (somewhat jittery) low-resolution software PWM output mechanism could also be feasible, perhaps even just as a user library/object. Kind of a "soft PWM" using a Timer-type object that had a high enough frequency (like maybe 8-bit resolution @100Hz, aka 25.6KHz) to run through a list of outputs to toggle at different duty-cycles. This would be a viable alternative to somewhat jitter-tolerant clients like LEDs (and *possibly* servos) that required a lot of output channels and maybe little work to do in their main loops.

ericwertz
 
Posts: 42
Joined: Sun Jun 01, 2008 4:18 am

Re: after first two PWMOuts, "RuntimeError: All timers in us

by tannewt2 on Wed Dec 06, 2017 10:59 pm

I'm not sure we'd need software PWM because most pins are covered by timers.

SAMD21 timers have an additional concept of Wave Outs which are outputs derived (potentially inverted) from a capture compare channel. So, the fanciest timer TCC0 has 4 capture compare channels and 8 wave outs. With your example you not only hit on the shared timers case (which is fine for PWM because its all derived from the same frequency) but also matching capture compare channels.

D9 and D6 share a capture compare channel on D6. It works with the order swapped because D9 has both TCC0 and TCC2 to choose from but D6 only has TCC0. So, if you init with D9 first the naive code picks TCC0 thus blocking D6. Swapping it lets D6 pick TCC0 and then D9 can pick TCC2.

So, we can't do anything with individual allocations because that would mean swapping the underlying timer of D9 to TCC2 dynamically. Knowing all outputs at once though would let us be smarter about it.

I hope that helps explain it better. The datasheet for the SAMD21 is worth a read too if you are curious to learn more about its timers.

tannewt2
 
Posts: 429
Joined: Thu Oct 06, 2016 8:48 pm

Please be positive and constructive with your questions and comments.