Fading example code
#include "driver/gpio.h" #include "driver/ledc.h" #include "esp_timer.h" #include "driver/gptimer.h" uint16_t ti = 20000; uint8_t ch = 1; #define NUM_CHANNELS 5 static uint16_t start_values_LED1[NUM_CHANNELS]; static uint16_t target_values_LED1[NUM_CHANNELS]; static int16_t step_values_LED1[NUM_CHANNELS]; static int16_t steps_taken_LED1[NUM_CHANNELS]; static bool fade_active_LED1 = false; static uint16_t steps_remaining_LED1 = 0; uint32_t Rtrig = ti; uint32_t Gtrig = ti*2; uint32_t Btrig = ti*3; hw_timer_t *LEDtimer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; void IRAM_ATTR onLEDTimer(){ if(ch == 1){ if (steps_remaining_LED1 > 0) { for (int i = 0; i < NUM_CHANNELS; i++) { if(steps_taken_LED1[i] == 0){ if(start_values_LED1[i] != target_values_LED1[i]){ start_values_LED1[i] = start_values_LED1[i] + step_values_LED1[i]; ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i, (start_values_LED1[i])); ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i); } else {step_values_LED1[i] = 0;} } else if (steps_taken_LED1[i] == 1 || steps_taken_LED1[i] == -1){ if((start_values_LED1[i] != 0 && steps_taken_LED1[i] < 0) || (start_values_LED1[i] != 65535 && steps_taken_LED1[i] > 0)){ start_values_LED1[i] = start_values_LED1[i] + steps_taken_LED1[i]; } steps_taken_LED1[i] = step_values_LED1[i]; ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i, (start_values_LED1[i])); ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i); } else if (steps_taken_LED1[i] > 1){ steps_taken_LED1[i] = steps_taken_LED1[i] - 1; } else if (steps_taken_LED1[i] < -1){ steps_taken_LED1[i] = steps_taken_LED1[i] + 1; } } steps_remaining_LED1--; if (steps_remaining_LED1 == 0){ for (int i = 0; i < NUM_CHANNELS; i++) { start_values_LED1[i] = target_values_LED1[i]; ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i, (target_values_LED1[i])); ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)i); } } } else { timerStop(LEDtimer); } } else if(ch ==4){ ch = 1; } else { ch++; } } void setup(){ //initializePins(); Serial.begin(115200); initializeLEDs(); LEDtimer = timerBegin(10000); // Timer 10kHz timerAttachInterrupt(LEDtimer, &onLEDTimer); timerAlarm(LEDtimer, 10, true, 0); timerStop(LEDtimer); } void loop(){ uint16_t x = 3000; if(millis() > Rtrig){ Rtrig = millis() + ti*3; uint16_t current_values[NUM_CHANNELS] = {0, 0, x, 0, 0}; uint16_t target_values[NUM_CHANNELS] = {x, 0, 0, 0, 0}; fade(current_values, target_values, ti); // 1000ms transition } if(millis() > Gtrig){ Gtrig = millis() + ti*3; uint16_t current_values1[NUM_CHANNELS] = {x, 0, 0, 0, 0}; uint16_t target_values1[NUM_CHANNELS] = {0, x, 0, 0, 0}; fade(current_values1, target_values1, ti); // 1000ms transition } if(millis() > Btrig){ Btrig = millis() + ti*3; uint16_t current_values2[NUM_CHANNELS] = {0, x, 0, 0, 0}; uint16_t target_values2[NUM_CHANNELS] = {0, 0, x, 0, 0}; fade(current_values2, target_values2, ti); // 1000ms transition } Serial.print(start_values_LED1[0]); Serial.print(","); Serial.print(start_values_LED1[1]); Serial.print(","); Serial.print(x); Serial.print(","); Serial.print(0); Serial.print(","); Serial.println(start_values_LED1[2]); } void fade(uint16_t *current_values, uint16_t *new_values, uint16_t transition_ms) { if (fade_active_LED1){ timerStop(LEDtimer); // Stop the timer interrupt } transition_ms = transition_ms/4; //1ms interrupt divided between 4 channels steps_remaining_LED1 = transition_ms; //Duration divided by 4 is the amount of steps for (int i = 0; i < NUM_CHANNELS; i++) { //For every color channel start_values_LED1[i] = current_values[i]; //Write to global variable target_values_LED1[i] = new_values[i]; //Write to global variable if ((target_values_LED1[i] - start_values_LED1[i]) == 0){ //If there's no change in this color channel step_values_LED1[i] = 0; //The step size is 0 } else { step_values_LED1[i] = (target_values_LED1[i] - start_values_LED1[i]) / (int16_t)transition_ms; //Calculate the step size if(step_values_LED1[i] == 0){ //If the step value is 0, The difference between current and asked LED brightness is smaller than the transition time. We thus have to skip steps step_values_LED1[i] = (float)transition_ms/((float)target_values_LED1[i] - (float)start_values_LED1[i]); //The amount of interrupt runs to skip in order to achieve the required change within the requested timeframe steps_taken_LED1[i] = step_values_LED1[i]; //We'll decrement the steps taken in the interrupt } else { steps_taken_LED1[i] = 0; //If no steps should be skipped, steps taken should be 0 to indicate the same to the interrupt function } } } fade_active_LED1 = true; //Enable the fade flag timerStart(LEDtimer); // Start the timer interrupt } void initializeLEDs(){ ledc_timer_config_t ledc_timer = { .speed_mode = LEDC_LOW_SPEED_MODE, .duty_resolution = LEDC_TIMER_16_BIT, .timer_num = LEDC_TIMER_0, .freq_hz = 120, .clk_cfg = LEDC_USE_RC_FAST_CLK }; ledc_timer_config(&ledc_timer); ledc_channel_config_t ledc_channel = { .gpio_num = 19, .speed_mode = LEDC_LOW_SPEED_MODE, .channel = LEDC_CHANNEL_0, .intr_type = LEDC_INTR_DISABLE, .timer_sel = LEDC_TIMER_0, .duty = 0, .hpoint = 0 }; ledc_channel_config(&ledc_channel); ledc_channel.gpio_num = 15; ledc_channel.channel = LEDC_CHANNEL_1; ledc_channel_config(&ledc_channel); ledc_channel.gpio_num = 16; ledc_channel.channel = LEDC_CHANNEL_2; ledc_channel_config(&ledc_channel); ledc_channel.gpio_num = 17; ledc_channel.channel = LEDC_CHANNEL_3; ledc_channel_config(&ledc_channel); ledc_channel.gpio_num = 18; ledc_channel.channel = LEDC_CHANNEL_4; ledc_channel_config(&ledc_channel); }
Leave a Comment