Frage zum TIMER2 des ATMEGA

OP #1233267
Lesenswert?
• ▲
▼
Hallo!

Ich möchte mit dem Timer2 des ATMEGA16 ein Servo Signal erzeugen, d.h. 
ich benötige eine High Phase von 0,8 ... 2,2ms aber nur alle 20ms.

Ich grübel gerade wie man das am besten realisieren kann. Mein Timer2 
benötigt 4,6ms um einmal hoch und wieder runter zu laufen, wenn er das 
einmal gemacht hat würd eich ihn gerne dazu benutzen die Pause von 
15,34ms zu timen. Das Problem ist wie erkenne ich dass er genau einmal 
hoch und wieder runter gelaufen ist? Overflow und Compare Match 
Interrupt helfen mir hier nicht. Mir fällt dazu keine Lösung ein... Hat 
jemand einen Tipp? Geh ich die Sache vielleicht komplett falsch / zu 
kompliziert an?
Gast #1233290
Lesenswert?
• ▲
▼
Warum hoch und runter? Es genügt die Fast-PWM und die läuft nur hoch. 
Das Problem ist der geringe Zählumfang des Timer2, da dies nur ein 
8-Bit-Timer ist. Du wirst damit also nicht gleichzeitig die Impulsdauer 
von 1..2 ms und die Periodendauer von 20 ms abbilden können, zumindest 
nicht halbwegs feinstufig aufgelöst.

Servoimpulse sind aber aus Sicht des AVRs dermaßen schnarchlangsam, dass 
man sie ohne Weiteres per Software im OCR-Interrupt generieren kann. 
Siehe z.B. hier: http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html

...
#1233297
Lesenswert?
• ▲
▼
5*HW-Servo-PWM auf mega1281 (3xtimer1 & 2xtimer3)

void PWM_Init (void) {
  DDRB |= (1<<PB5) | (1<<PB6) | (1<<PB7);
  DDRE |= (1<<PE3) | (1<<PE4);

  // Reset
  TCCR1A = 0;
  TCCR1B = 0;
  ICR1 = 0;
  // Mode (Fast-PWM TOP=ICRn)
  TCCR1A |= (1<<WGM11);
  TCCR1B |= (1<<WGM13) | (1<<WGM12);
  // Output-Pins
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<COM1C1);
  // Prescaler
  TCCR1B |= (1<<CS11);
  // Top (Overflow)
  ICR1 = 10000;

  OCR1A = 500 + 255;
  OCR1B = 500 + 255;
  OCR1C = 500 + 255;

  // Reset
  TCCR3A = 0;
  TCCR3B = 0;
  ICR3 = 0;
  // Mode (Fast-PWM TOP=ICRn)
  TCCR3A |= (1<<WGM31);
  TCCR3B |= (1<<WGM33) | (1<<WGM32);
  // Output-Pins
  TCCR3A |= (1<<COM3A1) | (1<<COM3B1);
  // Prescaler
  TCCR3B |= (1<<CS31);
  // Top (Overflow)
  ICR3 = 10000;

  OCR3A = 500 + 255;
  OCR3B = 500 + 255;

  sei();
}

Mit Software-PWM währe ich Vorsichtig, je nach dem wie viel die MCU noch 
zu tun hat (IRQ's) kann es ekelhafte Zuckungen in den Servos kommen !!!
Gast #1233410
Lesenswert?
• ▲
▼
>Gibt es denn keine Möglichkeit zu
>erkennen ob er einmal hoch und wieder runter gelaufen ist?

Jein, es kommt auf den PWM-Mode an. Das, was du schreibst, klingt nach 
dem Phase-Correct-PWM-Mode. Ungünstige Wahl, wobei man da den oberen 
"Umschaltpunkt" erkennen kann.
Man sollte aber (wie Hannes es schon ansprach), den Timer nur in einer 
Richtung laufen lassen z.B. FastPWM-Mode
Da kann man dann für den Impuls eine obere Grenze setzen, bei der der 
zugehörige Pin ausgeschaltet wird. Eingeschaltet wird der Pin bei 0.
Beim Erreichen der oberen Impulsgrenze wird ein Interrupt ausgelöst, in 
dessen ServiceRoutine dann der Pinschaltautomatismus wieder abgeschaltet 
wird.
Jetzt zählt man noch die Anzahl der Timerüberlaufe und kann so die 20ms 
abschätzen. Die müssen nämlich nicht hoch genau eingehalten werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren