Ui , das hat meiner Seits jetzt etwas gedauert
-
so, vor dem ganzen selbst-beweihräucherndem Geschwätz unten, erstmal ein blinkender Teaser
Chaser Try 3 - YouTube
auf einige genannte Aspekte geh ich mal selektiv ein - meine aktuell schlussendliche Lösung ist dann ganz unten - soll nicht methaphorisch gemeint sein :>
Wie viele LED sollen es nun maximal werden und welche Controller(-familie) sollen verwendet werden?
Ja, das erstmal vor ab - läuft auf einer STM32-Bluepill und ich hab ein Framework von einem RogerClark aus Melbourne da drauf und nutze auch dessen WS2812 Bibliothek,
"Das kannst Du durch einen zyklisch behandelten Ausgabepuffe"
Ist auch so geworden. Für jeden Farbkanal gibt es ein Buffer-Vector, -> "Dazu muss der Controller "wissen" wie viele LED's angeschlossen sind"
Weiß er, da die von mir verwendete library für die PixelLED ohnehin ein #define fordert
"Die einzelnen Chaser haben ja eine endliche Länge, diese dürfte in einem Fall die minimale Anzahl der LED's festlegen. Bei mehr LED's müsste man hochskalieren..."
Ich hatte mich jetzt dazu entschieden, (erstmal) keine Skalierungs oder Step-Interpolationen ein zu bauen. Wollte den Aufwand überschaubar halten, um das Konzept
was mir vorschwebte erstmal aus zu probieren. => Try-Of-Concept so zu sagen
Wann läuft dann der Effekt zurück damit es gut aussieht
Richtig, es gibt definitiv Konstelationen - insbesondere wenn ich es langsam laufen lasse - wo man das Ruckeln sieht. Das habe ich im Moment gekauft, weil es bei "mittlerer" Effektdynamik und fahrendem Vehicle nicht ins Auge fällt.
Ein anderer Weg wäre die maximale Anzahl von Steps und damit LED's in den einzelnen Chasern zu verwenden und dann bei weniger LED's Steps zu überspringen.
Muss zugeben, ich habe auf die Schnelle das gedankliche Konzeptkostrukt hinter der Aussage nicht verstanden.
Meine Mimik funktioniert aktuell so, dass die Pixelposition des ersten Pixel eines Chasers ausgerechnet wird nach (ich benutze nicht 100(%) Einheiten, sondern 1000, weil der Kram auf int-Typen läuft.
Ist zugegeben eher nonsense auf einem µC der FPU hat.
posCalcDyn = (pos*segmentGroup[0].length) / 1000;//calculates position of first Pixel of kernel
Die Folgepixel werden einfach stumpf ohne ausrechnen auf die Folge-Indexe des Segmentes geschrieben. Dadurch bleibt die Enten-Pixelfamilie zusammen ;>
-
Um zum Ausgangsgedanken zurück zu kommen - ich denke, ein Überspringen würde sich damit von alleine ergeben. Hab es aber nicht explizit getestet, sondern nur
geschaut, ob ich mit der aktuellen Erscheinung zu mindet 85% zu frieden bin
################################################## ################################################## #############################
Mein aktuelles Konzept was nach erster Benutzung zwar funktioniert, aber ganz sicher nutzungs-ergonomische Macken hat (typischer Fall von "von innen nach außen entwickelt - statt außen nach innen):
Es gibt pro Farbe einen uint16_t vector. Ich habe uint16_t gewählt, weil sich dann Überläufe bin zu einem gewissen Maße erkennen lassen, wenn der Wert > 255 ist. Außer es haben so viele
Effekte drauf geschrieben, dass das der Wert von 2^16 übergelaufen ist.
Grundsätzlich folgt mein Ansatz einem Petruschka-Prinzip (selbst erfundenes Wort), wo jeder Layer eine bestimmten Baustein in der Abstraktion liefert.
Segmente definieren Ausschnitte vom Framebuffer einer Farbe. Segmente gleicher Länge können in Vectoren zu Segmentgruppen zusammengefasst werden - das hilft für symmetrische Effekte
Es gibt Kernel, welche nicht farbsensitiv sind, und nur vector-basiert eine Ansammlung von Werten darstellen.
Segmentegruppen und Kernel werden einem Kernel-Mover übergeben. Wie der Name impliziert, bewegt dieser den Kernel über die angegeben Segmente. Dazu bekommt er eine relative Position, die er mit Hilfe der Vector.Size() Eigenschaft
der Segmente auf die konkrete Pixelzahl der Segmente normiert.
-
Ein Kernelmover wird EINEM Effekt mitgegeben. Die Aufgabe eines Effektes ist, seinen Kernelmover mit einer Position zu versorgen. Dabei kann der Effekt "seinen" Kernel parametrisierbar oft mit ebenfalls parametrisierbarem Positions-Shift anwenden.
-
Mehrere KernelMover wiederrum können einer Sequenz übergeben werden. Eine Sequenz macht aus einem Tick(); unter Verwendung einer speed-Variable durch Auf akkumulieren einen Position, die dann eben an die Effekte geht.
Über den numerischen Wert, der speed-Variable kann die Effektgeschwindigkeit eingestellt werden.
=> Da die Position wie oben beschrieben letztendlich auf die konkrete Segmentlänge normiert wird, laufen alle Segmente innerhalb einer Sequenz synchron mit der gleichen Geschwindigkeit. Das ergib für das Auge eine zeitlich-symmetrische Erscheinung. Da das menschliche Hirn u.A. darauf programmiert ist, nach Symmetrien zu suchen, wird das am ehesten als "stimmig" wahr genommen.
Lesezeichen