- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 10 von 17

Thema: Atmega168 Timer initialisieren und an/aus-schalten

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter-Spezialist Avatar von erik_wolfram
    Registriert seit
    02.12.2009
    Ort
    Berlin
    Beiträge
    406

    Atmega168 Timer initialisieren und an/aus-schalten

    Hallo!

    Ich versuche einen optimalen Code für meinen Quadrupped mit 12 Modellbauservos zu schreiben und stehe vor vor folgendem Problem:

    Hierfür möchte ich 2 Timer verwenden.
    Ein Timer (Timer1 16-Bit) der alle 20 Sekunden auslöst und den 2. Timer (Timer0 8-Bit) aktiviert. Der 2. Timer arbeitet dann alle Servoimpulslängen ab und beendet sich danach bis er wieder vom 1. Timer aktiviert wird.

    Das klappt eigentlich auch schon fast, aber beim "Anschalten" des 2. Timers löst dieser sofort aus anstatt der vorgegebenen Zeit zu warten.
    Danach hält er sich an die Zeiten.
    Also habe ich den Timer0 wie folgt aktiviert:

    Code:
        TCNT0 = 0;                                // um sicherzustellen, dass er von Null aufwärtszählt
        OCR0A = 50;
        TIMSK0 |= (1 << OCIE0A);        // Timer0 aktivieren
    Aber egal welchen Wert ich für OCR0A eingebe, er startet immer sofort...
    Der andere Timer wartet artig seine 20 ms ab bevor er zum ersten mal auslöst.

    Hier nochmal ein bisschen mehr Code zur Übersicht:
    Code:
    ...
    
    int main(void)
    {
       
        // Timer0 - 8-Bit 
        TCCR0A |= (1 << WGM01);                    // Clear Timer on compare
        TCCR0B |= (1 << CS02);                    // Prescaler 256, Interrupt max Verzögerung 4,1 ms
        //TIMSK0 |= (1 << OCIE0A);                // Compare-mode aktivieren
        
        
        // Timer1 - 16-Bit
        // Servo Impuls-Zeit
        TCCR1B |= (1 << WGM12) | (1 << CS12);    // Prescaler 256, Clear Timer on compare
        OCR1A = 1249;                            // Interrupt Verzögerung 20 ms
        TIMSK1 |= (1 << OCIE1A);                // Compare-mode aktivieren
            
        sei();                                    // Interrupts global ein
        
       ....
    }
        
    
    ...
    
    ISR (TIMER0_COMPA_vect)
    {
             ....
            OCR0A = wartezeit[zaehler];   // Hier gibts die neue Wartezeit - diese wird auch eingehalten!
    }
    
    
    ISR (TIMER1_COMPA_vect)
    {
       ... 
        
        TCNT0 = 0;
        OCR0A = 50;                             // <-------------------------------------dieser Wert wird ignoriert
        TIMSK0 |= (1 << OCIE0A);        // Timer0 aktivieren
    }
    Zum beenden des Timer0 setze ich TIMSK0 = 0.


    Vielleicht sieht hier jemand meinen Fehler? Ich wäre für jede Hilfe dankbar

    Zur Herangehensweise:
    Ich habe schon einen anderen Code zur Ansteuerung der 12 Servos verwendet, dieser ist aber sehr unsauber und die Servos bewegen sich nur sehr ungenau.
    Deshalb möchte ich UNBEDINGT diese Methode zum laufen bekommen um auch die Pausenzeiten konstant zu halten.

    Gruß Erik
    Meine Projekte auf Youtube

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Deine Problembeschreibung verwirrt mich etwas.

    Aber: Timer schaltet man ab in dem man ihren Takt deaktiviert, nur den Interrupt stummzuschalten reicht nicht. Wenn du den Interrupt wieder zulässt, löst das vorher irgendwann Mal gesetzte Interrupt-Flag (im TIFR-Register) den Interrupt gleich aus.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  3. #3
    Erfahrener Benutzer Roboter-Spezialist Avatar von erik_wolfram
    Registriert seit
    02.12.2009
    Ort
    Berlin
    Beiträge
    406
    Hallo,

    Super! Danke für den Tip. Ich habe diese Möglichkeit nicht gesehen...
    Wenn ich nun den Prescaler deaktiviere und wieder setzte funktiert alles so wie es soll!
    Man lernt immer dazu - danke für die schnelle Hilfe!

    Hier nochmal der Code für andere:
    Code:
    OCR0A = 50;
    TCCR0B |= (1 << CS02);
    ..zum starten und
    Code:
    TCCR0B = 0;
    ...zum Beenden

    TIMSK bleibt dabei die ganze Zeit gesetzt.

    Gruß Erik
    Meine Projekte auf Youtube

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.694
    Zitat Zitat von markusj Beitrag anzeigen
    ... Timer schaltet man ab in dem man ihren Takt deaktiviert, nur den Interrupt stummzuschalten reicht nicht ...
    Hmmmm, reicht wirklich nicht? Ich habe eine ähnliche Routine auf einem mega328/20MHz laufen für zehn Servos auf Timer1. ISRCompA macht mir die 2 ms-Schritte, startet den zuständigen Portpin und lädt OCR1B und setzt OCIE1B. ISRCompA gibt bei zehn Durchläufen 20 ms. Die ISRCompB schaltet den Interrupt ab und löscht den zuständigen Portpin - und es läuft und läuft und ....

    Code:
    // ============================================================================== =
    // ===  Nicht unterbrechbare ISR für TIMER1_COMPB_vect     ====================== =
      ISR (TIMER1_COMPB_vect)       // VECTOR 19                                   S 65
      {                             //
        TIMSK1 &= ~(1<<OCIE1B);     // Tmr/Cntr1 CompB Match interrupt disabled
    // - - - - - - - - - - - - - - -
        if (Svpt ==  1) PORTB &= ~(1<<1); //
        if (Svpt ==  2) PORTB &= ~(1<<2); //
        if (Svpt ==  3) PORTD &= ~(1<<3); //
        if (Svpt ==  4) PORTD &= ~(1<<4); //
        if (Svpt ==  5) PORTD &= ~(1<<5); //
        if (Svpt ==  6) PORTD &= ~(1<<6); //
        if (Svpt ==  7) PORTD &= ~(1<<7); //
        if (Svpt ==  8) PORTB &= ~(1<<0); //
        if (Svpt ==  9) PORTC &= ~(1<<0); //
        if (Svpt == 10) PORTC &= ~(1<<1); //
    // - - - - - - - - - - - - - - -
      }                             //
    // ============================================================================== =
    Vorteile: genaue Periodenlänge und für den Puls habe ich - natürlich je nach Servo - reichlich Schritte. Aktuell kann ich OCR1B von 120 bis 780 fahren - dann gehts wirklich Anschlag bis Anschlag, rund 180°. Brauch ich aber nicht, für mich (neee, für die Servos) sind 300 Ticks für ziemlich genaue 90 Grad mehr als genug.
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    So wird beim Freischalten des Interrupts direkt erst Mal noch einer ausgelöst werden, außer du löschst das Flag im TIFR. Die Output-Compare-Unit setzt das Flag solange der Timer läuft, unabhängig von der Interruptfreigabe.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.694
    Zitat Zitat von markusj Beitrag anzeigen
    ... außer du löschst das Flag im TIFR ...
    Genau. Wollt ja nur andeuten, dass es doch geht (und wollte nicht irgendwie besserwisserisch sein). Irgendeinen Tod muss man - ähhhhh - irgend ein Bit muss man doch immer setzen oder löschen.

    Der (für mich ziemlich markante) Nachteil beim Deaktivieren des Taktes ist natürlich, dass dann der andere Timer auch abgeschaltet wird - und von den datenblattbekannten zwei unabhängigen Output Compare Units ist nur noch eine funktionierende übrig geblieben. Wer natürlich für den Puls nen eigenen Timer spendiert, der kann den Takt deaktivieren. Ich komme ja mit einem einzigen Timer für die Servobedienung aus.
    Geändert von oberallgeier (02.01.2013 um 18:24 Uhr)
    Ciao sagt der JoeamBerg

  7. #7
    Erfahrener Benutzer Roboter-Spezialist Avatar von erik_wolfram
    Registriert seit
    02.12.2009
    Ort
    Berlin
    Beiträge
    406
    Hallo,

    das eine Problem habe ich gelöst, da tut sich schon das nächste größere auf ... dieser Versuch die 12 Servos zu steuern hat sich als problematisch erwiesen. Zur Übersicht nochmal eine Zusammenfassung des Ablaufs:

    Nach jeder erfolgreichen Servoansteuerung (also 20 ms) werden die neuen Positionen berechnet (Dauer ca 4 ms). Dann werden die Einschaltzeiten nach der Dauer sortiert, die Differenzen berechnet und in einem Array abgespeichert (1 ms).
    Jetzt beginnt der Zyklus, der 20 ms Timer aktiviert alle Ausgänge für die Servos und den 2. Timer mit der kürztesten Servozeit. Wenn dann der 2. Timer auslöst wird der 1. Ausgang der Sortierreihenfolge auf Aus gesetzt und es wird die nächste Differenzwartezeit für diesen Timer gesetzt. Und der nächste Servo wird abgeschaltet ... usw usw...

    Dummerweise benötigt der Vergleich im Timer 2, welcher Servo als nächstes ausgeschaltet werden muss, ganze 15 µs - also verzögert sich der 2. Timer jedesmal um diese Zeit. Bei 12 Servos macht das dann ca 180 µs. Bedenkt man jetzt die Impulszeit für die Servos von 1-2 ms so sind das minimal 9% Abweichung des Drehwinkels der letzten Servos.

    Als Mikrocontroller verwende ich den genannten Atmega168 mit einem 16-Bit Timer und zwei 8-Bit Timern und einer Taktung von 16 MHz.

    Nun Suche ich nach einem alternativen Lösungsweg, wie ich es schaffen kann die Servos sauber (ohne Abweichung) anzusteuern und trotzdem nebenbei noch Berechnungen auszuführen. Ich möchte keine komplette Lösung, aber vielleicht hätte jemand einen Denkanstoß, wie ich das lösen könnte?
    Ich weis, dass 3 Timer eigentlich zu wenig für diese Aufgabe ist, aber trotzdem würde ich es gerne schaffen, den Roboter endlich mal fertigzustellen!

    Gruß Erik
    Meine Projekte auf Youtube

Ähnliche Themen

  1. LED an und aus schalten
    Von Lightstorm im Forum C - Programmierung (GCC u.a.)
    Antworten: 23
    Letzter Beitrag: 12.03.2010, 10:49
  2. Timer 2 als PWM bei Atmega168
    Von timmy83 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 23.03.2008, 16:49
  3. Über USB einfach ein und aus schalten
    Von Forchtenauer im Forum PC-, Pocket PC, Tablet PC, Smartphone oder Notebook
    Antworten: 8
    Letzter Beitrag: 10.03.2008, 23:59
  4. Timer und PWM im Tiny25 initialisieren ?
    Von grumpf im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 27.01.2008, 19:58
  5. Problem mit Timer und Atmega168
    Von applican im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 26.07.2007, 01:25

Berechtigungen

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

fchao-Sinus-Wechselrichter AliExpress