2022-11-26 11:17 AM
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 */
}
2022-11-26 11:35 PM
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.
2022-11-27 03:13 PM
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.
2022-11-28 02:10 PM
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.