Skip to main content
Visitor II
January 3, 2024
Question

WS2812B sporadic wrong color - DMA issue or?

  • January 3, 2024
  • 8 replies
  • 7089 views

I have a custom designed board using a single WS2812B RGB LED.

I use the DMA to control, just as "all" examples and drivers use it.

Fairly simple, and it works as a charm.

99% of the time...

Symptom:

Once in while, it starts to show a wrong color.

Fx. if I want to blink 3 times yellow, it may show 1*white + 2*yellow. Or other variations.

Green sometimes get cyan-like.

Red may also show as white.

More rare: OFF shows as green.

The wrong color is not completely random: It is most often white (-ish), or it is the wanted color but in a brighter version.

The LED can work OK for hours, and suddenly fails for a couple of minutes. Then OK again.

Tests performed:

Checked with oscilloscope: The timing is spot-on, and the control signal is sharp and OK.

Debugged code = OK

Hardware/Software

STM32H730

WS2812B is driven and controlled directly form 3V3 supply and MCU pins

Also running other timer interrupts. Running FreeRTOS.

Possible causes:

I am running out of ideas where to search for the problem.

I have searched everywhere for similar problems, but can't find any.

Do you have any ideas in which direction I should go?

- Timing ?

- Supply voltage ?

- Or ?

Thanks in advance !

    This topic has been closed for replies.

    8 replies

    Super User
    January 3, 2024

    Just guessing: DMA is not your problem, maybe just the signal ->

    H730 is really fast switching, so try: set port/pin speed to low , if not perfect then,  then try with a series resistor cpu/pin -> 100 ohms -> WS..../data line ; and check good solder contact to GND plane -> WS.../gnd line .

    KKjel.1Author
    Visitor II
    January 3, 2024

    Fast response, thanks :)

    When I use DMA, I have limited possibilities to set the port pin config: Both speed and drive strength is not available in CubeMX when the pin is not a generic GPIO port pin.

     

    I will check and test with the limiting resistor.

    Super User
    January 3, 2024

    Hey, DMA or not - you still use the pins and this you can set !

    ie. here dma -> spi -> GPIO pins

    AScha3_0-1704312834153.png

     

    Graduate II
    January 3, 2024

    How close is the signalling voltage to the 3V3 rail?  I've seen cases where if it's "too close" there can be occasional "flashes" of unintended colors, even if the bitstream timing is in spec.

    KKjel.1Author
    Visitor II
    January 3, 2024

    I checked with oscilloscope several weeks ago, so I don't remember exactly.

    But I checked that the signal was close to 3V3, to make sure that this was not the problem.

    It sounds strange if it could be the problem?

    I guess it's quite common to drive the device with the same voltage as the control signal, so it sounds crazy if it's necessary to force them to not be the same ?

    Super User
    January 3, 2024

    So: you drive signal from cpu pin , 0/3v3 level ?

    And supply for WSxx led ? also 3v3 ?

    Super User
    January 3, 2024

    > I use the DMA to control, just as "all" examples and drivers use it.

    What does this mean, exactly?

    DMA "copies" an array from RAM to some timer register(s), I presume? If so, how do you prevent your program from writing into the array while it's being "transmitted"?

    JW

     

    KKjel.1Author
    Visitor II
    January 3, 2024

    The typical way to operate the WS2812 is by DMA/PWM.

    I generate an array of timer values for each bit, and the DMA controls a PWM signal on the pin.

    If the application try to update the DMA before it is done, plus some extra time to let the WS2812 reset before next data, I simply ignore that update.

    Graduate
    January 4, 2024

    @KKjel.1 wrote:

    The typical way to operate the WS2812 is by DMA/PWM.

    I generate an array of timer values for each bit, and the DMA controls a PWM signal on the pin.


    Actually, this is quite bad and inefficient way of controlling WS2812. See these topics:

    https://community.st.com/t5/stm32-mcus-products/stm32103-bluepill-bare-metal-ws2812b-neopixel-driver-no/m-p/622687#M230914

    https://community.st.com/t5/stm32-mcus-products/ws2812-library-does-not-work-on-stm32f40/td-p/603041

    Some tips for your timer+DMA:

    Voltage levels - some WS2812 versions are sensitive to too-low logic high voltage. common tricks here are: powering the first WS2812 in a string via a diode to lower its voltage slightly or setting the output to open drain and using 1.5 kOhm resistor as pullup to 5 V.

    Make sure that you output logic low of the proper duration as reset pulse - set PWM duty to 0 at the end of transfer and keep it at 0 until the next transfer.

    Super User
    January 4, 2024

    > If the application try to update the DMA before it is done, plus some extra time

    How does the application know that update is not done yet?

    One simple way to confirm if this may or may not be the source of problem is to toggle a GPIO pin whenever you make a change of the output array, and then on oscilloscope observe both this and the timer-to-LED-output waveform; using appropriate persistence setting or some advanced trigger mode to capture eventual violation.

    > ... I simply ignore that update.

    So, can't that be the reason of your problem? Say if you say do a fade, and you ignore the last change for this reason?

    Of course there can be other software reasons, too. If you have a LA, you can try to capture a longer sequence, stopping when you see the error occurring, and then decode the last or few last output sequences manually.

    JW

    Super User
    January 5, 2024

    > Why do you think DMA is inefficient?

    gbm did not say DMA is inefficient, in fact he's using DMA, too. What he says is inefficient is using timer to transmit data, he's using UART.

    > Very long periode, > 400us, showed extreme bad behavior.

    That in fact is a good starting point to debug. Find out, why. This indeed indicates problem with the control voltage/thresholds.

    Also, reconsider ground arrangement - LEDs can draw significant current and the fact that there's a common "power ground" with the control signal return in effect lowers the control signal's voltage as seen by the LED controller.

    Try to construct a level shifter of some sort.

    JW

    KKjel.1Author
    Visitor II
    January 5, 2024

    gbm did not say DMA is inefficient, in fact he's using DMA, too. What he says is inefficient is using timer to transmit data, he's using UART.

    Yes, I can see from he's link that he do use DMA :)

    I just feed the DMA with the RGB datastream, and the DMA will handle all timer/clocking of the data. I can't see it can be done more efficiently, because it is all handled in the background by the controller.

     

    > Very long periode, > 400us, showed extreme bad behavior.

    That in fact is a good starting point to debug. Find out, why. This indeed indicates problem with the control voltage/thresholds.

    Try to construct a level shifter of some sort.

    gbm link tells to keep signal LOW between data streams. When I stop the DMA, it goes HIGH.

    This might also be a problem.

     

    I am working on both software/timing and hardware:

    - Leave signal LOW between transmissions.

    - Change to 5V supply / level shifter. 

    Graduate
    January 5, 2024

    If you use timer in PWM1 mode (the only reasonable for WS2812 transfer), you normally use period = 3 (ARR = 2), duty = 1 for data bit 0, duty = 2 for data bit 1. You should add one more duty value at the end of bit sequence, this duty = 0 produces the reset state for WS2812 which lasts until the start of the next transfer. The reset state of WS2812 data line may stay forever - there is no time limit.

    From what you report I guess you have some basic error in WS2812 data encoding or DMA programming. Since you haven't shared your code, nobody can help you.

    Graduate
    January 5, 2024

    For WS2812 data line in HIGH state is the same as sending 1. You are doing strange things. Just keep the data line at constant 0 (low) between transfers. All of this looks like a simple problem with your code - incorrect encoding or wrong reset timing. The only requirement for T0L and T1L is that it must be shorter than Treset (so it may be, for example, 5 us - no problem). Only T0Hmax and T1Lmin timing is really critical; T1H may also be much longer than the officially specified value. In other words, TxL of the last data bit *IS* Treset - the data line should not go high after the last data bit sent. There are many versions of WS2812 and WS2812-alikes which differ mainly by the minimum Treset (there is no maximum value); 60us may be too little for some versions. The correct sequence is: at least 60 periods of 0 state (constant 0, not data bits of value 0), data bits, then stay in 0 state as long as you want (so simply go back to the beginning).

    Also, some WS2812-alikes require longer T1L, so it might be a good idea to set the PWM period to 4 cycles instead of 3 (which is the normal value for the original WS2812). WS2812 will be perfectly happy with it, since, as I wrote above, TxL max is not critical..

    KKjel.1Author
    Visitor II
    January 7, 2024

    @gbm wrote:

    For WS2812 data line in HIGH state is the same as sending 1. You are doing strange things. Just keep the data line at constant 0 (low) between transfers.

    I did try to change how I start/stop the DMA, in order to leave data line LOW after the RESET periode. But i did not succeed. Therefore my little experiment.

    But, I promised to write an update on my little "cheat-experiment": It did not work...

     

     

    Last update: I am now quite convinced that the problem is NOT the code, and it's NOT the HIGH state between updates.

    The problem seems to be a lot more complicated: The WS2812B issue is just a SYMPTOM of the real problem...

    I realized this today, when I moved the WS2812B code to internal FLASH -> Works as a charm !

     

    I just don't know what this problem is right now, but I have STRUGGLED for weeks and months to find what is going on.

    I also have similar, random, timing-related issues with the ST2525R3918 SPI communication: Sometimes it suddenly blocks execution. In random places in the code, and random when it happens, and how often.

     

    Both these errors ONLY happen when application is executed from my external QSPI FLASH.

    When executed from internal FLASH, both WS2812B and ST25R3918 works with absolutely no problems.

     

    So the conclusion know is that this WS2812B issue is related to "something" going on when executing form QSPI FLASH.

    I have been in dialogue with ST on this issue for a long time, with no success yet.

    For now, I will leave this issue here, and have a talk with ST, now I have one more piece for the puzzle :)

    KKjel.1Author
    Visitor II
    January 12, 2024

    UPDATE:

    The problem is now localized:

    We have an NFC antenna on the board too, and this could cause some radiated noise into the WS2812B data pin.

    So every time I try to detect an NFC tag, the WS2812B could pick up the noise, and "remember" this data as part of an incomplete RGB update, until next update. Hence the weird color.

     

    The problem occured only once in a while, but we can almost always provoke the error by placing a finger over the NFC antenne(WS2812B. Not touching anything.

    An oscilloscope probe on the WS2812B datapin makes the signal stable/kills the radiated noise, so that's why I have never been able to see the problem on the oscilloscope.

     

    The cause/solution is a bit more complicated than this, because we do NOT see the problem when we run the application from internal FLASH, only when we run it from external QSPI FLASH.

    Of some reason, the port pin is more high impedant in this case, despite the fact that all registers/config of the GPIO/Timer/DMA is exactly the same.

     

    We are investigating this with ST.

     

    Thanks for all the inputs here !

    Super User
    January 12, 2024

    > Of some reason, the port pin is more high impedant in this case, despite the fact that all registers/config of the  GPIO/Timer/DMA is exactly the same.

    By "port pin" you mean the pin controlling the LED?

    No it isn't; from insufficient data you've drawn incorrect conclusions .

    It's probably the surrounding circuitry (probably the QSPI pins and tracks) which are of different impedance, thus changing the amount of coupling between the NFC circuitry and the LED-controlling pin+track. This should be relatively simple to test.

    I also reiterate the fact that GND is always part of the circuit.

    JW

     

    Graduate
    January 13, 2024

    My another wild guess (maybe totally incorrect):

    If you stop the timer PWM output when not transmitting data to WS2812 (quite likely if you use HAL for this WS2812 TIM + DMA setup), WS2812 data output PIN may behave strangely. Make sure the PWM is still active between transfers with PWM duty set to 0 (once, after the last data bit set).

    Somehow it's hard to believe that the problem you experience is related to anytyhing other than incorrect WS2812 data output control.

    Graduate
    March 20, 2024