Skip to main content
salvi.a
Associate II
November 26, 2022
Question

Can't Update WS2812B LEDs After Initial

  • November 26, 2022
  • 2 replies
  • 1247 views

Hello,

I managed to light up WS2812B LEDs by using PWM-DMA. It working well when I set up LEDs before running the code. But when I try to on/off by button it doesn't make any change. Also if I create a function like rainbow loop or basically setting a LED light up it's not working. So it stays as same as first boot.

What should I review? Here is the code. Thanks in advance.

#define MAX_LED 8
#define USE_BRIGHTNESS 1
 
uint8_t LED_Data[MAX_LED][4];
uint8_t LED_Mod[MAX_LED][4]; // for brightness
 
int datasentflag=0;
 
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	HAL_TIM_PWM_Stop_DMA(&htim1, TIM_CHANNEL_1);
	datasentflag=1;
}
 
void Set_LED (int LEDnum, int Red, int Green, int Blue)
{
	LED_Data[LEDnum][0] = LEDnum;
	LED_Data[LEDnum][1] = Green;
	LED_Data[LEDnum][2] = Red;
	LED_Data[LEDnum][3] = Blue;
}
 
#define PI 3.14159265
 
void Set_Brightness (int brightness) // 0-45
{
#if USE_BRIGHTNESS
 
	if (brightness > 45) brightness = 45;
	for (int i=0; i<MAX_LED; i++)
	{
		LED_Mod[i][0] = LED_Data[i][0];
		for (int j=1; j<4; j++)
		{
			float angle = 90-brightness; // in degrees
			angle = angle*PI / 180; // in rad
			LED_Mod[i][j] = (LED_Data[i][j])/(tan(angle));
		}
	}
 
#endif
 
}
 
uint16_t pwmData[(24*MAX_LED)+50];
 
void WS2812_Send (void)
{
	uint32_t indx=0;
	uint32_t color;
 
 
	for (int i= 0; i<MAX_LED; i++)
	{
#if USE_BRIGHTNESS
		color = ((LED_Mod[i][1]<<16) | (LED_Mod[i][2]<<8) | (LED_Mod[i][3]));
#else
		color = ((LED_Data[i][1]<<16) | (LED_Data[i][2]<<8) | (LED_Data[i][3]));
#endif
 
		for (int i=23; i>=0; i--)
		{
			if (color&(1<<i))
			{
				pwmData[indx] = 40; // 2/3 of 90
			}
 
			else pwmData[indx] = 20; // 1/3 of 90
 
			indx++;
		}
 
	}
 
	for (int i=0; i<50; i++)
	{
		pwmData[indx] = 0;
		indx++;
	}
 
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)pwmData, indx);
	while (!datasentflag){};
	datasentflag = 0;
}
 
void Reset_LED (void)
{
	for (int i=0; i<MAX_LED; i++)
	{
		Set_LED(i, 0, 0, 0);
	}
}
 
 
uint16_t effStep = 0;
 
uint8_t rainbow_effect_right() {
 // Strip ID: 0 - Effect: Rainbow - LEDS: 8
 // Steps: 14 - Delay: 30
 // Colors: 3 (255.0.0, 0.255.0, 0.0.255)
 // Options: rainbowlen=8, toLeft=false,
// if(millis() - strip_0.effStart < 30 * (strip_0.effStep)) return 0x00;
 float factor1, factor2;
 uint16_t ind;
 for(uint16_t j=0;j<8;j++) {
 ind = 14 - (int16_t)(effStep - j * 1.75) % 14;
 switch((int)((ind % 14) / 4.666666666666667)) {
 case 0: factor1 = 1.0 - ((float)(ind % 14 - 0 * 4.666666666666667) / 4.666666666666667);
 factor2 = (float)((int)(ind - 0) % 14) / 4.666666666666667;
 Set_LED(j, 255 * factor1 + 0 * factor2, 0 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2);
 WS2812_Send();
 break;
 case 1: factor1 = 1.0 - ((float)(ind % 14 - 1 * 4.666666666666667) / 4.666666666666667);
 factor2 = (float)((int)(ind - 4.666666666666667) % 14) / 4.666666666666667;
 Set_LED(j, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2, 0 * factor1 + 255 * factor2);
 WS2812_Send();
 break;
 case 2: factor1 = 1.0 - ((float)(ind % 14 - 2 * 4.666666666666667) / 4.666666666666667);
 factor2 = (float)((int)(ind - 9.333333333333334) % 14) / 4.666666666666667;
 Set_LED(j, 0 * factor1 + 255 * factor2, 0 * factor1 + 0 * factor2, 255 * factor1 + 0 * factor2);
 WS2812_Send();
 break;
 }
 }
 if(effStep >= 14) {effStep = 0; return 0x03; }
 else effStep++;
 return 0x01;
}
 
/* USER CODE END 0 */
 
/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_TIM1_Init();
 MX_USART1_UART_Init();
 /* USER CODE BEGIN 2 */
	
	//uint8_t rxData[1];
	
	
 
 Set_LED(0, 255, 0, 0);
 Set_LED(1, 0, 255, 0);
 Set_LED(2, 0, 0, 255);
 
 Set_LED(3, 46, 89, 128);
 
 Set_LED(4, 156, 233, 100);
	
	Set_Brightness(10);
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
		
		rainbow_effect_right();
		WS2812_Send();
			
		/*HAL_UART_Receive(&huart1, rxData, 1, 100);
		
		if(rxData[0] == '1'){
			Reset_LED();
			Set_LED(15, 123, 123, 0);
		Set_Brightness(10);
		WS2812_Send();
		}
 else if(rxData[0] == '0'){
			Reset_LED();
		} */
			
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */ 
 }
 /* USER CODE END 3 */
}

This topic has been closed for replies.

2 replies

gbm
Principal
November 27, 2022

volatile _Bool datasentflag=0;

And why don't you use SPI or UART for that purpose? I't much easier and more efficient, as you only need to prepare <= 3 bits of data instead of 16 per each WS2812 bit.

Also, there are numerous prblems with calculations in your code.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
salvi.a
salvi.aAuthor
Associate II
November 27, 2022

I just changed that line but it didn't work.

I'm trying to run it by using SPI but currently I'm not successful.

gbm
Principal
November 28, 2022

Are you sure there is a break between WS2812 frames? Somehow I can't see it in your code. Using floating point with numerous conversions float<->int is a clear overkill here. Everything could be done with integer math.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice