PWM und Timer für Dumme

OP #1892397
Lesenswert?
• ▲
▼
Hallo!
Zuerstmal, ich hab mir schon einen Rechteck Generator mit Grafik LCD, 
variabler Pulsweite und Frequenz gebaut.
Auch ne Stoppuhr im ms Sekunden bereich mit GLCD hab ich hin bekommen 
aber ich bekomm es gerade nicht auf die Reihe ne simple Soft-PWM für nen 
Servo zu ralisieren die so funktioniert wie man erwarten sollte.

ATMega16 bei 5V und 16Mhz
Fuse auf ext. Crystal / High Freq
Das ganze in C

Ziel ist, Frequenz 50Hz, das sind 20ms.
Pulsweite von 1,5ms bis 2,5ms

Takt nach Prescaler:
16000000 / 8 = 2000000

Sekunde je Takt:
1 / 2000000 = 0,0000005000

Ein überlauf bei einem OCR0 wert von 200:
0,0000005000 / 200 = 0.0001 Sekunden

Zählschleife im Interrupt macht daraus 20ms wenn "pwmcounter" einen Wert 
von 200 hat:
0.0001 * 200 = 0,02 Sekunden

Jetzt wird "servo_pos[0]" mit "pwmcounter" vergliechen.
Eine Pulsweite von 1,5ms würde also einem "servo_pos[0]"-Wert von 150 
entsprechen.
Eine Pulsweite von 2,5ms würde also einem "servo_pos[0]"-Wert von 250 
entsprechen.

Da ist aber irgendwo ein Fehler drinn... Es geht nähmlich nicht, zum 
nachmessen habe ich leider nichts da...
Ich hab aber rausgefunden das ein Wert von 5 bis 20 den Servo zum 
bewegen bringt.
Habe drei verschiedene Servos:
Nummer1 geht mit werten von 5 bis 20
Nummer2 macht genau das gegenteil von Nummer1 mit werten von 5 bis 20
Nummer3 macht nur komische Sachen.

Wo hab ich den Fehler?

Aus dem Code:
1
// soft-PWM loop counter
2
uint8_t pwmcounter = 0;
3

4
// servo positions
5
volatile uint8_t servo_pos[10] = {15,16,16,16,16,7,22,40};

1
// initialise servos and timer
2
void init_servos(void) {
3
  
4
  // set servoport as output 
5
  SERVODDR = 0xFF;
6
  SERVOPORT = 0xFF;
7

8
  // soft-PWM timer0 in ctc mode with prescaler 8
9
  TCCR0 = (1<<WGM01) | (1<<CS01);
10

11
  // enable timer0 compare match interrupt
12
  TIMSK = (1<<OCF0);
13

14
  // timer0 compare value
15
  OCR0 = 200;
16
}

[c]
// timer0 soft-PWM interrupt
ISR(TIMER0_COMP_vect) {

  // when counter value is servo value set pin low
  if(pwmcounter == servo_pos[0]) {
    SERVOPORT &= ~(1<<SERVO0);
  }

  // reset soft-PWM counter set all pins high
  if( pwmcounter++ == 200) {
    pwmcounter = 0;
    SERVOPORT = 0xFF;
  }
}
[c]
#1892499
Lesenswert?
• ▲
▼
Peter F. schrieb:

> Zählschleife im Interrupt macht daraus 20ms wenn "pwmcounter" einen Wert
> von 200 hat:
> 0.0001 * 200 = 0,02 Sekunden
>
> Jetzt wird "servo_pos[0]" mit "pwmcounter" vergliechen.
> Eine Pulsweite von 1,5ms würde also einem "servo_pos[0]"-Wert von 150
> entsprechen.
> Eine Pulsweite von 2,5ms würde also einem "servo_pos[0]"-Wert von 250
> entsprechen.

Hmm
Ein Stück weiter oben hast du ausgerechnet, dass ein wert von 200 ganzen 
20ms entspricht. Und hier wäre dann ein wert von 250 auf einmal nur 
2.5ms?

Um es mit Ede Zimmermann zu sagen: Da stimmt doch was nicht.


Im übrigen: kleb nicht an den 20ms. Die sind das unwichtigste in der 
ganzen Ansteuerung.

PS2: Ein einzelnes Servo kann ein Timer auch ganz alleine in einem PWM 
Modus ansteuern.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.