hubmartin / WS2812B_STM32F3

WS2812 DMA library with low RAM needs. Up to 16 paralel outputs and thousands of LEDs on each of them
MIT License
61 stars 15 forks source link

Flicker due to Timer -> GPIO Delay #5

Closed brittanyb closed 4 years ago

brittanyb commented 6 years ago

Hi there,

First I must say I've really enjoyed your library, it's been interesting learning about how you've implemented this method of Timer->GPIO control. I've recently been working with an STM32F3DISCOVERY board implementing the STM32F303VCT6 microcontroller, and found a great deal of flicker when using a source clock as high as 72MHz w/ HSE.

I started with the assumption that there was a timing issue leading to occasional erroneous '1's that may have been '0's. To examine the flicker, I wrote my frame buffer to output all 0s on each color channel. I then used the timing constraints described at this link to move the CC1 and CC2 output compare events further apart. I found that approximating a period of 300 microseconds for a CC1 event, and an event of 900 microseconds for CC2 as opposed to the values used in the library of 350/700 completely removed my issue of flicker with no data loss, over about an hour of observation.

I modified lines 85 and 86 in ws2812b.c to:

uint32_t cc1 = (10 * tim_period) / 42; 
uint32_t cc2 = (10 * tim_period) / 14;

I'm sure the issue wasn't present on your nucleo test bench, as you have chosen these values, but it may be worth an extra note in the repository that the CC1 and CC2 events can be played with if flicker is a problem for some users.

Thanks again for an excellent library, regards,

hubmartin commented 6 years ago

Thank you @brittanyb that you did this troubleshoot and found a solution. IT could be that I had a different batch of WS2812 and the timing was on the edge. I'll take a look at F3 version sometimes soon on the scope. Can you share what your project is, how many LEDs and parallel LED strips dou you use? I never abused this library to the edge. Thank you

brittanyb commented 6 years ago

Sorry for the late reply @hubmartin , I'm afraid that my assumption before was actually incorrect. :) I found that by introducing a 5k resistor between the GPIO outputs and the WS2812B strip data, reverting to the original timing was possible with no data errors. My assumption now is that I was getting electrical interference due to the high current in the output data, and that I avoided it causing data errors by setting the CC periods further apart from one another in my single strip implementation. But that when connecting multiple strips, the issue became more dramatic, and needed to be addressed with reducing current, which I achieved with the 5k resistors for each data line.

I also found in doing this that I was able to significantly increase the supply voltage of my LEDs to around 4.8V, where my microcontroller is running at 3V. In my actual implementation I plan to use a 3.6V regulator for the microcontroller, so that I can use a standard 5V supply for the LEDs and not require a level shifter. -- Not too relevant to this library. But maybe good information to have around if someone else stumbles upon this topic.

And my project has 3 primary parts. High speed sensor data acquisition, data output to 9 strips of 16 LEDs, and a PC interface that works with both data sets through USB.

If you care at all about the standard I'm using for data communication: I pack 7 bit color data for all my LEDs into 6 packets, send over HID, and unpack on the device for my 9 frame buffers. LED update is triggered when processing of 6 packets is complete. With a USB 2.0 port, that allows me 83.3FPS light updates, and running through interrupt control, it allows real-time PC data for LED control, as opposed to being programmed device side. I'm happy to share my implementation when I'm done with it, if you would like to try it.

hubmartin commented 6 years ago

Yes, the voltage levels for data pin could be quite tricky. I did some tests and on the table i could driver data from 3V micro, but on longer cables it behaved sometimes very weird. I would highly suggest level shifters if you design your own hardware. I have used single channel buffer SN74LV1T34DBVR and quad buffer 74LV4T125 and they worked fine. Let me know when you publish your project, I'll add link to your project to the lib and my social networks.

brittanyb commented 6 years ago

Thanks Martin! I will happily show off the USB implementation for this library when I'm happy with it. :)

As a note - I found that when migrating the library for use with the current HAL drivers that the interrupt handlers were never being invoked, and so the LEDs would not update. Digging around (for far too long..) I found that the transfer complete and half transfer callback members of dmaCC2 were both being set to null at some point after initialization. I re-defined their function callback in WS2812B_sendbuf. This helped, but the colors were incorrect, and there was some flickering. After yet more digging, it seems that the new HAL implementation for DMA_Init now doesn't set the appropriate interrupt enable register for half transfers... So setting dmaCC2.Instance->CCR |= DMA_CCR_HTIE; after HAL_DMA_Start_IT is invoked finally solves the issue of incorrect color display. The flicker, as it turns out, disappears when we optimize compilation for speed, as opposed to debugging.

I'll get back in future with my implementation. Hopefully I can apply my fixes in a less 'hacky' way than at current.