- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 6 von 6

Thema: Servo code was mache ich falsch?

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    05.05.2008
    Beiträge
    51

    Servo code was mache ich falsch?

    Anzeige

    Praxistest und DIY Projekte
    Code:
    #define F_CPU 4000000UL
     
    #include <avr/io.h>
    #include <util/delay.h>
     #define SERVOPIN 7
    #define SERVOPORT PORTD
    #define DDRSERVO DDRD
    
    volatile unsigned char servopos;
    
    void servo_init()
    {
      TIMSK|=(1<<OCIE2);
      TCCR2 |= (1<<WGM21) | (1<<CS20);  //Prescale=1, CTC mode
      OCR2 = F_CPU/100000;      //alle 10µS ein IRQ
      DDRSERVO|=(1<<SERVOPIN);
    };
    
    ISR(TIMER2_COMP_vect)
    {
      static int count;
      if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
        else SERVOPORT|=(1<<SERVOPIN);
      if(count<2000)count++; // Die Impulse sollten alle 20ms gesendet werden! 6.2.11 mic
        else count=0;
    };
    
    int main (void)
    {
       servo_init();
       while(1)
       {
    
       }
      return 0;
    }
    Atmega 8 4Mhz
    Was ist da falsch es tut sich nichts

  2. #2
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von MrTaco Beitrag anzeigen
    Was ist da falsch es tut sich nichts
    Es könnte helfen, die Interrupts zu aktivieren.
    MfG
    Stefan

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    05.05.2008
    Beiträge
    51
    Code:
    #define F_CPU 4000000UL
     #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <util/delay.h>
     #define SERVOPIN 7
    #define SERVOPORT PORTD
    #define DDRSERVO DDRD
    
    volatile unsigned char servopos;
    
    void servo_init()
    {
      TIMSK|=(1<<OCIE2);
      TCCR2 |= (1<<WGM21) | (1<<CS20);  //Prescale=1, CTC mode
      OCR2 = F_CPU/100000;      //alle 10µS ein IRQ
      DDRSERVO|=(1<<SERVOPIN);
    };
    
    ISR(TIMER2_COMP_vect)
    {
      static int count;
      if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
        else SERVOPORT|=(1<<SERVOPIN);
      if(count<2000)count++; // Die Impulse sollten alle 20ms gesendet werden! 6.2.11 mic
        else count=0;
    };
    
    int main (void)
    {
         sei();
       servo_init();
       while(1)
       {
    
       }
      return 0;
    }
    geht dennoch leider nicht danke aber für den tip

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Du musst servopos auch passend vorbesetzen. Außerdem dauert Deine ISR min. 69 Takte, der OC2-Int löst aber alle 41 Takte aus. Was sagt uns das ?

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    05.05.2008
    Beiträge
    51
    Code:
    #define F_CPU 4000000UL
     #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <util/delay.h>
     #define SERVOPIN 7
    #define SERVOPORT PORTD
    #define DDRSERVO DDRD
    
    volatile unsigned char servopos = 150;
    
    void servo_init()
    {
                 
      TIMSK|=(1<<OCIE2);
      TCCR2 |= (1<<WGM21) | (1<<CS20);  //Prescale=1, CTC mode
      OCR2 = F_CPU/100000;      //alle 10µS ein IRQ
      DDRSERVO|=(1<<SERVOPIN);
    };
    
     
    
    int main (void)
    {
         
         DDRD = 0xff;
         sei();
       servo_init();
       while(1)
       {
             
       }
      return 0;
    }
    
    ISR(TIMER2_COMP_vect)
    {
         
      static int count;
      if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
        else SERVOPORT|=(1<<SERVOPIN);
      if(count<2000)count++; // Die Impulse sollten alle 20ms gesendet werden! 6.2.11 mic
        else count=0;
    };
    Ok hier ist jetzt meine neuer Code.
    OK ich mus die Interrupts in dem Interrupt deaktivieren ?

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.187
    Soweit ich weiß ist der Timer 2 beim ATMEGA 8 ein 8 Bit Timer.
    Also gehen Zahlen von 0 bis 255.
    Du läufst alle 10µs in diesen Interrupt, nach 40 Taktzyklen.
    Ich denk mal, das der Controller dabei welche verschluckt.

    Ich würde eine andere Vorgehensweise nehmen.
    1. nimm Timer 1, der hat schon mal 16 Bit.
    2. Verwende nicht! den CTC mode, das machts einfacher, geht aber auch mit.
    3. Nimm Prescaler 8, dann hast Du eine Auflösung von 2µs, also 5 mal besser als Deine Variante.

    4. Definiere eine Variable, die die entsprechende Ausgabephase hochzählt.
    Ist sie 0 dann Pause ist sie 1 Kanal 1. Dadurch lässt sich die Routine einfach auf mehrere Kanäle erweitern.

    Nehmen wir mal an der Zähler hat die Phase 0 = Pause. Im Comparematch Interrupt wird zum aktuellen Comparematchwert 9000 dazugezählt ( 18ms ) und wieder im Comparematch Register gespeichert. Alle Ausgänge werden auf 0 gesetzt.
    Der Phasenzähler wird auf 1 gesetzt.

    Im nächsten Comparematch Interrupt wird dann Ausgang 1 gesetzt und die gewünschte Servoimpulslänge zum Comparematchregister dazugezählt.
    Z.B.750 für 1,5ms.
    Der Phasenzähler wird auf den nächsten Kanal ( 2 ) oder 0 gesetzt, wenn schon alle Kanäle dran waren.

    Beim nächsten Comparematch Interrupt wird Kanal 1 abgeschaltet es sind ja jetzt 1,5ms rum, der Ausgang für Kanal 2 eingeschaltet und der Wert für den zweiten Kanal zum Comparematch Wert dazuaddiert. Also z.B. 800 für 1,6ms.
    Jetzt auf weiteren Kanal, oder 0 im Phasenzähler setzen.

    Nehen wir an du wolltest nur 2 Kanäle, dann folgt nun wieder die allererste Phase mit der Pause und dem Abschalten aller Kanäle.

    Auch bei 1ms Impulslänge hast Du 4000 Taktzyklen, bis ein neuer Comparematch auftaucht, bei Dir sind es 40.
    Zudem hast Du ein 5x bessere Auflösung der Servoimpulslänge, als bei Deinem Vorschlag.

    Die Überläufe die nach den 16Bit also rund 130ms enstehen sind im Normalfall kein Problem, da diese einfach verworfen werden, solange du unsingned int verwendest. Bei signed kanns ein Problem geben, da eine führende 1 als negativer Wert interpretiert wird.

    Mit dieser Methode kannst Du maximal 8 Servos ansteuern, die Pause sollte für jeden zusätzlichen Servokanal um 2ms verkürzt werden, weil ein Servosignal ja maximal 2ms haben kann. Wenn Du keine Pause für eine Empfängersynchroniserung brauchst, gehen auch 10 Kanäle.

    Der Timer 1 hat 2 Comparematch Einheiten OCR1A und OCR1B. Jede dieser Einheiten kann somit maximal 10 Servos bearbeiten. Also insgesamt 20, das ist mehr als der ATMEGA 8 freie Ausgänge hat.

    Code:
    volatile unsigned char uc_count=0;
    unsigned int ui_servo[2]={750,800};
    
    ISR(TIMER1_COMPA_vect) 
    {   switch(uc_count)
       {
       CASE 0:
       PORTB=0x00;  //Alle Ausgänge abschalten Beispiel    OCR1A+=ui_servo[1]; //16ms Pause einfügen
       uc_count++;  //Zählvariable hochzählen
       break;
       
       CASE 1:
       PORTB=0x01;  //Ausgang 1 aktivieren
        OCR1A+=ui_servo[1]; //Impulslänge für Servo 1 dazuaddieren
       uc_count++; //Zählvariable hochzählen
        break;
    
       CASE 2:
       PORTB=0x00;  //Alle Ausgänge aus 
       PORTB=0x02;  //Ausgang 2 aktivieren
        OCR1A+=ui_servo[2]; //Impulslänge für Servo 2 dazuaddieren
       uc_count=0;  //Wieder mit Pause beginnen
       break; 
       }; 
    
    };
    Der Quelltext mal ohne Gewähr, das da Syntax Fehler drin sind, hab das mal eben aus dem Kopf gemacht.
    Die Werte hab ich direkt in den Code geschrieben, man kanns natürlich auch per define zuweisen.

Ähnliche Themen

  1. Was mache ich hier falsch?
    Von xythobuz im Forum Robby CCRP5
    Antworten: 2
    Letzter Beitrag: 30.12.2008, 21:26
  2. Mega16 und Adc; Was mache ich Falsch?
    Von x8r im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 20.01.2006, 19:42
  3. was mache ich falsch?
    Von ferdisdot im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 14
    Letzter Beitrag: 06.01.2006, 21:01
  4. Was mache ich falsch? Timer2
    Von Baumschubser im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 06.06.2005, 13:35
  5. CNY 70...was mache ich nur falsch??
    Von Involut im Forum Sensoren / Sensorik
    Antworten: 30
    Letzter Beitrag: 24.10.2004, 23:39

Berechtigungen

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

Labornetzteil AliExpress