mikrocontroller.net

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


Autor: Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
#define F_CPU 16000000L

#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned long t0_clk;
volatile unsigned long servo1;

SIGNAL( TIMER0_COMP_vect ) {
  t0_clk++;
  if( t0_clk == 5000 ) t0_clk = 0;  //alle 20ms
  if( t0_clk == 0 ) PORTA |= 0xFF;  //setze Servopin(s) auf an
  if( t0_clk == servo1 ) PORTA &= 0x00; //Servowinkel erricht
}

void servoGrad(int grad) { //von -60 bis 60;
    if ((grad >= -60) && (grad <= 60)) {
    servo1 = 375+((250/120)*grad);
  }
}

int main()
{
  DDRA  = 0xFF; //Ausgänge (LEDS und Servo hängen dran)
  PORTA = 0x01; //Start-LED einschalten, rest ausschalten
  

  TCNT0 = 0x00;    // Timer auf 0 Setzen
  
  TCCR0 = ( 0 << CS02 ) | ( 1 << CS01 ) | ( 1 << CS00 );    /* Prescaler: 1 / 64  */
  TCCR0 |= ( 1 << WGM01 ) | ( 0 << WGM00 );    /* CTC-Modus ein  */
  TCCR0 |= ( 1 << COM01 );    /* Clear OC0 on compare  */

  OCR0  = 0x01;        //Immer wenns 1 wird
  TIMSK = ( 1 << OCIE0 );   /* Compare Match einschalten       */

  t0_clk = 0;

  servo1 = 300;

  sei();                    /* Interrupts anschalten      */
  
  while( 1 ) {
  }
}


Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist du dir mit den 16MHz sicher?

Autor: Schwurbl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Schwurbl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne, ich meine 16MHz : 64 : 2 = 125kHz :-)

Autor: Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.