-         

Ergebnis 1 bis 5 von 5

Thema: Timer verwenden zur Servoansteuerung

  1. #1

    Timer verwenden zur Servoansteuerung

    Anzeige

    Hallo mal wieder ,

    nachdem ich mein Timer funktioniert, hab ich mich an meine nächste Aufgabe gesetzt. ich wollte ein modellbauservo ansteuern. Dazu habe ich meinen Timer umgebaut. Wie ein Servo funktioniert hab ich kapiert. Ich hab mir jetzt gedacht ich schalte meinen Servoport an und nach 1.5ms schalte ich ihn wieder ab (hört sich erstmal nicht sooo sinnig an, will aber step by step weiter machen). Somit müßte ich doch einen definierten Ausschlag haben. Und zwar Mittelstellung. Mein Code habe ich angehängt.

    Das Servo verhält sich aber folgendermaßen: Es läuft in Stufen auf eine Position, leider auf keine definierte. Wenn ich den uC resete läuft er weiter. Dürfte doch eigenltich nicht sein oder?

    LG Anna
    Code:
    #include <stdlib.h>
    #include <avr/interrupt.h>
                                     
    volatile uint16_t Izeit_1;         // Timervariable
    volatile double servopos;
    
    
    void wait_1_5ms(void)	//kann eingestellt werden bis zu 3 s
    {
      cli();
      Izeit_1 = 0;
      sei();
    
      while(Izeit_1<(20*servopos)) //zweite zahl in klammern steht für die zeit in ms
      {
        {
        } 
      }
    }
    
    
    void Timer2_init(void)                 
    {       
        TCCR2 |= (1<<WGM21) | (1<<CS01); // Prescaler eingestellt auf 8            
        OCR0   = 100;                     // nach der Formel foc0=fclk/(2*N*(1+ocr0))  
        TIMSK |= (1<<OCIE2);     
    }     
    
                           
    ISR(TIMER2_COMP_vect)           
    {
        if (Izeit_1 <= 60000)       
          Izeit_1 ++;               
                                    
        else
        {   
            Izeit_1 = 0;            
        }     
             
    }  
    
    int main(void)
    {
      Timer2_init();
      DDRC |= 0xff;
      DDRD |= 0xff;
      PORTC=0x00;
      PORTD=0x00;
    
    //while(1)
    {
    	PORTC |=  (1<<PC0);		//LED anschalten, zur Kontrolle
    	PORTD |= (1 << PD5);   //Servoport anschalten 
    	servopos =1.5;
    	wait_1_5ms();
    	PORTD &= ~(1 << PD5);   //Servoport ausschalten
    	PORTC &= ~(1 << PC0);  //LED ausschalten, zur Kontrolle
    
    
    
    
     }
    }

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    06.07.2007
    Alter
    30
    Beiträge
    81
    Hallo,

    bisschen ungewöhnlicher Ansatz
    Von deiner Kontroll-LED wirst du nicht viel sehen - höchstens mit m Oszi und dann kannst du auch den Servopin beobachten.
    Wenn ich das richtig aus deinem mainloop interpretiere gibst du nicht wirklich n richtiges Servosignal aus.
    Dabei sollte eine Pause zwischen den Impulsen sein (Periodendauer 20ms, Servoimpuls 1-2ms).

    Ich habe das mit dem Timer 1 gemacht (ATmega. Damit kannst du verschiedene Interrupts erzeugen (1x Overflow und 2x Compare). Habe den Timer so eingestellt, dass er alle 20ms einen Overflow hat und dabei den Ausgang/die Ausgänge von den Servos auf high setzen. Dann muss nur noch der/die Compare Register richtig geladen werden, damit der Impuls in dem Bereich liegt, und mit ihnen der Ausgang wieder auf low gesetzt wird.

    Damit kannst du mit dem Timer 2 Servos relativ "Arbeitssparend" außerhalb dem Hauptprogramm ansteuern.

    MFG Mixxer

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Wenn man schon Timer 1 (16 Bit) nimmt, kann man das Servosignal auch gleich im PWM mode erzeugen. Da kann man auch leicht 2 Kanäle machen. Einfach im PWM Mode starten und die Pulslänge in OCRx Register schreiben, den Rest macht die Hardware.

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.556
    Hi beginner1101,

    so gehts "im Prinzip" - allerdings mit Änderungen. Dass man den Servo hardwareseitig an eine PWM hängen kann - und sich damit viel erspart - steht ja schon oben.

    Den von Dir angedachten Weg gehe ich allerdings gelegentlich auch - aber NUR wenn die PWMs anderweitig vergeben sind. So - dann kommen wir zu den Änderungen, aber erstmal etwas Grundlegendes das auch Mixxer schon beschreibt.

    Wenn das Servosignal auf high geht (die Servorampe startet) dann darf das nächste Servosignal gemäß Spezifikation erst nach 20 ms wieder auf high gehen - das ist die Periodendauer des Signals. Meist sind die Servos tolerant und manche verdauen hier Zeiten, die ein paar Millisekunden länger oder kürzer sind - aber bleib möglichst nahe bei diesen 20 ms. Dein 1,5 ms-Signal für die Mittenstellung ist ganz gut gewählt - spezifikationsmässig sogar genau richtig - aber nicht alle Servos sind exakt ! ! ! NACHDEM Du die 1,5-ms-Rampe abgeschaltet hast, musst Du warten, bis - siehe oben - die 20ms seit Rampenstart vorbei sind und darfst erst danach die Rampe wieder starten.

    >>> In dieser Beziehung ist die Skizze zur Servoansteuerung im RNWissen falsch <<< - die 20 ms gehen eben von steigender Flanke bis zur nächsten steigenden Flanke ! ! ! Genau - und etwas besser verständlich - ist die Skizze hier.

    Grundlegendes ist jetzt vorbei.

    Du müsstest also in Deinem main nach dem Ausschalten des Servoports noch rund 18,5 ms warten bis die Signalleitung zum Servo wieder eingeschaltet wird. !!! Dieses Verfahren solltest Du aber nur zu Übungszwecken machen - ansonsten steht Dein Controller ja meist auf "wait" und tut sonst nix.

    Sinnvoll wäre folgende Lösung:
    Du baust einen Timer - ähnlich wie Deine bestehende Lösung - der beispielsweise in 1 sec 10 000 Interrupts generiert. In diesem Timer zählst Du - sagen wir mal die Variable IRS_zeit hoch bis 10 000 und wenns so weit ist setzt Du den auf eins zurück. Damit wird 1 ms in 10 Teile geteilt *gggg*. Im main kannst Du jetzt eine Variable setzen auf SRV_pos - z.B. = 15. Wenn Du Deine IRS_zeit auf eins zurücksetzt, dann schaltest Du in der ISR den Servo ein, wenn IRS_zeit gleich SRV_pso (also 15) ist, dann schaltest Du den Servo in der IRS wieder aus. OK?

    BTW: Kann es sein, dass Du den Code für Deine Timerroutine bei mir gefunden hast - Variablenname und "60000" deuten darauf hin? WENN Du von 0 bis (Izeit_1 <= 60000) zählst, dann sind das natürlich 60 001 Schritte ! ! !

    Viel Erfolg
    Ciao sagt der JoeamBerg

  5. #5
    Hallo an alle,

    vielen Dank für eure Unterstützung. Ich weis ist ein ungewöhnlicher Ansatz. Hab aber irgendwie die pwm nicht auf dir reihe bekommen.

    Ich werd demnächst mal eure Ansätze umsetzen.

    Vielen Dank schon mal ich meld mich wenn es Neuigkeiten gibt.

    Gruß Anna


    PS: @oberallgaier: ja es der code ist teilweise von dir (du hast mir damals super geholfen danke noch mal)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •