ATtiny85 icm FastLED weird issue in IF-else-statement

Hi all,

The subject was kind of hard to put into words, but please read on.
I really, really don't know what's causing this weird issue...

I'm trying to recreate a bought lantern\candle with my own NeoPixel Stick (the 8 LED stick, unknown brand (I didn't knew better then)) and ATtiny85.

This is my first project ever with a brand new Arduino Uno R4 Minima. I'm using the FastLED library because this actually works (with some effort) with the R4's.

The code works when using the Arduino itself. But I wanted it to work with an ATtiny85.
Using ATTinyCore i've burned the bootloader (well, set the fuses) to 8MHz.

When uploading (with using the Arduino as a programmer) the blink sketch, it works flawlessly. When using FastLED in combination with some simple self-written code it also works great. Basically, I loop this:

fill_solid(leds, NUM_LEDS, CHSV(random(0,256),random(0,256),random(50, BRIGHTNESS)));
FastLED.show();
delay(random(10, 200));

No problems here.

When I uploaded my actual sketch, all LEDs stayed off. After a lot of debugging I seem to have it tracked to either a large IF-statement, doing something in the else within the if or something FastLED related. I know if it's stuck somewhere because the bottom 3 LEDs are separately pulsing. If the code breaks, everything is dark.

  • When replacing the IF-statement with (i == 1), it works.
  • When commenting out setting an 2-dimensional array item, it works.
  • When moving setting the array below the IF-statement, it works.

Another odd thing is, when adding FastLED code to turn a LED on, to within the IF-statement (or it's else) it also breaks when it DID work before with above edits.
I also thought it could have something to do with volatile vars in combination with the IF-statement, but this didn't seem to work as well.

The issue seems to be within this IF-statement:

if ((timing_LED_OnOff[i] == 1 && timeNow >= (timings[i] - 2) && timeNow <= (arr_fade[i][1] + 2)) || (timing_LED_OnOff[i] == 0 && timeNow >= (arr_fade[i][1] - 2) && timeNow <= (timings[i] + 2))) {

When commenting out this piece within the else of the above IF-statement it also works (as in the bottom LEDs turn on\code is not stuck):

arr_fade[i][2] = DEFAULT_BRIGHTNESS;

Now for the code:

#include <FastLED.h>
//CRGB(255,94,5)); // flame-like orange (RGB)
//CHSV(20, 255, 255); // 20 = flame-like orange (HSV) (h=20 for naked eye, or h=60 with red foil)

#define DATA_PIN    4 // Arduino pin 6, ATtiny85 pin 4 (4 for testing, 1 for production)
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    8
CRGB leds[NUM_LEDS];

const PROGMEM int16_t BRIGHTNESS = 255; // This is a hard limit in the loop! Always set to MAX(255) if not otherwise required.

const PROGMEM int16_t FLAMECOLOR = 20; // Flame-like orange (h=20 for naked eye, or h=60 with red foil)
const PROGMEM int16_t HUE = 255; // full orange, no saturation (h=255)
const PROGMEM int16_t MAX_BRIGHTNESS = 255; // The max set brightness of the flames. 192 Is about 75% of max.
const PROGMEM int16_t MIN_BRIGHTNESS = 28; // The minimum brightness to keep the light orange and not red.

const PROGMEM int16_t DEFAULT_BRIGHTNESS = (MAX_BRIGHTNESS * 0.5);

const PROGMEM int16_t FADE_START = 100;
const PROGMEM int16_t END_TIME = 2450;
const PROGMEM unsigned long DEVIATION = 2;

unsigned long timeNow = millis();
unsigned long Sequence_Start;

unsigned long progress_base;
int16_t pulse_1_old = DEFAULT_BRIGHTNESS;
int16_t pulse_1 = DEFAULT_BRIGHTNESS;
unsigned long timer_1 = 500; // one half of a second
unsigned long LED_1_start = millis();

const PROGMEM int16_t timing_count = 39;
const PROGMEM int16_t timings[] = {10,75,140,205,270,340,410,410,440,520,575,640,705,780,840,910,1010,1075,1140,1240,1310,1370,1510,1575,1640,1640,1700,1705,1770,1850,1875,1940,2000,2040,2070,2130,2140,2210,END_TIME};
const PROGMEM int16_t timing_LEDs[] = {4,5,6,6,6,6,4,5,4,5,6,7,7,6,5,4,4,5,6,6,5,4,4,5,4,6,5,7,6,7,4,5,6,4,7,5,6,7,7};
const PROGMEM int16_t timing_LED_OnOff[] = {1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,0,0,0,0};
int16_t arr_fade[timing_count][4];

void setup() {
  /*
  Serial.begin(9600); // For debugging
  // while the serial stream is not open, do nothing:
  while (!Serial) ;
  */

  // Create the fade array. Set the fade value (in ms) to 100 of the timing it has since the last 'on' if it is less then 100. It (should) always begin(s) with a LED to on and ends with a LED to off.
  for (int i = 0; i <= timing_count - 2; i++) { // note the - 2 instead of the usual -1. This is because I don't need the last array item 'END_TIME'.
    arr_fade[i][0] = timing_LEDs[i];
    if (timing_LED_OnOff[i] == 0) { // LED that turn off
      for (int j = i - 1; j >= 0; j--) {
        if (timing_LEDs[i] == timing_LEDs[j]) {
          arr_fade[i][1] = timings[i] - timings[j];
          if (arr_fade[i][1] < FADE_START) {
            arr_fade[i][1] = timings[j] + DEVIATION;
          } else if (arr_fade[i][1] < 0) {
            arr_fade[i][1] = 0;
          } else {
            arr_fade[i][1] = timings[i] - FADE_START;
          }
          break;
        }
      }
    } else { // LED that turn on (aka: the rest)
      for (int j = i + 1; j <= timing_count; j++) {
        if (timing_LEDs[i] == timing_LEDs[j]) {
          arr_fade[i][1] = timings[j] - timings[i];
          if (arr_fade[i][1] < FADE_START) {
            arr_fade[i][1] = timings[j] - DEVIATION;
          } else if (arr_fade[i][1] > END_TIME) {
            arr_fade[i][1] = END_TIME;
          } else {
            arr_fade[i][1] = timings[i] + FADE_START;
          }
        break;
        }
      }
    }
  }

  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS); // set master brightness control
  FastLED.clear(); // clear all leds
  FastLED.show(); // show... well... nothing. Not required, but does forces the clear.
}

void loop() {
  // put your main code here, to run repeatedly:
  if (millis() - Sequence_Start > END_TIME) {
    Sequence_Start = millis();
  }
  // Pulse the bottom leds 0, 1, 2. Always
  progress_base = (millis() - LED_1_start);
  if (progress_base <= timer_1) {
    if (pulse_1 > MAX_BRIGHTNESS) {
      pulse_1 = MAX_BRIGHTNESS;
    }
    int16_t LED_1_brightness = map(progress_base, 0, timer_1, pulse_1_old, pulse_1); // syntax: map(value, fromLow, fromHigh, toLow, toHigh)
    toggle_led(0, 1, LED_1_brightness);
    toggle_led(1, 1, LED_1_brightness);
    toggle_led(2, 1, LED_1_brightness);
  } else {
    LED_1_start = millis();  // restart fade again
    pulse_1_old = pulse_1;
    // An extra random chance for a LED to shine brighter
    if (random(0, 10) < 8) {
      pulse_1 = random(DEFAULT_BRIGHTNESS * 0.65, DEFAULT_BRIGHTNESS * 1.4);
      timer_1 = random(100, 250);
    } else {
      pulse_1 = random(DEFAULT_BRIGHTNESS * 0.9, DEFAULT_BRIGHTNESS * 1.75);
      timer_1 = random(75, 175);
    }
  }
  
  timeNow = (millis() - Sequence_Start);
  // Loop the whole array and check if there are times to fade in\out
  for (int i = 0; i <= (timing_count - 2); i++) {
    //if ((timing_LED_OnOff[i] == 1 && timeNow >= low_milli(timings[i]) && timeNow <= high_milli(arr_fade[i][1])) || (timing_LED_OnOff[i] == 0 && timeNow >= low_milli(arr_fade[i][1]) && timeNow <= high_milli(timings[i]))) {
    if ((timing_LED_OnOff[i] == 1 && timeNow >= (timings[i] - 2) && timeNow <= (arr_fade[i][1] + 2)) || (timing_LED_OnOff[i] == 0 && timeNow >= (arr_fade[i][1] - 2) && timeNow <= (timings[i] + 2))) {
    //if (i == 1) {
      int16_t func_brightness = set_LED_brightness(i);
      fade_LED(arr_fade[i][0], func_brightness);
    } else {
      //leds[7] = CHSV(FLAMECOLOR, HUE, 255);
      //FastLED.show();
      arr_fade[i][2] = DEFAULT_BRIGHTNESS;
    }
  }

  // Set all changes to the LEDs! Without this, no NeoPixel will change state
  FastLED.show();
}

// Return the imput milliseconds - 2 for a bit of margin on the low end (milliseconds are not always exactly reached)
unsigned long low_milli(unsigned long cur_milli) {
  //unsigned long return_milli = (cur_milli - DEVIATION);
  //return return_milli;
}

// Return the imput milliseconds + 2 for a bit of margin on the high end (milliseconds are not always exactly reached)
unsigned long high_milli(unsigned long cur_milli) {
  //unsigned long return_milli = (cur_milli + DEVIATION);
  //return return_milli;
}

// Set the chosen led to the default color and hue to a given brightness
void fade_LED(int16_t lednr, int16_t brightness) {
  /*
  // Fade the LED to it's new brightness value. If the brightness is less then the color allows (28 in the case of the flameorange), just turn the LED off.
  if (brightness < MIN_BRIGHTNESS) {
    toggle_led(lednr, 0, 0);
  } else {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(FLAMECOLOR, HUE, brightness);
    }
    leds[lednr] = CHSV(FLAMECOLOR, HUE, brightness);
  }
  */
}

// Toggle the given LED on or off. If the LED is nr 4, automatically do the same with 3. If it's on, use the given brightness. If off, always set brightness to 0 for off.
void toggle_led(int16_t lednr, int16_t OnOff, int16_t func_Brightness) {
  if (OnOff == 1) {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(FLAMECOLOR, HUE, func_Brightness);
    }
    leds[lednr] = CHSV(FLAMECOLOR, HUE, func_Brightness);
  } else {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(FLAMECOLOR, HUE, 0);
    }
    leds[lednr] = CHSV(FLAMECOLOR, HUE, 0);
  }
}

// Fade a given led. It is faded within the timeframe of 50ms (of less if the last action of that LEDnr was less ms ago). From the default brightness to 0 if time allows.
int16_t set_LED_brightness(int16_t arraynr) {
  /*
  arr_fade[arraynr][3] = millis() - arr_fade[arraynr][3];
  if (timing_LED_OnOff[arraynr] == 0) {
    arr_fade[arraynr][2] = map(arr_fade[arraynr][3], 0, timings[arraynr] - arr_fade[arraynr][2], DEFAULT_BRIGHTNESS, 0);
    if (arr_fade[arraynr][2] < 0) {
      arr_fade[arraynr][2] = 0;
    }
  }
  if (timing_LED_OnOff[arraynr] == 1) {
    arr_fade[arraynr][2] = map(arr_fade[arraynr][3], 0, timings[arraynr] - arr_fade[arraynr][2], 0, DEFAULT_BRIGHTNESS);
    if (arr_fade[arraynr][2] > DEFAULT_BRIGHTNESS) {
      arr_fade[arraynr][2] = DEFAULT_BRIGHTNESS;
    }
  }
  return arr_fade[arraynr][2];
  */
  return 20; // TEST TEST TEST
}

Do note that I commented out some code within functions to have less code to debug.

Also, it may or may well not have nothing something to do with this, but I would've expected ATTinyCore to include an AVR platform, but it seems to include the library: "FastLED\src\platforms\esp\32\clockless_rmt_esp32.cpp".

I hope someone will get my probably badly written story.

Can someone please help me track this down?

Kind regards,
Tri.

I recommend always use parenthesis to separate conditions in long if statements.
This recommendation becomes mandatory if you are using a mixture of or and and conditions.

Am I not doing that enough?

I've added more, but no joy.

if (((timing_LED_OnOff[i] == 1) && (timeNow >= (timings[i] - 2)) && (timeNow <= (arr_fade[i][1] + 2))) || ((timing_LED_OnOff[i] == 0) && (timeNow >= (arr_fade[i][1] - 2)) && (timeNow <= (timings[i] + 2)))) {

In the condition below

timeNow is a millis counter and timings[i] is a constant value not greater then 2450 .

That is, your program is not designed to work more than 2.5 seconds after the controller is restarted?

Indeed. The whole 'flame' loops every 2450 ms.

if (millis() - Sequence_Start > END_TIME) {
    Sequence_Start = millis();
}

together with

timeNow = (millis() - Sequence_Start);

Would see to that loop.

Edit:
Basically I have an array with specific timings and that IF-statement checks every value against the 'timeNow', which loops from 0 to 2450 over and over. The -2 and +2 are there to prevent missing specific millisecond values.

The code itself works on my Arduino. I just don't know why the ATtiny85 won't take it...

yes, I didn't see that

You're not using pgm_read_word() to access your PROGMEM arrays.
It'll work anyway on an R4 because of the different way that PROGMEM is implemented, but on an AVR you MUST use the function calls to access PROGMEM data.

This could be a memory issue
The local variables uses about a 370 bytes (72%) of Attiny85 RAM in total

1 Like

That is really usefull information.
It does work even less well now. haha

I tried to quickly find some info about this. Do I need includes for this? Like

#include <avr/io.h>
#include <avr/pgmspace.h>

Edit: Tested it out, adding the includes didn't work either.

I thought of that, but with 8 LEDs it shoudn't be an issue right?

Sketch uses 4676 bytes (57%) of program storage space. Maximum is 8192 bytes.
Global variables use 455 bytes (88%) of dynamic memory, leaving 57 bytes for local variables. Maximum is 512 bytes.

What's the connection to the number of leds?

Adding the includes is a little part of work.
You must add pgm_read_word() to every access to your PROGMEM variables

I read that each NeoPixel LED takes about 3 bytes of RAM or something. So I thought you mentioned RAM because of that.

no,

this array alone takes up two thirds of the board's total memory

Ah yeah, it was [6] before :slight_smile:
But since the project is (was) finished codewise, I didn't feel like optimizing even more. Especially since it fit the memory just fine with 88-90%.

Ahh, I thought I needed to add pgm_read_work() to only the array's.

Ok, this is a job for tomorrow. It's about 01:13 and have to get up early. :sweat_smile:

Thanks for the help so far!

The diagnostic show only global variables. For local ones (used in your code and in libraries) leaves only 57 bytes. This is a very strict limitation and the program can easily freeze due to lack of memory.

Here are some ATtiny85/WS2812 functions that you can try...

And a few boooring LEDs....

I reduced my arr_fade array by 1/4. Still no joy.

Global variables use 379 bytes (74%) of dynamic memory, leaving 133 bytes for local variables. Maximum is 512 bytes.

Also I've implemented pgm_read_word() on all PROGMEM'd vars. Still nothing.

I really think it's something else. Something weird with the IF or else. It's just very strange that when the setting of the arr_fade[i][2] is moved just out of\directly below the IF-statement it works fine! It's called even more and it's working - how's that for strange?

Please show your revised code

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <FastLED.h>
//CRGB(255,94,5)); // flame-like orange (RGB)
//CHSV(20, 255, 255); // 20 = flame-like orange (HSV) (h=20 for naked eye, or h=60 with red foil)

#define DATA_PIN    4 // Arduino pin 6, ATtiny85 pin 4 (4 for testing, 1 for production)
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    8
CRGB leds[NUM_LEDS];

const PROGMEM int16_t BRIGHTNESS = 255; // This is a hard limit in the loop! Always set to MAX(255) if not otherwise required.

const PROGMEM int16_t FLAMECOLOR = 20; // Flame-like orange (h=20 for naked eye, or h=60 with red foil)
const PROGMEM int16_t HUE = 255; // full orange, no saturation (h=255)
const PROGMEM int16_t MAX_BRIGHTNESS = 255; // The max set brightness of the flames. 192 Is about 75% of max.
const PROGMEM int16_t MIN_BRIGHTNESS = 28; // The minimum brightness to keep the light orange and not red.

const PROGMEM int16_t DEFAULT_BRIGHTNESS = (255 * 0.5); // TEST look at the written value vs MAX_BRIGHTNESS

const PROGMEM int16_t FADE_START = 100;
const PROGMEM int16_t END_TIME = 2450;
const PROGMEM unsigned long DEVIATION = 2;

unsigned long timeNow = millis();
unsigned long Sequence_Start = 0;
//int16_t timeNow = millis();
//int16_t Sequence_Start;

unsigned long progress_base;
int16_t pulse_1_old = 127; // TEST look at the written value vs DEFAULT_BRIGHTNESS
int16_t pulse_1 = 127; // TEST look at the written value vs DEFAULT_BRIGHTNESS
unsigned long timer_1 = 500; // one half of a second
unsigned long LED_1_start = millis();

const PROGMEM int16_t timing_count = 39;
const PROGMEM int16_t timings[] = {10,75,140,205,270,340,410,410,440,520,575,640,705,780,840,910,1010,1075,1140,1240,1310,1370,1510,1575,1640,1640,1700,1705,1770,1850,1875,1940,2000,2040,2070,2130,2140,2210,2450}; // TEST look at the written value vs END_TME
const PROGMEM int16_t timing_LEDs[] = {4,5,6,6,6,6,4,5,4,5,6,7,7,6,5,4,4,5,6,6,5,4,4,5,4,6,5,7,6,7,4,5,6,4,7,5,6,7,7};
const PROGMEM int16_t timing_LED_OnOff[] = {1,1,1,0,1,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,0,0,0,0};
int16_t arr_fade[timing_count][3];

void setup() {
  /*
  Serial.begin(9600); // For debugging
  // while the serial stream is not open, do nothing:
  while (!Serial) ;
  */

  // Create the fade array. Set the fade value (in ms) to 100 of the timing it has since the last 'on' if it is less then 100. It (should) always begin(s) with a LED to on and ends with a LED to off.
  for (int i = 0; i <= pgm_read_word(timing_count) - 2; i++) { // note the - 2 instead of the usual -1. This is because I don't need the last array item 'END_TIME'.
    if (pgm_read_word(timing_LED_OnOff[i]) == 0) { // LED that turn off
      for (int j = i - 1; j >= 0; j--) {
        if (pgm_read_word(timing_LEDs[i]) == pgm_read_word(timing_LEDs[j])) {
          arr_fade[i][0] = pgm_read_word(timings[i]) - pgm_read_word(timings[j]);
          if (arr_fade[i][0] < pgm_read_word(FADE_START)) {
            arr_fade[i][0] = pgm_read_word(timings[j]) + pgm_read_word(DEVIATION);
          } else if (arr_fade[i][0] < 0) {
            arr_fade[i][0] = 0;
          } else {
            arr_fade[i][0] = pgm_read_word(timings[i]) - pgm_read_word(FADE_START);
          }
          break;
        }
      }
    } else { // LED that turn on (aka: the rest)
      for (int j = i + 1; j <= pgm_read_word(timing_count); j++) {
        if (pgm_read_word(timing_LEDs[i]) == pgm_read_word(timing_LEDs[j])) {
          arr_fade[i][0] = pgm_read_word(timings[j]) - pgm_read_word(timings[i]);
          if (arr_fade[i][0] < pgm_read_word(FADE_START)) {
            arr_fade[i][0] = pgm_read_word(timings[j]) - pgm_read_word(DEVIATION);
          } else if (arr_fade[i][0] > pgm_read_word(END_TIME)) {
            arr_fade[i][0] = pgm_read_word(END_TIME);
          } else {
            arr_fade[i][0] = pgm_read_word(timings[i]) + pgm_read_word(FADE_START);
          }
        break;
        }
      }
    }
  }

  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(pgm_read_word(BRIGHTNESS)); // set master brightness control
  FastLED.clear(); // clear all leds
  FastLED.show(); // show... well... nothing. Not required, but does forces the clear.
}

void loop() {
  // put your main code here, to run repeatedly:
  if (millis() - Sequence_Start > pgm_read_word(END_TIME)) {
    Sequence_Start = millis();
  }
  // Pulse the bottom leds 0, 1, 2. Always
  progress_base = (millis() - LED_1_start);
  if (progress_base <= timer_1) {
    if (pulse_1 > pgm_read_word(MAX_BRIGHTNESS)) {
      pulse_1 = pgm_read_word(MAX_BRIGHTNESS);
    }
    int16_t LED_1_brightness = map(progress_base, 0, timer_1, pulse_1_old, pulse_1); // syntax: map(value, fromLow, fromHigh, toLow, toHigh)
    toggle_led(0, 1, LED_1_brightness);
    toggle_led(1, 1, LED_1_brightness);
    toggle_led(2, 1, LED_1_brightness);
  } else {
    LED_1_start = millis();  // restart fade again
    pulse_1_old = pulse_1;
    // An extra random chance for a LED to shine brighter
    if (random(0, 10) < 8) {
      pulse_1 = random(pgm_read_word(DEFAULT_BRIGHTNESS) * 0.65, pgm_read_word(DEFAULT_BRIGHTNESS) * 1.4);
      timer_1 = random(100, 250);
    } else {
      pulse_1 = random(pgm_read_word(DEFAULT_BRIGHTNESS) * 0.9, pgm_read_word(DEFAULT_BRIGHTNESS) * 1.75);
      timer_1 = random(75, 175);
    }
  }
  
  timeNow = (millis() - Sequence_Start);
  // Loop the whole array and check if there are times to fade in\out
  for (int i = 0; i <= (pgm_read_word(timing_count) - 2); i++) {
    //if ((pgm_read_word(timing_LED_OnOff[i] == 1 && timeNow >= low_milli(pgm_read_word(timings[i]) && timeNow <= high_milli(arr_fade[i][0])) || (pgm_read_word(timing_LED_OnOff[i] == 0 && timeNow >= low_milli(arr_fade[i][0]) && timeNow <= high_milli(pgm_read_word(timings[i]))) {
    if (((pgm_read_word(timing_LED_OnOff[i]) == 1) && (timeNow >= (pgm_read_word(timings[i]) - 2)) && (timeNow <= (arr_fade[i][0] + 2))) || ((pgm_read_word(timing_LED_OnOff[i]) == 0) && (timeNow >= (arr_fade[i][0] - 2)) && (timeNow <= (pgm_read_word(timings[i]) + 2)))) {
    //if (i == 1) {
      int16_t func_brightness = set_LED_brightness(i);
      fade_LED(pgm_read_word(timing_LEDs[i]), func_brightness);
    } else {
      //leds[7] = CHSV(FLAMECOLOR, HUE, 255);
      //FastLED.show();
      arr_fade[i][1] = pgm_read_word(DEFAULT_BRIGHTNESS);
    }
  }

  // Set all changes to the LEDs! Without this, no NeoPixel will change state
  FastLED.show();
}

/*
// Return the imput milliseconds - 2 for a bit of margin on the low end (milliseconds are not always exactly reached)
unsigned long low_milli(unsigned long cur_milli) {
  //unsigned long return_milli = (cur_milli - DEVIATION);
  //return return_milli;
}

// Return the imput milliseconds + 2 for a bit of margin on the high end (milliseconds are not always exactly reached)
unsigned long high_milli(unsigned long cur_milli) {
  //unsigned long return_milli = (cur_milli + DEVIATION);
  //return return_milli;
}
*/

// Set the chosen led to the default color and hue to a given brightness
void fade_LED(int16_t lednr, int16_t brightness) {
  /*
  // Fade the LED to it's new brightness value. If the brightness is less then the color allows (28 in the case of the flameorange), just turn the LED off.
  if (brightness < MIN_BRIGHTNESS) {
    toggle_led(lednr, 0, 0);
  } else {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(FLAMECOLOR, HUE, brightness);
    }
    leds[lednr] = CHSV(FLAMECOLOR, HUE, brightness);
  }
  */
}

// Toggle the given LED on or off. If the LED is nr 4, automatically do the same with 3. If it's on, use the given brightness. If off, always set brightness to 0 for off.
void toggle_led(int16_t lednr, int16_t OnOff, int16_t func_Brightness) {
  if (OnOff == 1) {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(pgm_read_word(FLAMECOLOR), pgm_read_word(HUE), func_Brightness);
    }
    leds[lednr] = CHSV(pgm_read_word(FLAMECOLOR), pgm_read_word(HUE), func_Brightness);
  } else {
    if (lednr == 4) {
      leds[lednr - 1] = CHSV(pgm_read_word(FLAMECOLOR), pgm_read_word(HUE), 0);
    }
    leds[lednr] = CHSV(pgm_read_word(FLAMECOLOR), pgm_read_word(HUE), 0);
  }
}

// Fade a given led. It is faded within the timeframe of 50ms (of less if the last action of that LEDnr was less ms ago). From the default brightness to 0 if time allows.
int16_t set_LED_brightness(int16_t arraynr) {
  /*
  arr_fade[arraynr][2] = millis() - arr_fade[arraynr][2];
  if (pgm_read_word(timing_LED_OnOff[arraynr]) == 0) {
    arr_fade[arraynr][1] = map(arr_fade[arraynr][2], 0, pgm_read_word(timings[arraynr]) - arr_fade[arraynr][1], DEFAULT_BRIGHTNESS, 0);
    if (arr_fade[arraynr][1] < 0) {
      arr_fade[arraynr][1] = 0;
    }
  }
  if (pgm_read_word(timing_LED_OnOff[arraynr]) == 1) {
    arr_fade[arraynr][1] = map(arr_fade[arraynr][2], 0, pgm_read_word(timings[arraynr]) - arr_fade[arraynr][1], 0, DEFAULT_BRIGHTNESS);
    if (arr_fade[arraynr][1] > DEFAULT_BRIGHTNESS) {
      arr_fade[arraynr][1] = DEFAULT_BRIGHTNESS;
    }
  }
  return arr_fade[arraynr][1];
  */
  return 20; // TEST TEST TEST
}