Forum: Mikrocontroller und Digitale Elektronik PWM Verständnisfrage


von Elias B. (bouni)


Angehängte Dateien:

Lesenswert?

Hi,

Ich weiss das das schon oft gefragt wurde, aber eine Klare Antwort hab 
ich auch nach Tagelangem suchen noch nicht gefunden.

Im Anhang ist eine Grafik die sich an  die des Tutorials anlehnt.

Ist das was ich in dieser Grafik gezeichnet habe soweit korrekt ??

Ich möchte mittels der PWM eines 8515 einen Servo (Conrad 4,95) 
ansteuern.
Ist es richtig das die Periodendauer 20ms betragen sollte, aber eher 
unkritisch ist, und der Puls zwischen 1 und 2ms ??

Ist meine Berechnung der Obergrenze und des Vergleichswertes so richtig 
??

Dank für eure Antworten!

Bouni

von PicPic (Gast)


Lesenswert?

@Elias B. (bouni)

Nach meinen Informationen hast du deine Fragen schon selbst richtig 
beantwortet.

von Elias B. (bouni)


Lesenswert?

Hi,

Hab mir das Tutorial nochmal durchgelesen und bin stutzig geworden.
Was hat es mit den 8, 9 oder 10Bit auf sich?

Im Tutorial steht das dadurch die Obergrenze gesetzt wird (10-Bit = 
1023),
Im Beispielprogramm jedoch steht
1
//  den Endwert (TOP) für den Zähler setzen
2
//  der Zähler zählt bis zu diesem Wert
3
 
4
ICR1 = 0x6FFF; -> 28671 dez

Wieso ist die Obergrenze grösser als 10-Bit ??
1
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);

Denn hier wird ja WGM11 & WGM10  auf 1 gesetzt = 10Bit PWM.

Ich steh auf m Schlauch :)

Danke für eure Hilfe

Bouni

von Der M. (steinadler)


Lesenswert?

Das is sicher n Druckfehler.
Wenn du das binär mal anschaust, muss statt der 6 eine 3 stehen.
Also 0x3FFF

von Johannes M. (johnny-m)


Lesenswert?

Elias B. wrote:
> Hab mir das Tutorial nochmal durchgelesen und bin stutzig geworden.
> Was hat es mit den 8, 9 oder 10Bit auf sich?
Das legt eine feste Obergrenze (TOP) und damit abhängig vom 
eingestellten Prescaler-Wert eine feste PWM-Frequenz fest.

> Im Tutorial steht das dadurch die Obergrenze gesetzt wird (10-Bit =
> 1023),
> Im Beispielprogramm jedoch steht
> [...]
> Wieso ist die Obergrenze grösser als 10-Bit ??
>
>
1
> TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
2
>
>
> Denn hier wird ja WGM11 & WGM10  auf 1 gesetzt = 10Bit PWM.
Und was ist mit WGM12 und WGM13 im TCCR1B? Wenn WGM13 auch gesetzt ist 
(was ich aus dem Zusammenhang heraus mal vermute), dann ist das nämlich 
keine 10-Bit-PWM, sondern Phase Correct PWM mit ICR1 als TOP...

Bei 8-, 9- und 10-Bit-PWM wird der TOP-Wert nicht explizit angegeben, 
sondern ist fest vorgegeben (eben je nachdem 0xFF, 0x1FF oder 0x3FF). 
Wenn im ICR1 ein TOP-Wert angegeben wird, dann handelt es sich um einen 
anderen PWM-Modus, bei dem TOP frei gewählt werden kann.

von Johannes M. (johnny-m)


Lesenswert?

Micha R. wrote:
> Das is sicher n Druckfehler.
Und nein, das ist höchstwahrscheinlich kein "Druckfehler"

> Wenn du das binär mal anschaust, muss statt der 6 eine 3 stehen.
> Also 0x3FFF
Siehe oben. 0x3FFF wären übrigens 14 Bit, und die gibt's nicht als feste 
Obergrenze...

Es gibt übrigens im Datenblatt eine schöne, übersichtliche und mit 
Liebe gemachte Tabelle (steht bei der Beschreibung der Steuerregister 
des Timers), in der alle Timer-Betriebsarten mit den dazugehörenden 
Konfigurationen der 4 Steuerbits WGM13..10 dargestellt sind. Und jetzt 
frag bitte keiner, wo man denn das Datenblatt herbekommt...

von Elias B. (bouni)


Angehängte Dateien:

Lesenswert?

Der Vollständigkeit halber:

Hier die Tabelle:


Bouni

von Der M. (steinadler)


Lesenswert?

Johannes M. wrote:
> Micha R. wrote:
>> Das is sicher n Druckfehler.
> Und nein, das ist höchstwahrscheinlich kein "Druckfehler"
>
>> Wenn du das binär mal anschaust, muss statt der 6 eine 3 stehen.
>> Also 0x3FFF
> Siehe oben. 0x3FFF wären übrigens 14 Bit, und die gibt's nicht als feste
> Obergrenze...

Ich entschuldige mich vieltausendmal für diese Fehlinformation von mir.
Soll nicht wieder vorkommen.

von Johannes M. (johnny-m)


Lesenswert?

Elias B. wrote:
> Der Vollständigkeit halber:
>
> Hier die Tabelle:
Das hättest Du Dir sparen können, steht alles im Datenblatt (und v.a. in 
besserer Qualität!).

Allerdings hatte ich mich oben verguckt. Du hattest geschrieben, dass 
WGM11 und WGM10 gesetzt sind. Dann macht das mit ICR1 keinen Sinn. 
ICR1 wird nur in den Modi 8, 10, 12 und 14 benötigt. Der "Fehler" liegt 
also woanders.

EDIT:
Im Tutorial (habe grad nachgesehen) steht
erstens eindeutig, dass es sich auf PWM-Modus 14 bezieht (wie von mir 
bereits weiter oben wegen der Benutzung von ICR1 vermutet) und
zweitens nichts davon, dass WGM10 gesetzt werden soll! Klar, dass das 
mit den Angaben widersprüchlich ist. Das "1 << WGM10" gehört da schlicht 
und ergreifend nicht hin. Wenn Du Änderungen am Code des Tutorials 
machst, darfst Du Dich nicht wundern, wenn er nicht das macht, was da 
steht.

von Johannes M. (johnny-m)


Lesenswert?

So, nach weiterer Recherche neue Erkenntnisse:
In 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#PWM_.28Pulsweitenmodulation.29 
steht eine Beispielzeile im Text, in der beide WGM-Bits in TCCR1A 
gesetzt werden. Diese Zeile gehört aber nicht zum 
Initialisierungsbeispiel für Modus 14 darunter, aus dem die Zeile "ICR1A 
= 0x6FFF;" stammt! Deshalb gehören die beiden Zeilen, auf die sich die 
Frage bezog, gar nicht zusammen. Das Beispiel zur Initialisierung für 
Modus 14 ist soweit völlig korrekt und vollständig. Die andere Zeile ist 
nur als Beispiel für die Verwendung der (mittlerweile gar nicht mehr so) 
neuen Bezeichnungen der Bits gedacht.

von Elias B. (bouni)


Lesenswert?

Hallo zusammen,

Ich bin grade wieder am servo probieren.

Ich bin jetzt so weit das er an den Anschlag im Uhrzeigersinn läuft :(


Ich arbeite mit folgendem Code auf dem Atmega8515L:
1
#include <avr/io.h>
2
 
3
int main()
4
{
5
6
  DDRB = (1 << PD5 ); 
7
8
// beim Atmega 8515L der OC1A
9
 
10
  TCCR1A = (1<<COM1A1) | (1<<WGM11);
11
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS01);
12
13
// CS02 CS01 CS00 Description
14
//   0    1    0  clkI/O/8 (From prescaler)
15
//
16
// Mode WGM13 WGM12 WGM11 WGM10    Typ    TOP UPDATE
17
//  14    1     1     1     0   Fast PWM ICR1 BOTTOM 
18
//
19
// COM1A1 = 1 :Clear OC1A/OC1B on Compare Match (Set output to low level).
20
21
  ICR1 = 0x1200; // = 4608 dezimal
22
23
  OCR1A = 0x0159; // = 345 dezimal
24
 
25
 
26
  while( 1 )
27
    ;  
28
}

Mein CPU Takt ist 3686400 Hz
Mein Prescaler ist 8
Prescaled Takt = 460800Hz
Periodendauer = 1/460800Hz = 2,17e-6 sek
für 20ms brauche ich demnach 0,02s/2,17e-6s = 9216 Perioden,
 Da aber nur die hälfte der 20ms hochzuzählen ist ist die Obergrenze bei 
4608 zu setzen.
4608 dez = 0x1200

Da der Servo zwischen 1 und 2ms Takte braucht um die Position anzufahren 
muss ich den Zählerwert zwischen
4608/20ms = dez 230
und
4608/(20ms*2) = dez 460
wählen

die Mittelstellung sollte demnach bei dez 345 liegen (0x159)

Das tue ich doch, aber wo liegt mein Fehler ??

Ich bin ratlos!

Danke im Voraus


Bouni

von Elias B. (bouni)


Lesenswert?

Jetzt tuts komischer weise ?!

Bouni

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.