Skip to content

Soft pwm enhancement #6015

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

Conversation

StefanBruens
Copy link
Contributor

@StefanBruens StefanBruens commented Mar 12, 2017

Includes fix for #6003: For low duty cyles, the actual duty cycle is larger than wanted

Supersedes #5997
Dithering allows to mitigate the resolution loss caused by the scaling.

A 128 step PWM has 127 intervals (0/127 ... 127/127 duty). Currently, a
PWM setting of 1/127 is active for 2/128, i.e. double the expected time,
or, in general n+1/128 instead of n/127.
Fixes issue#6003.

Signed-off-by: Stefan Brüns <[email protected]>
@StefanBruens StefanBruens force-pushed the SOFT_PWM_enhancement branch from 90d12ba to 676ab2c Compare March 12, 2017 21:15
@oysteinkrog
Copy link
Contributor

Does the dithering add any performance overhead?

@StefanBruens
Copy link
Contributor Author

The performance overhead is very low - AFAICT it adds one machine instruction per PWM channel on each timer interrupt (1kHz).

@StefanBruens
Copy link
Contributor Author

Small correction, it is three instructions, but of course only run once every PWM cycle, i.e. 16 times a second for SCALE 1.
I have another patch which reduces code size/instruction count on every isr invocation.

@StefanBruens
Copy link
Contributor Author

Device: atmega1284p, TinyBoy2 (using U8glib)

FW size without SR applied:

  text    data     bss     dec     hex filename
115554     632    4223  120409   1d659 applet/Marlin.elf

With SR:

  text    data     bss     dec     hex filename
115556     632    4223  120411   1d65b applet/Marlin.elf

const uint8_t pwm_mask = _BV(SOFT_PWM_SCALE) - 1;
#else
const uint8_t pwm_mask = 0;
#endif
Copy link
Member

@thinkyhead thinkyhead Mar 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The const lines should be indented. This is also good:

const uint8_t pwm_mask = 0
  #if ENABLED(SOFT_PWM_DITHER)
    + _BV(SOFT_PWM_SCALE) - 1
  #endif
;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indented the declaration, fixed the commit subject (s/is/if)

If dithering is enabled, the remainder of the soft_pwm_X duty value at
turnoff time is added to the next cycle. If e.g. the duty is set to 9 and
SCALE is set to 2, the PWM will be active for 8 counts for 3 cycles and
12 counts on each fourth cycle, i.e. the average is 9 cycles.

This compensates the resolution loss at higher scales and allows running
fans with SOFT_PWM with significantly reduced noise.

Signed-off-by: Stefan Brüns <[email protected]>
The compiler is not able to reuse the value of pwm_count, but reloads it
on every evaluation, if is stored in a static variable, as it cannot prove
it will be unchanged. A variable with local scope may not be modified from
the outside, so its value can be reused.
Doing so reduces text size and instruction count.

Signed-off-by: Stefan Brüns <[email protected]>
After wraparound, pwm_count <= pwm_mask holds, thus soft_pwm_X <= pwm_count
guarantees soft_pwm_X < pwm_mask is true, and the heater will be switched
off in the first branch.
Do not evaluate the pwm conditions a second time, this reduces the
instruction count (4 instructions per PWM) and text size (6 byte).

Signed-off-by: Stefan Brüns <[email protected]>
@thinkyhead
Copy link
Member

Superseded by #6100

@thinkyhead thinkyhead closed this Mar 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants