Skip to main content
salvi.a
Associate II
Nov 26, 2022 7:17 PM UTC
Question

Can't Update WS2812B LEDs After Initial

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.

3 replies

gbm
Super User
Nov 27, 2022 7:35 AM UTC

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
Nov 27, 2022 11:13 PM UTC

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
Super User
Nov 28, 2022 10:10 PM UTC

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