Hallo zusammen,
Ich habe folgendes Problem:
Mit dem ATMega168 soll eine PWM per Hardware erzeugt werden. Das
funktioniert wunderbar mit folgendem Code:
Soweit sogut. Das PWM-Signal wird nun am OC1A-Pin ausgegeben. Nun soll
aber ein invertiertes Signal davon wahlweise auf einen von drei anderen
Pins ausgegeben werden. Ich habe dann mal probiert den COMPARE_A
Interrupt von diesem Timer zu benutzen, um das invertierte PWM zu
erzeugen:
1
TIMSK1|=(1<<OCIE1A);// Compare A Interrupt Timer 1 (PWM)
Das LED-Zeugs sind defines, die sollten ja selbsterklärend sein.
Mit Variante 1 kriege ich an der LED ein einwandfreies invertiertes
Signal, wie ich es mir wünsche. Nur mit Toggeln ist natürlich nicht, da
man natürlich nicht mit Sicherheit sagen kann ob das Signal auch
wirklich invertiert herauskommt.
Also Probierte ich Variante 2. Da Frage ich einfach den Status vom
OC1A-Pin ab und steuere entsprechend entgegengesetzt den anderen Ausgang
an. Doch auf dem Oszilloskop sieht das nicht gerade optimal aus (siehe
Anhang). Oben das nicht invertierte PWM vom OC1A, unten das Invertierte.
Es ist zwar ein korrektes Muster zu erkennen, doch ich vermute mal meine
Funktion funktioniert nur bei jedem zweiten Durchlauf korrekt.
Hat jemand eine Idee, wie ich das problem lösen könnte? Irgendwie müsste
ich herausfinden, ob der Timer gerade am hoch- oder am runterzählen ist,
aber ich vermute mal das ist nicht möglich?!
Vielen Dank schonmal.
mfg
ALs erstes solltest du dich fragen, ob es unbedingt eine
phase-correct-PWM sein muss. phase-correct-PWM braucht man nur, wenn das
PWM Signal in einer festen zeitlichen Beziehung zu einem anderen Signal
sein muss, so dass sich die PWM symetrisch zu diesem anderen Signal
verbreiter/verschmälert.
Mit einer Fast-PWM wäre das alles kein Problem:
2 ISR, eine für den Compare und 1 für den 0-Durchgang (Overflow oder
2.ten COmpare)
Hallo,
Ja ich fürchte es muss wirklich Phase Correct sein. Das PWM-Signal wird
nämlich für die Ansteuerung eines Brushless-Motors verwendet, und da
soll es angeblich ja von Vorteil sein dass man Phase Correct PWM
benutzt, da man dann nämlich z.B. Strommessungen oder ev. auch die
Auswertung des BEMF Signales, im Overflow-Ereignis vom PWM-Timer
ausführen kann. Dies soll dann einen korrekten Mittelwert darstellen.
Man könnte natürlich das ganze PWM-zeugs auch von Hand mit dem Timer
machen, doch meine Variante wäre wohl viel einfacher zu realisieren und
ist eher zuverlässiger. Da ich halt noch nicht sooo viel Erfahrung habe
mit Timern, wollte ich euch mal fragen ob ihr eine Idee habt, wie man
das oben genannte Problem lösen könnte.
mfg
Urban B. schrieb:> Hallo,>> Ja ich fürchte es muss wirklich Phase Correct sein.
Hmmm.
Da fällt mir softwareseitig auch nichts dazu ein.
Würde ich in Hardware mit einem Transistor als Inverter machen. Das
kommt dann auch vom Timing her genauer hin.
Okay...das habe ich fast befürchtet.
Hätte ja sein können dass es da irgend ein nützliches Flag gibt oder so
;-)
Also dann mal vielen Dank für deine Antworten!
Falls jemand noch eine Idee hat, immer her damit ;D
mfg
Urban B. schrieb:> Oben das nicht invertierte PWM vom OC1A, unten das Invertierte.> Es ist zwar ein korrektes Muster zu erkennen, doch ich vermute mal meine> Funktion funktioniert nur bei jedem zweiten Durchlauf korrekt.
Das liegt daran, daß beide Male Led1 angesprochen wird, und Variante 1
dann gleich Variante 2 stört. Nimm' das Toggle raus und das Signal wird
ok sein.
MWS schrieb:> Das liegt daran, daß beide Male Led1 angesprochen wird, und Variante 1> dann gleich Variante 2 stört. Nimm' das Toggle raus und das Signal wird> ok sein.
Die beiden Varianten habe ich hier einfach in die selbe ISR geschrieben,
natürlich habe ich sie nacheinander ausprobiert, also jeweils eine
Zeile ausgeklammert.
Das Signal sieht dann trotzdem so aus wie im Bild zu sehen.
Urban B. schrieb:> Das Signal sieht dann trotzdem so aus wie im Bild zu sehen.
Nur auf 'nem ATM32 überprüft :D
Dir ist schon klar, daß aufgrund der Interruptlaufzeit besonders kleine,
als auch große Werte nahe ICR1 zu einem falschen Auslösen der ISR führt
?
@ Urban B. (kami89)
>Soweit sogut. Das PWM-Signal wird nun am OC1A-Pin ausgegeben. Nun soll>aber ein invertiertes Signal davon wahlweise auf einen von drei anderen>Pins ausgegeben werden.
Keine gute Idee. Nutze OC1B, das kann man per Hardware direkt und 100%
korrekt erzeugen. Wenn es aussen WIRKLICH an drei verschiedenen Pins
benötigt wird, nutze einen externen Demultiplexer.
Bei Software spucken die Verzögerungen ein.
Mfg
Falk
Ich würde nicht den ATmega168 nehmen, sondern den ATtiny261.
Der hat 3 PWM-Ausgänge mit Invertierung, Totzeiteinstellung und
Fehlerabschaltung.
Warum Atmel jedem AVR immmer unterschiedliche Timerfunktionen einbauen
muß, ist mir rätselhaft. Jeder AVR sollte einen maximal ausgerüsteten
Timer haben, d.h. mit allen Funktionen. Soviel Siliziumfläche kann das
doch nicht sein.
Peter
MWS schrieb:> Nur auf 'nem ATM32 überprüft :D
hmm das ist ja komisch... warum funktioniert das bei mir nicht? Ich
hoffe jetzt mal mein Oszi zeigt das wenigstens richtig an, es ist schon
alt und hat auch schon leicht falsche Signale dargestellt. Ende des
Monats sollte dann aber ein nagelneues DSO kommen, spätestens dann kann
ich das Signal ganz bestimmt korrekt anzeigen :-)
> Dir ist schon klar, daß aufgrund der Interruptlaufzeit besonders kleine,> als auch große Werte nahe ICR1 zu einem falschen Auslösen der ISR führt> ?
Das leuchtet mir jetzt nicht so ganz ein, kannst du das mal genauer
erläutern?
NACHTRAG: wenn du den Prozentualen Fehler meinst, dann verstehe ich es
:-)
Aber das sollten ja höchstens ein paar wenige Takte sein.
Falk Brunner schrieb:> Keine gute Idee. Nutze OC1B, das kann man per Hardware direkt und 100%> korrekt erzeugen. Wenn es aussen WIRKLICH an drei verschiedenen Pins> benötigt wird, nutze einen externen Demultiplexer.
HW-PWM will ich nun wirklich vermeiden, um den Schaltungsaufwand in
Grenzen zu halten.
Nun habe ich aber gerade bemerkt, dass ich das Software-PWM gar nicht
mehr brauche, wenn ich statt dem IR2101 Treiber den IR2104 nehme. Ich
dachte eigentlich dass der IR2101 auch Cross-Conduction verhindert, doch
bei einem kleinen Test vorher habe ich die Mosfets fast verbraten...also
nochmal ins Datenblatt geschaut, und gestaunt dass die Teile eigentlich
gar nicht das machen was ich will^^ Nach etwas recherche bin ich dann
auf die IR2104 gekommen, die schalten die beiden Ausgänge dann nur noch
in Abhängigkeit von EINEM Eingang. Wenn ich da mein PWM draufgebe,
werden die oberen und unteren Mosfets abwechselnd eingeschaltet, genau
so wie ich es mir wünsche. (Es sei denn, ich habe wieder etwas im
Datenblatt übersehen...)
Also vielen Dank für die Hilfe, doch ich werde nun wohl die IR2104
bestellen, dann sollte sich das Problem erübrigt haben.
Gruss Urban
Mal die Oszi-Kanäle tauschen und nochmal probieren.
Bei Phase-Correct-PWM können Interruptauslösungen sehr nah beieinander
liegen, bei OCR1A = 5 löst der Int jeweils bei 5 beim Runterzählen und
Raufzählen aus. Mit Prescaler 1 liegen da 12 Takte dazwischen
(Zählerstand 0 eingerechnet). Meine ISR benötigt für die komplette
Ausführung 12 Takte. Wird der OCR1A-Wert noch kleiner, dann erfolgt die
Auslösung schneller als de Abarbetung. An der oberen Grenze bei ICR1
entsteht das gleiche Problem.
Kanäle tauschen habe ich probiert, bringt leider auch nichts.
OK das mit der Ungenauigkeit habe ich soweit verstanden. Damit aber
solche kleinen Softwareungenauigkeiten meine Mosfets nicht verbraten
können, wollte ich eben einen Treiber mit Kurzschlussschutz haben. Nur
habe ich mich da mit den IR2101 ein bisschen vertan...Jetzt bestelle ich
erstmal ein paar von den IR2104, dann mache ich weiter mit dem
Programmieren. Diese Treiber sollten dann auch die Software viel weniger
aufwändig machen, und vorallem droht die Gefahr von Kurzschlüssen nicht
mehr ;-)
mfg
Urban B. schrieb:> Kanäle tauschen habe ich probiert, bringt leider auch nichts.
Fehlerhaftes Oszibild dann auf dem oberen Kanal, eigenartig...
Werte für meinen Test waren 256 & 128.
> Jetzt bestelle ich erstmal ein paar von den IR2104,...
Hab' ich schon bemerkt, dachte Du wolltest noch eine Erklärung.
Ich werde mir das dann mit dem neuen DSO vermutlich nochmal anschauen,
aber das dauert noch bis das kommt.
MWS schrieb:> Hab' ich schon bemerkt, dachte Du wolltest noch eine Erklärung.
Jop, auch wenn ich neue Treiber bestelle bin ich froh über jede
Erläuterung. Bin nämlich relativ neu in der AVR-Welt und vorallem bei
den Timern gibts da noch viel Lernpotenzial :-)
Urban B. schrieb:> Ich werde mir das dann mit dem neuen DSO vermutlich nochmal anschauen,> aber das dauert noch bis das kommt.
So, jetzt ist es soweit :-)
Ich habe den Test nochmal wiederholt und mit dem neuen DSO angeschaut.
Und da erkennt man nun etwas ganz komisches...
Die Invertierung funktioniert 9ms lange, dann ist 11ms lang still am
invertierten Ausgang. Und das wiederholt sich dann unendlich lange ;)
Im Anhang die Oszibiler einmal weit weggezoomt, und einmal direkt an
einen Übergang von "funktioniert" zu "funktioniert nicht mehr" gezoomt.
Habs übrigens auch mal mit den Werten 256 und 128 probiert, funktioniert
auch nicht.
Naja, interessante Sache (meiner Meinung nach total misteriös),
letztendlich ist es dann aber auch egal. Habe jetzt die IR2104
eingelötet und nun funktionierts ohne Invertierte-Soft-PWM.
Immerhin hat mein altes Oszi kein Quatsch angezeigt, da bin ich froh ;-)
mfg
Urban B. schrieb:> Naja, interessante Sache (meiner Meinung nach total misteriös),> letztendlich ist es dann aber auch egal.
Nur ohne Originalcode mysteriös :D
Bei mir hat's ja auch funktioniert, liegt also an dem von Dir
verwendeten Code. Wenn's nicht ganz egal ist, dann häng' den mal an.
Oh mann, ich habe den Fehler gerade selbst gefunden ;-)
1
if(PINB&&(1<<PB1))
sollte besser
1
if(PINB&(1<<PB1))
heissen...Das ist wohl die Strafe dafür, dass ich die C-Grundlagen nie
angeschaut habe ;-)
Übrigens, falls es jemand interessiert, die Verzögerung von invertierten
Signal zur Original-PWM beträgt 1,3 Mikrosekunden.
Vielen Dank für die vielen konstruktiven Antworten!
mfg