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
WS2812 LEDs - Driver
Re: WS2812 LEDs - Driver
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)
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)
- 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
Hi,
F3 and F4 have very different DMAs, it is possible the difference is all here.
Giovanni
F3 and F4 have very different DMAs, it is possible the difference is all here.
Giovanni
Re: WS2812 LEDs - Driver
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 )
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 )
- 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
I found another driver, which seems simpler (well that one was coded for a F1 ). 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???
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 ???
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 >>>
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:
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;
}
Re: WS2812 LEDs - Driver
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?
- 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
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
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
Re: WS2812 LEDs - Driver
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 .
More next week.
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 .
More next week.
- 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
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
That STM32_DMA_CR_CHSEL() is the main difference with the F3, so focus on that and its meaning.
Giovanni
Who is online
Users browsing this forum: No registered users and 5 guests