Hallo, ich bräuchte mal eure Hilfe bei einem PWM Problem. Ich möchte 27 * 10 Bit (Soft-)PWM Kanäle bei mindestens 200Hz realisieren. Meine Methode ist im Moment die Register 24 und 25 per ADIW als Zähler zu benutzen. Der Timer0 übernimmt dabei das "Incrementieren". Nach jedem INC wird R25 > 0b11 überprüft und evtl. zurückgesetzt, außerdem werden alle 27 Kanäle auf ne Änderung überprüft usw.... Über die Formel XTAL // F_PWM // B_PWM kommt man bei 8MHz auf ca. 40 Cycles bei 20MHz auf 98 nach denen der Timer0 ein interrupt auslöst um zu "Incrementieren". Das Problem is nun, dass nur in Gedanken der Mikrocontroller schon nicht mehr nachkommt mit dem Überprüfen der 27 Kanäle, mal ganz abgesehen von Fernbedienung und som zeug. Meine Frage an euch: Wenn ich suche finde ich immer wieder Threats wo Leute von X Kanälen mit hunderten von Hz sprechen was auf ihren Systemen laufen würde, nur finde ich nirgends ne gescheite Anleitung. Also gibts ne bessere Methode und wo finde ich die?
Gast
#2042937
du solltest das inkrementieren dem eingebauten zähler überlassen, wenn dein chip einen hat, dann muss der prozessor nur dann arbeiten, wenn wirklich ein flankenwechsel ansteht und er hat zeit für noch andere aufgaben.
Gast
#2042941
Du lässt den Timer0 einfach im kreis laufen und fragst 27 mal mit unterschiedlichen Werten den Timer ab. z.B. if (timerwert>= Vergleichswert1) dann Ausgang an; else Ausgang aus; Das dann 27 mal untereinander
Gast
#2042942
dazu musst du halt wissen, welche lampe als nächstes ausgeknippst wird (musst halt die tabelle deiner 27 ausgänge nach pulsdauer sortieren)
@ poo: Ich Arbeite/"Simuliere" im Moment auf einem ATMEGA48. Sobald das Ganze aber verwirklicht wird kommt ein 32 her wegen den 27 IO Pins. Wenn ich dich richtig verstehe soll ich den Timer selber benutzen, nur wie bekomme ich dann raus ob ich einen der 27 Werte erreicht habe (stehen ja nur 2 OC einheiten zur verfügung bei dem 16Bit Timer)? @ Düsendieb: Du meinst Timer mit 200Hz laufen lassen und in der Hauptschleife einfach immer wieder abfragen? Wenn er in 1/200s von 0 bis 1024 zählen muss kommen trotzdem nur 40 Cycles raus zwischen zwei werten, also das gleiche Problem wie am Anfang beschrieben (oder mach ich irgend wo n denkfehler)?
Moin, du hast das Prinzip (glaub ich) noch nicht ganz verstanden. Du willst doch eigentlich "nur" regelmäßig abfragen, ob deine Vergleichswerte erreicht wurden, oder nicht. Diese Regelmäßigkeit erzeugt dir der Timer durch seine Interrupts. Wenn du 10 Bit, also 1024 PWM-Werte bei 200 Hz haben willst, dann mußt du deine Abfragen mit einer Frequenz von 1024 * 200, also 404800 Hz (ca. 405 kHz) machen. Du würdest deinen Timer also so einstellen, daß er seine Interrupts mit 405 kHz schmeißt, in dem du dann immer deine Zustände abfragst. Aber mit Verlaub, 27 Kanäle, 10 Bit bei 200 Hz wird "knapp". Vor allem, wenn du dann auch noch was nebenher machen willst (Tastverhältnisse über einen Zeitraum ändern, Kommunikation...). Ich hab das mal mit 24 Kanälen, 7 Bit und ca. 110 Hz gemacht. Das lief aber auf nem Tiny45 mit 3 Schieberegistern dran. Du könntest vielleicht auf sowas wie den TLC5940 umsteigen. Dann kriegst du die Auflösung und die Frequenz locker hin... Gruß
Gast
#2043078
Wieviel RAM steht denn zur Verfügung? Wenn genug RAM vorhanden ist, z. B. 4000 Byte (1000 x 32 bit), zerfällt die 27-fache Abfrage in einen einzigen RAM-Zugriff. Allerdings müssen dafür im Gegenzug bei Verstellung eines einzelnen Wertes mindestens soviele Bytes in der Tabelle neu beschrieben werden, um die sich der Wert geändert hat. Beispiel: Alle PWM-Werte werden auf 0 initialisiert, eine Tabelle der aktuellen Werte wird auch mitgeführt:
1 | |
2 | |
3 | |
Der PWM-Wert "17" soll auf 400 gesetzt werden:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Im Interrupt (zeitkritischen Teil) wird es dagegen sehr schnell. Der Interrupt muss mit einem Timer auf 200 kHz eingestellt werden:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
Aber wie gesagt, dieses Prinzip geht nur, wenn genügend Speicherplatz vorhanden ist und mit der Einschränkung, dass das Verstellen ggf. länger braucht.
Joachim B. schrieb: > Aber mit Verlaub, 27 Kanäle, 10 Bit bei 200 Hz wird "knapp". Seh ich auch so. > Vor allem, > wenn du dann auch noch was nebenher machen willst (Tastverhältnisse über > einen Zeitraum ändern, Kommunikation...). Ich hab das mal mit 24 > Kanälen, 7 Bit und ca. 110 Hz gemacht. Wobei der Knackpunkt hier die 7 Bit waren. Jedes Bit PWM-Auflösung weniger hilft enorm, weil es die notwendige Interrupt-Frequenz halbiert. Ein paar Kanäle mehr oder weniger fallen dagegen nicht so sehr ins Gewicht.
Mit Falks 'intelligenter Methode' http://www.mikrocontroller.net/articles/Soft-PWM#Intelligenter_L.C3.B6sungsansatz müsste noch was gehen.
Karl heinz Buchegger schrieb: > Wobei der Knackpunkt hier die 7 Bit waren. Jedes Bit PWM-Auflösung > weniger hilft enorm, weil es die notwendige Interrupt-Frequenz halbiert. Klaro, das stimmt :) . Kommt natürlich noch n bissl darauf an, das du in der Zwischenzeit mit den anderen PWM-Werten machst. Angenommen man wolle nach jedem Interrupt neue PWM-Werte laden, die aus einer bösen rand()-Funktion unter Verwendung des ADC hervorgehen , dann merkt man jeden Kanal ;) . Aber wie gesagt, unter den o.g. Bedingungen hat es bei mir gut geklappt. Mit SPI und allem. Prozessorauslastung von 20% oder so (ich weiß es grad nicht mehr genau). Ich würde entweder die Anforderungen herunterschrauben, oder auf Treiber zurückgreifen. Der "Intelligente Lösungsansatz" war mir bisher immer zu hoch -_0 ... Gruß
Joachim B. schrieb: > Karl heinz Buchegger schrieb: >> Wobei der Knackpunkt hier die 7 Bit waren. Jedes Bit PWM-Auflösung >> weniger hilft enorm, weil es die notwendige Interrupt-Frequenz halbiert. > > Klaro, das stimmt :) . Kommt natürlich noch n bissl darauf an, das du in > der Zwischenzeit mit den anderen PWM-Werten machst. Angenommen man wolle > nach jedem Interrupt neue PWM-Werte laden, die aus einer bösen > rand()-Funktion unter Verwendung des ADC hervorgehen , dann merkt man > jeden Kanal ;) . sowas ähnliches hab ich gemacht. Ähnlich wie du: An Schieberegister 64 LED mit einer 6 Bit PWM. rand() wurde benutzt um die Leuchtdauer und die Intensität der einzelnen LED zufällig zu verteilen. Noch eine UART zur Parametereinsteuerung dazu. Wurde mit 11Mhz schon etwas eng.
Gast
#2043257
Karl heinz Buchegger schrieb: > Mit Falks 'intelligenter Methode' > http://www.mikrocontroller.net/articles/Soft-PWM#Intelligenter_L.C3.B6sungsansatz > müsste noch was gehen. Leider fehlt dort die Version 4, die mit minimalem Code und noch wichtiger mit "wirklich" minimaler Rechenzeit im Interrupt auskommt. Trade-off dieser Version mit "vollständiger Tabelle" (siehe mein Beispiel oben) ist das aufwändigere Verstellen - allerdings: schneller als die PWM-Periode selbst macht das Verstellen auch wenig Sinn. Außerdem ist dieses Verfahren bei üblicherweise doch eher kleinen Verstellschritten ebenfalls nicht mehr langsam. Insofern bliebe eigentlich nur der RAM-Bedarf das Kriterium. Aber eine Über-alles-Abschätzung des Rechenaufwands muss schon vorher durchgeführt werden.
Gast
#2043843
Ich gebe noch ein weiteres Beispiel mit vollständiger Tabelle, das um ein Epsilon in der Interrupt-Ausführung langsamer ist (mit Read-modify-write- statt reinen Write-Befehlen), aber dafür fast optimal schnell auch in der Verstellung arbeitet. Dazu beinhaltet die Tabelle nicht den absoluten Port-Status, sondern indiziert an entsprechender Stelle den Pegelwechsel. Alle PWM-Werte werden auf 0 initialisiert, eine Tabelle der aktuellen Werte wird auch mitgeführt:
1 | |
2 | |
Verstellen eines PWM-Wertes (nicht reentrant, ansonsten schützen):
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Für den aktuellen PWM-Durchlauf kann ggf. durch das Umschalten eine "0-Runde" entstehen. Theoretisch ließen sich dagegen Vorkehrungen treffen (z. B. Synchronisierung durch Double-Buffering oder Abfrage der aktuellen PWM-Phase und manuelles Korrigieren des Port-Status in geschützter Region - das wäre in wenigen linearen Code-Zeilen getan). Im Interrupt (zeitkritischen Teil) ist es immer noch sehr schnell. Der Interrupt muss mit einem Timer auf 200 kHz eingestellt werden:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
Für eine PWM mit 8 Bit Auflösung und 8 Kanälen (entsprechend dem Beispiel "Soft-PWM") fielen gerade mal 256 Byte RAM an, für den OP-Code vermutlich nicht mehr als 200 Byte und die Interrupt-Last wäre sicher noch mal um einen nicht unerheblichen Faktor kleiner als im beim sogenannten "Intelligenten Lösungsansatz".
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.