Forum: Mikrocontroller und Digitale Elektronik Aus Hardware-PWM ein Invertiertes per Software erzeugen


von Gelöscht (kami89)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Ich habe folgendes Problem:
Mit dem ATMega168 soll eine PWM per Hardware erzeugt werden. Das 
funktioniert wunderbar mit folgendem Code:
1
TCCR1A = (1<<COM1A1) | (1<<WGM11); // Mode 11 (Phase Correct PWM)
2
TCCR1B = (1<<WGM13) | (1<<CS10); // Prescaler 0
3
4
ICR1 = PWM_F / khz;    // Periodendauer
5
OCR1A = (ICR1 / 100) * percent;  // On-Time von der PWM

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)
2
3
ISR(TIMER1_COMPA_vect){
4
5
  LED1_TOGGLE // Variante 1
6
  if (PINB && (1<<PB1)) LED1_EIN else LED1_AUS  // Variante 2
7
8
}

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von Gelöscht (kami89)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Gelöscht (kami89)


Lesenswert?

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

von MWS (Gast)


Lesenswert?

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.

von Gelöscht (kami89)


Lesenswert?

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.

von MWS (Gast)


Angehängte Dateien:

Lesenswert?

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 
?

von Falk B. (falk)


Lesenswert?

@  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

von Peter D. (peda)


Lesenswert?

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

von Gelöscht (kami89)


Lesenswert?

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

von MWS (Gast)


Lesenswert?

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.

von Gelöscht (kami89)


Lesenswert?

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

von MWS (Gast)


Lesenswert?

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.

von Gelöscht (kami89)


Lesenswert?

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 :-)

von Gelöscht (kami89)


Angehängte Dateien:

Lesenswert?

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

von MWS (Gast)


Lesenswert?

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.

von Gelöscht (kami89)


Lesenswert?

OK, es ist zwar genau das selbe wie im ersten Beitrag zu sehen, aber 
bitteschön:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
5
#define FCPU 16000000
6
7
int main(void){
8
9
  DDRD |= (1<<PD2); // LED
10
  DDRB |= (1<<PB1); // PWM
11
12
  TCCR1A = (1<<COM1A1) | (1<<WGM11); // Mode 11 (Phase Correct PWM)
13
  TCCR1B = (1<<WGM13) | (1<<CS10); // Prescaler 0
14
  TIMSK1 |= (1<<OCIE1A); // Compare A Interrupt Timer 1 (PWM)
15
16
  ICR1 = 256;
17
  OCR1A = 128;
18
19
  sei();
20
21
  while(1){
22
23
  }
24
}
25
26
ISR(TIMER1_COMPA_vect){
27
28
  if (PINB && (1<<PB1)) PORTD |= (1<<PD2); else PORTD &= ~(1<<PD2) ;
29
30
}

verwendet wird der ATMega168 mit 16MHz

von Gelöscht (kami89)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.