Autor Thema: Programmierung WS2812  (Gelesen 23847 mal)

Offline Darkside

  • Newbie
  • *
  • Beiträge: 45
    • Profil anzeigen
Re: Programmierung WS2812
« Antwort #30 am: Dezember 23, 2014, 16:25:15 Nachmittag »
16 Befehls Zyklen?
das ist doch aber schon zu lange, um SPI mit neuen Daten zu versorgen?!

Generall habe ich auch nachgedacht, mit einem Timer zu arbeiten, aus der Überlegung, den LEDs Leben einzuhauchen.
25Mal in der Sekunde für Wechsel zu sorgen, sollte ja ausreichen. Und per Timer, damit Wechsel der Ausgabe nicht nach fertiger Berechnung, sondern nach konstanter Zeit erfolgt. Man hätte also 40mS für Berechnungen, leider dann abzüglich der Zeit, die man zum Senden der Daten an die LEDs braucht. Bei effektiven 8MhZ hätte man also 320000 Prozessortakte minus der Zeit der Ausgabe (Abhängig der LED Anzahl), um Berechnungen anzustellen.

Mittlerweile ist das Programm so aufgebaut, dass es jeder LED die nötigen Daten schickt, danach wird der Interrupt abgeschaltet. Dann könnte eine neue Berechnung erfolgen und die geänderten Daten könnte bei aktiviertem Interrupt wieder an die LEDs geschickt werden.
Die Zeit, die man hat, während ein Byte vom SPI gesendet wird ist so knapp, dass man kaum etwas anderes unternehmen kann.

Selbst das direkte arbeiten mit einem Array war problematisch.
Einfach nur den gleichen Wert vom Array (led[a] bzw, led[0][0]) ans SPI zu übergeben, war nicht möglich. Die Erstan LEDs wurden korrekt angesteuert, dann war die zeitliche diskrepanz zu groß, da der Zugriff auf ein Array wohl zu viel Zeit benötigt.

Auf den einen oder anderen Umweg ist dies jedoch jetzt auch möglich.
Jedoch ist keine Zeit, während die LEDs mit Werten versogt werden müssen, da noch Berechnungen laufen zu lassen.
Deshalb könnte man fast schon nur eine Ausgaberoutine machen, die erst komplett durchläuft, bevor man sich anderen Aufgaben widmen kann.
Deshalb ist auch die Überlegung da, einen Timerinterrupt zu machen, der dann das Senden aktiviert, damit dies immer zu einer konstanten Zeit geschieht.
Aber da wird noch geschaut, was man wie machen kann. Gibt einige Ideen, die umgesetzt werden müssen und wo geschaut werden muss, wie es klappt.
Denke über einige Funktionen zur verschiebung von Farbmustern nach links/rechts ist sinnvoll, sowie zur Helligkeitsänderungen etc.
Evtl auch mal Tools wie gLEDiator mal angucken etc.
Denke es ist aber sinnvoll nur einen PIC zu verwenden, der sich um die LEDs kümmert und keine weiteren Aufgaben übernimmt, als dementsprechende Berechnungen oder Daten von anderen Quellen zu übernehmen, um diese dann auszugeben und evtl mit Effekten zu versehen....

Muss auch mal gucken, wie das mit dem Speicher hinhaut, da ich momentan 2 Arrays verwende, evtl wird sich dies als Sinnvoll oder als Blödsinn herausstellen.
Denkbar wäre auch, dass ein PIC mit External Memory Bus von Vorteil wäre, denn schließlich ist auch eine Grafikkarte ohne Speicher nichts.
Mal gucken, welche PICs ausser dem 18F8722 den haben. Damit kann man dann wohl bis 2MB ansprechen. Wenn natürlich andere Peripherie fehlt, die man für die Ansteuerung der LEDs haben sollte, ist das auch nichts...

picalic

  • Gast
Re: Programmierung WS2812
« Antwort #31 am: Dezember 24, 2014, 00:19:46 Vormittag »
Klar, die Berechnung erst zu machen, wenn das SPI schon die Daten haben will, haut nicht hin! Ich rechne so: Bei maximaler Übertragungsrate wird alle 10.5 µs ein Byte gesendet, das sind 84 Befehlszyklen (=252 pro LED). Meine Ausgabe-ISR benötigt 24 Zyklen, um ein Byte aus dem FIFO-Puffer auszugeben (*3 = 72 pro LED). Also bleiben 252-72 = 180 Zyklen, um die Daten für eine LED zu berechnen und im FIFO abzulegen, um praktisch unbegrenzt lange LED-Ketten anzusteuern. 
Wenn die Berechnung der Daten für ein paar LEDs mal länger dauert, ist es auch kein Problem, wenn es bei anderen LEDs dann mal wieder schneller geht - das gleicht das FIFO aus.
Das FIFO ist also der Schlüssel, um die Berechnungszeit von der Zeit zur Datenübertragung zu entkoppeln.
Wenn dauerhaft mehr Berechnungszeit pro LED benötigt wird, kann man die Zeit durch verringern der Übertragungsrate strecken. An meinem LED-Streifen mit 288 LEDs habe ich es mit 250 kbps (4µs/Bit) probiert und es geht einwandfrei! Damit habe ich 708 Zyklen pro LED zur Berechnung!
Die "0"-Impulslängen dürfen bei langsamerer Datenübertragung nicht länger werden, die "1" Impulse können länger werden (sind bei mir immer 1/2 Bitrahmen) oder ihre normale Länge behalten. Die LEDs kürzen zu lange "1"-Impulse ggf. am Ausgang zur nächsten LED wieder auf "Normallänge" ab. 
Wenn die Anzahl der LEDs begrenzt ist, hat man noch mehr Zeit zur Berechnung. Wenn z.B. das FIFO Daten für 50 LEDs aufnehmen kann und der LED-Streifen 100 LEDs lang ist, hat man viel mehr Rechenzeit, wenn die Ausgabe erst gestartet wird, wenn das FIFO voll ist. Die Daten der ersten 50 LEDs sind bei Ausgabe der 1.LED schon berechnet, und in der Zeit bis zur Ausgabe der 100. LED müssen nur noch 50 LEDs berechnet werden!

Meine Systemzeit erzeuge ich ohne Interrupt (bin halt mit den Zyklen in der ISR knauserig!). Dafür muss ich allerdings im Hauptprogramm irgendwann (im Abstand < 4ms) eine Service-Routine aufrufen. Diese benutzt den TMR0, um die Systemzeit (in Millisekunden) zu aktualisieren.
Der "Patternmover" (so nenne ich die Funktion, die die "Patterns", dh. Licht-Muster, verschiebt) benutzt die Systemzeit und die in der Pattern-Datenstruktur eingetragene Geschwindigkeit, um die neue Position für das jeweilige Pattern auszurechnen.   

gLEDiator - hmm, vielleicht sollte ich den Jungs mal meinen PIC12F1840-Code geben - der schafft die Umsetzung von 1000000 Baud seriell auf mehr(!) als 1024 WS2812-Pixels locker! Wer braucht schon so'n riesigen, schrottigen und teuren (Mega-)Arduino...  ;)

« Letzte Änderung: Dezember 24, 2014, 00:27:13 Vormittag von picalic »

Offline Darkside

  • Newbie
  • *
  • Beiträge: 45
    • Profil anzeigen
Re: Programmierung WS2812
« Antwort #32 am: Dezember 24, 2014, 16:06:42 Nachmittag »
Hm.
Also, zunächst wollte in der Interruptroutine einen Wert aus einem 2-Dimensionalen Array lesen. Doch das dauert wohl auch zu lange.
Deshalb schreibe in den Wert schon in eine Variable und ordnen diesen Wert zuerst dem SPI-Speicher zu.
Danach wird der nächste Wert der Variablen zugeordnet, damit dieser wieder direkt beim Interrupt zur Verfügung steht.

Als ich jedoch dieses 2-Dimensionale Array verwendet habe, gab dies wieder Probleme. Während der Zeit, wo SPI die Daten sendet, besteht nicht genügend Zeit.
Hatte mich für ein 2-Dimensionales Array entschieden. Der eine Wert gibt quasi an, welche LED und der andere Wert, welche Farbe. a[10][0] gibt also z.B. an, die 11. LED und die Farbe Grün, bzw. den Wert für die Farbe grün.
Bin der meinung so kann man einfacher/übersichtlicher mit den Daten umgehen, analog zur Bildverarbeitung...

Wenn ich jedoch nach dem Interrupt dementsprechend die Farben hochzähle und am Ende mit IF schaue, ob man zur nächsten LED gehen muss und von den Farben von vorne anfängt, dann gibt es Probleme. Denke die Zeit reicht dann schon nicht mehr aus, weswegen ich keine anderen Berechnungen mache, während die Werte an den ganzen LED-Streifen übergeben werden sollen.
Deswegen bin ich da gerade mit dem Speicher sehr verschwenderisch und kopiere das 2-Dimensionale Array in ein eindimensionales Array, damit man das einfach von vorne nach hinten durchzählen kann. Bin da halt auch noch am herum probieren.
Für andere Berechnungen sollte dementsprechend dann auch zwischen der Ausgabe keine Zeit sein.

Offline Darkside

  • Newbie
  • *
  • Beiträge: 45
    • Profil anzeigen
Re: Programmierung WS2812
« Antwort #33 am: Dezember 25, 2014, 21:43:42 Nachmittag »
Hm,
1,15us ist der 0 Code lang, 1,3us der 1 Code.
Das macht nach meiner Berechnung abgerundete 10 Rechenschritte pro bit. Bei 8 Bit, also gerundete 83. Stimmt also.
Evtl sollte ich mal überprüfen, ob ein Fehler vorliegt und mal überlegen, wie ich zwischenzeitlich die nächste LED am besten berechne.
Aber vielleicht sollte ich auch mal nachrechnen, bei Wievielen LEDs mit der momentanen Methode möglich sind.
Danke für diese Erkenntnisse. Werde da mal anfangen in diese Richtung Gedanken an zu stellen und zu schauen, ob dies auch in C möglich ist.

picalic

  • Gast
Re: Programmierung WS2812
« Antwort #34 am: Dezember 29, 2014, 14:31:01 Nachmittag »
Servus,

ich habe auch schon mal daran gedacht, ein gemischtes Projekt (C und ASM) daraus zu machen, d.h. die zeitkritischen Sachen wie ISR und den Pattern-Display-Prozessor (der berechnet die Daten parallel zur Ausgabe) in ASM, Pattern-Mover (der läuft in den Ausgabe-Pausen und ist demnach eher zeitunkritisch) in C. Das wäre dann praktisch mein Einstieg in C mit PIC-MPUs.
Eine Herausforderung dabei scheint mir die "Verheiratung" von C- und ASM-Code zu sein, d.h. wie können beide relativ komplexe Datenstrukturen miteinander teilen. Habe schonmal ein wenig in der Doku zum XC8-Compiler geschmökert: der Zugriff auf einfache Variablen ist wohl kein großes Problem, und auch die Übergabe von einfachen Parametern bei Aufrufen von ASM-Funktionen aus C sollte kein großes Problem sein. Aber lässt der C-Compiler z.B. überhaupt ein Bank-übergreifendes Array zu? Der Zugriff auf meine Datenstrukturen erfolgt im ASM-Code über die lineare Adressierung durch die FSRx-Register (mit FSRxH = 0x20), da muss ich mal schauen, ob und wie man den C-Compiler dazu überreden kann, es ebenso zu tun?

Die Control-Struktur für die Pattern-Daten würden in C-Codierung ungefähr so aussehen:
typedef struct
{
  unsigned char pdp_flags; // some control/status flags
  signed char pm_speed; // speed for moving pattern (-128..+127)
  unsigned char pm_taccu; // (used for move timing)
  unsigned char pdp_substep; // for microstepping
  signed int pdp_startled; // LED number, where pattern starts
  unsigned int pdp_gap; // gap between patterns in tile mode
  GRB_data_t *pdp_srcstart; // pointer to start of source pattern
  GRB_data_t *pdp_srcend; // pointer to end of source pattern (+1)
  GRB_data_t *pdp_srcptr; // currently processed source pattern data
  unsigned char pdp_blendmode; // blend mode
} Pattern_t;

Die Zeiger (pdp_srcstart, pdp_srcend) definieren dabei die Quelldaten  (z.B. ein Regenbogen-Farbmuster im ROM).
pdp_flags enthält Steuerbits, die u.A. angeben, wie das Muster auf dem LED-Streifen erscheinen soll, z.B.:
  einfach: das Farbmuster fängt bei der LED (pdp_startled) an und wird nur einmal dargestellt.
  Tile Mode: das Muster wird Kachel-artig wiederholt und füllt den gesamten LED-Streifen (Start-LED bis zum Ende), bei aktiviertem Wrapping auch vor der Start-LED, dann also über den gesamten LED-Streifen.
  Wrapping: wenn das Muster über das Ende des Streifens hinausgeht, wird es am Anfang des Streifens fortgesetzt (z.B. für LED-Ringe)
pm_speed enthält die Geschwindigkeit, mit der sich das Farbmuster über den Steifen bewegt (normalerweise in LEDs/Sekunde, bei aktivierten "Microsteps" sind es Schritte/Sekunde)
pdp_gap: Bei Kachel-Darstellung: Lücke zwischen der Muster-Wiederholung (in LEDs)
pdp_substep: es besteht die Möglichkeit, Muster in kleineren Schritten, als LEDs auf dem Streifen zu positionieren (sog. "Microsteps", aktuell: 1/8 Schritte). Bei langsamen Bewegungen führt das zu einem gleichmässigeren Bewegungseindruck. Der Pattern-Prozessor interpoliert dabei die Daten zwischen zwei LEDs linear. Diese Variable enthält die 1/8-Schritte, die dann zusammen mit der
pd_startled = LED-Nummer
die Startposition des Musters auf dem Streifen bilden.
Die LED-Nummer kann negativ werden, so daß z.B. bei pd_startled=-10 und einer Länge des Musters von 20 LEDs die 2.Hälfte des Musters ab dem Streifenanfang erscheint.
pdp_blendmode: Art der Farbmischung zwischen darunter liegenden Ebenen und dem aktuellen Pattern. Es gibt (optional) mehrere Ebenen ("Layers") und deshalb ein Array aus Pattern-Datenstrukturen:
Pattern_t PatternData[N_LAYERS];
Diese werden vom Pattern-Prozessor für Layer 0 (unterste) bis  N_LAYERS-1 (oberste) nacheinander abgearbeitet.
Blendmodes können z.B. sein:
BM_OPAQUE: die LED-Farbe wird durch Daten aus dem aktuellen Pattern ersetzt,
BM_MIX: es wird der Mittelwert zwischen aktuellem Pattern und darunter liegender Farbe gebildet,
BM_ADD, BM_SUBTRACT: Addition bzw. Subtraktion,
BM_MULTIPLY (noch nicht implementiert):  dafür brauche ich die schnelle 8x8 Multiplikation...

   
 
 

Offline Darkside

  • Newbie
  • *
  • Beiträge: 45
    • Profil anzeigen
Re: Programmierung WS2812
« Antwort #35 am: Dezember 30, 2014, 19:29:44 Nachmittag »
Hm,

im MPLAB XC8 C Compiler User's Guide gibt es ja den Abschnitt Mixing C and Assembly Code.
Dennoch wird dort auch abgeraten, zu mischen, wegen der Kompatibilität bzw. wartbarkeit.
Soll wohl gehen, Funktionen in Assambler zu schreiben und diese Funktionen dann in XC8 zu integrieren. Dazu sollte etwas beim Linker stehen, wie man auch Assambler-Dateien verknüpft.

Das mit den übergreifenden Variablen scheint ja recht kompfortabel zu sein, so wie es im C Compiler User's Guide steht.
Wie dies jedoch bei arrays aussieht? Letzten endes wird aber auch C Arrays über mehrere  Banken verteilen müssen, je nach Gegebenheiten.

Evtl findet man auch etwas unter:
http://microchip.wikidot.com/faq:21
http://microchip.wikidot.com/faq:38
...

oder in einem Microchip Forum:
http://www.microchip.com/forums/m699608.aspx

Evtl. wird es sich aber auch lohnen, davor zu schauen, wie gut alles Echtzeitfähig ist, wenn es komplett in C geschrieben ist.
Irgend wo habe ich gelesen, die Interruptroutine braucht schon einige Prozessortakte...
Da könnte man ansetzen und schauen, wie lange es braucht.
Bzw. ohne Interrupts alles verwirklichen, gnadenlos ins Spi schreiben und die Zeit dazwischen für Berechnungen nutzen, so dass auch alles passt.
Am Anfang ist der C-Kompiler ja auch für 30 Tage oder so als Pro, also mit Optimierungen bzw. ohne den Code mit Müll voll zu stopfen.

Wie es aussieht, hat sich da jemand schon gut in das Thema hineingefuchst und schon diverses implementiert.
Respekt.
Bei den Pics scheint es da auch noch recht wenig zu geben. Bei Arduino oder so scheint es ja Bibliotheken zu geben... aber keine Ahnung.


picalic

  • Gast
Re: Programmierung WS2812
« Antwort #36 am: Januar 21, 2015, 02:23:53 Vormittag »
So, endlich hab ich's mal geschafft, die Web-Doku zu meinem PIC2WS2812-Projekt fertigzustellen...
Wenn's interessiert: http://www.picalic.de/PIC2WS2812/

Grüße,

Thomas

 


* Recent Topics