Fading example code

 avatar
unknown
c_cpp
a month ago
6.5 kB
3
Indexable
#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