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

Support >256 PWM levels #2

Open
per1234 opened this issue Mar 8, 2016 · 6 comments
Open

Support >256 PWM levels #2

per1234 opened this issue Mar 8, 2016 · 6 comments

Comments

@per1234
Copy link
Owner

per1234 commented Mar 8, 2016

When using this library with LEDs there is a large difference between PWM levels at low brightness so the option of more PWM levels than 256 would be useful.

@Palatis
Copy link

Palatis commented Mar 24, 2016

arduino is a 8bit mcu, if we try to use more than 8bit to store pwm levels, we have to do uint16_t arithmetic, that's like 2 times slower.
http://www.avrfreaks.net/forum/multiply-divide-add-performance-various-data-types

the "timer frequency" is calculated as number of brightness levels * pwm frequency, for example, 256 levels * 60hz = 15360hz (60hz is an ideal pwm frequency to NOT cause visual flicker), on a 16Mhz mcu we have 16Mhz / 15.36Khz = 1041.66 cycles to finish the task.
each channel takes 4 instructions, plus some overhead (around 10 instructions), if we're targeting 16 channels it's 16 * 4 + 10 = 74 instructions to be executed every 1041.66 cycles, yields a cpu load of ~7.1%.

and say, we now want 512 levels, 512 levels * 60hz = 30720hz, around 16Mhz / 30.72Khz = 520.83 cycles to complete each timer isr.
and the timer ISR now take 16 * 8 + 20 = 148 instructions due to uint16_t arithmetic (512 can't be stored in a uint8_t), the cpu load is now 148 / 520.83 ~= 28.4%.

even if we still do 256 levels but store the levels in a uint16_t, the isr load is bumped by a factor of 2.
so ~14% cpu load.
well if we can make c++ automatically select optimal storage type for levels we may be able to achieve this without sacrificing performance, however I don't know how......

@per1234
Copy link
Owner Author

per1234 commented Mar 24, 2016

Thanks for the information! I was thinking of using preprocessor directive to switch the support for >256 PWM levels so the performance hit would only be incurred if the feature is needed. I do think 256 levels is sufficient for most applications. I've made some attempts at this but haven't been successful yet. It sounds like you're saying it is actually possible to accomplish this(at a cost) so that's good to know. I've managed to get around the issue by never fully turning the LEDs off but it was previously enough of a problem that I thought it worth considering adding this functionality.

@Palatis
Copy link

Palatis commented Mar 25, 2016

i was thinking about something like

template<int levels> class levelsToType { public: typedef uint16_t levels_t; };
template< > class levelsToType<0> { }; // let it fail, we can't have 0 level...
template< > class levelsToType<1> { }; // let it fail, we can't have only 1 level...
template< > class levelsToType<2> { public: typedef uint8_t levels_t; };
template< > class levelsToType<3> { public: typedef uint8_t levels_t; };
...
template< > class levelsToType<254> { public: typedef uint8_t levels_t; };
template< > class levelsToType<255> { public: typedef uint8_t levels_t; };

and use levelsToType<pwm_levels>::levels_t _levels; when defining the variable.

@Palatis
Copy link

Palatis commented Mar 25, 2016

maybe something like this...
http://ideone.com/lllWv9

for 256 levels we have to use uint16_t... because we do digitalWrite<PIN>((_current_level < _user_level) ? HIGH : LOW);

@per1234
Copy link
Owner Author

per1234 commented Mar 27, 2016

@Palatis I really appreciate you giving me this information! Now that I know this is possible and you have pointed me in the right direction I'm sure I can achieve my goal. This is a bit above my current programming skills so it will take me a little while to get there but it will also provide an opportunity to learn new things in the process.

@Palatis
Copy link

Palatis commented Mar 28, 2016

this paradigm is called c++ template meta-programming.

this whole softpwm library wouldn't be possible without it.

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

No branches or pull requests

2 participants