arneboe / ws-dmx-ban-alt-firmware

an alternative firmware for the ws-dmx-ban led controllers
GNU General Public License v3.0
6 stars 2 forks source link

Faster PWM #2

Open regnarg opened 3 years ago

regnarg commented 3 years ago

Hi! Just FYI, I created another alternative firmware that can do PWM up to 32 kHz (I find 400 Hz still very unpleasant): https://github.com/regnarg/ws-dmx-ban-hf-pwm/. Sorry to spam your project but perhaps someone who stumbles upon here will find it useful. Its currently a bit rudimentary but I think it could be brought to feature parity.

arneboe commented 3 years ago

Thanks for the info! Nice that more people are actively working on better firmware for those boards :-)

I will definitely take a look at it to understand how you achieved that high update rate and if possible port it to my firmware.

I also experimented with higher update rates but for me the dmx reception became unstable when going above 400hz because the uart interrupt was interrupted by the pwm interrupt so much that it was losing bytes.

regnarg commented 3 years ago

Yes, interrupts are a bit finicky and have a large overhead (I did not measure it but I would guess tens to hundreds of cycles). My code is completely interrupt-less, in fact, I disable all interrupts at the very beginning. I use one hardware timer as a time base, poll it in a hand-optimized tight loop (I ended up writing some assembly to save a few cycles but even the C version was usable). One iteration of the loop has something like 10 instructions (for updating three channels), I did not count the exact cycles but I would guess under 20 cycles. This would theoretically allow for 24 MHz / 20 = 1.2 MHz GPIO updates per second. Then you have to take into account the length of the PWM period (longer period -> more brightness steps but lower frequency). All in all, 32 kHZ seemed as a reasonable compromise. As a bonus, you do not risk audible buzz as it is above human hearing. You also have to save a few cycles for polling UART but that seems doable (polling the RI is just a few cycles).

The most tricky part would be to do some more complex processing of UART messages because you do not want to "stall" the PWM update loop and create visible flickers. This can be achieved by interspersing any longer processing code with regular calls to update() which will update the PWM outputs even during any processing / computation. It may be a tricky balance but seems realistic.

My goals are probably a bit different: I want to use this to control home lighting, so I do not need strobe effects and similar, just simple per-channel brightness control is fine). I also do not need DMX512 per se (I do not have any other DMX512 hardware) but I am not opposed to implementing it. Perhaps, it would be possible to create a unified codebase that offers all the different features via ifdef-s, even if they cannot be enabled at the same time due to memory limitations...