Forum: Mikrocontroller und Digitale Elektronik M32: Timer0 Compare Match Servo-Ansteuerung


von Uli (Gast)


Lesenswert?

Hallo,

wie die Überschrift schon sagt, möchte ich Servomotoren (hier PortA, 
konkret an PA7, PA0-3 sind LEDS) an meinem ATmega32 mit 16MHz Quarz über 
Timer0 steuern. (hfuse=c9, lfuse=9f)
Dafür habe ich folgende Überlegung angestellt:
16.000.000 mit Prescaler 1/64 macht 250.000 Ticks pro Sekunde, das wären 
250 Ticks pro ms. Das wäre ja fast genau das was ich brauche (mein Servo 
braucht anscheinend eher 0,8ms als 1ms für einen Vollausschlag). Also 
fluchs noch Compare so gesetzt, dass es nur noch einen Tick machen muss, 
und dann sollte das ja eigentlich klappen...

--- tuts aber net, und ich steh einfach aufm Schlauch was da schuld dran 
sein mag ---

... die LEDs flackern so, dass mans noch gut mit dem Auge sehen kann, 
somit denke ich, dass ich wohl in meiner Berechnung einen Fehler drinen 
habe, und alles viel zu langsam läuft.

Grüße Uli

PS: Der Servo geht auf Linksanschlag.

PPS: Ich weiß, das CTC hier eventuell etwas ungünstig gewählt ist, aber 
da ich dies bisher noch nie genutzt habe, und eventuell noch genauere 
Feineinstellungen vornehmen will, halte ich das für am geeignetsten.
1
#define F_CPU 16000000L
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
volatile unsigned long t0_clk;
7
volatile unsigned long servo1;
8
9
SIGNAL( TIMER0_COMP_vect ) {
10
  t0_clk++;
11
  if( t0_clk == 5000 ) t0_clk = 0;  //alle 20ms
12
  if( t0_clk == 0 ) PORTA |= 0xFF;  //setze Servopin(s) auf an
13
  if( t0_clk == servo1 ) PORTA &= 0x00; //Servowinkel erricht
14
}
15
16
void servoGrad(int grad) { //von -60 bis 60;
17
    if ((grad >= -60) && (grad <= 60)) {
18
    servo1 = 375+((250/120)*grad);
19
  }
20
}
21
22
int main()
23
{
24
  DDRA  = 0xFF; //Ausgänge (LEDS und Servo hängen dran)
25
  PORTA = 0x01; //Start-LED einschalten, rest ausschalten
26
  
27
28
  TCNT0 = 0x00;    // Timer auf 0 Setzen
29
  
30
  TCCR0 = ( 0 << CS02 ) | ( 1 << CS01 ) | ( 1 << CS00 );    /* Prescaler: 1 / 64  */
31
  TCCR0 |= ( 1 << WGM01 ) | ( 0 << WGM00 );    /* CTC-Modus ein  */
32
  TCCR0 |= ( 1 << COM01 );    /* Clear OC0 on compare  */
33
34
  OCR0  = 0x01;        //Immer wenns 1 wird
35
  TIMSK = ( 1 << OCIE0 );   /* Compare Match einschalten       */
36
37
  t0_clk = 0;
38
39
  servo1 = 300;
40
41
  sei();                    /* Interrupts anschalten      */
42
  
43
  while( 1 ) {
44
  }
45
}

von STK500-Besitzer (Gast)


Lesenswert?

>Der Servo geht auf Linksanschlag.

Es wird auch nur ein Wert gesetzt... kann es sein, dass es sich bei 
diesem um den linken Anschlag handelt?

>volatile unsigned long t0_clk;

int sollte reichen...

Was bei dem Programm schief läuft, kann ich jetzt nicht mehr 
nachvollziehen.
Wenn ich meins finde, poste ich das mal.

von Uli (Gast)


Lesenswert?

Leider denke ich nicht, dass das was mit dem Linksausschlag zu tun hat. 
Ich denke eher, das sind irgendwie komplett falsche timings, die den 
servo dazu verleiten immer einen bestimten Winkel nach links 
weiterzudrehen bei jedem "Puls"...
Soll heißen, wenn ich ihn nach rechts drehe, hoppelt er Stück für Stück 
nach links.

von STK500-Besitzer (Gast)


Lesenswert?

Bist du dir mit den 16MHz sicher?

von Schwurbl (Gast)


Lesenswert?

Wenn OCR0 auf 1 gesetzt wird, kommst Du auf eine Interruptfrequenz von 
16000000MHz  64  2 = 125kHz, womit sich eine PWM-Frequenz von 25Hz 
statt 50Hz einstellt. Ich täte den Prescaler auf 1:1 und OCR0 auf 63 
setzen.

von Schwurbl (Gast)


Lesenswert?

Ne, ich meine 16MHz : 64 : 2 = 125kHz :-)

von Uli (Gast)


Lesenswert?

@Schwurbl: das es schon reichlich spät zum nachdenken ist, hab ich 
deinen Vorschlag einfach mal getestet, aber es ändert sich nicht 
wirklich was...

@STK500-Besitzer: ja, ziemlich sicher, weil ich ihn verbaut hab, und er 
unter dem Atmega eingesperrt net weglaufen kann.
Und dass der Quarz defekt ist / net benutzt wird kann ich eigentlich 
auch ausschließen, weil die Kommunikation an diesem Board über USART 
problemlos funktionert.

von Uli (Gast)


Lesenswert?

Hmm.. ich weiß vlt, warum das nicht funktioniert - ich hab mir mal nen 
Windows aufgespielt und AVR Studio draufgehauen... laut AVR Simulator 
schafft er die schleife so alle 0,01 - 0,02 ms, ich habe aber 
rechnerisch gesehn 0,004 angepeilt.

Kann mir jemand diese Vermutung bestätigen oder entkräftigen?

Grüße Uli

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.