Hallo zusammen, für ein Projekt zu Hause brauche ich eine "PWM", bei der ich die Ein- und Auszeit über zwei Potis separat vorgeben kann. Das ganze soll auf einem Atmega88 Unterschlupf finden. CPU-Takt ist 8MHz (intern). Das Problem hierbei: Einschaltzeit: 1-1024 µs (10-bit ADC-Wert von Poti 1 + 1) Ausschaltzeit: 1-1024 ms (10-bit ADC-Wert von Poti 2 + 1) Im Hauptprogramm finden noch einige Dinge statt (ADC-Werte einlesen, LCD-Ausgabe), die aber nicht wirklich zeitkritisch sind. Über "normale" PWM ist das ja schonmal so einfach nicht zu machen (Timer-Auflösung zu gering). Im schlimmsten Fall beträgt meine Periodendauer ja ca. 1 Sekunde, bei einer Auflösung von 1 µs :/ ... Mein Ansatz bisher war, den 16-bit Timer mit Prescaler 8 laufen zu lassen (1 MHz) und den TOP-Wert direkt von Poti 1 zu übernehmen. In der OVF-ISR wird dann der Prescaler auf 64 und der TOP-Wert auf 125 gesetzt (ca. 1 kHz) und bei jeder weiteren ISR eine Variable hochgezählt, die dann mit meinem Potiwert 2 verglichen wird. Sind die beiden Werte gleich, Prescaler wieder auf 8 stellen, usw... Ein entsprechendes "Flag", was ich zur Unterscheidung innerhalb der ISR nutze, hab ich natürlich (schneller Betrieb oder langsamer "Vergleich-Betrieb"). Mit diesem Ansatz klappt es aber überhaupt nicht und ich glaub da bin ich irgendwie auf dem Holzweg. Ich will jetzt nicht, daß ihr meinen Kram debuggt. Aber es wäre toll, wenn ich von euch ein paar Denkanstöße kriegen könnte, wie ihr das lösen würdet! Danke schonmal! Grüße Joachim
Der ATmega88 hat 2 8 bit PWM Kanäle, und ich würde als erstes überlegen, ob mir nicht 256 PWM Stufen mit 4us Auflösung reichen, dann ist die Implementierung nämlich eingfach. Aber man kann die Hardware-PWM auch durch umprogrammieren der Vergleichswerte durch Software auf 10 bit erweitern, es gibt ja einen Interrupt (der allerindings wenig hilft wenn man Counter-Werte von 0-10 programmieren muss, da braucht man einen Interrupt der deutlich früher kommt, also vom zweiten Timer). Also: Setze PWM-Timer und Interrupt-Timer auf 1us Aufkösung. Programmiere Interupts alle 128us (PWM läuft ja 256us). In diesem Interrupt wird der Output Compare Wert der beiden PWM Kanäle umprogrammiert, und zwar genau dann, wenn der nächste Compare Wert weit genug weg ist (zumindest 10us) damit es zu keinen Störungen kommt. Neben dieser Methode, ständigem umprogrammieren der Vergleichswerte, ist 1us bei 8MHz Takt auch komplett in Software machbar, ohne Interrupts kann man vergleichen und ein bit auf den Port ausgeben. Da man bei 2 PWM Kanälen a 10 bit nur 4 mal in 1ms was machen muss, hat man zwischen den Momenten auch Zeit für längere Operationen auf LCD und ADC. Man muss sich nach Rückkehr von diesen Operationen bloss wider sysnchronisieren, in dem man auf den durczlaufenden Timer1 per polling guckt Damit diese reine Software ohne Interrupts sauber läuft, musst du deine LCD und ADC Routinen so schreiben, daß sie weniger als 250us benötigen. Das sollte ja kein Problem sein. Die eigentliche in 1us durchlaufende Programmschleife macht nun folgendes: Vergleiche Timer1 mit nächsten Event, wenn der Event gekommen ist, Event ausführen (nein, das ist KEINE Subroutine, der Call-Overhead wäre zu hoch) und zum nächsten Event weiterschalten (das kann man gut machen, in dem man die Schleife aufrollt und 7 mal hintereinander schreibt und nur ein mal zurückspringt) Es gibt die Events: PWM Ausgänge ändern PWM0 und PWM1 auf 0 PWM1 auf 0 und PWM1 auf 1 PWM1 auf 1 und PWM1 auf 0 PWM0 und PWM1 auf 1 und eine Routine aufrufen LCD Routine aufrufen ADC Routine aufrufen Events neu berechnen Das Einordnen, welche Events kommen, macht man ausserhalb der engen Schleife. Die platziert die 7 oben aufgeführten Events zu passenden Zeiten, d.h. die LCD Routine wird in die Event-Liste eingefügt, wenn der nächst Timer-Event mindestens 256us weg ist (uns so einen Timeslot gibt es immer, weil deine 4 Operationen während der 1us nicht schlechter verteilt sein können). Klingt schwierig ? Es ist nicht schwieriger, als das umprogrammieren der PWM on the fly. Und es hat den Vorteil, daß man auch 8 PWM Kanäle nutzen könnte, weil keine PWM Hardwware nötig ist. Es läuft also auf jedem noch so einfach gestrickten Prozessor.
Es gibt doch 2 Compare Register die du verwenden kannst. So kannst du bei jeder Übereinstimmung einen Interrupt auslösen im ersten schaltest du den Portpin High im 2ten Interrupt auf Low. Deine Adc Werte musst du halt entsprechend hochmultiplizieren.
MaWin schrieb: > Klingt schwierig ? Es ist nicht schwieriger, als das umprogrammieren der > PWM on the fly. Und es hat den Vorteil, daß man auch 8 PWM Kanäle nutzen > könnte, weil keine PWM Hardwware nötig ist. Es läuft also auf jedem noch > so einfach gestrickten Prozessor. Danke für deine Idee und deine Mühe! Klingt dennnoch im ersten Moment nach hartem Tobak ;) . Ich werde aber mal gucken, ob ich das irgendwie umsetzen kann. Es klingt auf jeden Fall recht souverän und robust. @Thomas: wie meinst du das? Quasi als normale schnelle PWM? Kannst du das kurz näher beschreiben? DANKE! Gruß
Joachim B. schrieb: > für ein Projekt zu Hause brauche ich eine "PWM", bei der ich die Ein- > und Auszeit über zwei Potis separat vorgeben kann. > Einschaltzeit: 1-1024 *µs* > Ausschaltzeit: 1-1024 *ms* In Hardware würde ich da einfach zwei Monoflops nehmen, die sich gegenseitig triggern. Z.B. in Form eines 4538-ICs. Gruss Harald
Ich versuche es mal einfach zu erklären und gehe mal von 255 Bit aus. Wobei man hier nicht viel Zeit für die Interrupts hat wenn man keinen Taktteiler verwendet ADC Werte der beiden Potis einlesen z.b. 10 und 245 eigentlich würde man dafür nur 1 Poti benötigen, da man sich die 245 auch ausrechnen kann. Diese gibt man an die beiden Compareregister, initialisier die Interrupts... Setzt den Ausgangspin auf high wenn der Wert1 nicht 0 ist, danach Timer starten, sobald nun der Timer den Wert des ersten Compareregisters erreicht hat wird ein Interrupt ausgelöst, dein Programm verzweigt als an die vorgegebene stelle wo z.B. steht der Ausgangspin wieder auf low zu setzen ist, der Timer zählt weiter und wenn Comparewert 255 erreicht hat ist wird wieder auf high zu setzen. Wenn eine Wandlung fertig ist kann man wiederum per Interrupt die Comparewerte neu schreiben und dann läuft das ganze z.B. mit 30 und 255 ab. |---| |---| |---| | |------------------| |----------------| | 10 245 255 10 245 255 10 es gibt aber sehr viele Möglichkeiten wie man das macht, man kann den Timer automatisch zurücksetzen lassen, ihn einfach weiterlaufen lassen, alles per Hand machen, also Timerwert selber löschen...es gibt sehr viele Möglichkeiten deswegen musst du mal schauen was für deine Anwendung brauchst. Schau dir die verschiedenen Möglichkeiten im Datenblatt an. Und wenn du 10Bit ADC Werte hast dein Timer aber mit 16Bit läuft kannst du die ADC Werte einfach um 6 Stellen nach links schieben oder du addierst 64 Messungen zu einem 16Bit Wert zusammen und hast da gleich eine Mittelung deines Ergebnisses drin und deine Werte schwanken auch nicht mehr so stark.
Du mußt Dir die Zeiten ein wenig anpassen; dann sollte das Programm Deine Wünsche erfüllen. http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp1 Im Anschluß ist ein Programm, wo die Daten per RS232 eingegeben und im EEPROM fürs nächste Einschalten hinterlegt werden. http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp2
Harald Wilhelms schrieb: > In Hardware würde ich da einfach zwei Monoflops nehmen, die sich > gegenseitig triggern. Z.B. in Form eines 4538-ICs. > Gruss > Harald Ui, das klingt auch gut. Da hab ich doch glatt wieder den NE555 im Kopf ;) ... @Thomas: super, vielen Dank für die Ausführung! Ich werd mich heut abend mal daran machen eure Ideen um zu setzen. Gruß und danke!
Hallo JoJo, da du die Einheiten µs und ms extra hervorgehoben hast gehe ich davon aus das du eine PWM im Verhältnis von max. ca. 1 zu 1 Million realisieren willst. Bist Du dir da sicher? Die 10bit Auflösung der ADC ist auch nur graue Theorie. Vielleicht beschreibst Du mal was du damit regeln willst. Bestimmt finden wir dann eine realistische Lösung. Gruß Roman
RomanK schrieb: > da du die Einheiten µs und ms extra hervorgehoben hast gehe ich davon > aus das du eine PWM im Verhältnis von max. ca. 1 zu 1 Million > realisieren willst. Ich lese dies gerade. Die beiden genannten Zeiten sind jeweils 1:1024, einmal in 'µs' und einmal in 'ms'. Es gibt keinen Grund diese miteinander zu multiplizieren. Der ATmega88-interne ADC reicht für diese Auflösung aus und es gibt auch keinen Grund, die Auflösung auf 1:256 zu reduzieren oder auf Monoflops auszuweichen.
m.n. schrieb: > Ich lese dies gerade. Die beiden genannten Zeiten sind jeweils 1:1024, > einmal in 'µs' und einmal in 'ms'. Es gibt keinen Grund diese > miteinander zu multiplizieren. Wie willst du das denn sonst nennen, wenn als Extremwerte Pulslänge von 1024µs mit 1ms Pause (i.e. Tastverhältnis 50%) und im anderen Grenzfall 1µs mit 1024ms Pause (i.e. Tastverhältnis 0.00009765625%) genannt werden.
Mike schrieb: > Wie willst du das denn sonst nennen, wenn als Extremwerte Pulslänge von > 1024µs mit 1ms Pause (i.e. Tastverhältnis 50%) und im anderen Grenzfall > 1µs mit 1024ms Pause (i.e. Tastverhältnis 0.00009765625%) genannt > werden. Ja. Und von PWM kann dann mit Sicherheit nicht mehr die Rede sein. Zumindest kenne ich nichts mit solch einem Tastverhaltnis, dass sich PWM nennt.
Mike schrieb: > Wie willst du das denn sonst nennen, Es geht hier nicht um PWM-Tastverhältnisse, sondern um zwei separate Zeiten, für die jeweils einzeln ein Verhältnis von max. 1:1024 einstellbar sein soll. Wo ist das Problem? Wenn hieraus eine "PWM im Verhältnis von max. ca. 1 zu 1 Million" konstruiert wird, dann vermutlich mit dem Gedanken, die Anforderungen dramatisch ins Unlösbare zu treiben. Die Aufgabe ist aber durchaus uneingeschränkt mit wenig Aufwand lösbar, selbst wenn man 'wackelige' Monoflops nehmen möchte!
m.n. schrieb: > Es geht hier nicht um PWM-Tastverhältnisse, sondern um zwei separate > Zeiten, für die jeweils einzeln ein Verhältnis von max. 1:1024 > einstellbar sein soll. Wo ist das Problem? Thread name: PWM über 2 Potis Du magst Recht haben, aber TO nicht. Eine Uhr, bei der 2 LEDs im Sekundentakt blinken, ist mit Sicherheit nicht PWM gesteuert, egal ob 100ms an oder 600ms an. Auch Blaulicht ist mit etwa 10Hz nicht PWM gesteuert. Gelblicht an einer Ampel... Blinken und PWM haben genau nichts miteinander zu tun.
Ich glaube deswegen hat der TO im Text dann auch PWM in Anführungszeichen gesetzt ;)
Jörg Esser schrieb: > Ich glaube deswegen hat der TO im Text dann auch PWM in > Anführungszeichen gesetzt ;) Kann sein. Irgendetwas mit PWM steuern, hört sich irgendwie besser an, als: Irgendetwas periodisch für eine bestimmte Zeit ein- und ausschalten. Klingt irgendwie komplizierter, zeugt von Kenntnis der Materie. Auch wenn es nicht annähernd stimmt.
Joachim B. schrieb: > Einschaltzeit: 1-1024 µs (10-bit ADC-Wert von Poti 1 + 1) > Ausschaltzeit: 1-1024 ms (10-bit ADC-Wert von Poti 2 + 1) Also ergibt sich daraus eine Frequenz von 1 Hz bis 1 KHz mit einem Dutycycle von 0,0000001 % bis 50 %. ( falls ich mich jetzt bei den Nullen nicht verzählt hab) Also der Timer muss mit einer Schrittweite von 1µs auflösen. Sollte im AVR machbar sein. Aber der Timer muss bei dieser Auflösung bis auf eine Sekunde kommen. ==> Anzahl Schritt 1.000.000 ==> 2^20. Das heißt es wird ein Timer mit eine Bitbreite von mindesten 20 Bit benötigt. ==> vergiss den AVR , das kann der nicht. Bei den Rahmenbedingungen bleiben dir jetzt 3 Möglichkeiten. 1. eine Softwarelösung mit Interuptgetriebenen Umkonfigurierungen des Timers. Hier musst du sehr darauf achten das du mit den anderen Programmfunktionen nicht in die Quere kommst. ==> Verschiebungen der Timereinstellungen, Aussetzer auf der PWM, Verzögerte Displayausgaben,..... Diese Umschlatung des Timers muss ja auch bei einer Frequenz von 1 KHz noch funktionieren. sportlich 2. Such einen µC der entsprechend breite Timerregister hat. Ich kenne da jetzt nur eine µC Familie, es gibt bestimmt mehrere. (TI ARM µC mit HighEndTimer Device HET , bis zu 27 Bit Registerbreite im Timer) 3. Überdenke die Rahmenbedingungen ob diese extreme Bandbreite wirklich benötigt wird und reduziere diese auf ein praktikables Maß. 10 Bit ADC. Bei der üblichen Beschaltung der ADC's wirst du mit viel Glück 8 nutzbare Bits aus dem ADC erhalten. Die beiden Lowbits werden soviel springen das du diese glatt vergessen kannst. ==> nutzbar 8 Bit ==> 256 Bits Auflösung für beide Potis. Erhöht die Schrittweite auf 4 µs, dann brauchst du einen 18 Bit Timer. reicht im AVR immer noch nicht. Eine Beschaltung der ADC die eine Nutzung der 10 Bit erlaubt, ist mit praktikablen Aufwand im Hobbybereich nicht umsetzbar.
Pappnasen. Eine PWM kann man auch periodisch An- und Ausschalten, bzw. für viele Perioden auf PWM-Wert "0" setzen, und dann für eine Periode auf einen entsprechenden Wert für den us-Impuls.
Genervter schrieb: > Pappnasen. Köln? Karneval? Sportler haben festgestellt, daß Marmelade Fett enthält! Tätä, Tätä, Tätä...
Ralph schrieb: > Aber der Timer muss bei dieser Auflösung bis auf eine Sekunde kommen. > ==> Anzahl Schritt 1.000.000 ==> 2^20. > Das heißt es wird ein Timer mit eine Bitbreite von mindesten 20 Bit > benötigt. > > ==> vergiss den AVR , das kann der nicht. Weiter oben habe ich doch ein Programm gezeigt, was einen 32-Bit Timer zur Verfügung stellt: Auflösung 50ns @20MHz. Ralph schrieb: > 10 Bit ADC. > Bei der üblichen Beschaltung der ADC's wirst du mit viel Glück 8 > nutzbare Bits aus dem ADC erhalten. > Die beiden Lowbits werden soviel springen das du diese glatt vergessen > kannst. Das ist absoluter Blödsinn! Der ADC wandelt deutlich besser als die Potis eine lineare Kennlinie vorgeben könnten. Zudem empfiehlt es sich, dem µC einen Abblockkondensator zu spendieren. Probiere es doch mal aus! Genervter schrieb: > Pappnasen. Eine PWM kann man auch periodisch An- und Ausschalten, Dann geht PWM bestimmt auch rückwärts? Paul Baumann schrieb: > Tätä, Tätä, Tätä... Das ist der beste Kommentar dazu ;-)
Genervter schrieb: > Pappnasen. Eine PWM kann man auch periodisch An- und Ausschalten, bzw. > für viele Perioden auf PWM-Wert "0" setzen, und dann für eine Periode > auf einen entsprechenden Wert für den us-Impuls. Troll. Hier existiert keine PWM, die ein- und ausgeschaltet wird, hier soll irgendetwas in veränderlichen Zeitabständen für eine variable Zeit eingeschaltet werden. Oder kennst du eine PWM mit eins zu eine Million ? Es ist in etwa so, als ob ich eine Glühbirne alle 2 Wochen für eine Sekunde einschalte, nach 9 Tagen dann für 2 Sekunden einschalte und dann behaupte, meine Küchenbeleuchtung wird PWM gesteuert.
:
Bearbeitet durch User
Nun streitet euch doch mal bitte nicht. Ok, die Titel war vielleicht nicht ganz glücklich gewählt. Wobei man dennnoch auch in diesem Fall noch eingeschränkt von "PWM" sprechen kann... sei es drum... Also es geht wirklich nur um ein ganz kurzes Anschalten und dann eine längere Pause. Konkret um den Unterbrecher ("Interrupter") für eine DRSSTC. Den könnte man natürlich auch analog/dirkret aufbauen, aber ich möchte die aktuell eingestellten Zeiten gern auf einem LCD ablesen können, um den optimalen Arbeitspunkt leichter ermitteln zu können. Das geht einfach leichter, wenn man "was sieht" -> LCD. Und wenn ich eh schon nen µC einsetze, wollte ich auch gleich die Pulse vom Controller kommen lassen. Darum sind auch die Zeiten so sehr unterschiedlich, weil ich zum einen 1-1000 BPS erzeugen möchte und zum anderen die maximal zulässige An-Zeit stark variieren kann. Meist liegt die aber im Bereich von einigen zig bis wenigen 100 µs. Aber wie gesagt, streitet euch nicht um Begrifflichkeiten. Bringt doch nichts! Ich hab einige tolle Vorschläge erhalten -> vielen Dank für diese Anregungen! Peace ;)
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.