- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 12

Thema: Servo-Dauerlauf ohne delay();

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Benutzer Stammmitglied Avatar von porter91
    Registriert seit
    15.07.2012
    Beiträge
    54
    Hey

    Mach mal aus:
    long previousMillis = 0;
    auch mal ein unsigned
    Bin gerene bereit Hilfe zu leisten, freue mich wenn auch mir geholfen werden kann.
    Entschuldigt bitte Rechtschreibfehler falls welche vorkommen

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    17.09.2004
    Alter
    40
    Beiträge
    647
    Hi,

    also ich finde die Lib bei Arduino ja prinzipiell gut aber manchmal kriegt man mehr Performance wenn man sich selbst die benötigten Funktionen schreibt.

    Deshalb habe ich mir eine eigene Servoroutine geschrieben. Die lässt sich sicher noch deutlich optimieren. Ich werde mich nachher mal ran machen die zu verbessern. Fürs erste möchte ich trotzdem mal zeigen, wie ich das gelöst habe.
    Code:
    byte state = 1;
    int pwm_hi = 0;
    int pwm_lo = 0;
    int led_w = 13;
    int servo_1 = 12;
    int servo_1_pos = 150;
    int servo_state = 0;
    int n = 0;
    
    void setup(){
    pinMode(led_w, OUTPUT); 
    pinMode(servo_1, OUTPUT);
        setup_timer1();
      
    }
    
    void setup_timer1(){
      cli();                 // disable interrupts
      TCCR1A = 0;            // Register TCCR1A auf 0 setzen
      TCCR1B = 0;            // Register TCCR1B auf 0 setzen um Timer zu beenden
    
      //CTC setzen
      OCR1A = 19;         // bis 15624 ticken dann interrupt
    
      //enable CTC
      TCCR1B |= (1 << WGM12);
      // Set CS10 bit so timer runs at clock speed:
      //Timerresolution: 1/(16*10^6 / 1024)
      TCCR1B |= (0 << CS10);
      TCCR1B |= (1 << CS11);
      TCCR1B |= (0 << CS12);  // prescaler 1024
      // enable Timer1 compare interrupt
      TIMSK1 |= (1 << OCIE1A);
      // enable global interrupts:
      sei();
    }
    
    
    void loop()
    {
    if(servo_state == 0)
    {
       delay(20);
       servo_1_pos = servo_1_pos + 1;
       if(servo_1_pos ==200)
       {
       servo_state = 1;
       }
     }
    
    if(servo_state == 1)
    {
       delay(20);
       servo_1_pos = servo_1_pos - 1;
       if(servo_1_pos ==100)
       {
       servo_state = 0;
       }
     }
    
    }
    
    ISR(TIMER1_COMPA_vect)
    {
     if (n == 20000)
      {
        digitalWrite(led_w, !digitalRead(led_w)); 
        n = 0;
      }
      n++;
    
    if (pwm_hi > 0)
    {
    digitalWrite(servo_1,HIGH);
    pwm_hi = pwm_hi - 1;
    pwm_lo = 0;
    }
    else if(pwm_hi == 0)
    {
    pwm_lo++;
    digitalWrite(servo_1,LOW);
    }
    if (pwm_lo == 2000 - servo_1_pos)
    {
    pwm_hi = servo_1_pos;
    }
    }
    Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    17.09.2004
    Alter
    40
    Beiträge
    647
    Versuch mal nicht von 0 - 180 zu verfahren. Ich glaube das dein Servo eine Pause einlegt liegt daran, das dein Servo nicht bis 0 bzw. 180 fahren kann. Versuchs mal von 20 - 160. Wird die Pause kleiner bzw verschwindet liegt es da dran. So war es bei mir.

    Das mit deiner millis() und ner For schleife funktioniert so nicht. Weil er zwar im passenden Interval zu for schleife kommt diese dann aber mit fullspeed abarbeitet.

    Ich habe das ganze jetzt so gelöst:
    Code:
    long interval = 600; 
    
    
    void loop()
    {
    
      if(n > interval){
         digitalWrite(led_w, !digitalRead(led_w)); 
        if(servo_state == 0)
        {
          servo_1_pos = servo_1_pos + 1;
          n=0;
          if(servo_1_pos ==185)
          {
            servo_state = 1;
          }
        }
    
        if(servo_state == 1)
        {
          servo_1_pos = servo_1_pos - 1;
          n=0;
          if(servo_1_pos ==75)
          {
            servo_state = 0;
          }
        }
      }
    
    }
    In der ISR wird n hochgezählt mit "n++;".

    Das Problem ist allerdings, das es scheint als würde das Servo irgendwann durcheinander kommen. Dann macht es einen Sprung. Je größer der Interval desto länger läuft es bis es springt. Ich vermute irgendwann passt das Timing für die PWM nicht mehr läuft über und das Servo weiss dann kurz nicht was es machen soll.
    Geändert von DanielSan (01.08.2013 um 12:46 Uhr)
    Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    7
    Zitat Zitat von porter91 Beitrag anzeigen
    Hey

    Mach mal aus:

    auch mal ein unsigned
    Hat leider keine Wirkung

    Versuch mal nicht von 0 - 180 zu verfahren. Ich glaube das dein Servo eine Pause einlegt liegt daran, das dein Servo nicht bis 0 bzw. 180 fahren kann. Versuchs mal von 20 - 160. Wird die Pause kleiner bzw verschwindet liegt es da dran. So war es bei mir.
    Bringt auch nichts, der Servo ist ein AS-16 acoms

    Das Problem ist allerdings, das es scheint als würde das Servo irgendwann durcheinander kommen. Dann macht es einen Sprung. Je größer der Interval desto länger läuft es bis es springt. Ich vermute irgendwann passt das Timing für die PWM nicht mehr läuft über und das Servo weiss dann kurz nicht was es machen soll.
    Ich habe deine beiden Codes zusammen kopiert und jetzt läuft er, aber mit den von dir erwähnten Sprüngen in unregelmäßigen Abständen


    Trotzdem vielen Dank für die Mühen

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    17.09.2004
    Alter
    40
    Beiträge
    647
    Ich bin mit dem Ergebniss noch nicht zufrieden. Werde mir das morgen nochmal genauer ansehen. Habe eben noch mit einem Kumpel gesprochen er hat wohl eine "hardware" Lösung mit 2 Timern gemacht. Dasguck ich mir mal an.
    Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    29.07.2013
    Beiträge
    7
    Eine Hardware-Lösung würde ich gerne vermeiden. Ich habs jetzt erstma anderweitig gelöst, jetzt fährt er dauerhaft zwischen zwei Positionen hin und her, z.b. 30° und 150°. Das dürfte für meine Zwecke reichen.

    Allerdings komm ich damit im Moment nicht weiter wenn ich in die Loop noch eine andere Funktion packe.

    1+2 = fail

    1
    Code:
    #include <Servo.h>
    int pos = 0;
    Servo myservo;
    long previousMillis1 = 0;
    long previousMillis2 = 300;
    
    
     
    void setup(){
     myservo.attach(10);
    }
    
     void loop(){
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis1 >= 600) {      //yes 200
        myservo.write(30);
        previousMillis1 = currentMillis;
      }
      if(currentMillis - previousMillis2 >= 600) {      //yes 200
        myservo.write(150);
        previousMillis2 = currentMillis;
      }
    }
    2
    Code:
    #define echoPin 46 // Echo Pin
    #define trigPin 47 // Trigger Pin
     int maximumRange = 200; // Maximum range needed
     int minimumRange = 0; // Minimum range needed
     long interval = 50;    // Scanrate
     long previousMillis = 0;
     long duration, distance;
     
     
    void setup() {
     Serial.begin (9600);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
    }
     
    
    void loop() {
      scan();
    }
     
     
    int scan(){
     unsigned long currentMillis = millis();
     if(currentMillis - previousMillis >= interval) {
      digitalWrite(trigPin, LOW); 
      delayMicroseconds(2); 
    
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10); 
     
      digitalWrite(trigPin, LOW);
      duration = pulseIn(echoPin, HIGH);
     
      Serial.println(distance);
      distance = duration/58.2;  //Calculate the distance (in cm) based on the speed of sound.
      previousMillis = currentMillis;
     }
    }
    fail
    Code:
    #include <Servo.h>
    #define echoPin 46 // Echo Pin
    #define trigPin 47 // Trigger Pin
     int maximumRange = 200; // Maximum range needed
     int minimumRange = 0; // Minimum range needed
     int pos = 0;
     long interval = 50;    // Scanrate
     long previousMillis = 0;
     long previousMillis1 = 0;
    long previousMillis2 = 300;
     long duration, distance;
     Servo myservo;
    
     
    void setup() {
     Serial.begin (9600);
     myservo.attach(10);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
    }
     
    
    void loop(){
      scan();
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis1 >= 600) {      //yes 200
        myservo.write(30);
        previousMillis1 = currentMillis;
      }
      if(currentMillis - previousMillis2 >= 600) {      //yes 200
        myservo.write(150);
        previousMillis2 = currentMillis;
      }
    }
     
     
    int scan(){
     unsigned long currentMillis = millis();
     if(currentMillis - previousMillis >= interval) {
      digitalWrite(trigPin, LOW); 
      delayMicroseconds(2); 
    
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10); 
     
      digitalWrite(trigPin, LOW);
      duration = pulseIn(echoPin, HIGH);
     
      Serial.println(distance);
      distance = duration/58.2;  //Calculate the distance (in cm) based on the speed of sound.
      previousMillis = currentMillis;
     }
    }
    Scannen, also die Entfernung messen, macht er perfekt, allerdings fährt der Servo nur auf Position 150° und schläft ein.
    Einzelnd betrachtet funktionieren die Sketche. Kommt er mit den ganzen 'currentMillis = millis();' nicht klar und verzählt sich oder kommt aus dem takt?

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    17.09.2004
    Alter
    40
    Beiträge
    647
    Hi,

    ich habe heute wieder was an der Servogeschichte getan. Bin aber nicht wirklich weiter gekommen. Habe Hauptsächlich im Inet gesucht und verschiedene Lib ausprobiert. Die machen aber alle nicht das was ich will. Ich setze mich evtl. Morgen nochmal dran.

    Zu deinem Problem...
    Bei dir kollidieren die Timer. Die Servo Lib nutzt Timer1 genau wie die Lib welche die Funktionen currentMillis etc zur Verfügung stellt.
    Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]

Ähnliche Themen

  1. Antworten: 10
    Letzter Beitrag: 09.07.2008, 23:02
  2. Zeiten ohne Delay
    Von Spongebob85 im Forum C - Programmierung (GCC u.a.)
    Antworten: 21
    Letzter Beitrag: 22.10.2007, 00:22
  3. [Frage?] die Delay TIme nicht stimmt mit <util/delay.h>
    Von PaMan im Forum C - Programmierung (GCC u.a.)
    Antworten: 9
    Letzter Beitrag: 03.08.2007, 15:57
  4. Servo dreht ohne Controller ???
    Von michiE im Forum Elektronik
    Antworten: 7
    Letzter Beitrag: 20.06.2005, 14:13
  5. [ERLEDIGT] Servo dreht ohne Impuls
    Von Raimond1 im Forum Motoren
    Antworten: 23
    Letzter Beitrag: 06.05.2005, 15:15

Berechtigungen

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

Labornetzteil AliExpress