Go Down

Topic: [GELÖST] Wie FastLED Animation bzw. Effekt überlagern? (Read 5181 times) previous topic - next topic

Verzweifler

#30
Oct 12, 2018, 11:49 pm Last Edit: Oct 13, 2018, 12:07 am by Verzweifler
So mal kurz rumgespielt:

Code: [Select]
/******* Skylight *******/

/******* Adafruit Pro Trinket, 1m APA102C LED strip *******/

/******* LIBRARIES *******/

#include "FastLED.h"

/******* VARIABLES *******/

const byte pinData = 3;
const byte pinClock = 4;

const byte ledCount = 144; // Standard number for 1m APA102C LED strip
byte maxBrightness = 255; // Values from 0 - 255, can be changed interactively with a potentiometer

DEFINE_GRADIENT_PALETTE(testSky) {
  0,  33, 55, 153,
  25,  80, 119, 197,
  89, 153, 215, 250,
  95, 199, 233, 252,
  102, 255, 255, 255,
  120, 197, 219, 240,
  147, 150, 187, 223,
  200, 159, 171, 172,
  255, 169, 154, 128
};

CRGBPalette16 activePalette = testSky;

struct CRGB leds[ledCount];

/******* FUNCTIONS *******/

void setup() {
  LEDS.addLeds<APA102, pinData, pinClock, BGR>(leds, ledCount); // BGR for APA102C LED strips
  LEDS.setBrightness(maxBrightness);
  LEDS.setCorrection(UncorrectedColor); //LEDS.setCorrection(Candle); or (Tungsten40W)
} // End of setup

void loop() {
  sky();
  shimmer();
  FastLED.delay(100);
} // End of loop

void sky() { // Static variables local to the function, but persist between calls

  static const float transitionDuration = 1; // Minutes (10 minutes: one step = 2343.75 ms; 1 hour = 14062.5 ms)
  static const float interval = ((float)(transitionDuration * 60) / 256) * 1000; // Steps in milliseconds
  static byte paletteIndex = 0; // Current gradient palette colour

  CRGB colour = ColorFromPalette(activePalette, paletteIndex, 255, LINEARBLEND); // Or use a built-in palette
  fill_solid(leds, ledCount, colour); // Set whole strip to colour fetched from the palette

  EVERY_N_MILLISECONDS(interval) { // Timed palette traversal
    if (paletteIndex < 240) { // Don't use 255, see https://github.com/FastLED/FastLED/issues/515#issuecomment-340627525
      paletteIndex++;
    }
  }
} // End of sky

#define NORMAL_BRIGHTNESS 127
#define SHIMMER_AMOUNT 100
#define CHANCE_OF_SHIMMER 20 //Higher => lower chance
void shimmer() {
  for (int led = 0; led < ledCount; led++) {

    if (random8(CHANCE_OF_SHIMMER) == 0) {
      if (random8(2)) { //Brighter
        leds[led].fadeToBlackBy(255 - (NORMAL_BRIGHTNESS - SHIMMER_AMOUNT));
      }
      else { //Darker
        leds[led].fadeToBlackBy(255 - (NORMAL_BRIGHTNESS + SHIMMER_AMOUNT));
      }
    }

    else { //If no shimmer is applied
      leds[led].fadeToBlackBy(255 - NORMAL_BRIGHTNESS);
    }
  }
} //shimmer()


Ich hoffe mal die #defines vor shimmer() sind erlärend genug :P
Ich habe die Werte für die Normale Helligkeit und wie stark der Effekt ist mal überdimensioniert, um den Effekt gut sehen zu können.

Was noch dazugekommen ist ist FastLED.delay(100);
Einfach um den Effekt ordentlich zu sehen.

Und ja, mein Code ist nicht perfekt, aber als Vorlage wie es zumindest funktioniert reichts.

Grüße

Edit:

Mal schnell was getestet:
Code: [Select]
#define NOISESCALE 16

void cloudySky() {
  static uint32_t dist;
  byte offset = millis() / 5000;
  for (int i = 0; i < ledCount; i++) {
    uint8_t index = inoise8(i * NOISESCALE, dist + i * NOISESCALE) % 255;
    leds[i] = ColorFromPalette(CloudColors_p, index, 255, LINEARBLEND);
  }
  EVERY_N_MILLISECONDS(20) dist += beatsin8(6, 0, 6);
}


Soll Wolkigen Himmel simulieren, wahlweise auch mit shimmer(). Das FastLED.delay(100); würde ich aber vorher rausnehmen.

Grüße

Lagom

#31
Oct 13, 2018, 01:46 am Last Edit: Oct 13, 2018, 02:03 am by Lagom
@Verzweifler

Vielen Dank, das kommt der gesuchten Sache äußerst nahe. Der FastLED-Bezeichnung der method nach hätte ich nicht gedacht, daß man

Code: [Select]
leds[i].fadeToBlackBy(#);
für beide Fälle, also aufhellen/abdunkeln benutzen könnte, von einem Normalwert NORMAL_BRIGHTNESS ausgehend. Mit Ihrem sketch wird die Farbe beim Abdunkeln auch nicht verfälscht, wie bei meinen Stümpereien; das ist gut.

Der Schimmer-Effekt, den ich bereits hatte, funktionierte bereits gut; weiches Abdunkeln/Aufhellen und das recht langsam. Allerdings ist der Effekt bei einem FastLED.delay(128); immer noch zu schnell bzw. hektisch, und je höher der delay-Wert, desto stufiger sieht der Schimmer aus.

Im englischsprachigen Forum sagte man mir vor längerem, daß an Stelle von delay besser EVERY_N_MILLISECONDS und seine Verwandten zu benutzen wären. Aber das ist hier wohl erstmal zweitrangig - Hauptsache, es schimmert so gemächlich wie möglich, da der quasi wolkige Hauptteil sich über acht Stunden hinzieht und nicht wie das Flackern in einer Diskothek aussehen sollte.

Ich haben den shimmer() sketch hier noch einmal angefügt, dann können Sie sehen, daß er für sich stehend gut funktioniert, von der natürlich unschönen Stufigkeit einmal abgesehen.

Code: [Select]
#include "FastLED.h"

const byte pinData = 3;
const byte pinClock = 4;

const byte ledCount = 144;
byte maxBrightness = 255; // Can be changed on the fly; 10k potentiometer, etc.

#define DARKEST_COLOUR CRGB(24,32,27)
#define BRIGHTEST_COLOUR CRGB(218,226,221)
#define DARKEN_LED CRGB(7,7,7)
#define BRIGHTEN_LED CRGB(23,23,23)

enum {ledConstant, ledBrightens, ledDarkens}; // A flag for the LED states
byte ledState[ledCount];

struct CRGB leds[ledCount];

void setup() {
  LEDS.addLeds<APA102, pinData, pinClock, BGR>(leds, ledCount);
  LEDS.setBrightness(maxBrightness);
  LEDS.setCorrection(Candle); // Candle too warm, Tungsten40W too cold - in-between correction how?
  memset(ledState, ledConstant, sizeof(ledState)); // Set all LEDs to constant state
  fill_solid(leds, ledCount, DARKEST_COLOUR);
}

void loop()
{
  shimmer();
  FastLED.show();
  FastLED.delay(128); // Higher number = slower, but introduces "steppiness" : (
}

void shimmer()
{
  for ( byte i = 0; i < ledCount; i++) { // Go through the entire strip
    if ( ledState[i] == ledConstant) { // If LED is in constant state...
      if ( random8() < 7) { // ...randomly select it based on a threshold (higher number = busier shimmer)...
        ledState[i] = ledBrightens; // ...and set it to brightening state
      }

    } else if ( ledState[i] == ledBrightens ) { // If LED is in brightening state...
      if ( leds[i] >= BRIGHTEST_COLOUR ) { // ...and reached brightest colour...
        ledState[i] = ledDarkens; // ...set it to darkening state
      } else {
        leds[i] += BRIGHTEN_LED; // If not, continue brightening it
      }

    } else {
      if ( leds[i] <= DARKEST_COLOUR ) { // If LED reached darkest colour...
        leds[i] = DARKEST_COLOUR; // ...keep it there...
        ledState[i] = ledConstant; // ...and set it to constant state
      } else {
        leds[i] -= DARKEN_LED; // If not, continue darkening it
      }
    }
  }


Quote
Wolkigen Himmel simulieren
Damit haben Sie den Nagel genau auf den Kopf getroffen. Langsames, weiches, gemütliches Schimmern. Nochmals vielen Dank soweit!

Verzweifler

Freut mich zu hören, dass es soweit passt.

Als der Shimmer Effekt soll nun zufällige LEDs langsam heller/dunkler machen?

Das kann eventuell etwas knifflig werden, ich würde da ein extra daten array für nutzen um zustände der Leds zu speichern und für das heller/dunkler faden.
Dank 2KB RAM hat man zum Glück genug Speicher.

Oder mit perlin noise das Shimmern machen! Noise hab ich schon bei meiner cloudySky Animation genutzt. Das kann auch was werden...

Da werd ich mal ein bisschen rumprobieren, gute Animationen schreiben ist wahre Kunst.

Aber nochwas nebenbei:

Du willst nun mehrere Systeme aus Trinket Pro und Leds installieren, welche alle die gleiche Animation abspielen sollen, richtig?

Da könnten sich dann die Schwankungen des Oszillators der Trinkets bemerkbar machen.

Wenn du noch die sky() Animation aus deinem ersten Post zum einfärben der LEDs nimmst kann der Himmel von System zu System unterschiedliche Farben haben, ob man das nach 8 Stunden Betrieb bemerkt ist eine andere Frage, aber mal dran denken sollte man schon.

Ne schnelle Lösung wäre es, dass ein Trinket einen Impuls zum hochzählen von paletteIndex an die restlichen Systeme schickt.

Gruße




Lagom

#33
Oct 13, 2018, 09:08 pm Last Edit: Oct 13, 2018, 09:10 pm by Lagom
Quote
Als der Shimmer Effekt soll nun zufällige LEDs langsam heller/dunkler machen?
Richtig, wie im shimmer() sketch, den ich im vorangegangenen Kommentar eingefügt hatte; wenn Sie ihn hochladen, sehen Sie, daß er für sich alleine genommen sehr gut funktioniert. Ich muß ihn nur so umbauen, daß er das macht, was Ihr Beispiel gezeigt hat - nämlich daß man problemlos den von einer gradient palette dauerbeschriebenen leds array mit einer separaten Funktion manipulieren kann.

Da die von mir eingefügte recht ähnlich Ihrer shimmer-routine ist, denke ich nicht, daß ein zusätzlicher array gebraucht wird, oder? Vielleicht haben Sie noch einen Hinweis für mich, wie das zu bewerkstelligen wäre? Eine separate shimmer() Funktion mit eigenem EVERY_N_MILLISECONDS timing ließe sich dann auf viele andere sketches mit gradient palette anwenden.

Es sollen alle Trinkets, ich denke am Ende 16 Stück mit je einem Streifen, betrieben werden, die alle relativ ähnliche gradient palettes abspielen sollen. Sie unterscheiden sich nur minimal in den Palettenfarben und der Schimmer-Geschwindigkeit. Das einzige, was bei allen gleich ist, ist die Dauer von Sonnenaufgang, Tag, und Sonnenuntergang. Aber wenn es da Abweichungen von ein paar Minuten gibt, ist das nicht weiter von Belang, da alles sehr langsam und unmerklich von Statten geht.

Lagom

#34
Oct 15, 2018, 10:10 pm Last Edit: Oct 16, 2018, 08:53 am by Lagom
@Verzweifler

Also Ihre shimmer() Funktion funktionierte ja gut, nur "blinken" die LEDs nicht langsam und weich, wie in meinem standalone shimmer() sketch weiter oben. Man müßte beide vielleicht "verheiraten"? Wenn ich meinen shimmer() sketch einfach sozusagen schimmerlos hinzufüge, wie im Beispiel hier ganz unten, sehe ich, daß ganz am Anfang die LEDs für vielleicht eine Sekunde schimmern, dann aber nicht mehr, während die gradient palette schön ihr Ding macht. Ich schätze, das liegt unter Anderem an den zwei Bedingungen

Code: [Select]
#define DARKEST_COLOUR CRGB(16,16,16)
#define BRIGHTEST_COLOUR CRGB(128,128,128)
...
if ( leds[i] >= BRIGHTEST_COLOUR )
if ( leds[i] <= DARKEST_COLOUR )

wo ein Test darauf nicht funktioniert. Für einen zweiten Zähl-array

Code: [Select]
byte ledState[ledCount];
ist im Pro Trinket genug Platz, oder?

Hätten Sie vielleicht noch eine Idee, wie beides zusammenzubringen wäre? Jede LED braucht ja sozusagen einen "Umkehrpunkt", abgesehen von der zufälligen Auswahl. Vielleicht ließe sich das nötige state flag ledConstant, ledBrightens, ledDarkens mit Ihrem "Zufallsprinzip" setzen, anstatt auf BRIGHTEST_COLOUR und DARKEST_COLOUR zu testen? Also die Schimmerfunktion von Farb- bzw. Helligkeitswerten unabhängig zu machen, wie in Ihrem Beispiel?


Ich habe nur eine Schachtel voll Trinkets, kann also keine Zahlen zu Testzwecken über den serial port ausgeben, das wäre sicherlich hilfreich; wo ich gerade bin, kann ich leider so bald keinen anderen µC bekommen.

Code: [Select]
#include "FastLED.h"

const byte pinData = 3;
const byte pinClock = 4;

const byte ledCount = 144; // Standard number for 1m APA102C LED strip
byte maxBrightness = 255; // Values from 0 - 255; can be changed on the fly via sensor, 10k potentiometer, etc.

DEFINE_GRADIENT_PALETTE(testPalette) {
 0, 255, 0,  0,
  128,  0,  255,  0,
  255,  0,  0,  255
};

CRGBPalette16 activePalette = testPalette;

struct CRGB leds[ledCount];

void setup() {
  LEDS.addLeds<APA102, pinData, pinClock, BGR>(leds, ledCount); // BGR for APA102C LED strips
  LEDS.setBrightness(maxBrightness);
  LEDS.setCorrection(UncorrectedColor); //LEDS.setCorrection(Candle) or (Tungsten40W), etc.
} // End of setup

void loop() {
  sky();
  shimmer();
  FastLED.show();
} // End of loop

void sky() { // Static variables local to the function, but persist between calls

  static const float transitionDuration = 2; // Minutes (10 minutes: one step = 2343.75 ms; 1 hour = 14062.5 ms)
  static const float interval = ((float)(transitionDuration * 60) / 256) * 1000; // Steps in milliseconds
  static byte paletteIndex = 0; // Current gradient palette colour

  CRGB colour = ColorFromPalette(activePalette, paletteIndex, maxBrightness, LINEARBLEND); // Or use a built-in palette
  fill_solid(leds, ledCount, colour); // Set whole strip to colour fetched from the palette

  EVERY_N_MILLISECONDS(interval) { // Timed palette traversal
    if (paletteIndex < 240) { // Don't use 255, see https://github.com/FastLED/FastLED/issues/515#issuecomment-340627525
      paletteIndex++;
    }
  }
}

#define DARKEST_COLOUR CRGB(16,16,16) // How to determine from palette?
#define BRIGHTEST_COLOUR CRGB(128,128,128) // How to determine from palette?
#define DARKEN_LED CRGB(32,32,32)
#define BRIGHTEN_LED CRGB(16,16,16)

enum {ledConstant, ledBrightens, ledDarkens}; // A flag for the LED states
byte ledState[ledCount]; // Array of states of all LEDs

void shimmer()
{
  for ( byte i = 0; i < ledCount; i++) { // Go through the entire strip
    if ( ledState[i] == ledConstant) { // If LED is in constant state...
      if ( random8() < 11) { // ...randomly select it based on a threshold (higher number = busier shimmer)...
        ledState[i] = ledBrightens; // ...and set it to brightening state
      }

    } else if ( ledState[i] == ledBrightens ) { // If LED is in brightening state...
      if ( leds[i] >= BRIGHTEST_COLOUR ) { // ...and reached brightest colour...
        ledState[i] = ledDarkens; // ...set it to darkening state
      } else {
        leds[i] += BRIGHTEN_LED; // If not, continue brightening
      }

    } else {
      if ( leds[i] <= DARKEST_COLOUR ) { // If LED reached darkest colour...
        leds[i] = DARKEST_COLOUR; // ...keep it there...
        ledState[i] = ledConstant; // ...and set it to constant state
      } else {
        leds[i] -= DARKEN_LED; // If not, continue darkening
      }
    }
  }
}

Verzweifler

Servus:

Thema RAM: Der Trinket Pro basiert auf dem Atmega328P, der gleiche AVR wie im Uno, Nano,... Der hat 2kb RAM, das reicht locker.

Meine Noise Idee hat übrigens nicht so funktioniert, daher versuche ichs mal so:

Die Color Twinkle Animation von Mark Kriegsman (https://gist.github.com/kriegsman/5408ecd397744ba0393e) macht eigentlich genau das, was du willst. Nur eben mit Farbe.

Ich versuch mich mal daran, dass ich die Animation so umschreibe, dass sie nun ein array mit Helligkeiten füllt.

Mal schauen...

Grüße.

Lagom

Vielleicht ist

leds.getAverageLight();

die Lösung? Zu Beginn des for-loops von schimmer(), vor den if-statements, könnte ich so die Helligkeit von leds erhalten und dann für die drei LED states testen?

Eine Bing-Suche danach bringt leider kaum Ergebnisse.

Verzweifler

Code: [Select]
leds.getAverageLight()

Der Befehl gibt aber die Durchschnittliche Helligkeit des kompletten Arrays zurück. (Glaube ich?!)

Für einzelne Leds gibts da extra Funktionen. Steht in der Doku.

Lagom

@Verzweifler

Danke!

Was der Herr Kriegsmann da hat, sieht zumindest für mich als Laien etwas verquast aus. Was Sie da hatten (nur blizte es eben, anstatt zu schimmern), bzw. was ich da als alleinstehender sketch hier postete, war doch schon ganz nah am Ergebnis?

Das Ziel ist ja, via EVERY_N_IRGENDEINE_ZEIT zu irgendwelchen anderen Effekten, hier eine gradient palette, einen Schimmer hinzuzufügen, der einfach stumpf die Helligkeit von was immer sich im leds array befindet variiert. Der shimmer() wird sozusagen nach Belieben and das, was schon da ist, angeflanscht.

Aber vielleicht kann man mit FastLED keine dergestalt modularen sketches umsetzen? Ich kann das mangels Erfahrung nicht beurteilen.

Tommy56

FastLED ist gut dokumentiert. Die beste Doku ist aber der Quelltext.

Gemäß dem Motto: Use the source, Luke.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Lagom

#40
Oct 16, 2018, 08:44 pm Last Edit: Oct 16, 2018, 08:48 pm by Lagom
Für einzelne Leds gibts da extra Funktionen. Steht in der Doku.
Ich habe diese Funktionen noch nicht gefunden. Im FastLED WIKI steht allerdings:

The library also provides functions for looking up the apparent (or mathematical) brightness of a color.

Code: [Select]
// Get brightness, or luma (brightness, adjusted for eye's sensitivity to
// different light colors.   See http://en.wikipedia.org/wiki/Luma_(video) )
uint8_t luma = leds[i].getLuma();
uint8_t avgLight = leds[i].getAverageLight();

Ich finde die Namensgebung vieler Funktionen bei FastLED etwas, sagen wir mal vorsichtig, altfränksch bzw. mehrdeutig. Aber ich bin ein alter Sack aus dem Analogzeitalter.

Verzweifler

Naja FastLED hat dermaßen viele Funktionen, dass man da leicht den überblick verliert oder eher andauernd neue Funktionen findet.

Da hilft nur Doku lesen und sich die Sketche von möglichst vielen Animationen ansehen!

FastLED ist durchaus dazu fähig, das zu machen, was du willst. Aber es ist das gleiche Problem wie bei anderen Arduino Projekte: Seine Gedanken und Vorstellungen in Code zu übersetzen.

Daran hakts grad auch bei mir...

Also Version B doch mit Perlin Noise:

Code: [Select]
void shimmerySky(){
  #define NOISESCALE 50
  #define MIN_BRIGHTNESS 20
  #define MAX_BRIGHTNESS 225

  static const float transitionDuration = 2; // Minutes (10 minutes: one step = 2343.75 ms; 1 hour = 14062.5 ms)
  static const float interval = ((float)(transitionDuration * 60) / 256) * 1000; // Steps in milliseconds
  static byte paletteIndex = 0; // Current gradient palette colour
 
  static uint32_t dist;
  for (int i = 0; i < ledCount; i++) {
    uint8_t brightness = map(inoise8(dist - i * NOISESCALE, dist + i * NOISESCALE) % 255, 0, 255, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
    leds[i] = ColorFromPalette(activePalette, paletteIndex, brightness, LINEARBLEND);
  }

  //Manipulate Speed in function below: beatsin8(bpm, min, max);
  dist += beatsin8(10, 2, 8);

  EVERY_N_MILLISECONDS(interval) { // Timed palette traversal
    if (paletteIndex < 240) { // Don't use 255, see https://github.com/FastLED/FastLED/issues/515#issuecomment-340627525
      paletteIndex++;
    }
  }
}


Grüße

Lagom

#42
Oct 17, 2018, 08:23 am Last Edit: Oct 17, 2018, 08:30 am by Lagom
Quote
Da hilft nur Doku lesen und sich die Sketche von möglichst vielen Animationen ansehen!
Da haben Sie sicherlich Recht; ich habe auch schon viele Animationen gefunden, also deren code versucht nachzuvollziehen, allerdings bisher nur, sagen wir mal, "Diskothekeneffekte", gefunden, bei denen viel Buntes animiert wird, aber keine Dokumentation, bzw. Animationen, in denen man grundsätzliche Funktionen sehen könnte, wie z. B.

Code: [Select]
leds[i].getBrightness()
leds[i].setBrightness()
leds[i].darken()
leds[i].brighten()

Im englischsprachigen Arduino-Forum wies man mich des Öfteren darauf hin, daß es für Anfänger, wichtig sei, den code zu modularisieren, also

- Eine Funktion() füllt den leds array
- Eine Funktion() moduliert unabhängig davon die Farbe aller oder ausgewählter leds array Elemente
- Eine Funktion() moduliert unabhängig davon die Helligkeit aller oder ausgewählter leds array Elemente
- Eine Funktion() ist für Zufall zuständig
- usw.

so daß man am Ende eine Reihe von Funktionen hat, die sich je nach gewünschtem Effekt beliebig zusammensetzen und in loop() vor FastLED.show() aufrufen lassen.

Aber gut, ich kann das nicht beurteilen und versuche es also weiter, mit Ihrer "Perlin noise" sowie

Code: [Select]
uint8_t luma = leds[i].getLuma();
uint8_t avgLight = leds[i].getAverageLight();

mit denen man vielleicht doch die gerade in einem leds array Element vorliegende Helligkeit auslesen kann (anscheinend verwendet die niemand, Ich fand jedenfalls nur zwei code Beispiele damit), um dann mit if darauf zu testen, wie im shimmer() sketch, der ja für sich alleine stehend, sehr gut funktioniert.

Lagom

#43
Oct 17, 2018, 08:37 pm Last Edit: Oct 17, 2018, 09:02 pm by Lagom
Nochmal "laut" überlegen... Der standalone shimmer() sketch für sich funktioniert sehr schön, siehe code Beispiel unten (ebenso der standalone sky() sketch mit der gradient palette). Also:

setup()

1. der leds array wird einmalig mit CRGB(8,8,8) gefüllt und
2. alle Elemente erhalten das status flag ledConstant

loop()/shimmer()

1. per Zufall erhalten einige leds array Elemente das status flag ledBrightens
2. dann wird je nach status flag und CRGB(8,8,8) oder CRGB(248,248,248) verglichen
3. und entschieden ob
-> aufgehellt += BRIGHTEN_LED; oder
-> abgedunkelt -= DARKEN_LED; oder wenn
-> das untere Ende erreicht ist = DARKEST_COLOUR; wieder das status flag ledConstant gesetzt wird, und das leds array Element wieder für die Zufallsauswahl bereit steht
4. und wieder von vorne - das funktioniert, sieht gut aus, läßt sich "flackeriger" oder "ruhiger" machen

Das Problem ist nun also - wenn der leds array in loop() mit der sky() Funktion via fill_solid(leds, ledCount, CRGB colour); kontinuierlich mit interpolierten Farben vollgeschrieben wird - daß die shimmer() Funktion nicht mehr mit DARKEST_COLOUR CRGB(8,8,8) oder BRIGHTEST_COLOUR CRGB(248,248,248) vergleichen kann, da diese Farben unbekannt sind, also nicht mehr hardcoded, wie im standalone shimmer() sketch hier unten.

Die Frage ist dann, auf was kann anstelle von DARKEST_COLOUR oder BRIGHTEST_COLOUR getestet werden, um das status flag zum abdunkeln oder aufhellen zu setzen? Ich dachte, da es interpolierte Farben sind, könnte man das vielleicht über den Helligkeitswert der leds array Elemente machen; die gradient palette "fängt ja auch erstmal dunkel an", wenn auch nicht mit CRGB(8,8,8). Aber dann wird ja schon interpoliert, und was ist dann das Äquivalent zum vormals hardcoded DARKEST_COLOUR oder BRIGHTEST_COLOUR? Wenn ich willkürlich das erste Farbtripel der gradient palette z. B. auf 7,7,7 setze, dann schimmert es genau ein Mal für ca. eine Sekunde, und dann nicht wieder, da ja 8,8,8 nicht wieder auftaucht.

Also denke ich, man muß den Test auf DARKEST_COLOUR oder BRIGHTEST_COLOUR im Kombinationsfall mit einer gradient palette aufgeben und ihn durch "etwas anderes" ersetzen, auf das man dann per if... testen und so das status flag setzen kann, um dann wie gehabt mit += BRIGHTEN_LED; oder -= DARKEN_LED; aufzuhellen oder abzudunkeln. Und dieses "etwas anderes" kann kein Farbtripel sein.

ps: Entschuldigung; danke, das rhythmische "wellenartige Gewaber" mit der "Perlin Noise" sieht auch recht interessant aus, auch wenn es nicht so "vor sich hin schimmert und perlt" wie shimmer().

Code: [Select]
DEFINE_GRADIENT_PALETTE(testPalette) {
  0,  7, 7, 7,
  25,  80, 119, 197,
  89, 153, 215, 250,
  95, 199, 233, 252,
  102, 255, 255, 255,
  120, 197, 219, 240,
  147, 150, 187, 223,
  200, 159, 171, 172,
  255, 169, 154, 128
};


Code: [Select]
#include "FastLED.h"

const byte pinData = 3;
const byte pinClock = 4;

const byte ledCount = 144;
byte maxBrightness = 128; // Values from 0 - 255; can be changed on the fly via sensor, 10k potentiometer, etc.

#define DARKEST_COLOUR CRGB(8,8,8)
#define BRIGHTEST_COLOUR CRGB(248,248,248)
#define DARKEN_LED CRGB(4,4,4)
#define BRIGHTEN_LED CRGB(8,8,8) //Brighten faster than darken

enum {ledConstant, ledBrightens, ledDarkens}; // A flag for the LED states
byte ledState[ledCount]; // Array of states of all LEDs

struct CRGB leds[ledCount];

void setup() {
  LEDS.addLeds<APA102, pinData, pinClock, BGR>(leds, ledCount);
  LEDS.setBrightness(maxBrightness);
  LEDS.setCorrection(Candle); //LEDS.setCorrection(UncorrectedColor) or (Tungsten40W), etc.
  memset(ledState, ledConstant, sizeof(ledState)); // Set all LEDs to constant state
  fill_solid(leds, ledCount, DARKEST_COLOUR);
}

void loop()
{
  shimmer();
  FastLED.show();
  FastLED.delay(64); // Higher number = slower, but introduces "steppiness" : (
}

void shimmer()
{
  for ( byte i = 0; i < ledCount; i++) { // Go through the entire strip
    if ( ledState[i] == ledConstant) { // If LED is in constant state...
      if ( random8() < 7) { // ...randomly select it based on a threshold (higher number = busier shimmer)...
        ledState[i] = ledBrightens; // ...and set it to brightening state
      }

    } else if ( ledState[i] == ledBrightens ) { // If LED is in brightening state...
      if ( leds[i] >= BRIGHTEST_COLOUR ) { // ...and reached brightest colour...
        ledState[i] = ledDarkens; // ...set it to darkening state
      } else {
        leds[i] += BRIGHTEN_LED; // If not, continue brightening
      }

    } else {
      if ( leds[i] <= DARKEST_COLOUR ) { // If LED reached darkest colour...
        leds[i] = DARKEST_COLOUR; // ...keep it there...
        ledState[i] = ledConstant; // ...and set it to constant state
      } else {
        leds[i] -= DARKEN_LED; // If not, continue darkening
      }
    }
  }
}

Verzweifler

Deine Sky Animation überschreibt bei jedem Aufruf dein komplettes Leds Array, alle Änderungen bleiben nur bis zum nächsten Aufruf von sky() erhalten.

Deine shimmer() Animation mag zwar alleine laufen, aber der aktuelle Stand der Animation geht bei jedem überschreiben des leds[] array verloren.

Thema Modularität:

Kann man machen, muss man aber nicht. Hab ich so auch nie angewendet. Wenn ich mehrere Animationen in meinem Projekt habe unterscheiden sich diese auch zu deutlich, um Programmteile mehrmals zu verwenden. Ist aber egal, im Endeffekt zählt ja nur, dass die Sache läuft.

Wenn das eine Konzept nicht hinhaut versucht man es eben anders, es gibt unzählige Möglichkeiten.

Wie fandest du übrigens meine shimmerySky() Animation? Ich finde sie sieht ganz nett aus. Je nachdem wie du deine Led Streifen installierst, verschimmt das Licht der einzelnen Leds mehr oder weniger, einzelne in ihrer Helligkeit veränderte Pixel kann man da je nach dem gar nicht erkennen.  Bei Noise sind es eher Gruppen von Pixeln, die Heller oder Dunkler werden, mit einem weichen Übergang zu den anderen Pixeln.

Grüße



Go Up