Go Down

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

Lagom

Hej,

auf dem englischen Forum ging's nicht weiter, vielleicht gibt es deutschsprachige FastLED Anwender, die mir weiterhelfen können.

Ich habe eine Animation sky(), die alle 144 LEDs eines APA102C Streifens im Verlauf einer Stunde sukzessive mit Farben aus einer Palette füllt.

Code: [Select]
DEFINE_GRADIENT_PALETTE(skyPalette) {
  Position,  R, G, B ,
  Position, ...
  ...
};
...

CRGBPalette16 activePalette = skyPalette;
...

CRGB colour = ColorFromPalette(activePalette, paletteIndex);
fill_solid(leds, ledCount, colour);
...

EVERY_N_SECONDS(interval) {
    if (paletteIndex < 240) {
      paletteIndex++;
    }
}


Alle N Sekunden wird also der gesamte leds array mit einem neuen CRGB colour bzw. weichem Übergang zwischen den extrapolierten Palettenfarben gefüllt. Das funktioniert, wie in der FastLED Anleitung beschrieben, gut.

Eine zweite Animation shimmer() soll nun einige wenige immer wieder neu zufällig ausgewählte LEDs if ( random8() < 7) des durch die Palette "befüllten" leds array um z.B. 30% aufhellen/abdunkeln, so daß ein "Schimmer-Effekt" entsteht. Das zufällige Auswählen und bestimmen, wann aufgehellt oder abgedunkelt werden soll, funktioniert mit status flags enum {ledConstant, ledBrightens, ledDarkens}; ebenfalls, wie beschrieben.

Aber, wie lassen sich die ständig durch die Palette gefüllten LEDs des leds arrays in ihrer Helligkeit modifizieren? Mit

leds[number].addToRGB(value);
leds[number].subtractFromRGB(value);

geht es nicht gut, da Farben wie z.B. {241, 17, 238} auf/über 255 gehen können, und so Farbinformation verlieren oder Farben verfälschen.

Gibt es eine Möglichkeit, LEDs via HSV zu beeinflussen, und zwar nur den Wert von V?

Danke für hilfreiche Hinweise!

Tommy56

#1
Oct 10, 2018, 03:23 pm Last Edit: Oct 10, 2018, 03:23 pm by Tommy56
Doku lesen könnte zu Erkenntnissen führen. z.B. hier.

Oder einfach
Code: [Select]

FastLED.setBrightness( BRIGHTNESS );


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

Lagom

#2
Oct 10, 2018, 05:46 pm Last Edit: Oct 10, 2018, 05:50 pm by Lagom
Quote
Doku lesen könnte zu Erkenntnissen führen.
In der Tat. Dann hätten Sie, bevor Sie eine schnippische Antwort geben, nämlich erkennen können:

"Use FastLED.setBrightness( 0..255) to adjust the brightness of your whole animation."

Das jedoch war nicht meine Frage. In meinem Fall geht es um die Modifikation der Helligkeit einzelner zufällig ausgewählter LEDs eines zuvor mit Farbwerten beschriebenen leds arrays.

Beste Grüße

Tommy56

Ok, dann habe ich wohl Deine Beschreibung falsch verstanden. Das schnippisch gebe ich gern zurück und viel Spaß noch.

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

postmaster-ino

Hi

@Tommy - man muß auch Mal einstecken können, fand die Antwort eigentlich ganz passabel.

@Lagom
Du kannst die LED-Farbe (sehr wahrscheinlich) auslesen, Deine Helligkeit aufaddieren und die Werte, gedeckelt auf 255, wieder zurück schreiben.
Dabei geht Dir aber die Grund-Farb-Information verloren.
Wenn Dein Zufall hier quasi 2x den gleichen Pixel trifft, wird Dieser 'super-hell', statt nur aufgehellt.

MfG

PS: (sehr wahrscheinlich) eingefügt, da ich die FastLED-Lib noch nie benutzt habe - bei meinen 08/15 WS2812B-Spielereien reichte mir bisher die NeoPixel-Lib von AdaFruit.

Lagom

#5
Oct 10, 2018, 09:10 pm Last Edit: Oct 10, 2018, 09:16 pm by Lagom
@Tommy56 Nichts für ungut

@postmaster-ino danke für Ihren Hinweis. Ich ging auch davon aus, daß sich das in jedem leds array element (= LED) befindliche Farbentripel auslesen läßt.

Das CRGB object hat drei one-byte data members und diverse setter methods, dito das CHSV object siehe hier. Aber tatsächlich keine getter methods. Man kann also, als Laie zumindest, bereits in den leds array geschriebene Werte nicht auslesen (= getter). Es gibt allerdings auch keine setter method, die es erlaubt, nur den V-Wert von HSV zu setzen, obwohl das für H und S geht. Eine merkwürdige Auslassung, denn wer will nicht die Helligkeit einzelner LEDs im leds array programmatisch modifizieren, ohne daß sich die Farbe ändert, bzw. die Farbwerte ab 255 "überlaufen", wie es im RGB Modell stattfände. Bei HSV kann das nicht passieren.

Die Adafruit library kenne ich noch nicht. Gibt es da Zugriff auf V oder andere getter methods, um nur die Helligkeit eines schon im leds array (oder wie es bei Adafruit benannt ist) befindlichen Farbtripels zu ändern?

Danke im Voraus!

postmaster-ino

Hi

Meines Wissen kann die NeoPixel-Library kein HSV.
Bei der FastLED-Library habe ich, auf die Schnelle, auch Nichts gefunden, womit man den Farbwert zurück lesen könnte - allerdings sind dort einige zig .h-Files, Die ich nicht Alle durchgesucht habe.

Was mir aber gerade unter kam: die Umrechnung RGB<->HSV - könnte sogar direkt im Arduino laufen, also ähnelt einem Sketch schon sehr:
https://wisotop.de/rgb-nach-hsv.php
Vll. kannst Du mit der NeoPixel-Library und dieser Formeln was zusammen backen.

MfG

Tommy56

Für das, was Du willst, hast Du im Endeffekt nach meiner Ansicht 3 Wege.

1. Du arbeitest mit dem Array CRGB leds[anzahl];
1. (der Beste Weg) Du fragst die Jungs von fastled.io
2. Du hällst lokal ein HSV-Array deiner LEDS vor und nimmst das als Quelle (wenn der Speicher es her gibt)

Wobei Dein Array leds (1) schon die RGB-Werte Deiner Leds beinhaltet, Du hast also alles.

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

Lagom

#8
Oct 10, 2018, 11:10 pm Last Edit: Oct 10, 2018, 11:12 pm by Lagom
Das Problem ist, daß man aus dem leds array keine Werte auslesen kann, um sie dann zu modifizieren. Funktionen wie z.B. die außerordentlich nützliche gradient palette extrapolieren die Farbwerte aus nur wenigen Farbtripeln, aber man kommt nicht an diese Werte heran, weil es keine getter methods gibt, während der leds array vollgeschrieben wird.

Bei FastLED erfuhr ich von den maintainern: Es gibt nur eine leds[value].setHue(#);, aber keine leds[value].setSat(#); bzw. leds[value].setVal(#); und um diese der library hinzuzufügen, reichen meine Kenntnisse bei Weitem nicht aus.

Bleiben also nur die vorhandenen RGB methods (brighten/darken):

leds[value].addToRGB(#);
leds[value].subtractFromRGB(#);

Also nochmals trotzdem vielen Dank!

noiasca

#9
Oct 11, 2018, 08:36 am Last Edit: Oct 11, 2018, 08:41 am by noiasca
schau dir die ,addToRGB und .substractFromRGB halt mal in der Lib an.

Im einfachsten Fall:
mach eine Lokale Kopie der Lib in deinem Projekt
include die lokale Kopie mit "" stat < >
bau deine Grenzwertabsicherung in die zwei Methoden - oder zwei neue ein.

Das man das normalerweise anders löst ist schon klar, aber obiges finde ich anfängertauglich.
Wenn du den Inhalt der zwei Methoden nicht verstehst, poste eine davon hier in code-Tags, vieleicht gibt es dann jemanden der dich in die richtige Richtung schubst.
DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

agmue

Schau mal, ob Du damit was anfangen kannst:

Code: [Select]
#include "FastLED.h"
#define NUM_LEDS 9
#define DATA_PIN 2
CRGB leds[NUM_LEDS];
CHSV hsvleds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
  CHSV myColor( 160, 255, 30);
  hsvleds[0] = myColor;
  leds[0] = hsvleds[0];
  CHSV newColor( hsvleds[0] );
  newColor.val = 200;
  leds[1] = newColor;
  FastLED.show();
}

void loop() {}

Tommy56

Das Problem ist, daß man aus dem leds array keine Werte auslesen kann
Wieso? Schau Dir doch einfach mal die Datei  an. Da steht doch, wie Du auf die Werte zugreifen kannst.
Code: [Select]

/// Representation of an RGB pixel (Red, Green, Blue)
struct CRGB {
union {
struct {
            union {
                uint8_t r;
                uint8_t red;
            };
            union {
                uint8_t g;
                uint8_t green;
            };
            union {
                uint8_t b;
                uint8_t blue;
            };
        };
uint8_t raw[3];
};



Also mit leds[index].green solltest Du den Wert für Grün des Pixels an Position index bekommen und setzen können.

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

agmue

#12
Oct 11, 2018, 03:42 pm Last Edit: Oct 11, 2018, 05:16 pm by agmue
Also mit leds[index].green solltest Du den Wert für Grün des Pixels an Position index bekommen und setzen können.
Vollkommen richtig, man kann Werte aus dem Feld leds auslesen. Der TO möchte aber die Helligkeit beeinflussen, die im HSV-Farbmodell enthalten ist.

Das Problem ist, daß man aus dem leds array keine Werte auslesen kann, um sie dann zu modifizieren.
Diese Aussage ist falsch, siehe oben. Allerdings ist das nicht Dein Problem, sondern dies: "There is no conversion back from CRGB to CHSV provided with the library at this point."

Wenn Du es donnoch machen möchtest, findest Du eine Formel im Link in #6. Da mußt Du auf die abweichenden Wertebereiche 0 bis 360 und 0 bis 1 in Fließkomma achten.

Code: [Select]
#include "FastLED.h"
#define NUM_LEDS 9
#define DATA_PIN 2
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
  leds[0] = CRGB( 255, 0, 0);
  byte h, s, v;
  RGBtoHSV( leds[0].r, leds[0].g, leds[0].b, &h, &s, &v);
  CHSV newColor( h, s, v );
  newColor.v = 100;
  leds[1] = newColor;
  FastLED.show();
}

void loop() {}

void RGBtoHSV( byte r, byte g, byte b, byte *h, byte *s, byte *v) {
  float fh, fs, fv;
  RGBtoHSVfloat( r / 255.0, g / 255.0, b / 255.0, &fh, &fs, &fv);
  *h = byte(fh / 360.0 * 255.0);
  *s = byte(fs * 255.0);
  *v = byte(fv * 255.0);
}

// Quelle: https://wisotop.de/rgb-nach-hsv.php
// r,g,b-Werte zwischen 0 und 1
// h = [0,360], s = [0,1], v = [0,1]
// Wenn s == 0, dann h = -1 (undefined)
void RGBtoHSVfloat( float r, float g, float b, float *h, float *s, float *v) {
  float minwert, maxwert, delta;
  minwert = min(r, g); // MIN( r, g, b );
  minwert = min(minwert, b);
  maxwert = max(r, g); // MAX( r, g, b );
  maxwert = max(maxwert, b);
  *v = maxwert;                        // v
  delta = maxwert - minwert;
  if ( maxwert != 0 ) *s = delta / maxwert;
  else {                           // r = g = b = 0
    // *s = 0; *h = -1; return;
    *s = 0; *h = 0; return;
  }
  if (maxwert == minwert) {                // hier ist alles Grau
    *h = 0; *s = 0; return;
  }
  if ( r == maxwert )
    *h = ( g - b ) / delta;       // zwischen Gelb und Magenta
  else if ( g == maxwert )
    *h = 2 + ( b - r ) / delta;   // zwischen Cyan und Gelb
  else
    *h = 4 + ( r - g ) / delta;   // zwischen Magenta und Zyan
  *h *= 60;                     // degrees
  if ( *h < 0 )
    *h += 360;
}

Möglicherweise kommt Dir "Rainbow" vs "Spectrum" in die Quere. Dann könnte eine eigene Funktion HSVtoRGB Abhilfe schaffen.

Wenn Du Dich gedanklich von HSV löst: Hast Du schon fadeLightBy() probiert?

Lagom

#13
Oct 11, 2018, 06:43 pm Last Edit: Oct 11, 2018, 06:53 pm by Lagom
@noiasca @Tommy56 @agmue

Vielen Dank für die Hinweise. An der library zu Werke zu gehen übersteigt meinen Horizont. Ich ging davon aus, daß es wie mit

Code: [Select]
leds[i].addToRGB(#);
leds[i].subtractFromRGB(#);

dergleichen für HSV gibt - "add..." bzw. "subtract..." ist klar und auch dem Laien verständlich. Ich werde es mit

Code: [Select]
leds[i].fadeLightBy(#);
leds[i].maximizeBrightness(#); < maximiert anscheinend nicht, sondern akzeptiert einen Wert


probieren, obwohl, alleine schon per Namensgebung, diese beiden methods vielleicht nicht das bewirken, was ich benötige, nämlich "addToV" und "subtractFromV" oder wie immer man es bezeichnen sollte. Der maintainer schreibt dazu auch etwas in seinen GitHub Kommentaren.

Es ist scheint wohl am Besten zu sein, der Einfachheit halber erst einmal bei RGB zu bleiben und bei "add..." bzw. "subtract..." aufzupassen, daß man keine Werte über 255 generiert. Vielleicht hat Daniel Garcia irgendwann einmal vielleicht Zeit, methods für H, S und V bereitzustellen und auch für Paletten ,wie er schrieb, HSV anzubieten.

postmaster-ino

Hi

Den Post von agmue hast Du aber schon gesehen?
Vll. auch Mal auf Dein 'Steinchen' aufgebrutzelt?

So wie ich den Sketch verstehe, wird der erste Pixel auf 'Voll-Rot' gesetzt.
Dann werden die Werte des Pixel ausgelesen, umgerechnet, und als H-S-V dem zweiten Pixel gesetzt.
Mit etwas Glück leuchten beide Pixel in gleicher Farbe.

Nun ist es an Dir, zwischen der Umrechnung und dem Setzen an den Werten zu Spielen - z.B. was an der Helligkeit drehen.

MfG

Go Up