Forum: Mikrocontroller und Digitale Elektronik Frage PWM ATmega32u4


von Oskar H. (marginru)


Lesenswert?

Hallo zusammen,

Habe ein kleines Problem beim verstehen der PWM/Timer0 des ATmega32u4.

Ich möchte einen Servomotor ansteuern mittels Timer0 (8-Bit) wobei die 
PWM folgendermaßen aussieht:
1ms   = 0°  (Links)
1,5ms = 90° (Mitte)
2ms   = 180°(Rechts)

Ich versteh nun nicht ganz wie genau ich mit der im Datenblatt 
angegebenen Formel diese Zeiten/Stellungen am Servo bekomme.

fpwm = fcpu/(N*256)
Mit der obigen Formel weiß ich aber nicht ganz recht wie ich mein Ziel 
erreichen soll.

Habe mir gedacht, dass OCR0B=0 Links entspricht und OCR0B=255 Rechts.
Wäre das richtig so?

Mein bisher programmierter Code dazu:
1
#include <stdio.h>
2
#include "dev/usb_serial.h"
3
#include <util/delay.h>
4
#include <avr/io.h>
5
#include "dev/adc.h"
6
#include <avr/interrupt.h>
7
8
9
10
int main(void)
11
{
12
  DDRD |= (1<<PORTD6); //Output
13
  PORTD |= 0x00;
14
  
15
  TCCR0A |= ((1<<COM0B1) | (1<<COM0B0) | (1<<WGM00) | (1<<WGM01)); //COM: Set OC0B on Compare Match, clear OC0B at TOP / FAST PWM
16
        
17
  TCCR0B |= ( (1<<CS00) | (1<<CS02) ); //Prescaler auf 1024     
18
  sei();
19
  
20
  while(1)
21
  {
22
    if(pos < 0) //pos soll später eine Variable sein welche von einem Joystick übergeben wird (-100 = Links / 0 = Mitte / 100 = Rechts)
23
    {
24
      OCR0B |= ((pos/100) * 128) + 128;
25
    }
26
    
27
    if(pos > 0)
28
    {
29
      OCR0B |= ((pos/100) * 128) + 127;
30
    }
31
    
32
    if(pos = 0)
33
    {
34
      OCR0B |= 128;
35
    }
36
  }
37
}

Wäre über jede Antwort dankbar! :)

von Veit D. (devil-elec)


Lesenswert?

Hallo,

überlege dir einmal wie PWM arbeitet. Dann überlegste dir oder spielst 
einfach mal damit rum wie die PWM Timer Modi arbeiten. Dann wirst du 
irgendwann darauf kommen, dass ein Wert die Frequenz bestimmt und der 
zweite Wert das Duty Cycle. Funktionell nah an den Pulsen von Servo, 
aber nicht dafür zugebrauchen. Mit Duty Cycle 0 haste Pulsweite 0%. Mit 
Duty Cycle 255 haste Pulsweite 100%. Diese [%] Pulsweiten in Zeiten 
umgerechnet sind abhängig der einstellten Timerfrequenz. Stichwort 
Periodendauer.

von Oskar H. (marginru)


Lesenswert?

Hallo,

Das mit der PWM verstehe ich soweit.
Nur wie bekomme ich meine 50Hz, also 20ms Periodendauer zusammen, mit 
dem Prescaler und der obigen Formel bekomme ich min. 61Hz heraus, nicht 
weniger.

So weit ich das verstanden habe, davon also von den 20ms Periodendauer 
die ich haben möchte, den jeweiligen Prozentanteil, also 2ms sind dann 
10% und eben 1ms sind 5%.

Ist das richtig so?

Danke für deine Antwort!

von Äxl (geloescht) (Gast)


Lesenswert?

ersteinmal richtig, da Du aber schon erwähnst, das es nur 20% am einem 
Anschlag und nur 5% am anderen Servoanschlag sind, brauchst Du natürlich 
ordentlich Auflösung zwischen disen beiden Punkten. Du bekommst, selbst 
wenn Du nur diese drei Stellungen, (links, mitte, rechts) benötigst, 
dein Servo sonst nicht genau genug positioniert. Ob sich hierfür der 
8-Bit Timer immernoch eignet?

Äxl

von Oliver S. (oliverso)


Lesenswert?

Vielleicht hilft ja das hier weiter:

https://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung

Wenn nicht, liefert es zumindest die passenden Stichworte für eine 
weiterführende Google-Suche.

Oliver

von Oskar H. (marginru)


Lesenswert?

Danke für den Link!

Mein Problem ist Momentan dass ich nur den 8-Bit Timer (=Timer0) 
verwenden kann. Laut meinem Programmier-Freund gibt es eine Lösung, 
möchte er mir aber nicht verraten, ich soll selbst draufkommen.

Wenn ich einen 16MHz Clock habe und den Prescaler von 1024 verwenden 
bekomme ich 15625. Das sind 0,064ms. Wenn ich auf die 20ms kommen möchte 
kann ich hierbei jedoch max. 255 dazu multiplizieren, ergibt 16,32ms.

Rein logisch ginge sich das nie aus mit den 8-Bit, oder übersehe ich 
hier etwas?

von Äxl (geloescht) (Gast)


Lesenswert?

>Laut meinem Programmier-Freund
toller Freund, den Du da hast...

Äxl

von Äxl (geloescht) (Gast)


Lesenswert?


von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich wette der Freund sucht selbst funktionierenden Code.  :-)

Der verlinkte Code von hier gefällt mir persönlich nicht so richtig. Ich 
erkläre dir mal meine Lösung. Das erfordert jedoch das du dich mit dem 
Timer und Interrupt an sich schon beschäftigt hast. Du hast ein Servo 
welches sich zwischen 0° und 180° bewegen kann. Wir nehmen mal an das 
die 0° Position 1ms Pulsweite entsprechen und 180° Position 2ms 
Pulsweite. Ich glaube es zwar nicht, aber das musst du wissen was dein 
Servo kann. Spielt auch keine entscheidende Rolle, ist durch Umrechnung 
alles anpassbar.

Jetzt möchtest du das Servo mit einer Auflösung von 1° bewegen. Was 
bedeutet, du musst die 1ms Spielraum (2ms-1ms = 1ms) durch 180° teilen. 
Das ergibt 5,55µs. Jetzt baust du dir einen Timer im CTC Mode, der aller 
5,55µs seinen Compare Match ISR aufruft. Du suchst dir ein setup was nah 
ran kommt. In der Timer ISR läuft ein Zähler. Mit dem regelst du deine 
Pulsweiten von so vielen Servos wie du möchtest. Du weißt ja das ein 
Inkrement des Zählers von ca. 5,55µs einem Grad Stellwinkel entsprechen.

Ich mach das so, dass ich immer bei Zähler 0 alle Servos einschalte und 
dann nur noch den Zählerstand vergleiche mit der gewünschten 
Servostellung und entsprechend das Servo abschalte. Damit erzeuge ich 
die Pulsweiten. Dann warte ich ca. weitere 18ms und das Spiel geht von 
vorn los. Als Feature schalte ich den Timer in den Pulspausen ab, damit 
die "CPU Last" geringer ist.

Der "eigene Zähler" hat nichts mit irgendwelchen Timerregistern zu tun. 
Der zählt nur im Zyklus der 5,55µs hoch. Nachdem die 20ms vorbei sind 
oder nachdem die letzte Pulsweite fertig ist wird er genullt. Jetzt mach 
daraus ... oder denkst dir eine noch bessere Lösung aus ...  :-)

Ein Datalogger oder Oszi wäre auch nicht schlecht damit du siehst was du 
machst bis es läuft.

von Luggi F. (luggi_f)


Lesenswert?

Hallo

Da hat also wer Mikrocontroller LU ?.
Tipp: 61 Hz sind auch in Ordnung!

von Wolfgang (Gast)


Lesenswert?

Äxl (geloescht) schrieb:
> Ob sich hierfür der 8-Bit Timer immernoch eignet?

Die 20ms Wiederholperiode ist völlig unkritisch, d.h. man kann mit dem 8 
Bit Timer den 1..2ms Puls generieren und muss ihn nur ungefähr alle 20ms 
anstoßen (Monoflop). Die Auflösung für die Position läge dann etwa um 
1%.

von Klaus (Gast)


Lesenswert?

Veit D. schrieb:
> Ich mach das so, dass ich immer bei Zähler 0 alle Servos einschalte und
> dann nur noch den Zählerstand vergleiche mit der gewünschten
> Servostellung und entsprechend das Servo abschalte.

Man könnte die Servopulse auch nacheinander erzeugen und zum Schluss auf 
20ms auffüllen. Dann sieht das so aus, wie es auch vom Fernsteuersender 
kommt. Und wenn man nicht genügend IOs zur Verfügung hat, kann man das 
Sinal an einem Pin ausgeben und es, wie in den klassischen Empfängern, 
mit einem simplen Schieberegister dekodieren.

MfG Klaus

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.