cancel
Showing results for 
Search instead for 
Did you mean: 

WS2812B sporadic wrong color - DMA issue or?

KKjel.1
Associate III

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 !

28 REPLIES 28

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. 

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.

KKjel.1
Associate III

My code does what I want it to do, verified by oscilloscope, i.e. it's not my code that is the problem. That's why I did not want to post this as the first thing. I think the behavior of the WS2812B is more interesting 🙂

It works 99% of the time, so my main focus is to get some ideas of what can cause this instability.

From your former post, I saw that you mention the data line to be LOW after the LOW reset period, between the updates.

Mine is left HIGH. The data sheet does not really tell me exactly, but this indicates that HIGH should be OK:

KKjel1_0-1704461368889.png

I had 50 periodes of LOW after each update, to make a 50*1,25 = 62,5us RESET periode (>50us).

I have now tried to let the signal stay LOW also after the RESET periode, and until next update. I did not succeed, it just keeps go HIGH after the DMA finnishes. Also if I do not call the STOP DMA function.

Now, I have made an alternative solution: I simply add 50 LOW pulses BEFORE the update. This should reset the WS2812B before the update, and my hope was that this would work.

Until now (1½ hour), it seems to work ! 🙂

 

Original sequence:                RGB data -> 50*0's -> HIGH -> Wait 100 ms -> Repeat

New sequence:       50*0's ->RGB data -> 50*0's -> HIGH -> Wait 100 ms -> Repeat

 

I will keep you updated when I feel confident that this is the solution, and give som Kudos 🙂

It will take some time, because I have to stare at the LED sequence for 1 day...

gbm
Lead III

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.1
Associate III

@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 🙂

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 !

> 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

 

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.

nimaltd
Senior