Hi everyone,
this one has me stuck for a couple of nights now and I think I need you help to figure it out. I'm writing to a strip of ws2812b LEDs and I am simulating every second one drop that is falling until it reaches a "surface" of solid color. On impact, the drop's color blends into the solid color.
To do that, I store the time of drop impact in a variable "DropImpactMillis" and then fade out in every loop() iteration according to the drop's age (Difference between millis() and the stored time). 750ms for the fade out looks good to me.
This works quite nicely and looks like I wanted it to. Unfortunately, this only works for short strips and high gravity (where I have more than the 750ms for the fade-out) because every new drop falling breaks the animation of the fade-out. It's weird to me because the two have nothing to so with oneanother and apparently my variable "DropImpactMillis" gets changed by an unknown function.
This is my code (should be sufficient to look at loop() only):
#include <DS1307RTC.h>
#include <TimeLib.h>
#include <DCF77.h>
#include <FastLED.h>
FASTLED_USING_NAMESPACE
bool inflight = false;
unsigned long DropImpactMillis = 0;
unsigned long DropFallingMillis = 0;
int FallingDropPos = 0;
time_t LastIChecked;
#define DATA_PIN_UpperRow 11 //Hardware SPI - data 11, clock 13
#define DATA_PIN_BottomRow 10 //USART SPI - data 1, clock 4
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS 14
#define LEDS_PER_M 60
#define STANDARD_GRAVITY 9.80665
//#define STANDARD_GRAVITY 0.5
#define FRAMES_PER_SECOND 120
#define MAXLENGTHDROPS 5
CRGB leds_UpperRow[NUM_LEDS];
CRGB leds_BottomRow[NUM_LEDS];
CRGB RGBs_Drop[MAXLENGTHDROPS];
void setup() {
// // Serial Monitor Communication. Delete when done.
Serial.begin(57600);
while (!Serial) ; // wait until Arduino Serial Monitor opens
//Bei jedem Einschalten: Zeit aus der RTC lesen
setSyncProvider(RTC.get); // the function to get the time from the RTC
setSyncInterval(600); // Set the number of seconds between re-sync (600 = 10 Minutes) --> now() triggers it
// if(timeStatus()!= timeSet)
// Serial.println("Unable to sync with the RTC");
// else
// Serial.println("RTC has set the system time");
// tell FastLED about the LED strip configuration
FastLED.addLeds<LED_TYPE,DATA_PIN_UpperRow, COLOR_ORDER>(leds_UpperRow, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE,DATA_PIN_BottomRow,COLOR_ORDER>(leds_BottomRow, NUM_LEDS).setCorrection(TypicalLEDStrip);
// set master brightness control
LEDS.setBrightness(84);
FastLED.setMaxPowerInMilliWatts(500);
}
void FadeOutDrop(CRGB (&leds)[NUM_LEDS], int beginning, int width, CRGB color, double decayMillis, double ageMillis){
if (ageMillis<decayMillis) {
fill_solid(RGBs_Drop, MAXLENGTHDROPS, CRGB::Black); // clear the overlay
fill_gradient_RGB(RGBs_Drop, 0, color, width, CRGB::Black); // prepare the overlay
int age = 255.0 * ageMillis / decayMillis; //"age" the overlay
fadeToBlackBy(RGBs_Drop, MAXLENGTHDROPS, age);
for( int i = 0 ; i < width ; i++) { // put at the right place and simply add to what is already there.
leds[i+beginning] += RGBs_Drop[i];
}
}
}
int GetFallingDropPos(float freefallMillis, CRGB color){
float f;
f = STANDARD_GRAVITY * freefallMillis/1000; // Velocity
f = f * 0.6; // Scale the length of the tail. Should be around 0.1 for long strips and Standard-Gravity.
fill_solid(RGBs_Drop, MAXLENGTHDROPS, CRGB::Black); // clear the overlay
fill_gradient_RGB(RGBs_Drop, 0, color, 3, CRGB::Black); // prepare the overlay. Replace 3 with f but doesn't work. ??
f = STANDARD_GRAVITY * freefallMillis/1000 * freefallMillis/1000 / 2; // Distance fallen in m
return (f*LEDS_PER_M);
}
void loop() {
EVERY_N_SECONDS( 1 ) {
DropFallingMillis = millis();
inflight = true;
LastIChecked = now();
}
fill_solid(leds_UpperRow, NUM_LEDS, CRGB::Black); // Clear the strip
fill_gradient_RGB(leds_UpperRow, 10, CRGB::Red, 10+4, CRGB::Black); // Write the time
if (inflight) {
FallingDropPos = GetFallingDropPos(millis()-DropFallingMillis, CRGB::Blue);
if (FallingDropPos > 10) { // Eigentlich: Größer als Abstand zur Oberfläche in Pixeln
Serial.print("Set @ ");
DropImpactMillis = millis(); // Initiate dissolving drop on contact with surface.
Serial.println(DropImpactMillis);
inflight = false;
FallingDropPos = 10; //Paint one last time, at the moment of impact
}
for( int i = 0 ; i < MAXLENGTHDROPS ; i++) { // put at the right place
leds_UpperRow[FallingDropPos-i] = RGBs_Drop[i]; // tail fades out
}
}
Serial.print(millis());
Serial.print(" - ");
Serial.print(DropImpactMillis);
Serial.print(" = ");
Serial.println(millis()-DropImpactMillis);
FadeOutDrop(leds_UpperRow, 10, 4, CRGB::Green, 750.0, (millis()-DropImpactMillis)); // Let the drops glow after impact
FastLED.show();
FastLED.delay(1000/FRAMES_PER_SECOND); // Maybe unnecessary with all the other clock stuff I'll be running on the side.
}
As you can see, the variable is only ever set to 0 (on creation) and millis() (on every impact) but this is get from my debugging (DropImpactMillis is in the 2nd "column" of this output):
Set @ 6202 // on impact
6202 - 6202 = 1
6212 - 6202 = 10
6224 - 6202 = 22
6235 - 6202 = 33
6247 - 6202 = 45
6257 - 6202 = 55
6269 - 6202 = 67
6280 - 6202 = 78
6292 - 6202 = 90
6302 - 6202 = 100
6315 - 6202 = 113
6325 - 6202 = 123
6337 - 6202 = 135
6347 - 6202 = 145
6360 - 6202 = 158
6370 - 6202 = 168
6382 - 6202 = 180
6392 - 6202 = 190
6403 - 6202 = 201
6415 - 6202 = 213
6427 - 6202 = 225
6437 - 6202 = 235
6448 - 6202 = 246
6460 - 6202 = 258
6470 - 6202 = 268
6482 - 6202 = 280
6493 - 6202 = 291
6505 - 6202 = 303
6515 - 6202 = 313
6528 - 6202 = 326
6538 - 6202 = 336
6550 - 6202 = 348
6560 - 6202 = 358
6573 - 6202 = 371
6583 - 6202 = 381
6595 - 6202 = 393
6605 - 6202 = 403
6616 - 6202 = 414
6628 - 6202 = 426
6640 - 6202 = 438
6650 - 6202 = 448
6661 - 6202 = 459
6673 - 6202 = 471
6685 - 6202 = 483
6695 - 6202 = 493
6706 - 6202 = 504
6718 - 6202 = 516
6730 - 6202 = 528
6740 - 6202 = 538
6753 - 6202 = 551
6763 - 6202 = 561
6775 - 6202 = 573
6786 - 6202 = 584
6798 - 6202 = 596
6808 - 6202 = 606
6818 - 6202 = 616
6828 - 6202 = 627
6841 - 6202 = 639
6853 - 6202 = 651
6863 - 6202 = 661
6873 - 6202 = 672
6886 - 6202 = 684
6898 - 6202 = 696
6908 - 6202 = 706
6918 - 6202 = 717
6931 - 6202 = 729
6943 - 6202 = 741
6953 - 6202 = 751
6966 - 6202 = 764
6976 - 6202 = 774
6988 - 6202 = 786
6999 - 6202 = 797
7011 - 5570560 = 4289403748 // This is the time the new drop starts falling. Totally unrelated in my understanding!? And where is that value coming from!? It's the same value always, not time related.
7021 - 5570560 = 4289403758
7031 - 5570560 = 4289403768
7042 - 5570560 = 4289403778
7054 - 5570560 = 4289403791
7067 - 5570560 = 4289403803
7079 - 0 = 7079 // Here again! The variable nevery gets zero (except in its original initiation) but here it is!?
7090 - 0 = 7090
7102 - 0 = 7102
7114 - 0 = 7114
7124 - 0 = 7124
7137 - 0 = 7137
7147 - 0 = 7147
7159 - 0 = 7159
7170 - 0 = 7170
7182 - 0 = 7183
7192 - 0 = 7192
7204 - 0 = 7205
I've had some trouble with variable types as well, so don't be confused by my explicit and "colorful" type casting. It cannot be at the heart of this problem, however, because this one always is and unsigned long...
Thank you, your help is much appreciated!
Hajo