cancel
Showing results for 
Search instead for 
Did you mean: 

PWM

SGian.1
Senior

Hi there,

i start to use aSTM32G031 Nucleo with some W2812b . I configure timer1 PWM output but when i try to generate the PWM i just say a lot of noise. I use one library i wrote for another microcontroller and i'm sure work. I share my configuration and i hope someone can help me .

0693W00000WJ8LmQAL.png 

and the code

uint8_t led[led_number][3];
HAL_TIM_PWM_Init(&htim1);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
		for(uint8_t cont=0; cont<255;cont++){
		for(uint8_t nLed=0; nLed<led_number;nLed++){
			led[nLed][0]=cont;
			led[nLed][1]=0;
			led[nLed][2]=0;			
		}
		ws2812sendData(led); 
		HAL_Delay(30);
	}
	for(uint8_t cont=255; cont>0;cont--){
		for(uint8_t nLed=0; nLed<led_number;nLed++){
			led[nLed][0]=cont;
			led[nLed][1]=0;
			led[nLed][2]=0;			
		}
		ws2812sendData(led);
		HAL_Delay(30);
	}
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

WS2812B.C

#include "WS2812.h"
#include "stm32g0xx_hal.h"
#include <stdio.h>
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
 
 
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
 
extern TIM_HandleTypeDef htim1;
extern DMA_HandleTypeDef hdma_tim1_ch4;
#define time &htim1
uint8_t indx=0;
uint8_t ws2812_hi;
uint8_t ws2812_lo;
uint8_t datasentflag=0;
uint16_t pwmData[(24*led_number)+50];
uint32_t time_period;	
 
 
uint8_t i=0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
 
 
 
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	HAL_TIM_PWM_Stop_DMA(&htim1, TIM_CHANNEL_4);
	datasentflag=1;
}
 
 
/**
  * @brief  
  * @param  None
  * @retval None
  */
 
void ws2812_init(void){
	uint32_t frequency;
	frequency = HAL_RCC_GetSysClockFreq();
	time_period = (frequency / ws2812_fequ)-1 ;
	ws2812_lo = time_period / 3;
	ws2812_hi = (time_period * 2)/3;
}
 
/**
  * @brief  
  * @param  None
  * @retval None
  */
 
void ws2812_fill_black(void){
	indx=0;;
	for(indx = 0 ; indx < led_data_size ; indx ++){
		pwmData[indx]= ws2812_lo;
		indx++;
	}
	ws2812_reset();
	ws2812Send();
}
 
 
/**
  * @brief  
  * @param  None
  * @retval None
  */
 
void ws2812sendData(uint8_t led[led_number][3]){
	indx=0;
	uint32_t color;
	for(i=0; i < led_number ;i++){
		color = ((led[i][1]<<16) | (led[i][0]<<8) | (led[i][2]));
		for(int8_t u=23; u>=0; u--){
			if (color&(1<<u))
			{
				pwmData[indx] = ws2812_hi; 
			}
			else{
				pwmData[indx] = ws2812_lo;  
			}
			indx++;
		}
	}
 	for (uint8_t y=0; y<50; y++){
		pwmData[indx] = ws2812_rst;
		indx++;
	}
	ws2812Send();
}	
 
/**
  * @brief  
  * @param  None
  * @retval None
  */
 
void ws2812_reset(void){
	for(indx = 0 ; indx < reset ; indx ++){
		pwmData[indx]= ws2812_rst;
		indx++;
	}
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_4, (uint32_t *)pwmData, 50);
	while (!datasentflag){};
	datasentflag = 0;	
}	
 
/**
  * @brief  
  * @param  None
  * @retval None
  */
 
void ws2812Send(void){
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_4, (uint32_t *)pwmData, indx);
	while (!datasentflag){};
	datasentflag = 0;
}

Thanks a lot

Sergio

3 REPLIES 3

make sure your GP output pins have their maximum output speed set to something greater than low.

Consider using an SPI port output bit for sending your patterns rather than bit banging.

The WS LEDs are pretty sensitive to timing and there's only two patterns, one for 1 and one for 0. If you can figure out a binary character made up of 00011111 or 11100000 patterns, with the right amount of high and low time, based on the bit width of your SPI, you can just fire out a bunch of characters using DMA.

But first, check your output wave forms with an oscilloscope. They may look terrible.

SGian.1
Senior

Hi

thanks for your replace.I check the pin with my oscilloscope but i just saw a lot of noie. I set the speed of the port at the max frequency but nothing. Interesting the SPI but if the frequecy of my W2812b i 800Khz my baut rate is ?

Your baud rate doesn't matter until you get your output pin working properly.

But...

From the data sheet:

0 == T0H + T0L

0.4us + 0.85us

1 = T1H + T1L

0.8us + 0.45us

both == 1.25us. If we take this to be made up of 10 bits, each bit would be 0.125us or 8MBaud.

So, a 0 would be 3 bits high, 7 bits low, and 1 would be 6 bits high and 4 bits low.

This would give 0 = 0.375us + .875us and 1 = .750us + 0.5us. Is this close enough?

There are a bunch of other solutions, but the simplification comes in because, according to the data sheet:

T0H needs to be 0.4us +/-150ns, so T0H can be between 250ns and 550ns.

T0L needs to be 0.85us +/-150ns, so T1H can be between 700ns and 1000ns.

it seems rather sloppy, but 8Mbaud should work nicely.