Skip to content

Make analogWrite(255) generate a PWM of 99.6% #4297

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
wants to merge 1 commit into from
Closed

Make analogWrite(255) generate a PWM of 99.6% #4297

wants to merge 1 commit into from

Conversation

cousteaulecommandant
Copy link
Contributor

Writing 255 on OCRxx generates a PWM of 99.6% (255/256). However, analogWrite(255) sets the pin permanently high, which is equivalent to a PWM of 100% (256/256), so there's a bigger step between analogWrite(254) and analogWrite(255) than any other analogWrite(x) and analogWrite(x+1).
This patch changes the range of analogWrite() from 0..255 to 0..256. Additionally, it makes out of range values (<0, >256) be treated always as a digital write rather than "overflowing" as they do now.

Writing 255 on OCRxx generates a PWM of 99.6% (255/256).  However, analogWrite(255) sets the pin permanently high, which is equivalent to a PWM of 100% (256/256), so there's a bigger step between analogWrite(254) and analogWrite(255) than any other analogWrite(x) and analogWrite(x+1).
This patch changes the range of analogWrite() from 0..255 to 0..256.  Additionally, it makes out of range values (<0, >256) be treated always as a digital write rather than "overflowing" as they do now.
@PaulStoffregen
Copy link
Contributor

FWIW, this is how Teensy 3.x implements analogWrite. It's been well received and hasn't ever been reported as causing a problem.

@NicoHood
Copy link
Contributor

I also think you are wrong. 0-255 are 256 steps, 8bit. So 255 is the maximum.

@PaulStoffregen However you could consider to add the >= and <= which makes sense to me.

@cousteaulecommandant
Copy link
Contributor Author

@NicoHood I'm reading https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM and it seems that you may be right IF the timers work on "phase correct mode". If they work in "fast PWM mode" then the range of duty cycles goes from 1/256 (for OCRxx=0) to 256/256 (for OCRxx=255); i.e. the "extra step" that is missing would be at 0, not 255 as I thought (unless that tutorial is wrong).
It seems that pins 5 and 6 work in fast mode and 3,9,10,11 in phase correct mode, so they have different PWM value ranges, making this more complicated than I thought.

@cousteaulecommandant
Copy link
Contributor Author

Confirmed; pins 5 and 6 behave differently from 9,10,11,3. analogWrite(6,256) produces an intermediate value between analogWrite(6,0) (totally off) and analogWrite(6,1) (on for 2/256 of a cycle), because pins 5 and 6 work on fast PWM mode rather than phase corrected mode. However, analogWrite(9,256) just turns off the pin just as analogWrite(9,0) does.

Is there a reason for this behavior? Personally I see no point on using phase corrected PWM for everyday applications, and although having a PWM value range from 0 to 255 makes more sense than 0 to 256 it's weird to have each pin have a different behavior.

I'm closing this PR since it doesn't offer a correct solution for all the pins (actually, any of the pins; although I was close for 5 and 6). But it'd be nice if there could be a unified PWM behavior for all the timers.

@ffissore ffissore added this to the Release 1.6.7 milestone Dec 14, 2015
@cousteaulecommandant
Copy link
Contributor Author

(Nevertheless I agree that adding the >= <= would be a good idea; it doesn't add more overhead than the current ==s do)

@NicoHood
Copy link
Contributor

Go ahead and open another PR.
In general I'd rather use uint8_t anyways as input.

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

Successfully merging this pull request may close these issues.

4 participants