Skip to content
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

RP2040 PWMIO module throws All timers for this pin are in use when defining two or more pins #4143

Closed
jposada202020 opened this issue Feb 6, 2021 · 24 comments
Labels
bug rp2040 Raspberry Pi RP2040
Milestone

Comments

@jposada202020
Copy link

When using the following code, I am getting the error that all the timers are used for pinblue(GP19)

import pwmio
import board


pinred = pwmio.PWMOut(board.GP17, frequency=5000, duty_cycle=0)
pingreen = pwmio.PWMOut(board.GP18, frequency=5000, duty_cycle=0)
pinblue = pwmio.PWMOut(board.GP19, frequency=5000, duty_cycle=0)

code.py output:
Traceback (most recent call last):
File "code.py", line 7, in
ValueError: All timers for this pin are in use

On the REPL this was reproduced

Adafruit CircuitPython 6.2.0-beta.1 on 2021-01-27; Raspberry Pi Pico with rp2040

import pwmio
import board
pinred = pwmio.PWMOut(board.GP17, frequency=5000, duty_cycle=0)
pingreen = pwmio.PWMOut(board.GP18, frequency=5000, duty_cycle=0)
pinblue = pwmio.PWMOut(board.GP19, frequency=5000, duty_cycle=0)
Traceback (most recent call last):
File "", line 1, in
ValueError: All timers for this pin are in use

Inversing the order of the pin definition will throw the same error, so I am assuming this is related with the pwmio definitions
Adafruit CircuitPython 6.2.0-beta.1 on 2021-01-27; Raspberry Pi Pico with rp2040

import pwmio
import board
pinred = pwmio.PWMOut(board.GP17, frequency=5000, duty_cycle=0)
pinblue = pwmio.PWMOut(board.GP19, frequency=5000, duty_cycle=0)
pingreen = pwmio.PWMOut(board.GP18, frequency=5000, duty_cycle=0)
Traceback (most recent call last):
File "", line 1, in
ValueError: All timers for this pin are in use

This code will pass

import pwmio
import board
ping1 = pwmio.PWMOut(board.GP21, frequency=700)
ping2 = pwmio.PWMOut(board.GP22, frequency=5000)
ping4 = pwmio.PWMOut(board.GP11, frequency=400)
ping5 = pwmio.PWMOut(board.GP16, frequency=400)

this will fail

import pwmio
import board
ping1 = pwmio.PWMOut(board.GP21, frequency=700)
ping2 = pwmio.PWMOut(board.GP22, frequency=5000)
ping4 = pwmio.PWMOut(board.GP11, frequency=400)
ping5 = pwmio.PWMOut(board.GP16, frequency=400)
ping6 = pwmio.PWMOut(board.GP5, frequency=400)

I am wondering if when the mask is defined, in the code, we are missing something. I cannot test that part of the code. However, if you select any pins in the same (8 2 Channel Slice) the code will fail. If we take the table 526 in the RP2040 datasheet, we could predict more or less which pins will fail. For example, for PIN 2, associated pins in the (8 2 Channel) will be 3, 8 and 9 and if we try in the following code all will have the same error.

import pwmio
import board
ping1 = pwmio.PWMOut(board.GP2, frequency=550)
ping2 = pwmio.PWMOut(board.GP19, frequency=550) 

So I am not sure if this is related with the mask or the slice definition

@tannewt tannewt added bug rp2040 Raspberry Pi RP2040 labels Feb 9, 2021
@tannewt tannewt added this to the 6.2.0 milestone Feb 9, 2021
@tannewt
Copy link
Member

tannewt commented Feb 9, 2021

@DavePutz Do you want to take a look at this and find my bug?

@timonsku
Copy link

timonsku commented Feb 9, 2021

hitting the same issue when using just two pwm's (16, 17)

@DavePutz
Copy link
Collaborator

DavePutz commented Feb 9, 2021

@tannewt - I'll take a look at it.

@tannewt
Copy link
Member

tannewt commented Feb 9, 2021

Thanks @DavePutz!

@DavePutz
Copy link
Collaborator

DavePutz commented Feb 9, 2021

@tannewt - We are currently checking whether a PWM channel is in use and throwing an error if it is. That is why the reported error it hit when GPIOs 21 and 5 are both used - they share channel 2B. However, the datasheet says "The same PWM output can be selected on two GPIO pins; the same signal will appear on each GPIO.". So, should we just take out the check for channel re-use?

@tannewt
Copy link
Member

tannewt commented Feb 9, 2021

@DavePutz No, lets not allow outputting the same channel to multiple pins because the api implies their duty cycle would be independent.

@DavePutz
Copy link
Collaborator

DavePutz commented Feb 9, 2021

@tannewt - Ok, I'll submit a PR for another issue causing the error (we throw the same error for 4 different conditions :-( and leave the channel check in.

@jedgarpark
Copy link

jedgarpark commented Feb 10, 2021

Finding this issue here just saved me a lot of heartache :) I didn't pay attention to the "two pins per PWM channel" thing until seeing this.

@timonsku
Copy link

oh so this is fixed? I thought the PWM channels could be freely mapped. Where did you find that table with the channel pairs?

@jfurcean
Copy link

Table 526 on page 536 of the data sheet. Also in Table 290 on page 252.

@tannewt
Copy link
Member

tannewt commented Feb 10, 2021

This was fixed by #4165

@tannewt tannewt closed this as completed Feb 10, 2021
@Bhavithiran97
Copy link

I am still getting "ValueError: All timers for this pin are in use" when using GP18 and GP19 as PWMOut.

@DavePutz
Copy link
Collaborator

DavePutz commented Feb 11, 2021 via email

@Bhavithiran97
Copy link

What do you mean by patch in ?

@d-c-d
Copy link

d-c-d commented Feb 11, 2021 via email

@dhalbert
Copy link
Collaborator

dhalbert commented Feb 11, 2021

Did you test again with 6.2.0-beta.2? It incorporates the #4165 fix.

[edit: typo: 6.1.0 -> 6.2.0]

@Bhavithiran97
Copy link

Bhavithiran97 commented Feb 15, 2021

import pwmio
import board
ping1 = pwmio.PWMOut(board.GP18, variable_frequency=True)
ping2 = pwmio.PWMOut(board.GP19, variable_frequency=True)

Getting "ValueError: All timers for this pin are in use".

I want to change the frequency in a function, both GP18 and GP19 to same frequency. How can I do that ?

@timonsku
Copy link

@Bhavithiran97 you can't, check out the table here: #4143 (comment)
Some pins are paired. While you can adjust the duty cycle you can not adjust the frequency. If you need a different frequency on each pin you need to choose a different set of pins that don't share their PWM bank.
What this patch fixes is that you can still use them both but not if you construct them both with variable_frequency=True as you can not change their frequency independently in this configuration. If you were to use GP20 instead of GP19 f.e. this would work again.

@tannewt
Copy link
Member

tannewt commented Feb 16, 2021

I want to change the frequency in a function, both GP18 and GP19 to same frequency. How can I do that ?

The CircuitPython API doesn't allow for two PWM outputs to share a variable frequency. Instead, variable frequency requires separate underlying hardware. On the RP2040 that means separate PWM slices.

@Bhavithiran97
Copy link

import machine
import utime


C4  = 262
D4  = 294
E4  = 330

tone = [C4,D4,E4]

audio_left = machine.PWM(machine.Pin(18))
audio_right = machine.PWM(machine.Pin(19))

for i in tone:
    audio_left.freq(i)
    audio_right.freq(i)
    audio_left.duty_u16(19660)
    audio_right.duty_u16(19600) #30%
    utime.sleep(0.15)
    audio_left.duty_u16(0)
    audio_right.duty_u16(0)

I can change both frequecy for GP18 and GP19 in MicroPython. I can't do it in CircuitPython ?

@tannewt
Copy link
Member

tannewt commented Feb 18, 2021

I can change both frequecy for GP18 and GP19 in MicroPython. I can't do it in CircuitPython ?

No. frequency is dictated by the TOP value and clock divider which are shared for the two channels output from a PWM slice. CircuitPython prevents you from changing these values from a single output because it could lead to unexpectedly changing the frequency of the other channel. MicroPython doesn't check this for you. Therefore, in CircuitPython you need to use pins with separate slices for each output.

(For audio playback check out audiopwmio that is in the "absolute latest" builds currently.)

jepler pushed a commit to jepler/circuitpython that referenced this issue Aug 27, 2021
@sdelabs
Copy link

sdelabs commented Jan 18, 2024

Running Circuitpython 8.2.9 on Itsybitsy M4:

This code:
import board, pwmio
M1A = pwmio.PWMOut(board.D13, frequency=1000)
M1B = pwmio.PWMOut(board.D10, frequency=1000)
M2A = pwmio.PWMOut(board.D4, frequency=1000)
M2B = pwmio.PWMOut(board.D7, frequency=1000)
Throws the error:
ValueError: All timers for this pin are in use

While this code:
M2A = pwmio.PWMOut(board.D4, frequency=1000)
M2B = pwmio.PWMOut(board.D7, frequency=1000)
M1A = pwmio.PWMOut(board.D13, frequency=1000)
M1B = pwmio.PWMOut(board.D10, frequency=1000)

Does not: using the same pins, same configuration, only the order of assignment is different.

@tannewt
Copy link
Member

tannewt commented Jan 18, 2024

Running Circuitpython 8.2.9 on Itsybitsy M4:

Please file a new issue. This issue is about the RP2040. Not the SAMD51 "M4".

@dhalbert
Copy link
Collaborator

New issue created: #8811.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug rp2040 Raspberry Pi RP2040
Projects
None yet
Development

No branches or pull requests

10 participants