Forum: Mikrocontroller und Digitale Elektronik PWM-Fragen ATmega2560


von batty m. (battyman)


Lesenswert?

Nabends allerseits. Wie ja schon so mitbekommen spiele ich seit einiger 
Zeit mit meinem STK600 - ATmega2560 rum. Zuletzt hatte ich ja die 
AD-Wandlung am Wickel. Diese ist zum Glück nun zu 80% verstanden und das 
Programm läuft so wie gewollt. Ergo, SUPER.
Nach dem das nun erledigt ist habe ich mich der Hardware-PWM gewidmet. 
Vorerst mal steht das Programm durch die gut gemachten Artikel und 
Tutorials.
Die Pulsweiten kann ich auch wie gewünscht ändern und die ausgebene 
Spannung ist im Mittelwert um 0,1V auch der errechneten und gewünschten 
entsprechend.

Nun aber mal zu meinen offenen Fragen.
1.)
Ich gebe ja die Taktfrequenz des CPUs vor. In meinem Fall 16MHz
1
 F_CPU 16000000UL
Den Prescaler habe ich auf 1 gesetzt und somit ja keine Teilung
1
 TCCR1B = (1<<CS10);
Wenn ich einfach die Sys-frequ. angenommen halbiere, dann müsste doch 
die PWM-Frequenz auch halbiert werden? Und das ist bei mir nie der Fall. 
Egal ob ich 16Mhz, 8Mhz oder 2MHz austesete, am Oszi liegt immer 313 Hz 
an.
Im selben Zusammenhang stellte sich mir dadurch die Frage, warum dem so 
sei? Ich dachte mir folgendes:
- CPU bekommt Taktfrequenz vorgegeben (16MHz)
- setzte die Register entsprechend für Fast-PWM und invertiert, sowie 
eben den Vorteiler von 1
- danach setze ich den Zähl-Endwert
1
ICR1=0x0C80; //3200
- zum Schluss noch den Zählvergleichswert um den Rechteckpuls zu 
generieren
1
OCR1A=0x0A00; //2560
So, wenn ich nun mit 16Mhz zur 3200 zähle, dann brauch ich dafür 0,2ms, 
was 5kHz entsprechen würde. Aber laut Oszi stehen da nur 313Hz an. Erst 
wenn ich
1
ICR1=0x00C8; //200
 setzte und natürlch OCR1A auch entsprechend reduziere, komme ich in den 
kHz-Bereich. Wie kommt denn die Frequenz zu stande???

2.)
Nach der Ausgabe des PWM-Signals habe ich ein RC-Glied hinten dran. 
R=100Ohm, C=220nF, Vcc=5V. Ich versteh noch nicht ganz die Analogie mit 
der Mittelwertspannung. Also wie die zustande kommt schon. Jedoch ist 
laut Oszi eine Gleichspannung von z.B. 600mV drauf. Die nachgeschaltete 
LED leuchtet trotzdem noch, obwohl die mit n Laborschaltnetzteil erst ab 
ca. 1,5V schwach zu leuchten beginnt. Häää??

3.) Weiterhin dachte ich, dass ich mit dem RC-Glied eine sinusförmige 
Wechselspannung generiere. Bzw. in 1.Ord. einen Dreieckspuls und bei 
weiterem integrieren eine sinusförmige Wechselspannung. Dabei kommt eine 
relativ gleichmäße Gleichspannung raus, auch wenn immer gut 0,1V weniger 
wie errechnet. Wo ist mein derzeitig nicht zu sehender Denkfehler?

Ach so, ich habe die Toolchain-Optimize aus Os gesetzt.

Ich danke recht herzlich für weiterhin hilfreiche Aufklärungen und 
Erläuterungen warum ich ich wo gedanklich hänge.

THX

von Conny G. (conny_g)


Lesenswert?

batty man schrieb:
> Nabends allerseits. Wie ja schon so mitbekommen spiele ich seit einiger
> Zeit mit meinem STK600 - ATmega2560 rum. Zuletzt hatte ich ja die
> AD-Wandlung am Wickel. Diese ist zum Glück nun zu 80% verstanden und das
> Programm läuft so wie gewollt. Ergo, SUPER.
> Nach dem das nun erledigt ist habe ich mich der Hardware-PWM gewidmet.
> Vorerst mal steht das Programm durch die gut gemachten Artikel und
> Tutorials.
> Die Pulsweiten kann ich auch wie gewünscht ändern und die ausgebene
> Spannung ist im Mittelwert um 0,1V auch der errechneten und gewünschten
> entsprechend.
>
> Nun aber mal zu meinen offenen Fragen.
> 1.)
> Ich gebe ja die Taktfrequenz des CPUs vor. In meinem Fall 16MHz
>
1
 F_CPU 16000000UL

Damit setzt Du aber nicht die uC-Taktfrequenz, sondern nur ein 
Compiler-Define, dass alle Macros wissen, was die Rechenbasis ist.

Den Takt des uC setzt Du über die Fuses (interner oder externe 
Taktquelle, bei der internen gibt's noch Stufen, bei Extern musst 
verschiedene Oszillatoren anschliessen).

> Den Prescaler habe ich auf 1 gesetzt und somit ja keine Teilung
>
1
 TCCR1B = (1<<CS10);
> Wenn ich einfach die Sys-frequ. angenommen halbiere, dann müsste doch
> die PWM-Frequenz auch halbiert werden? Und das ist bei mir nie der Fall.
> Egal ob ich 16Mhz, 8Mhz oder 2MHz austesete, am Oszi liegt immer 313 Hz
> an.
> Im selben Zusammenhang stellte sich mir dadurch die Frage, warum dem so
> sei? Ich dachte mir folgendes:
> - CPU bekommt Taktfrequenz vorgegeben (16MHz)

Falls Du das so machst wie Du oben geschrieben hast, mit dem F_CPU, dann 
ändert sich tatsächlich nichts, der AVR macht weiter seinen 
Standardtakt. Weiss nicht, welcher der Beim Atmega2560 ist, 1 Mhz oder 8 
Mhz?

Ah ja, sehe gerade, der hat Standard auch 8 Mhz mit internem Oszillator 
und das CKDIV8 gesetzt, also läuft er mit 1 Mhz.

> - setzte die Register entsprechend für Fast-PWM und invertiert, sowie
> eben den Vorteiler von 1
> - danach setze ich den Zähl-Endwert
1
ICR1=0x0C80; //3200
> - zum Schluss noch den Zählvergleichswert um den Rechteckpuls zu
> generieren
1
OCR1A=0x0A00; //2560
> So, wenn ich nun mit 16Mhz zur 3200 zähle, dann brauch ich dafür 0,2ms,
> was 5kHz entsprechen würde. Aber laut Oszi stehen da nur 313Hz an. Erst
> wenn ich
1
ICR1=0x00C8; //200
 setzte und natürlch OCR1A auch
> entsprechend reduziere, komme ich in den kHz-Bereich. Wie kommt denn die
> Frequenz zu stande???

1 Mhz / 3200 = 312 Hz

>
> 2.)
> Nach der Ausgabe des PWM-Signals habe ich ein RC-Glied hinten dran.
> R=100Ohm, C=220nF, Vcc=5V. Ich versteh noch nicht ganz die Analogie mit
> der Mittelwertspannung. Also wie die zustande kommt schon. Jedoch ist
> laut Oszi eine Gleichspannung von z.B. 600mV drauf. Die nachgeschaltete
> LED leuchtet trotzdem noch, obwohl die mit n Laborschaltnetzteil erst ab
> ca. 1,5V schwach zu leuchten beginnt. Häää??

Mmh, auf welches Zeitfenster hast Du das Oszi denn eingestellt, würdest 
Du das Rechteckssignal sehen, wenn Du vor dem RC-Glied misst?
Wenn nach dem RC-Glied noch eine gemäß dem PWM-Signal schwankende 
Spannung anliegt, dann leuchtet die LED, weil sie Schubweise immer genug 
Spannung bekommt.

Also wenn Du mal die Grenzfrequenz von R=100 Ohm und C = 220nf 
berechnest, dann kommt man auf 7.2kHz - d.h. bei einem PWM-Signal von 
300 Herz siehst Du noch nicht einmal richtig, dass das RC etwas tut - es 
lässt das Signal voll durch, es werden höchstens die Flanken etwas 
geschwächt.
http://www.sengpielaudio.com/Rechner-RCglied.htm

> 3.) Weiterhin dachte ich, dass ich mit dem RC-Glied eine sinusförmige
> Wechselspannung generiere. Bzw. in 1.Ord. einen Dreieckspuls und bei
> weiterem integrieren eine sinusförmige Wechselspannung. Dabei kommt eine
> relativ gleichmäße Gleichspannung raus, auch wenn immer gut 0,1V weniger
> wie errechnet. Wo ist mein derzeitig nicht zu sehender Denkfehler?
> Ach so, ich habe die Toolchain-Optimize aus Os gesetzt.
>
> Ich danke recht herzlich für weiterhin hilfreiche Aufklärungen und
> Erläuterungen warum ich ich wo gedanklich hänge.
>
> THX

von batty m. (battyman)


Lesenswert?

Conny G. schrieb:
> batty man schrieb:
> ...
> Den Takt des uC setzt Du über die Fuses (interner oder externe
> Taktquelle, bei der internen gibt's noch Stufen, bei Extern musst
> verschiedene Oszillatoren anschliessen).
> ...
> Ah ja, sehe gerade, der hat Standard auch 8 Mhz mit internem Oszillator
> und das CKDIV8 gesetzt, also läuft er mit 1 Mhz.
Aha, denn ists ja wirklich logisch, dass diese Änderungen von mir zu 
nichts führten. Danke. Zu dem ist somit wieder ein Sachverhalt bzw. 
Missverständnis meinerseits klarergeworden.

> Mmh, auf welches Zeitfenster hast Du das Oszi denn eingestellt, würdest
> Du das Rechteckssignal sehen, wenn Du vor dem RC-Glied misst?
> Wenn nach dem RC-Glied noch eine gemäß dem PWM-Signal schwankende
> Spannung anliegt, dann leuchtet die LED, weil sie Schubweise immer genug
> Spannung bekommt.
Ja, vor dem RC-Glied ist ein schönes Rechtecksignal zu messen. Wie 
gesagt ist das Signal im Mittelwert immer 0,1V unter dem der 
berrechneten, also ganz i.O..

> Also wenn Du mal die Grenzfrequenz von R=100 Ohm und C = 220nf
> berechnest, dann kommt man auf 7.2kHz - d.h. bei einem PWM-Signal von
> 300 Herz siehst Du noch nicht einmal richtig, dass das RC etwas tut - es
> lässt das Signal voll durch, es werden höchstens die Flanken etwas
> geschwächt.
> http://www.sengpielaudio.com/Rechner-RCglied.htm
Mit R=100 Ohm habe ich als Spannungsmax-Mittelwert ca 2,52V. Wenn ich 
mein R auf 160 kOhm z.B. erhöhe dann ist U-mittelwert-max nur noch 1,5 
V. Ausserdem reduziert sich meine Grenzfrequenz auf f=10Hz. Dann 
leuchtet keine LED mehr. Problem dabei war ja das die PWM-Frequenz nicht 
die der gewünschten ist. Denn anstatt der 312Hz wollte ich eigentlich 
5kHz generieren.

von Karl H. (kbuchegg)


Lesenswert?

Noch ein kleiner Tip.

Wenn du 3200 meinst, dann schreib auch 3200

Es ist perfekt, Zahlen in der Schreibweise zu schreiben, in der sie den 
meisten Sinn machen. Sei das Binär, sei das Hexadezimal, sei das 
Dezimal.
In deinem Fall macht Dezimal den meisten Sinn, denn das ist das System, 
in dem du normalerweise rechnest. So hast du dir ja auch den Wert 
ausgerechnet. Also ist
1
  ICR1 = 3200;
perfekt.

Selbiges natürlich auch für alle anderen Register. Man benutzt immer die 
Schreibweise, die in der gegebenen Situation den meisten Sinn macht. Ob 
der Compiler aus einer Hex-Zahl sich das Bitmuster generiert, welches in 
das Register zu laden ist, oder ob er das von einer Dezimalzahl 
ausgehend macht, ist dem Compiler egal. Aber dir als Mensch ist es nicht 
egal. Mit 3200 verbindest du viel mehr als mit 0x0C80.

Es spricht auch nichts dagegen, sich den zu ladenden Wert ausrechnen zu 
lassen.
1
#define F_CPU     1000000UL
2
#define FREQU     313
3
#define PRESCALER 1
4
5
6
...
7
    ICR1 = ((F_CPU / PRESCALER ) / FREQU ) - 1
8
...

und schon kannst du mittels
1
#define FREQU     313
die Frequenz relativ komfortabel einstellen. Auf die Grenzen müsste man 
noch achten, so dass ICR1 bei größer werdenden Frequenzen nicht 0 wird. 
Aber auch das könnte man mit noch ein paar Makros erledigen.

Fazit: Lass den Compiler für dich die Routine-Aufgaben übernehmen!
Genau dafür hast du ihn.

: Bearbeitet durch User
von batty m. (battyman)


Lesenswert?

So erst einmal Danke für den Tipp:
>Ah ja, sehe gerade, der hat Standard auch 8 Mhz mit internem Oszillator
>und das CKDIV8 gesetzt, also läuft er mit 1 Mhz.
ich habe jetzt in den Fuse das Bit CKDIV8 rausgenommen, wodurch sich die 
CPU-Frequenz auf 8MHz erhöht hat.
Promt stieg bei dem Zählendwert
1
 ICR1 = 3200;
 die PWM-Frequenz auf 2,5kHz. Voller Freude denn dann hab ich das mit 
der Frequenz nicht falsch berechnet sondern nur die falsche Angabe 
benutzt. Jetzt hab ich
1
ICR1 = 1600;
 und bekomme somit meine gewünschten 5kHz. Echt n dickes Danke. Freut 
mich voll.

Wenn mein Programm die Dezimalzahl auch frisst dann nutze ich natürlich 
diese. Thx for dis Tipp :D  liest sich auch wesentlich schneller und vor 
allem verständlicher.

Das mit der Rechnung:
1
#define F_CPU     1000000UL
2
#define FREQU     313
3
#define PRESCALER 1
4
5
6
...
7
    ICR1 = ((F_CPU / PRESCALER ) / FREQU ) - 1
8
...
ist ja auch ne geile übersichtliche Vereinfachung. Volle Logik, GEIL!!!



Jetzt muss ich nur noch was mit dem RC-Glied was vernünftiges anfangen. 
Fragt sich nur was bei 5kHz eine sinnvolle Grenzfrequenz so ist?!?



Mal so noch ne andere Frage:
Ist es an sich egal ob ich normale PWM oder invertierte erzeuge? Also 
das die Pulse immer zum Zählstartwert high oder eben bei Zählendwert low 
werden ist mir schon klar. Dadurch verschiebt sich ja mein Puls auch auf 
der Zeitskala. Welche Variante davon ist sinnvoller bzw. was wären denn 
die Vor-Nachteile der verfahren?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

batty man schrieb:

> der Zeitskala. Welche Variante davon ist sinnvoller bzw. was wären denn
> die Vor-Nachteile der verfahren?


Du kannst keine Hardware-PWM erzeugen, bei der du den Duty-Cycle 
komplett auf 0 stellst. Selbst bei
1
  OCR1A = 0;
hast du immer noch kurze Puls am Ausgang. Wohl aber kannst du OCR1A auf 
ICR1A bzw. größer setzen und erreichst damit eine PWM die tatsächlich 
100% der Zeit auf an ist.

D.h. du musst dich prinzipiell zwischen 2 Möglichkeiten entscheiden:
entweder du brauchst einen der beiden Endwerte 0% bzw. 100% nicht, dann 
kannst du mittels Pin-Invertierung den jeweils nicht gebrauchten Endwert 
der 0 im OCR1A Register 'zuordnen'
oder aber du musst den aufwändigeren Weg gehen und für eine PWM von 0 
den Timer vom Pin abkoppeln und händisch auf Dauer-0 (oder Dauer-1) 
stellen.

Abgesehen davon fällt mir dann nur noch ein, dass es ja nicht 
Gott-gegeben ist, das ein höherer OCR1A Wert auch automatisch ein 
höheres-was_auch_immer_am_Ausgang_hängt zur Folge haben muss. Du kannst 
ja genausogut auch ein 'Je höher der ADC-Wert desto dunkler die LED' 
haben wollen. Klar kann man das auch im Programm per Arithmetik 
erreichen, man kann aber auch einfach die PWM invertieren.

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.