LEDs nacheinander Einschalten mit "fade"-Effekt

Ich stehe gerade sehr auf dem Schlauch.

Ich habe 96 LEDs, die ich gerne nacheinander einschalten würde.
Verwendet wird die FastLED library.

Bisher habe ich

void swipe_one_color_all_hsv(byte hue, byte sat, byte val) 
{ 
    for(int i = 0 ; i <= 96; i++ ) 
    {
        leds[i] = CHSV( hue, sat, val);
        LEDS.show();       
        delay(20);
    }  
}

Jetzt sieht das allerdings nicht so toll aus, das die LEDs "plump" an gehen.

Weiß jemand wie man es hinbekommen kann die leds einzelnd heller werden zu lassen?

Irgendwie fehlt mir eine Grundsätzliche Idee, wie ich das bewerkstelligen kann. Wichtig ist vor allem, dass ich den HSV-Farbwert habe.

Natürlich wäre es super, wenn die LEDs quasi stufenlos (und am besten noch logarythmisch) heller gemacht werden.
Ein z.B. drei stufiges heller werden, wäre aber auch in Ordnung.

So sollte es dann aussehen (in den Eckigen klammern stehen die Helligkeitswerte in Prozent):

|LED1|LED2|LED3|LED4|LED5|
[0]      [0]   [0]   [0]   [0] 
[25]     [0]   [0]   [0]   [0] 
[65]    [25]  [0]   [0]   [0] 
[100]   [65]  [25]  [0]   [0] 
[100]  [100]  [65]  [25]  [0] 
[100]  [100] [100] [65] [25]

... (usw.)

icch hoffe jemand kann mir auf die Sprünge helfen.

Hallo,

schau mal ob du bei den Snippets das passende bei findest. Led Effekte - #71 by sschultewolter - Deutsch - Arduino Forum
Der Larsson Scanner/Knight Rider müsstest du dafür ein bisschen modifizieren.

void ledsLarsonScanner(uint8_t hue, uint8_t saturation, uint8_t brightness, uint32_t duration, uint8_t width)
{
	static uint32_t lastMillis;
	static int16_t led;
	static bool reverse;

	if (millis() - lastMillis >= duration)
	{
		lastMillis = millis();
		if (led <= 0) reverse = false;
		else if (led >= NUM_LEDS - 1) reverse = true;
		if (reverse) led--;
		else led++;

		for (int rwLed = 1; rwLed <= width && led + rwLed < NUM_LEDS; rwLed++)
		{
			leds[led + rwLed] = CHSV(hue, saturation, brightness *(width - rwLed) / width);
		}
		leds[led] = CHSV(hue, saturation, brightness);
		for (int fwLed = 1; fwLed <= width && (led - fwLed) >= 0; fwLed++)
		{
			leds[(led - fwLed)] = CHSV(hue, saturation, brightness *(width - fwLed) / width);
		}
		FastLED.show();
	}
}
void ledsLarsonScannerShiftColor(uint8_t saturation, uint8_t brightness, uint32_t duration, uint8_t width)
{
	static uint32_t lastMillis;
	static int16_t led;
	static bool reverse;
	static uint8_t hue;

	if (millis() - lastMillis >= duration)
	{
		lastMillis = millis();
		if (hue < 255) hue++;
		else hue = 0;
		if (led <= 0) reverse = false;
		else if (led >= NUM_LEDS - 1) reverse = true;
		if (reverse)led--;
		else led++;
		for (int rwLed = 1; rwLed <= width && led + rwLed < NUM_LEDS; rwLed++)
		{
			leds[led + rwLed] = CHSV(hue, saturation, brightness * (width - rwLed) / width);
		}
		leds[led] = CHSV(hue, saturation, brightness);
		for (int fwLed = 1; fwLed <= width && (led - fwLed) >= 0; fwLed++)
		{
			leds[(led - fwLed)] = CHSV(hue, saturation, brightness * (width - fwLed) / width);
		}
		FastLED.show();
	}
}

Logarithmisch ist soweit bekannt bei der FastLed Lib nicht notwendig. Das passiert glaube schon. Ansonsten mit Wertetabellen arbeiten (nicht jedesmal berechnen!!).

https://www.mikrocontroller.net/articles/LED-Fading

Ich habs mir jetzt mal genau angeschaut.
Mit "ein bisschen modifizieren" wird das leider nichts.

Problem ist, das diese Funktion nicht mehrfach aufgerufen wird, sondern nur einmal und dann alle LEDs (unterbrechungsfrei) aufleuchten sollen.
Außerdem kann ich "led" nicht einfach inkrementieren, weil ich ja die dunkleren LEDs vor mir her schiebe und nicht wie beim Nightrider-Effekt hinter mir her ziehe.

Ich habe heute bestimmt schon 4 mal von vorne angefangen mir einer Idee und immer nach etwa einer Stunde habe ich einen Knoten im Hirn und meine Idee war nicht ausgereift.

Bevor sich jetzt jemand hinsetzt und sich auch die mühe macht...

Ich hab jetzt was zusammengeschustert (mit 3 for schleifen) was ich allerdings heute nicht mehr testen werde.
Macht euch also erstmal keine Mühe, es sei denn das schüttelt jemand gerade aus dem Ärmel :wink:

Gute Nacht!

Mit ziehen und schieben ineinander umkehren hätte ich vielleicht einen Tipp. Per Map den Wertebereich umkehren. Das Problem hatte ich bei einem Aquariencontroller, der per PWM die Konstantstromquellen der Power-LEDs ansteuerte. Da ich an den µC Ausgängen noch einen Treibertransistor hatte, mußte ich noch ein zweites Mal invertieren, damit es wieder stimmte.

Das ist aber auch ziemlich speziell nix-mehr-frei ^^
Ich habe es jedenfalls hinbekommen.

Das Ganze blockiert zwar während des Effektes alles andere (die Funktion wird nur einmal durchlaufen und arbeitet mit delay() weil eh nichts anderes ausgeführt werden kann, in dieser Funktion) aber für mehr reicht es bei mir gerade einfach nicht.

Für alle die es interessiert:

#include <FastLED.h>
#define NUM_LEDS 19      //hab nur 19 LEDs zum testen
#define DATA_PIN 13
struct CRGB leds[NUM_LEDS];

byte HSV255[] = {227,221,230};

static int pause = 25;
static byte width = 15;
static byte LEDsDieAnGehenSollen = 19;
  
// Alle LEDs mit einer RBG-Farbe leuchten lassen
void one_color_all(int red, int grn, int blu) 
{ 
    for(int i = 0 ; i < NUM_LEDS; i++ ) 
    {
      leds[i].setRGB(red, grn, blu); 
    } 
   LEDS.show();     
}



void led_swipe_on(byte hue, byte sat, byte val)
{
  
  // die ersten LEDs heller werden lassen, bis die erste LED (led[0]) eine Stufe vor voller helligkeit ist  
  for(int i = 0 ; ( i < (width - 1) ) ; i++ ) 
  {       
    for(int j = 0 ; (i - j) >= 0 ; j++ ) 
    {
     leds[i - j] = CHSV( hue, sat, val / width * (j + 1) );
    }
      
    LEDS.show(); 
    delay (pause);
  } 
    
     
  // nacheinander die leds mit voller helligkeit (bis LEDsDieAnGehenSollen - width) leuchten lassen und die nachfolgenden "width"-leds jeweils abgestuft leuchten lassen
  for(int i = 0 ; i + width <= LEDsDieAnGehenSollen ; i++ ) 
  {      
    for(int j = 0 ; j < width ; j++ ) 
    {
      leds[i + j] = CHSV( hue, sat, val / width * (width - j) );
    }
       
    LEDS.show(); 
    delay (pause);
  }   
              
  // zum Schluss noch die letzten verbleibenden LEDs heller werden lassen
  for(int i = (width - 1) ; i >= 0 ; i-- ) 
  {
    for(int j = 0 ; (i - j) > 0 ; j++ ) 
    {
      leds[ LEDsDieAnGehenSollen - (i - j) ] = CHSV( hue, sat, val / width * (width - j) );
    }
    LEDS.show(); 
    delay (pause);     
  } 
  
}

void setup() 
{
 LEDS.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  
  one_color_all(0,0,0); // Alle LEDs ausschalten
  LEDS.show();          // Alle LEDs ausschalten
  delay(2);            // kurz warten
}

void loop() 
{
  static boolean einmalausfuehren = true;  
  if ( einmalausfuehren)
  {
    led_swipe_on(HSV255[0], HSV255[1], HSV255[2]);
    einmalausfuehren = false;
  }  
}

Falls jemand eine Idee hat, wie ich das zyklisch durchlaufen lassen kann und das Arduino somit auch während des Effekts ansprechbar machen kann, dann immer her damit ^^.

Vor allem müssen dann eben die pausen weg und gegen "if (millis() - lastMillis >= duration)" ersetzt werden und die Funktion muss nachdem alle LEDs komplett eingeschaltete sind nichts mehr tun.
Das ist eigentlich aber noch die kleinste Aufgabe.

Ich weiß einfach nicht, wie ich die for-schleifen so ersetzen kann, dass immer nur ein Teil verarbeitet wird.

Hallo,

guck mal hier in den vielen Bsp.:

Der ist auch hier im Forum unterwegs, manchmal, nur fällt mir leider sein Nickname nicht ein ...

Udo Klein

Warum soll die Funktion nur einmal aufgerufen werden?

Sinnvoller wäre es sich der Wert zu merken, was gerade läuft. Über einen return Wert der Funktion kannst du ggf. signalisieren, dass der Effekt beendet ist, um den Merker zurückzusetzen.

Hallo,

genau, Udo war's bzw. ist es noch. :wink:

Ich habe mal aus meinen Anfangstagen mit dem Arduino mein Würfelsketch rausgekramt. Dort habe ich als Effekt einen Kometenschweif mit eingebaut. Der sich beschleunigt und abbremst wenn jemand den Taster drückt usw. zum würfeln. Ich geb Dir mal den Würfelsketch und den gekürzten Sketch ohne das Würfel Gedöhns.
Vielleicht kannste damit was anfangen. Ist sicherlich noch nicht optimal, war mein Anfang. Den Effekt mußte dann nur umdrehen und schaltest die letzte LED nicht mehr aus.

Bei Udo seinem Code ist das alles kompakter und effektiver geschrieben. Deswegen solltest Du Dir besser den Code von Udo anschauen und versuchen zuverstehen.

Kometenschweif_01.ino (6.15 KB)

Wuerfel_004.ino (7.89 KB)