Forum: Mikrocontroller und Digitale Elektronik Timer PWM 50Hz Pd 20ms OCR0A float Probleme


von Digit-22 N. (digit-22)


Lesenswert?

Hej,

ich hätte da mal eine kleine Frage. ICh nutze den TimerA um ein 50Hz PWM 
Signal zu erzeugen. Die Periodendauer beträgt demnach 20ms. Für meine 
Zwecke sind die Pulsweiten von 1ms bis 2ms interessant. Das signal wird 
dazu genutzt um ein RC Servo anzusteuern. In dem ich den Wert von OCR0A 
ändere, ändert sich der Winkel des Servos. Für 1ms Pulsweite muss der 
Wert von OCR0A 15 und für 2ms 30 sein. Jetzt habe ich nur ein Problem:
Ich möchte manschmal eine den Wert z.B. um 0.5 ändern. Doch immer wenn 
ich eine Kommazahl eingebe, funktioniert das ganze nicht. (Natürlich mit 
. getrennt nicht mit ,).

Kann mir einer sagen welche Datentypen der OCR0A verwalten kann? Mir 
kommt es so vor als wenn der nur ganze Zahlen also int verwalten kann.




LG
Digit-22

von Paul B. (paul_baumann)


Lesenswert?

Shabi N. schrieb:
> Mir
> kommt es so vor als wenn der nur ganze Zahlen also int verwalten kann.

Mir auch.

MfG Paul

von Kirsch (Gast)


Lesenswert?

Du kannst nur Ganzzahlen zwischen 0 und 255 in die Register schreiben 
(uint8)

von Karl H. (kbuchegg)


Lesenswert?


von uwe (Gast)


Lesenswert?


von Digit-22 N. (digit-22)


Lesenswert?

hhhm

den Beitrag hab ich schon gelesen. Wenn die Auflösung von 0 bis 255 
wäre, könnte ich mir ja weiterhelfen. Aber bei mir sind von 0grad bis 
etwa 180grad  genau 8 bis 39. Hab dann mit meinem Digitaloszi die 
Pulsweite eingestellt und herausgefuden das von 1ms bis 2ms Pulsweite 
meine Wert 15 bis 30 ist. Dh. ich hab nur eine Auflösung von 15 
schritten.

Ich nutze einen Atmega328P mit 16MHz. Hab nen Preescaler von 1024 
genommen.
Laut Oszi liegt die Frequenz bei etwa 58 bis 60Hz. Was nicht weiter 
schlimm ist...

Warum ist meine Auflosung so gering?


Code kann ich erst in ein paar stunden poasten da ich nicht daheim bin.



LG

von Karl H. (kbuchegg)


Lesenswert?

Shabi N. schrieb:
> hhhm
>
> den Beitrag hab ich schon gelesen. Wenn die Auflösung von 0 bis 255
> wäre, könnte ich mir ja weiterhelfen. Aber bei mir sind von 0grad bis
> etwa 180grad  genau 8 bis 39.


Dann musst du deinen Timer anders einstellen.

Vergiss die 20ms, die sind uninteressant. Die sind nicht wichtig, wenn 
du Servopulse erzeugst. Stell deinen Timer so ein, dass dir ein 
vernünftiger Zahlenbereich bleibt, mit dem du die Pulslänge erzeugen 
kannst.

Neulinge stürzen sich aus irgendeinem Grund immer auf diese 20ms und 
versuchen die möglichst auf die Nanosekunde genau einzuhalten. Die 20ms 
interessieren dein Servo nicht.

> Warum ist meine Auflosung so gering?

Weil du nicht gerechnet hast, um dir eine ordentliche Kombination aus 
Prescaler und Wertebereich herauszusuchen, mit der du die Pulslänge 
einstellen kannst. Was zugegebenermassen mit einem 8 Bit Timer schwierig 
wird

Überleg einfach mal.
Wenn du den Timer so eingestellt hast, dass er mit seinem Wertebereich 
von 0 bis 255 die 20ms abbilden soll, in welchem Wertebereich bildet 
sich dann 1ms ab. Na offenbar in einem 1/20 von 256. 1/20 von 256 sind 
circa 12. rein rechnerisch kannst du daher Pulslängen von 1 bis 2 ms mit 
Werten von 12 bis 24 erzeugen. Das geht sich also hinten und vorne nicht 
besser aus mit diesem naiven Ansatz.

: Bearbeitet durch User
von Digit-22 N. (digit-22)


Lesenswert?

Ok

hier ist mal mein Code
1
//----------------------------------------------------------------------------------------------
2
  DDRB |= _BV(PB1); //PWM Ausgang Motor
3
  DDRD |= _BV(PD6); //PWM Ausgang Drahtführung
4
  //----------------------------------------------------------------------------------------------
5
  PORTC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3);
6
  //----------------------------------------------------------------------------------------------
7
  TCCR1A |= _BV(COM1A1) | _BV(WGM10);
8
  TCCR1B |= _BV(CS10) | _BV(CS12) | _BV(WGM12);
9
10
  TCCR0A |= _BV(COM0A1) | _BV(WGM00) | _BV(WGM01);
11
  TCCR0B |= _BV(CS00) | _BV(CS02);
12
  
13
  OCR1A = 15;  //PWM 15 bis 30
14
  OCR0A = 15;  //PWM 15 bis 30 servo
15
  //----------------------------------------------------------------------------------------------


Was hätte ich denn anders einstellen müssen? Ich hab den Timer auf PWM 
gestellt und den Preescaler 1024 um soweit wie möglich mit der frequenz 
runter zu kommen.

(Sorry hab noch nicht viel mit Timer gearbeitet... Ich programmiere 
haupsächlich ST in Codesys)


LG

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Shabi N. schrieb:
> Ich nutze einen Atmega328P mit 16MHz. Hab nen Preescaler von 1024
> genommen.

Nimm einen 16Bit Timer und Prescaler 8.

von Digit-22 N. (digit-22)


Lesenswert?

Morgen alle zusammen,

irgendwie check ich das mit dem 16 Bit Timer nicht. Hab mir das 
Datenblatt und auch einige Beispiele mal angeschaut aber komme einfach 
nicht aufm Trichter wie ich den 16 Bit Timer nutzen kann.

Beim 8 Bit ist es mir klar. Wie oben mein beispielcode. Timer festlegen, 
Mode einstellen, Prescaler einstellen... und den Wert in OCR0A beliebig 
ändern. Doch wie funktioniert das mit dem 16 Bit Timer? Und welchen 
Ausgang muss ich dafür nutzen.

Wie gesagt sind meine ersten richtigen Timer Einsätze. Daher bitte ich 
um Geduld mit mir.



LG

von Digit-22 N. (digit-22)


Lesenswert?

Hej
ich glaube ich hab da was.
1
    DDRB |= 1 << DDB2);
2
    
3
    TCCR1A |= (1 << COM1A1)|(1 << COM1B1); 
4
    TCCR1A |= (1 << WGM11);
5
    TCCR1B |= (1 << WGM12)|(1 << WGM13);
6
    OCR1 = 0xFFFF;
7
    TCCR1B |= (1 << CS11);
8
9
    OCR1B = Variable;


So hier eventuell? Kann es gerade nicht testen da ich nicht daheim bin.
Den Wert in OCR1B würder ich dann immer ändern.

LG

von Karl H. (kbuchegg)


Lesenswert?

Shabi N. schrieb:
> Morgen alle zusammen,
>
> irgendwie check ich das mit dem 16 Bit Timer nicht.


Was checkst du nicht.

VOn der Funktion her ist der auch nicht anders als der 8 Bit Timer. Die 
Register heissen anders, er kann ein paar Stückchen mehr und er zählt 
bis 65535 und nicht bis 255.
> Beim 8 Bit ist es mir klar. Wie oben mein beispielcode. Timer festlegen,
> Mode einstellen, Prescaler einstellen... und den Wert in OCR0A beliebig
> ändern. Doch wie funktioniert das mit dem 16 Bit Timer?

Vom Prinzip her genau gleich.

> Und welchen
> Ausgang muss ich dafür nutzen.

Steht im Datenblatt bei der Pinbelegung des IC ganz am Anfang. der 
Ausgang für den Timer 0 heisst OC0A. Der für den Timer 1 heisst OC1A. 
Die Zah steht für den Timer, der ihn bedient.

> Wie gesagt sind meine ersten richtigen Timer Einsätze. Daher bitte
> ich um Geduld mit mir.

FAQ: Timer

: Bearbeitet durch User
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.