WS2812 LEDs - Driver

This forum is about you. Feel free to discuss anything is related to embedded and electronics, your awesome projects, your ideas, your announcements, not necessarily related to ChibiOS but to embedded in general. This forum is NOT for support.
Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

WS2812 LEDs - Driver

Postby Noname » Wed Apr 29, 2015 3:34 pm

Hello

I need to drive some WS2812 LEDs. They use a NZR communication mode without clock signal, therefore the timing of the 800khz signal generation is critical.
I was happy to find a ChibiOS driver for those LEDs, but unfortunately I can't get it to work :/, and I really don't know how to debug it, I need some help please.

I don't have any oscilloscope to check the signal, but when I use my volt meter, it stays at 0V during the test routine where random color signals are generated, so I have the feeling that no signal at all comes out of the pin, and I have absolutely no idea why. :/

Has someone already successfully used that driver?

Thanks

Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

Re: WS2812 LEDs - Driver

Postby Noname » Sat May 02, 2015 11:40 am

The dmaStreamAllocate seems to work as it sends a FALSE value back which indicate that there was no error and that the stream was taken. The rest of the DMA setup seems equal to that seen for the ADC peripheral (adc_lld.c), only the parameters differs of course.

I can't imagine that the logic used to generate the signal with the help of DMA and PWM is wrong, he wouldn't have published it then. :?
Really strange. It was developed on STM32F3 Discovery. Is there an difference with my STM32F4 Discovery which may possibly explain the problem?
(I don't know which version of ChibiOS he used)

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: WS2812 LEDs - Driver

Postby Giovanni » Sat May 02, 2015 1:29 pm

Hi,

F3 and F4 have very different DMAs, it is possible the difference is all here.

Giovanni

Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

Re: WS2812 LEDs - Driver

Postby Noname » Sat May 02, 2015 5:42 pm

Hi,

Thanks for your answer :)
If the the problem is related to the different DMA implementation between F3 and F4, it may be a question of a wrong streamer and timer number?

(I'm a beginner, I do it as a hobby only :D )

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: WS2812 LEDs - Driver

Postby Giovanni » Sat May 02, 2015 9:17 pm

It is possible, F3 and F4 are very different.

Giovanni

Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

Re: WS2812 LEDs - Driver

Postby Noname » Sun May 03, 2015 5:14 pm

I found another driver, which seems simpler (well that one was coded for a F1 :D ). It uses only 1 DMA stream and 1 PWM/Timer, but it doesn't use ChibiOS.
So I need your help to convert some instructions.
https://github.com/devthrash/STM32F1-wo ... 812/main.c

How do I convert that thing in ChibiOS instructions???

Code: Select all

   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM3_CCR1_Address;   // physical address of Timer 3 CCR1
   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer;      // this is the buffer memory
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                  // data shifted from memory to peripheral
   DMA_InitStructure.DMA_BufferSize = 42;

DMA_PeripheralBaseAddr >>> dmaStreamSetPeripheral ???
DMA_MemoryBaseAddr >>> dmaStreamSetMemory0 ??? No idea, I still haven't understood the meaning of LED_BYTE_Buffer :?
DMA_DIR >>> STM32_DMA_CR_DIR_M2P, I suppose :?
DMA_BufferSize >>> dmaStreamSetTransactionSize ???

Code: Select all

   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;               // automatically increase buffer index
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                     // stop DMA feed after buffer size is reached
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_PeripheralInc >>> STM32_DMA_CR_PINC ???
DMA_MemoryInc >>> STM32_DMA_CR_MINC ???
DMA_PeripheralDataSize >>> STM32_DMA_CR_PSIZE_HWORD ???
DMA_MemoryDataSize >>> STM32_DMA_CR_MSIZE_HWORD ???
DMA_Mode >>> :?
DMA_Priority >>> Parameter in the dmaStreamAllocate function, not? :?
DMA_M2M >>> :?

Code: Select all

   DMA_Init(DMA1_Channel6, &DMA_InitStructure);
   
   /* TIM3 CC1 DMA Request enable */
   TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);

dmaStreamEnable(STM32_DMA1_STREAM6); ???

TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE); >>> PWMD4.tim->DIER |= TIM_DMA_CC1; ???



I feel a little bit lost :?

(I'm using PWMD4 [TIM4], not PWMD3)



EDIT:

Code: Select all

void WS2812DriverInit(BaseSequentialStream *chp) {

  bool_t dmaAllocError = TRUE;

  /* PWM configuration */
  palSetPadMode(GPIOD, GPIOD_LED4, PAL_MODE_ALTERNATE(2));
  pwmStart(&PWMD4, &pwm4cfg);

  /* DMA configuration  */
  dmaAllocError = dmaStreamAllocate(STM32_DMA1_STREAM2, 10, NULL, NULL);
  dmaStreamSetPeripheral(STM32_DMA1_STREAM2, (uint32_t)TIM3_CCR1_Address);
  dmaStreamSetMemory0(STM32_DMA1_STREAM6, (uint32_t)LED_BYTE_Buffer);
  dmaStreamSetTransactionSize(STM32_DMA1_STREAM6, 42);
  dmaStreamSetMode(STM32_DMA1_STREAM6,
                   STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_PSIZE_HWORD |
                   STM32_DMA_CR_MSIZE_HWORD);



  PWMD4.tim->DIER |= TIM_DMA_CC1;

}

Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

Re: WS2812 LEDs - Driver

Postby Noname » Sun May 03, 2015 7:47 pm

Code: Select all

   DMA_SetCurrDataCounter(DMA1_Channel6, buffersize);    // load number of bytes to be transferred
   DMA_Cmd(DMA1_Channel6, ENABLE);          // enable DMA channel 6
   TIM_Cmd(TIM3, ENABLE);                   // enable Timer 3
   while(!DMA_GetFlagStatus(DMA1_FLAG_TC6));    // wait until transfer complete
   TIM_Cmd(TIM3, DISABLE);                // disable Timer 3
   DMA_Cmd(DMA1_Channel6, DISABLE);          // disable DMA channel 6
   DMA_ClearFlag(DMA1_FLAG_TC6);             // clear DMA1 Channel 6 transfer complete flag

And that bloc in the WS2812_send function is equivalent to:

Code: Select all

  dmaStreamSetTransactionSize(STM32_DMA1_STREAM2, buffersize); // WRONG TYPE!!! load number of bytes to be transferred
  dmaStreamEnable(STM32_DMA1_STREAM2);                                // enable DMA1 channel 2
  pwmEnableChannel(&PWMD4, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD4, 5000)); // WRONG PULSE WIDTH!!! enable Timer 4
  dmaWaitCompletion(STM32_DMA1_STREAM2);                            // wait until transfer complete
  pwmDisableChannel(&PWMD4, 0);


Right?

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: WS2812 LEDs - Driver

Postby Giovanni » Sun May 03, 2015 8:00 pm

It looks OK, you have to test and see if the DMA registers are set as you expect and, after enabling the channel, decrements/increments as you expect.

Edit: it looks you have not specified the channel in the "mode" (STM32_DMA_CR_CHSEL() macro), please refer to the Reference Manual for details.

Giovanni

Noname
Posts: 36
Joined: Wed Oct 09, 2013 7:14 pm

Re: WS2812 LEDs - Driver

Postby Noname » Sun May 03, 2015 8:48 pm

Thank you for your help! :)

Yeah I definitively need to take a look at the manual, but it looks so much complicated for me who have only a few knowledge about all that low level stuff in general. I'm sure it will be funny :D.

More next week.

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: WS2812 LEDs - Driver

Postby Giovanni » Sun May 03, 2015 8:57 pm

The DMA driver is not even a real driver, it is an helper used by the other drivers, the details of the inner DMA unit are not really hidden. On the F4 the DMA it is *particularly* complex, you need to understand, the STM32 RM is your best friend for this.

That STM32_DMA_CR_CHSEL() is the main difference with the F3, so focus on that and its meaning.

Giovanni


Return to “User Projects”

Who is online

Users browsing this forum: No registered users and 4 guests