-
Notifications
You must be signed in to change notification settings - Fork 503
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
analogWrite()
and Servo::attach()
conflict
#459
Comments
Goals
Thoughts on how to fix...
|
// Use fixed PWM2, TODO could conflict with other usage |
list of potentially impacted functions
From the Arduino API references, here's a list of functions that might be impacted by fixing this. file paths are all under
|
@hathach -- Before I start finalizing and starting any testing of fixes in this, I would like your review of the intended higher-level (architectural) design. In particular, I would appreciate your review of the proposed method to detect whether the PWM peripheral is already in use. A later review will be on the wrapper API that makes this simple, and will focus on ensuring a method to atomically acquire a peripheral (only if not already in use) is exposed. To summarize the problem, various abstraction layers in the BSP have code that use peripherals, even if those peripherals are already in use (e.g., by other abstraction layers, libraries, etc). For PWM, the abstraction layers can include Tone, analogWrite, etc. At a very high level, the way to fix this...
For PWM, the proposed definition of "in use" for a PWM peripheral:
The above concept can detect any use of the peripheral, whether by the BSP or a 3rd party library. It allows for smooth transition ... as more code checks before starting to use a peripheral, the system gets more robust ... while not requiring any 3rd party code do these checks. Thanks! |
Thank you very much Henry, unfortunately I am currently porting esp32s2 to my TinyUSB stack. Making progress but it stills takes time. Since esp32s2 port blocks others from Adafruit team to work on circuit python port, it takes the priority. Please be patient meanwhile. |
FYI, I've started a branch for this in my fork, to give you a sense of what the design I've mentioned would look like.
The design fixes many bugs, which although not likely seen in short "example" sketches, can bite in attempts to use the board in more complex designs. The first few commits show how |
Sorry for the delayed response, I really like your idea and code on your branch. yeah I am fully aware of the potential conflict of PWM peripherals. Neopixel also use PWM as well (But we can leave that off for now). But I am too lazy to fix it unless it becomes a real problems. Not many sketches mix uses them to the point of conflict so far. For this PR, we don't have to resolve everything. We can just ignore digitalRead()/write() them user should not use the pin that already used by other purpose.
If you don't mind, you could create an (draft) PR for this. It would be much easier to review code changes. I will also try to submit pr to your pr as well if needed. |
We may have to disagree on whether ignoring such calls is correct... I do not think that it is good, you think it's OK.
Yes, if by "occupied by the same group of function", you mean analogWrite() is separate from Servo(), and both are separate from Tone(), all of which are separate from other libraries.
I suppose HardwarePWM could keep an opaque
Yes!
Yes!
Yes! |
If you are willing to work on this, that would be great. However, please make it as a separate PR. Since this is really optional to me. There are many things that will go wrong with many of Arduino libraries if user don't call API in a certain way. We won't able to fix everything. I see no problems if there are no complains 😄
Yes, it is what I mean. I am not native English speaker, I have trouble expressing my thought all the time :D . |
There is code in CircuitPython to do cross-peripheral timer management: https://github.com/adafruit/circuitpython/blob/master/ports/nrf/peripherals/nrf/timers.c |
Describe the bug
analogWriteResolution(uint8_t res)
will cycle through the three (or four) PWM peripherals, and set each PWM peripheral's maximum value by callingPWM::setMaxValue()
to reflect this maximum resolution.analogWrite(uint32_t pin, uint32_t value)
adds the pin to the first unused PWM channel. It will cycle through the three (or four) PWM peripherals, each of which has four channels, until it finds a free channel.Servo::attach(int pin, int min, int max)
also adds the pin to the first unused PWM channel, and also cycles through the three (or four) PWM peripherals, each of which has four channels, until it finds a free channel. It then unconditionally calls bothPWM::setClockDiv(7)
andPWM::setMaxValue(2500)
(for 20ms / 50Hz freq) for the PWM peripheral that had the free channel.Set up (please complete the following information)
Discovered via code review while investigating #447.
Based on code review, it appears that a call to
analogWrite()
on a first pin, followed by a call toServo::attach()
on a second pin, will result in both pins being controlled by a single PWM peripheral. In addition, the call toServo::attach()
will disrupt the PWM output from the first pin, because the maximum value and clock divisor will be changed.Expected behavior
analogWrite()
andServo::attach()
do not interact with each other.The text was updated successfully, but these errors were encountered: