[Project] NeopixelBusFX - WS2812 Effekt-Plugin für ESPEasy

Begonnen von djcysmic, 05 Juli 2017, 21:19:46

Vorheriges Thema - Nächstes Thema

Leguna

Hallo
Vielen Dank für die Antwort.
Habe heute den ganzen Tag rumprobiert und habs in der Form gelöst das ich die fehlerhaften Plugins einfach gelöscht habe.
Dann lief es durch.

Grüße Legu

ComputerZOO

#91
Moin,
ich habe mal passend für das NeopixelBusFX-Plugin ein passendes DOIF zusammengeschnurzelt:
defmod diNFX DOIF ## cmd_1: Ausschalten\
([$SELF:effect] eq "off") (\
set [$SELF:device] nfx off 1000 10\
)\
## cmd_2: Animation anhalten\
DOELSEIF ([$SELF:effect] eq "stop") (\
set [$SELF:device] nfx stop\
)\
## cmd_3: Einschalten\
DOELSEIF ([$SELF:effect] eq "on") (\
set [$SELF:device] nfx on 1000 10\
)\
## cmd_4: Alle Pixel auf eine Farbe setzen\
DOELSEIF ([$SELF:effect] eq "all") (\
set [$SELF:device] nfx all [$SELF:color_1]\
)\
## cmd_5: Regenbogen-Effekt\
DOELSEIF ([$SELF:effect] eq "rainbow") (\
set [$SELF:device] nfx rainbow [$SELF:speed]\
)\
## cmd_6: Feuer-Effekt\
DOELSEIF ([$SELF:effect] eq "fire") (\
set [$SELF:device] nfx fire [$SELF:speed] 255 40 20\
)\
## cmd_7: Fake TV Animation\
DOELSEIF ([$SELF:effect] eq "faketv") (\
set [$SELF:device] nfx faketv 1 72\
)\
## cmd_8: Colorfade\
DOELSEIF ([$SELF:effect] eq "colorfade") (\
set [$SELF:device] nfx colorfade [$SELF:color_1] [$SELF:color_2] 1 72\
)\
## cmd_9: Knightrider\
DOELSEIF ([$SELF:effect] eq "kitt") (\
set [$SELF:device] nfx kitt [$SELF:color_1] [$SELF:speed]\
)\
## cmd_10: Theater\
DOELSEIF ([$SELF:effect] eq "theatre") (\
set [$SELF:device] nfx theatre [$SELF:color_1] [$SELF:color_2] 5 [$SELF:speed]\
)\
## cmd_11: Twinklefade\
DOELSEIF ([$SELF:effect] eq "twinklefade") (\
set [$SELF:device] nfx twinklefade [$SELF:color_1] 8 [$SELF:speed]\
)\
## cmd_12: Wipe-Effekt\
DOELSEIF ([$SELF:effect] eq "wipe") (\
set [$SELF:device] nfx wipe [$SELF:color_1] [$SELF:color_2] [$SELF:speed]\
)\
## cmd_15: Twinkle\
DOELSEIF ([$SELF:effect] eq "twinkle") (\
set [$SELF:device] nfx twinkle [$SELF:color_1] [$SELF:color_2] [$SELF:speed]\
)\
## cmd_16: Comet\
DOELSEIF ([$SELF:effect] eq "comet") (\
set [$SELF:device] nfx comet [$SELF:color_1] [$SELF:speed]\
)\
## cmd_17: Scan\
DOELSEIF ([$SELF:effect] eq "scan") (\
set [$SELF:device] nfx scan [$SELF:color_1] [$SELF:color_2] [$SELF:speed]\
)\
## cmd_18: Dualscan\
DOELSEIF ([$SELF:effect] eq "dualscan") (\
set [$SELF:device] nfx dualscan [$SELF:color_1] [$SELF:color_2] [$SELF:speed]\
)\
## cmd_19: Sparkle\
DOELSEIF ([$SELF:effect] eq "sparkle") (\
set [$SELF:device] nfx sparkle [$SELF:color_1] [$SELF:color_2] [$SELF:speed]\
)
attr diNFX alias NeopixelBusFX
attr diNFX cmdIcon play:rc_PLAY stop:rc_STOP on:taster_ch_an_gruen off:taster_ch_aus_rot
attr diNFX do always
attr diNFX eventMap /effect on:on/effect off:off/effect stop:stop/
attr diNFX group 01_NeopixelBusFX
attr diNFX icon hue_filled_lightstrip
attr diNFX readingList speed,effect,color_1,color_2,device
attr diNFX room Baustelle
attr diNFX setList device:wemos_1,wemos_2 effect:wipe,all,fire,faketv,kitt,comet,theatre,rainbow,colorfade,scan,dualscan,twinkle,twinklefade,sparkle color_1:colorpicker,rgb color_2:colorpicker,rgb speed:selectnumbers,-50,1,50,0,lin
attr diNFX webCmd device:effect:color_1:color_2:speed:play:stop:on:off
attr diNFX webCmdLabel Controller:Effekt:Farbe ;1:Farbe ;2:Speed: ;: ;: ;: ;


Beim Attribut
attr diNFX setList device:wemos_1,wemos_2,............
werden die Devices angegeben, die einen WS2812-LED-Strip angeschlossen haben (in meinem Fall heißen die Devices wemos_1 und wemos_2)

Nun kann man schnell alle Effekte (es kommen bestimmt noch mehr  ;) ) allen vorgegebenen Devices zuweisen.

Ich hoffe ich konnte euch mit diesem kleinen Schmankerl die unendlichen Möglichkeiten von FHEM mit ESPEasy und dem NeopixelBusFX-Plugin etwas näher bringen.

Schöne Grüße von der Ostsee, MAX.


EDIT: Im DOIF ist die Pixelanzahl für die Funktionen faketv und colorfade in meinem Fall mit 72 fix angegeben, da es mMn keinen Sinn ergibt, für diese zwei Funktionen extra ein Reading mit Dropdown zu erstellen.

ComputerZOO

@djcysmic:
Wäre es (ohne Komplikationen) möglich, vom ESP ein JSON-Reading mit der Pixelanzahl des jeweiligen Strip (die in ESPEasy angegeben wurde) als Reading zurückzubekommen?

djcysmic

Ein sehr cooles DOIF - damit geht schon einiges...

Die Rückmeldung der Pixelanzahl habe ich gerade eingearbeitet und eingecheckt - die brauchst du allerdings nur als Maximalwert.
Wenn du faketv oder colorfade ohne Angabe der Pixelnummer startest, nutzt er automatisch den kompletten Stripe ;)

clumsy

Hallo

Super Plugin!! Danke!!

Bin grade dabei etwas damit rumzuspielen, da ich diverse Beleuchtungen mit WEMOS und nfx-Streifen machen möchte.

Dazu eine Frage / Vorschlag für eine Erweiterung: cool wäre, wenn man bei allen effekten jeweils ein Anfang und Ende angeben könnte und mehrere parallel betreiben. D.h. dass man z.b. Pixel 1-10 faketv, Pixel 20-30 rainbow etc. definieren könnte. Da an einem WEMOS prinzipiell ja nur ein Streifen angeschlossen werden kann, könnte man damit mehrere unterschiedliche Segmente resp. "Aufgaben" mit einem ESP lösen...

lg

STefan

DOM_jaCOBB

Hallo,

ich habe jetzt übers Wochenende den Code umgeschrieben, weil ich ja RGBW-Neopixel ansteuern will. Ich habe es auch geschafft über der hex2rgbw-Konvertierung den Weiß-Kanal anzusteuern.
Nur habe ich jetzt das Problem, dass auf einmal alle Kanäle angesteuert werden und somit weißes statt rotem Licht entsteht, wenn ich beim roten Kanal auf mehr als die Hälfte der Helligkeit (also 128 bzw. 80) gehe.
Habe auch schon viel rumprobiert, aber leider noch keine Lösung gefunden.
Die anderen Kanäle und Rot bis zur halben Helligkeit funktionieren normal.
Deswegen wollte ich fragen, ob ihr evtl. mal über den Code drüberschauen könntet? Wäre sehr nett ;)


int32_t rgbwStr2Num(String rgbwStr) {
  int32_t rgbwDec = (int) strtol( &rgbwStr[0], NULL, 16);
  return rgbwDec;
}

void hex2rgbw(String hexcolor) {
  colorStr = hexcolor;
  rgbw = RgbwColor ( rgbwStr2Num(hexcolor) >> 24, rgbwStr2Num(hexcolor) >> 16, rgbwStr2Num(hexcolor) >> 8, rgbwStr2Num(hexcolor) );
}

void hex2rrggbbww(String hexcolor) {
  backgroundcolorStr = hexcolor;
  rrggbbww = RgbwColor ( rgbwStr2Num(hexcolor) >> 24, rgbwStr2Num(hexcolor) >> 16, rgbwStr2Num(hexcolor) >> 8, rgbwStr2Num(hexcolor) );
}

void hex2rgbw_pixel(String hexcolor) {
  colorStr = hexcolor;
  for ( int i = 0; i < pixelCount; i++) {
    rgbw_target[i] = RgbwColor ( rgbwStr2Num(hexcolor) >> 24, rgbwStr2Num(hexcolor) >> 16, rgbwStr2Num(hexcolor) >> 8, rgbwStr2Num(hexcolor) );
  }
}


Grüße, Jakob

djcysmic

Zitat von: clumsy am 11 Oktober 2017, 11:14:03
Dazu eine Frage / Vorschlag für eine Erweiterung: cool wäre, wenn man bei allen effekten jeweils ein Anfang und Ende angeben könnte und mehrere parallel betreiben. D.h. dass man z.b. Pixel 1-10 faketv, Pixel 20-30 rainbow etc. definieren könnte. Da an einem WEMOS prinzipiell ja nur ein Streifen angeschlossen werden kann, könnte man damit mehrere unterschiedliche Segmente resp. "Aufgaben" mit einem ESP lösen...

Hallo Stefan,

grundsätzlich sollte das möglich sein, bedeutet aber eine Menge Programmieraufwand, da das komplett Plugin umgeschrieben und darauf ausgelegt werden muss.
Wie viel Segmente hast du dir denn vorgestellt? Meine Idee wäre, die Segmente vorab schon in den Plugin-Settings zu definieren und diese dann über einen zusätzlichen Parameter anzusteuern.

Zitat von: DOM_jaCOBB am 11 Oktober 2017, 19:53:47
Hallo,

ich habe jetzt übers Wochenende den Code umgeschrieben, weil ich ja RGBW-Neopixel ansteuern will. Ich habe es auch geschafft über der hex2rgbw-Konvertierung den Weiß-Kanal anzusteuern.
Nur habe ich jetzt das Problem, dass auf einmal alle Kanäle angesteuert werden und somit weißes statt rotem Licht entsteht, wenn ich beim roten Kanal auf mehr als die Hälfte der Helligkeit (also 128 bzw. 80) gehe.
Habe auch schon viel rumprobiert, aber leider noch keine Lösung gefunden.
Die anderen Kanäle und Rot bis zur halben Helligkeit funktionieren normal.
Deswegen wollte ich fragen, ob ihr evtl. mal über den Code drüberschauen könntet? Wäre sehr nett ;)

Hallo Jakob,

da ich (noch) keine RGBW-Neopixel habe, kann ich leider nur raten - hast du die Effekte auch angepasst? Diese erwarten und rechnen größtenteils mit RGB-Werten und evtl. bringt er da etwas durcheinander.
Ich habe mir jetzt mal ein paar RGBW-Pixel bestellt, um zu testen. Dann kann ich dir u. U. bald näheres dazu schreiben ;)

Viele Grüße
Nico

clumsy

Zitat von: djcysmic am 12 Oktober 2017, 19:44:00
grundsätzlich sollte das möglich sein, bedeutet aber eine Menge Programmieraufwand, da das komplett Plugin umgeschrieben und darauf ausgelegt werden muss.
Wie viel Segmente hast du dir denn vorgestellt? Meine Idee wäre, die Segmente vorab schon in den Plugin-Settings zu definieren und diese dann über einen zusätzlichen Parameter anzusteuern.

ja, das glaub ich... hatte mal ein teensy (arduino-clone) mit sowas programmiert... ich hab einfach für alle effekte ein array definiert in dem die ID's der LED's drin sind, dann den effekt jeweils auf das array angewendet und am ende alle led's neu geschrieben... (ich hatte eben auch segmente die nicht zusammenhängend waren, z.b. für laufschriften oder fläschen innerhalb einer grösseren matrix)..

aber ich denke das kappt schon aus memory gründen nicht hier...

deine idee, dass man vorher die segmente definert macht durchaus sinn, denn ändern werden die sich ja kaum dynamisch... die anzahl ist halt etwas abhängig von der anzahl LED's... ich denke so ca. anzahl LED's /10 oder so... d.h. 5 segmente für eine 50er-kette.... aber eben, nur so eine idee... ich denke generell mit 5 segmenten müsste man durchkommen... ist halt auch die frage wieviel memory und cpu das benötigt... erweitern kann mans ja immernoch..

beste Grüsse!

STefan

DOM_jaCOBB

Zitat von: djcysmic am 12 Oktober 2017, 19:44:00

Hallo Jakob,

da ich (noch) keine RGBW-Neopixel habe, kann ich leider nur raten - hast du die Effekte auch angepasst? Diese erwarten und rechnen größtenteils mit RGB-Werten und evtl. bringt er da etwas durcheinander.
Ich habe mir jetzt mal ein paar RGBW-Pixel bestellt, um zu testen. Dann kann ich dir u. U. bald näheres dazu schreiben ;)

Viele Grüße
Nico

Super, vielen Dank für deine Hilfe, Nico. :D

Ich werde mir die Effekte nochmal durchschauen, ich habe da aber nur die Namen der Funktionen und Variablen angepasst, RgbColor zu RgbwColor verändert und bei Effekten wie z.B. kitt noch einen 4. Wert für Weiß hinzugefügt.

Ich hätte noch Fragen zu 2 Funktionen im Code, wo ich leider nicht weiß, was sie im Einzelnen machen, vielleicht löst sich das Problem auch damit.  ;)
Weißt du vielleicht, was die Funktion parseString(string, "Zahl") macht, die immer hinter den hex2rgb steht? Ich habe leider nichts dazu gefunden, wo das näher beschrieben ist... Müsste man da die Zahl verändern, wenn man 4 statt 3 Farben ansteuern will?
Und weißt du, warum man genau >> 16 und >> 8 bei den hex2rgb-Konvertierungen unten im Code verwendet?
Bei der hex2rgbw habe ich für den Rot-Wert mehrere Werte größer als 16 (z.B. >> 24) probiert, aber leider kam immer dasselbe Problem, dass beim Ansteuern von Rot ab der halben Helligkeit alle LEDs angesteuert wurden...

Ich hoffe ich hab es verständlich beschrieben, bin leider noch nicht so firm im Programmieren.  ;)

Lg,
Jakob

djcysmic

Zitat von: DOM_jaCOBB am 15 Oktober 2017, 20:32:45
Weißt du vielleicht, was die Funktion parseString(string, "Zahl") macht, die immer hinter den hex2rgb steht? Ich habe leider nichts dazu gefunden, wo das näher beschrieben ist... Müsste man da die Zahl verändern, wenn man 4 statt 3 Farben ansteuern will?

Die parseString-Funktion liest die einzelnen Argumente beim Aufruf des Plugins aus - die "Zahl" ist dabei das jeweilige Argument (1=nfx, 2=kitt, 3=FF0000 usw.)
Die Zahlen solltest du so lassen, wie sie sind ;)

Zitat
Und weißt du, warum man genau >> 16 und >> 8 bei den hex2rgb-Konvertierungen unten im Code verwendet?
Bei der hex2rgbw habe ich für den Rot-Wert mehrere Werte größer als 16 (z.B. >> 24) probiert, aber leider kam immer dasselbe Problem, dass beim Ansteuern von Rot ab der halben Helligkeit alle LEDs angesteuert wurden...

Unsere RGB-Werte sind 3*8 Bit = 24 Bit lang und mit dem >> - Operator wird die Bitfolge jeweils um die angegebene Anzahl an Bits verschoben. Die einzelnen Farbargumente sind uint8, also unsigned 8 Bit - damit werden die letzten 8 Bit übernommen und der Rest verworfen.

>> 16 verschiebt die Bitfolge um 16 Bits nach rechts und übernimmt so die Rotwerte
>> 8 verschiebt die Bitfolge um 8 Bits und übernimmt die Grünwerte
Für die Blauwerte braucht nichts verschoben werden.

Hier mal symbolisch die Bitfolge mit jeweils 2 Bits dargestellt - die Werte in der Klammer werden verworfen:

(rrgg)bb >> 4 (0000)rr
(rrgg)bb >> 2 (00rr)gg
(rrgg)bb >> 0 (rrgg)bb

Ich hofffe, das ist einigermaßen verständlich beschrieben.
Eine gute Erklärung auf Englisch findest du auch hier: https://ryanclark.me/rgb-to-hex-via-binary-shifting/

Was für Farbwerte übergibst du denn an ESPEasy? RGB aus dem Colorpicker oder 4-Kanal-RGBW? Vielleicht ist da schon der Fehler.

DOM_jaCOBB

Deine Erklärungen haben mir sehr weitergeholfen, vielen Dank ;)

Mein Fehler war, glaube ich, dass ich alle Werte zusammen konvertieren wollte. Ich habe dabei für den Rot-Wert die Bitfolge um 24 Bits nach rechts verschoben, für den Grün-Wert um 16, für den Blau-Wert um 8 und für den Weiß-Wert gar nichts verschoben. Für den Rot-Wert hat das offensichtlich ab der halben Helligkeit aufwärts nicht funktioniert.

Ich habe jetzt den Code so umgeschrieben, dass ich die rgbStr2Num-Konvertierung so belassen habe und analog dazu noch eine weitere Konvertierung für den Weiß-Wert geschrieben habe. Diese Werte rufe ich dann unten zusammen als RgbwColor auf, sprich ich gebe zuerst die RGB-Werte und dann den Weiß-Wert jeweils als Hexadezimal-Werte ein.
Jetzt funktioniert alles, so wie es soll, und ich kann damit endlich alle 4 Kanäle richtig ansteuern. Die Effekte, die mit RGBW möglich sind (also alle bis auf Fire und Faketv) haben, als ich das ganze gestern an der Uni getestet habe, auch gut funktioniert ;D

Ich übergebe die Farbwerte in FHEM als Hexadezimal-Zahlen weil der Colorpicker ja glaube ich nur RGB-Werte übernehmen kann, aber das reicht mir für mein Uni-Projekt ;)

Der Befehl würde dann beispielsweise so ausschauen:
set <esp> nfx all rrggbb ww 1000

Wenn du willst, kann ich dir den bearbeiteten Code auch zukommen lassen, dann könntest ihn mit deinen neuen RGBW-Neopixeln mal ausprobieren ;)

Lg,
Jakob

djcysmic

Das freut mich, dass du es hinbekommen hast  :)

Ich habe da so eine Idee, warum es nicht funktioniert hat - die rgb2str-Funktion ist als 32-Bit-Integer mit Vorzeichenbit definiert, so dass 1 Bit für die Farben verloren geht.
Bei RGBW brauchen wir aber 4 x 8 Bit = 32 Bit.

Du könntest mal folgendes ausprobieren:

uint32_t rgbStr2Num(String rgbStr) {
uint32_t rgbDec = (int) strtol( &rgbStr[0], NULL, 16);
return rgbDec;
}


Da ich auch nur ein Hobbyprogrammierer bin, gibt es ja vielleicht jemanden hier, der mir sagen kann, wie ich das Feature (NeoGrbFeature, NeoRgbwFeature etc.) dynamisch ins Plugin einbinden kann.
Somit könnte die Einstellung in den Deviceparametern festgelegt werden und man hätte die Möglichkeit, die RGBW-Funktionalität ein- und auszuschalten.
Bisher sind alle meine Versuche in diese Richtung gescheitert...

clumsy

Hallo

Wenn man die Pixel in einem Kries hat und gewisse Dinge über das Ende/Anfang hinweg machen möchte wären kleine Änderungen nötig.. z.B. bei colorfade müsste man folgende beiden Zeilen ändern:

difference = (endpixel - startpixel + pixelCount) % pixelCount;
und
Plugin_124_pixels->SetPixelColor((i + startpixel)%pixelCount, updatedColor);


Da ich eine Art Uhr gebaut habe, hab ich das bei mir so angepasst. Falls interesse besteht, kann ich den Rest mal durchsehen und allenfalls diese "über das Ende hinaus" Änderungen einbauen...


djcysmic

Zitat von: clumsy am 22 Oktober 2017, 09:50:26
Da ich eine Art Uhr gebaut habe, hab ich das bei mir so angepasst. Falls interesse besteht, kann ich den Rest mal durchsehen und allenfalls diese "über das Ende hinaus" Änderungen einbauen...

Hallo clumsy,
sehr gerne - dann kann ich das direkt ins Github einchecken. Vielen Dank schonmal...

clumsy

Zitat von: djcysmic am 22 Oktober 2017, 16:00:13
sehr gerne - dann kann ich das direkt ins Github einchecken. Vielen Dank schonmal...
cool...

bin auch noch grad dran eine Uhr-Routine zu schreiben... Wie stehst du zu Erweiterungen von Deinem Modul? Magst das nicht so wenn jemand an deinem Code rumschraubt, würd ich das auslagern, oder willst es bei Dir einbauen dann?