Your code is currently written as blocking, so we can leave it that way and add another blocking nested loop. Let's take the colorWipeUP()
function as example:
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
setPixel(i, red, green, blue);
FastLED.show();
delay(SpeedDelay);
}
}
You go through all leds, lighting them up one after another with the provided color, delaying between the LEDs. The brightness of an LED is controlled by the overall RGB value. If you just multiply the RGB components red, green and blue with a number between 0 and 1, you (mostly) keep the color and only control the brightness. For example like this:
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
for(uint8_t brightness = 0; brightness <= 100; brightness++){
setPixel(i, red*brightness/100, green*brightness/100, blue*brightness/100);
FastLED.show();
delay(fadeDelay);
}
delay(SpeedDelay);
}
}
For every LED we are now going from zero brightness to 100% brightness in a loop, showing each individual step on the LED strip. fadeDelay
determines, how fast this fade in should be. You will have to tune both delays to fit your expectations. You can use the same principle for the wipe down.
You may be asking yourself, why I count from 0 to 100 and then dividing by 100 instead of directly counting from 0 to 1 in steps of 0.01. I've done this, because on AVR based microcontrollers you don't have native floating point calculations. This means, that every floating point calculation needs many instructions to execute (because the floating point math is implemented in software instead of hardware). Here I'm counting with integers and when calculating the brightness also only integer math is involved (dividing by 100 is an integer division, which will automatically cut all digits after the decimal point. We don't need them).
Note: With 300 LEDs, the call to FastLED.show()
will take some time. I haven't tested the code, but depending on your needs the fading might be too slow, even when you remove the delay call. Then you can simply increase the increment of the for loop, for example to use 10 steps instead of 100:
for(uint8_t brightness=0; brightness<100; brightness+=10)
something like a fade over 10 LEDs
For this I would use a totally different approach. If you view it mathematically, the brightness of each LED is a function of position and time. So we can implement a function much like a mathematical function, that returns the brightness for a given position and a given time. As I understood, you want the a function, that is first constantly zero, then it grows linearly with time and position and then it is constantly full brighntess. We can count the time from the moment, that the sensor is triggered, where we then start with zero brightness and let it rise linearly. Something like this:
int fadeBrightness(int position, unsigned long time){
int brightness = m_p*position+m_t*time;
if(brightness > 100) return 100;
if(brightness < 0) return 0;
return brightness;
}
m_p
and m_t
are constants, that you would need to define and fine tune. For fading over 10 LEDs, m_p
has to be -10
. time
is provided as milliseconds. I'm currently not sure about the value of m_t
, but you can simply try some values and use one that's fitting.
Then in your colorWipeUP()
function you can loop through all LEDs and set their pixel just like in the code above, but this time you use the newly created function.
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
unsigned long timestamp = millis();
while(millis()-timestamp < duration){
for (uint16_t i = 0; i < NUM_LEDS; i++) {
setPixel(i, red*fadeBrightness(i, millis()-timestamp)/100, green*fadeBrightness(i, millis()-timestamp)/100, blue*fadeBrightness(i, millis()-timestamp)/100);
}
FastLED.show();
}
}
You need to define the duration
according to how long the fading will take with your m_t
. If you set it longer, the loop will just loop longer, holding the brightness at 100%.
In the function we first create a timestamp from the millis()
function. Then we loop, while the duration of the effect hasn't passed. In each while loop iteration, we set the color components of each LED pixel with the brightness according to our fadeBrightness()
function. Then we show this on the LED strip. The function is constantly updating the strip at max speed. The actual speed of the animation is determined by the fadeBrightness()
function.
This version is also blocking code, but it can easily be transformed to non-blocking code, that you would call repeatedly until the animation is done.
analogWrite
and pulsed width modulation, or PWM, for how to fade LEDs.