cancel
Showing results for 
Search instead for 
Did you mean: 

Can't Update WS2812B LEDs After Initial

salvi.a
Associate II

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 */
}

3 REPLIES 3
gbm
Lead III

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.

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
Lead III

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.