Forum: Mikrocontroller und Digitale Elektronik Servo mit 16Bit PWM ansteuern


von H. G. (ledi)


Lesenswert?

ich möchte ein Servo mit dem 16Bit Timer per PWM ansteuern. Dazu habe 
ich folgenden Code geschrieben.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define F_CPU 1000000                 // CPU-Frequenz = 1MHz (1 Clockzyklus = 1 / 1MHz = 1us)
5
6
int main(void)
7
{
8
  DDRD = 0xFF;                   // PD2 (OC1A) = Ausgang
9
10
  TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1A0);   // Set OC1A on compare match
11
  TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);     // Fast PWM, Top = OCR1A, Prescaler = 1
12
13
  ICR1 = 19999;                   // compare match auf 19999 setzen
14
15
  while(1)
16
  {
17
    OCR1A = ICR1 - 800;             // Servo nach rechts drehen
18
    _delay_ms(100);               // 100ms warten
19
    OCR1A = ICR1 - 2200;             // Servo nach links drehen
20
    _delay_ms(100);               // 100ms warten
21
  }
22
}

Leider erhalte ich am Ausgang (OC1A) kein PWM Signal.
Hat wer eine Idee wo der Fehler liegt?

Mein Controller: AT90PWM316

von spess53 (Gast)


Lesenswert?

Hi

>Leider erhalte ich am Ausgang (OC1A) kein PWM Signal.

Wenn du OCR1A als Top deklarierst kann es nicht als Compareregister 
fungieren. Nimm PWM-Mode 14.

MfG Spess

von H. G. (ledi)


Lesenswert?

Hab ich doch gemacht:

Mode 14 = WGM13, WGM12 und WGM11 auf 1

Oder übersehe ich da jetzt was?

Ah ja, Sorry das Kommentar ist falsch. Muss heissen Top = ICR1

von STK500-Besitzer (Gast)


Lesenswert?

H. G. schrieb:
> ICR1 = 19999;                   // compare match auf 19999 setzen
> OCR1A = ICR1 - 800;

Was soll das werden?

Das ICR ist dein TOP-Register, enthält also den Wert, bis zu dem gezählt 
und dann wieder von 0 angefangen wird.
Wenn ICR das TOP-Register sein soll, musst du Timermode 14 auswählen, 
wie Spess schon geschrieben hat.

Den Capturewert OCR1A solltest du noch mal nachrechnen.
Die Impulse sind 1-2ms lang - nicht 17,8 bis 19,2 ms...

von H. G. (ledi)


Lesenswert?

Also im Mode 14 bin ich.
1
TCCR1A = (1<<WGM11)|(1<<COM1A1)|(1<<COM1A0);   // Set OC1A on compare match
2
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);   // Fast PWM, Top = ICR, Prescaler = 1

von Karl H. (kbuchegg)


Lesenswert?

Vielleicht sollten wir erst mal eines klären

> Leider erhalte ich am Ausgang (OC1A) kein PWM Signal.

Wie hast du das verifiziert?

Hast du ein Oszi drann gehängt und es kommen wirklich keine Pulse
oder
hast du ein Servo drann gehängt und das rührt sich nicht vom Fleck, weil 
die Pulslängen falsch sind

Also. Was ist es?

von H. G. (ledi)


Lesenswert?

Kein Signal am Oszi!

von spess53 (Gast)


Lesenswert?

Hi

>Ah ja, Sorry das Kommentar ist falsch. Muss heissen Top = ICR1

Ja, das hat mich irritiert. Du bist im Mode 14.

Im Moment fällt mir kein Fehler auf. Allerdings erschließt es sich mir 
nicht, warum du invertierte PWM mit der komischen Umrechnung (OCR1A = 
ICR1 - 800) benutzt. Bei nichtinvertierter PWM brauchst du einfach nur 
deinen Wert nach OCR1A schreiben.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Hmm. Ich seh allerdings nichts im Programm, was da jetzt dagegen 
sprechen würde.

Sicher das das Programm richtig geflasht wurde. Sicher das, der µC 
läuft? Sicher, dass du am richtigen Pin bist?

Mach da mal ein
1
  while(1)
2
  {
3
    OCR1A = ICR1 - 800;             // Servo nach rechts drehen
4
    _delay_ms(100);               // 100ms warten
5
    OCR1A = ICR1 - 2200;             // Servo nach links drehen
6
    _delay_ms(100);               // 100ms warten
7
8
    PORTD ^= ( 1 << PD0 );    // <-----    
9
  }

rein. AM Pin PD0 müsstest du Pulse sehen.

von H. G. (ledi)


Lesenswert?

also ich hab das jetzt so gemacht:
1
  while(1)
2
  {
3
    //OCR1A = ICR1 - 800;               // Servo nach rechts drehen
4
    //_delay_ms(100);               // 100ms warten
5
    //OCR1A = ICR1 - 2200;             // Servo nach links drehen
6
    //_delay_ms(100);               // 100ms warten
7
    PORTD ^= (1<<PD2);
8
    PORTD ^= (1<<PD0);
9
  }

Am PD0 erhalte ich die Impulse und am PD2 nichts. Ich werde mal mein 
Board nachprüfen.

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.