als Nicht-Programmierer:
technisch ähnelt die Funktion doch einer 10 - 20- Kanal Servosteuerung.
als Anregung hier:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=9063
gruss stupsi
Hallo!
In Bascom will es nicht richtig, deswegen hab ich mal vor, es in ASM zu probieren. Allerdings will ich wissen, ob ich dabei technisch überhaupt Erfolg haben kann. Ich muss 12 Software-PWMs (8 Bit) haben. Ausserdem soll der Mega8 noch als TWI-Slave arbeiten, um die PWM-Werte entgegenzunehmen. Ca. 30x12 Byte pro Sekunde. Was ich mich frage ist, ob die PWMs sichtbar unterbrochen werden, wenn Daten kommen (Es hängen 4 RGB-LEDs an dem Controller). Das wäre nämlich absolut gar nicht gut in der Anwendung.
-> MEIN PROJEKTBLOG <-
als Nicht-Programmierer:
technisch ähnelt die Funktion doch einer 10 - 20- Kanal Servosteuerung.
als Anregung hier:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=9063
gruss stupsi
hmmm gutes Beispiel. Der SD20 war mir auch schonmal in den Sinn gekommen. Das ist ja dann quasi Multithreading. Wie macht der AVR das?
-> MEIN PROJEKTBLOG <-
Im wesentlichen ist das von 3 Faktoren abhängig.12 Software-PWMs (8 Bit) haben. Ausserdem soll der Mega8 noch als TWI-Slave arbeiten, um die PWM-Werte entgegenzunehmen
1. Von der Taktfrequenz des Controllers, die ich hier schon mal auf 16MHz anheben würde.
2. Von der PWM Frequenz.
3. Von möglichst wenig Code in den Interruptroutinen.
Bei 16MHz und einem Taktteiler von 8 komm ich auf eine PWM Frequenz von 30 Hz. Der Controller kann dabei 2048 Takte (~Kommandos) zwischen 2 Interrupts ausführen.
Bei 16MHz und einem Taktteiler von 1 komm ich auf eine PWM Frequenz von 244 Hz. Der Controller kann dabei 256 Takte (~Kommandos) zwischen 2 Interrupts ausführen. Das dürfte vermutlich zu wenig für eine stabile Funktion sein.
Die Teilerfaktoren /2 und /4 lassen sich im Prescaler nicht einstellen.
Mein Vorschlag wäre die 16MHz Taktfrequenz extern zu teilen (/2, /4) und die geteilte Frequenz auf den T0 Eingang zu geben. Dieser Takteingang taktet dann den Timer0 mit Prescaler 1, der dann als PWM Quelle dient.
Ich würd diesen Timer mit Overflow Interrupt laufen lassen.
In diesem Overflow Interrupt wird ein weiterer Zähler hochgezählt der mit den gewünschten PWM Registern verglichen wird und je nach Zählerstand die 12 Ausgänge aus-, bzw einschaltet.
Bei einem Teilerfaktor von 4 krieg ich dann 1024 Prozessortakte bevor ein Overflow Interrupt ausgeführt wird, als PWM Frequenz krieg ich dabei 60Hz raus und das sollte passen.
Eventuell kann man auch den Timer 1 als Taktteiler (OC1A mit CTC ?)vergewaltigen, dann könntest Du ohne externe Bauteile auskommen.
Wieviel Prozessorleistung dein TWI noch schluckt kann ich nicht sagen.
Kannst ja deinen fertigen Code mal über den Simulator austesten.
Ein möglicher Lösungsansatz wäre auch noch die PWM Werte nach ihrem Wert zu sortieren und sie in aufsteigender Reihenfolge mit dem Comparematch Register des Timers 1 zu vergleichen.
Liegen die Werte allerdings sehr nahe beieinander oder sind sie gleich, wird es auch hier zu Problemen kommen.
Hallo,
und evtl. das TWI nicht per ISR erledigen, sondern einfach TWINT pollen, denn TWI kann ruhig mal ein paar Takte warten bis es bedient wird.
Wenn das PWM auf TWI warten müsste ist das gleich zu erkennen, andersrum nicht.
Noch ne Idee:
Den Timer 2 mit einem Teilerfaktor von 1024 laufen lassen und mit dem Comparematch Interrupt bei jedem neuen Zählerstand des TCNT2 Registers einen Interrupt auslösen lassen. Also OCR2 in jedem neuem Interrupt um 1 erhöhen. In diesem Interrupt auch die einzelnen Kanäle löschen oder setzen.
Das ergibt eine PWM Frequenz von 60Hz wenn ich mich nicht verrechnet hab.
Ausserdem wir auch nur ein Timer verbraten.
Das mit dem TWINT Pollen halt ich auch für eine gute Idee.
ohje leute, ihr überfordert mein hirn. ich hab vor allem bis auf ein lauflicht auf nem tiny noch nie asm geproggt.. ich hab gerad versucht nachzuvollziehen, was ihr mir genau sagen wollt, aber ich komm nicht auf den punkt. wie wäre es mit einem schnipsel pseudocode für einen unwissenden, nur damit mir der ablauf klar wird? danke!
-> MEIN PROJEKTBLOG <-
Mal die Timer 2 Idee:
Du initialisierst den Timer2, damit er mit einem Teilerfaktor von 1024 von der Taktfrequenz des Controllers läuft.
Du gibst den Output Comparematch 2 interrupt frei.
Du setzt das OCR2 Register auf 1.
Du gibst mit SEI alle Interrupts frei.
Das war schon mal die Initialisierung.
Jetzt musst Du noch die OCR Interrupt Routine schreiben.
1. Alle verwendeten Register + SREG auf dem Stack sichern "PUSH"
2. Du liest das OCR2 Register aus und vergleichst mit diesem Wert deine gewünschten PWM Werte.
Ist der OCR Wert kleiner oder gleich wird der entsprechende Kanal angeschaltet.
Ist der OCR Wert größer wird der entsprechende Kanal abgeschaltet.
3. Nun noch den OCR Wert um 1 erhöhen und schauen ob er nun den Wert 0 hat (läuft nach 256 Zyklen wieder auf 0, da ja nur 8 Bit).
4. Den OCR Wert in das OCR2 Register schreiben.
5. Hat der OCR Wert den Wert 0, nochmals um 1 erhöhen und in das OCR2 Register des Timers 2 zurückschreiben.
6. Gesicherte Register + SREG mit POP wieder zurückschreiben.
Codeschnipsel:
Das wars, deine Software PWM ist fertig.Code:PUSH r16 IN r16,SREG PUSH r16 PUSH r17 IN r16,OCR2 LDS r17,pwm1 CP r17,r16 BRCC k1ein CBI PORTB,0 ; 1.Kanal aus RJMP k2 k1ein: SBI PORTB,0 ; 1. Kanal ein k2: LDS r17,pwm2 CP r17,r16 BRCC k2ein CBI PORTB,1 ; 2.Kanal aus RJMP k3 k2ein: SBI PORTB,1 ; 1. Kanal ein k3: usw, usw, für alle PWM Kanäle...... INC r16 BRNE writeocr2 INC r16 writeocr2: OUT OCR2,r16 POP r17 POP r16 OUT SREG,r16 POP r16 RETI
Welche Register für die benötigten Teilerfaktoren, Interruptfreigaben wie beschrieben werden müssen, müsste ich jetzt selber im Datenblatt nachschauen, aber das kannst Du ja selber auch machen.
Hinweis:
Das mit dem 2x Erhöhen beim Wert 0 brauchst Du um die LED's auch mal ganz abschalten zu können, bei OCR2=0 und PWM Wert 0 würde sonst der entsprechende Kanal kurz eingeschaltet.
Problemlos möglich, ich hab vor nicht allzulanger Zeit 16 Software PWM Kanäle mit 8 Bit Auflösung bei 500 Hz realisiert.Zitat von Goblin
Der Mikrocontroller lief dabei mit 16 MHz und er war von der Rechenzeit her zu ca. 30% ausgelastet, insofern die PWM Werte konstant blieben.
Neue PWM Werte benötigten ca. 3-4 ms um verarbeitet zu werden.
Bei meiner Anwendung wurden die neuen Daten über die serielle Schnittstelle übertragen. Flackern oder Stehenbleiben gab er wären der Übertragung nicht.Zitat von Goblin
Im übrigen würde ich die TWI nicht pollen sondern mit einem Interupt und entsprechenden Statusflags arbeiten.
Vom Prinzip her funktioniert es recht einfach, der Code allerdings ist wesentlich komplexer und Assemblertypisch recht schlecht lesbar. Deshalb möchte ich hier davon Abstand nehmen ihn zu posten.
Das Funktionsprinzip (ein kurzer Umriss):
Ich benötige einen schnelllaufenden Timer, welcher für die Ansteuerung der LED`s zuständig ist.
Die eingehenden Daten werden in eine Kanalmatrix umgerechnet, welche neben dem tatsächlich angesprochenem Kanal(Pin) auch den entsprechenden Helligkeitswert beinhaltet. Anschließend wird die Kanalmatrix nach der Helligkeit sortiert und gepackt. Diese Daten stehen dann im RAM bereit und werden in der Timerroutine nur noch ausgegeben.
Bei Bedarf kann ich das System das dahinter steckt gerne näher erläutern.
Grüße,
Hanni
Grundregeln des Forenpostings:
1. Nutze niemals die Suchfunktion!
2. Überprüfe niemals die Topics nach Ähnlichkeiten!
3. Schreibe alles in hellgelb!
500 Hz bei 16 Kanälen - Bo eh, das würd mich schon interessieren wie Du das hingekriegt hast ????Bei Bedarf kann ich das System das dahinter steckt gerne näher erläutern
Kannst Du mal das Verarbeitungsschema posten ?
Lesezeichen