Hi zusammen, erstmal zur Vorgeschichte: Ich habe einen Atmega644, der einen TLC5940 "programmieren" soll. Der TLC ist ein Baustein, der bis zu 16 LEDs (ich verwende allerdings momentan nur 8) einzeln über eine PWM (12 Bit) modulieren kann. Wenn der TLC also geupdated werden soll, benötigt er 16 Kanäle x 12 Bit (PWM). Ich habe eine Library (wer genauer hinein schauen möchte, siehe Anhang), die den Umgang stark vereinfacht. Es muss lediglich eine Funktion aufgerufen werden: void TLC5940_SetGS(channel_t channel, uint16_t value) Die Funktion legt also fest, welcher der 16 Kanäle mit welcher Intensität / PWM laufen soll. Alle anderen Kanäle bleiben unberührt, also PWM = 0 (da liegt nachher auch mein Problem, werdet ihr sehen. Nun ist mein Ziel folgendes: Ich möchte eine Art "Terminkalender" anlegen, in die Zustände aller Kanäle zu verschiedenen Zeitpunkten speichern und später abrufen kann. Ziel wäre also bspw. solch einen Ablauf zu haben: (3 LEDs an) - 100 ms: Kanal 1, 4095 - 100 ms: Kanal 2, 4095 - 100 ms: Kanal 3, 2000 (2 LEDs aus) - 200 ms: Kanal 1, 0 - 200 ms: Kanal 3, 0 (die letzte verbleibende LED aus) - 310 ms: Kanal 2, 0 Zu diesem Zweck habe ich ein struct erstellt, das folgendes speichert: - Zeitpunkt - Kanal - Intensität/PWM Dann habe ich ein Array erstellt, das mit den Structs befüllt wird. Das struct wird dann nach Zeit sortiert (wie das vonstatten gehen soll, wurde hier besprochen: Beitrag "Struct Array sortieren") Der User befüllt den "Terminkalender" / das Array über die Serielle Schnittstelle, auf ein Kommando hin arbeitet er dann dieses Array ab und danach ist dann Ruhe. Nun habe ich folgendes Hauptproblem: Wenn der Serielle Stream geparsed wird, werden daraus beipsielsweise folgende Einträge in dem Array (bitte oben nochmal in das Beispiel schauen, ist wichtig): - 100 ms: Kanal 2, 4095 - 200 ms: neue Konfiguration der LEDs - 310 ms: Kanal 2, 0 Bei jedem Zeitereigbnis wird der TLC ja neu mit LED-Zuständen gefüllt, ABER: Zum Zeitpunk 100 ms, wird Kanal 2 eingeschaltet, zum Zeitpunkt 200 ms wird sein Zuständ aber NICHT verändert (er soll erst zum Zeitpunkt 310 ms ausgeschaltet werden). Die Library bzw. der jetzige Programmierstand bezieht aber alte Zustände nicht mit ein --> es findet pro Zeitpunkt sozusagen immer ein "Reset" statt. Nun kann ich ja schlecht vom Nutzer verlangen, dass er folgendes macht: - 100 ms: Kanal 1, 4095 - 100 ms: Kanal 2, 4095 - 100 ms: Kanal 3, 2000 - 200 ms: Kanal 1, 0 - 100 ms: Kanal 2, 4095 <--- BLEIB BITTE IMMER NOCH AN! - 200 ms: Kanal 3, 0 - 310 ms: Kanal 2, 0 <--- Ja, jetzt darfst du endlich aus gehen! Das ist natürlich sehr Fehleranfällig. Letztendlich möchte ich also, dass ich innerhalb meiner Programmierung also nur VERÄNDERUNGEN erfasse, wohingegen ich mit eine Lib arbeite, die nur neue Zustände bearbeitet. Ich hoffe, ich konnte das Problem deutlich machen, ansonsten gibts dann nachher den zweiten Versuch... Man könnte nun Fragen, warum ich mir nicht meine eigene Lib schreibe, wenn die jetzige die Funktionalität nicht aufbringt, die ich benötige: Ich bin noch nicht 100% ig sicher in C und ich wüsste auch davon abgesehen derzeitig nicht wie ich das Problem gelöst bekomme. Gruß, Durokh
Ralf S. schrieb: > Ich habe eine Library (wer genauer hinein schauen möchte, siehe Anhang), > die den Umgang stark vereinfacht. Es muss lediglich eine Funktion > aufgerufen werden: > void TLC5940_SetGS(channel_t channel, uint16_t value) > > Die Funktion legt also fest, welcher der 16 Kanäle mit welcher > Intensität / PWM laufen soll. Alle anderen Kanäle bleiben unberührt, > also PWM = 0 (da liegt nachher auch mein Problem, werdet ihr sehen. Nö. Wenn ich den Code beim überfliegen richtig gelesen haben, dann werden die mitnichten 0. Sie bleiben unberührt, heißt soviel wie "was immer ihr Wert ist, ein Aufruf dieser Funktion ändert sie nicht" > erst zum Zeitpunkt 310 ms ausgeschaltet werden). Die Library bzw. der > jetzige Programmierstand bezieht aber alte Zustände nicht mit ein --> es > findet pro Zeitpunkt sozusagen immer ein "Reset" statt. Das hätte ich jetzt in dem Code der Funktion aber nicht gesehen. (Aus dem Grund ist es immer schlecht, wenn du Code als PDF postest. Man sieht die Dinge da drinnen so schlecht, weil man kein Syntax-Highlighting hat, die Schreift meistens klein ist und man dauernd über Seitengrenzen hinweg scrollen muss.)
Dieser Code hier
1 | void TLC5940_SetGS(channel_t channel, uint16_t value) { |
2 | channel = numChannels - 1 - channel; |
3 | channel3_t i = (channel3_t)channel * 3 / 2; |
4 | |
5 | switch (channel % 2) { |
6 | case 0: |
7 | gsData[i] = (value >> 4); |
8 | i++; |
9 | gsData[i] = (gsData[i] & 0x0F) | (uint8_t)(value << 4); |
10 | break; |
11 | |
12 | default: // case 1: |
13 | gsData[i] = (gsData[i] & 0xF0) | (value >> 8); |
14 | i++; |
15 | gsData[i] = (uint8_t)value; |
16 | break; |
17 | }
|
18 | }
|
setzt definitiv nur die Werte des angegebenen Channels. Alle anderen bleiben so wie sie sind, also intakt. Wenn deine Idee also nicht funktioniert, dann hast du einen anderen Programmfehler. Die Funktion ist es jedenfalls nicht. Sieh mal deinen Code durch, ob du irgendwo 'generelle Löschfunktionen' aufrufst, wo es nicht sein sollte. Ich schätze mal, dass du selber dir beim Wechsel in den nächsten Zeitpunkt alle Einstellungen löscht, indem du einen
1 | TLC5940_SetAllGS( 0 ); |
Aufruf machst, wo er nicht sein sollte. Wenn du einfach nur anhand deiner im Array vorliegenden Anweisungen die entsprechenden Kanäle in der TLC5940_SetGS Funktion mit den neuen Werten beschickst, dann muss das sauber durchlaufen.
Oh, man. Mist. Du hast Recht. Das war mein Fehler. Wie blöde. Vielen Dank fürs drüberschauen!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.