hubmartin / WS2812B_STM32F4

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

STM32F401 - Can only get a solid white light #12

Open robin7331 opened 3 years ago

robin7331 commented 3 years ago

Hey! I like your approach of using DMA and a timer to generate the signal. However, I cannot achieve the rainbow or Christmas animation with my current setup.

I left your DMA channel/stream configuration as it is since I do not need TIM1 or this DMA configuration elsewhere.

My setup contains 12 chained WS2812-2020 LEDs. The PCB on which they are mounted to has a 5v and a 3v3 supply. The LEDs are driven by 5v and that data signal has a level shifter to connect to the 3v3 GPIO pin of the STM32F4.

Screenshot 2021-03-29 at 09 12 37

DATA_IN is directly connected to PB1 of the STM32.

The only modifications I have done to your code so far are those here 👇

// GPIO enable command
#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()

// LED output port
#define WS2812B_PORT GPIOB
// LED output pins
#define WS2812B_PINS (GPIO_PIN_1)
// How many LEDs are in the series - only valid multiples by two
#define WS2812B_NUMBER_OF_LEDS 12

// Number of paralel output LED strips. Each has its own buffer.
// Supports up to 16 outputs on a single GPIO port
#define WS2812_BUFFER_COUNT 1

My problem is that those LEDs are only lighting up in bright white. No animation no nothing.

IMG_1934 (every button has a pair of two leds. But all 12 LEDs are chained. There is only one Data-In for the entire module)

When I set breakpoints into the DMA_TransferCompleteHandler() or DMA_TransferHalfHandler() I can confirm that those are being called.

Also the two visHandle() and visInit() methods are called properly. Screenshot 2021-03-29 at 09 22 40

Having the white lights turned on means that the communication works. If there was an issue with the GPIO pin, DMA or Timers I would see nothing.. right?

Thanks for your help!

robin7331 commented 3 years ago

Update: Just hooked up my logic analyzer. Coincidentally it has a protocol analyzer for the LED protocol. It seems like my MCU is sending all white. For every LED.| Any idea why?

Screenshot 2021-03-30 at 09 45 21

hubmartin commented 3 years ago

Hi, did you set correctly the framebuffer? Try to set framebuffer to some value and comment out the animating effects. Can you see that the data is exactly for 12 LEDs you set in WS2812B_NUMBER_OF_LEDS ?

Is the systick and the HAL_GetTick working correctly? does the code gets inside this if block? https://github.com/hubmartin/WS2812B_STM32F4/blob/master/Src/visEffect.c#L109

If the IRQs are triggered and its generating correct waveform with white color, then the core code works fine and it seems like the issue is really in assingning the data to the buffer.

So you have to set some data to frameBuffer or frameBuffer2 to something like

frameBuffer[0] = 0xff;
frameBuffer[1] = 0x00;
frameBuffer[2] = 0x00;

to set RED (or maybe blue color,since WS2812 has BGR if I' not mistaken) Do not forget to disable/comment visHandle2 which does animation and would rewrite your framebuffer values https://github.com/hubmartin/WS2812B_STM32F4/blob/master/Src/visEffect.c#L163

hubmartin commented 3 years ago

Also check that your level shifter works correctly. I always used proper push-pull driver, not sure how fast that 10k pull-up resistor is. Check that with analog oscilloscope. It might be fine but I would check that.

Treeed commented 1 year ago

Just had the same issue and thought I'd quickly post the solution for anyone from the future: The critical point is, that the channel value does not correspond to the rank of the pins as given in WS2812B_PINS, but only to the pin number on the port. What happened in this case is that reducing WS2812_BUFFER_COUNT to 1 meant, that only the first element in the ws2812b item list was still available, however, the visInit() assigns items to pins 0 through 7 in order. Therefore, the only item (item 0) that was still active was assigned to pin 0 that was not only disabled, but also had nothing connected.

How to fix this if you want to change the active pins:

This is a valid configuration:

#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define WS2812B_PORT GPIOB
#define WS2812B_PINS (GPIO_PIN_6 | GPIO_PIN_13 | GPIO_PIN_9)
#define WS2812B_NUMBER_OF_LEDS 12
#define WS2812_BUFFER_COUNT 3
...
ws2812b.item[0].channel = 9
...
ws2812b.item[1].channel = 6
...
ws2812b.item[2].channel = 13

This is not:

#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define WS2812B_PORT GPIOB
#define WS2812B_PINS (GPIO_PIN_3 | GPIO_PIN_5 | GPIO_PIN_0)
#define WS2812B_NUMBER_OF_LEDS 12
#define WS2812_BUFFER_COUNT 4 //not the same number of buffers as pins
...
ws2812b.item[0].channel = 1 //pin PB1 is not active!
...
ws2812b.item[1].channel = 2` //pin PB2 is not active!
...
ws2812b.item[2].channel = 3` //this will output data on PB3
...
ws2812b.item[3].channel = 0 //this will output data on PB0
...
ws2812b.item[4].channel = 2 //you have only activated 4 channels, this would be the fifth (also, don't repeat pin numbers)

Another thing while I'm at it: The library doesn't compile anymore with newer compilers, it throws <long path>\tools\arm-none-eabi\bin\ld.exe: ./Core/Src/ws2812b.o:<long path>/ws2812b.h:88: multiple definition of 'ws2812b'; ./Core/Src/blink_controller.o:<long path>/ws2812b.h:88: first defined here instead. To fix it change line 20 of ws2812b.c to WS2812_Struct ws2812b; and line 88 of ws2812b.h to extern WS2812_Struct ws2812b; (basically swapping the lines).