- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 7 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 64

Thema: fahrzeug mit vier motoren und vier encodern

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180

    fahrzeug mit vier motoren und encodern

    Anzeige

    E-Bike
    hallo allerseits,

    in den letzten wochen habe ich ein vierrädriges fahrzeug entwickelt
    Klicke auf die Grafik für eine größere Ansicht

Name:	IMG_8750-1.jpg
Hits:	47
Größe:	66,1 KB
ID:	30867
    mit diesen getriebemotoren und encodern, verwendet wird ein arduino mega 2560 R3 und das motorshield L293D V1 von sainsmart (chinesischer clone):
    Klicke auf die Grafik für eine größere Ansicht

Name:	Arduino-Smart-Car-Robot-Plastic-Tire-Wheel-with-DC-motor.jpg
Hits:	32
Größe:	77,2 KB
ID:	30857Klicke auf die Grafik für eine größere Ansicht

Name:	encoder_SKU198452a.jpg
Hits:	32
Größe:	68,8 KB
ID:	30858Klicke auf die Grafik für eine größere Ansicht

Name:	motorshield_l293d.jpg
Hits:	27
Größe:	33,7 KB
ID:	30861

    der code für einen motor:
    Code:
    #include <AFMotor.h>
    
    AF_DCMotor motor_1(1);
    
    #define encoder_1 22
    int wert_1;
    int summe_1;
    int zaehler_1;
    
    void setup() 
    {
      pinMode(encoder_1, INPUT_PULLUP);
    
      Serial.begin(9600);
      Serial1.begin(9600);
    
      wert_1=0;
      summe_1=0;
      zaehler_1=0;
    }
    
    void loop() 
    {
      wert_1=digitalRead(encoder_1);
    
      if (summe_1 <= 19 && zaehler_1 == 0)
      {
        motor_1.setSpeed(120);
        motor_1.run(FORWARD);
        zaehler_1 = 1;
        Serial.print(wert_1);
        Serial.print("    ");
        Serial.println(summe_1);
      }
    
      else if (summe_1 <= 19 && zaehler_1 == 1)
      {
        zaehler_1 = 0;
        summe_1 = (summe_1 + wert_1);
        Serial.print(wert_1);
        Serial.print("    ");
        Serial.println(summe_1);
        motor_1.setSpeed(0);
        motor_1.run(RELEASE);
      }
      
    
    }
    hat auch (über den serialmonitor) durchaus brauchbare ergebnisse gebracht:
    Code:
    1    0 
    1    1 
    1    1 
    1    2 
    1    2 
    1    3 
    1    3 
    1    4 
    1    4 
    1    5 
    1    5 
    1    6 
    1    6 
    0    6 
    0    6 
    0    6 
    0    6 
    0    6 
    0    6 
    0    6 
    0    6 
    1    7 
    1    7 
    0    7 
    0    7 
    0    7 
    0    7 
    1    8 
    1    8 
    0    8 
    0    8 
    0    8 
    1    8 
    0    8 
    0    8 
    0    8 
    1    8 
    0    8 
    0    8 
    0    8 
    1    8 
    0    8 
    0    8 
    1    9 
    0    9 
    0    9 
    0    9 
    1    10 
    0    10 
    0    10 
    0    10 
    0    10 
    1    10 
    0    10 
    0    10 
    1    11 
    0    11 
    1    12 
    0    12 
    0    12 
    0    12 
    0    12 
    1    12 
    0    12 
    1    12 
    0    12 
    0    12 
    0    12 
    0    12 
    0    12 
    0    12 
    1    13 
    0    13 
    1    14 
    0    14 
    1    15 
    0    15 
    1    16 
    0    16 
    1    17 
    0    17 
    1    18 
    0    18 
    1    19 
    0    19 
    0    19 
    0    19 
    0    19 
    0    19 
    0    19 
    1    19 
    0    19 
    1    19 
    0    19 
    0    19 
    0    19 
    0    19 
    1    20
    das rad dreht sich noch nicht genau 1x um 360° beim erreichen der 20 signale vom encoder, dass wäre aber - dachte ich - beherrschbar...


    die erweiterung des codes für vier motoren (im prinzip das erste beispiel vervierfacht):
    Code:
    #include <AFMotor.h>
    
    AF_DCMotor motor_1(1);
    AF_DCMotor motor_2(2);
    AF_DCMotor motor_3(3);
    AF_DCMotor motor_4(4);
    
    #define encoder_1 22
    #define encoder_2 52
    #define encoder_3 53
    #define encoder_4 23
    
    int wert_1;
    int wert_2;
    int wert_3;
    int wert_4;
    
    int summe_1;
    int summe_2;
    int summe_3;
    int summe_4;
    
    int zaehler_1;
    int zaehler_2;
    int zaehler_3;
    int zaehler_4;
    
    void setup() 
    {
      pinMode(encoder_1, INPUT_PULLUP);
      pinMode(encoder_2, INPUT_PULLUP);
      pinMode(encoder_3, INPUT_PULLUP);
      pinMode(encoder_4, INPUT_PULLUP);
    
      Serial.begin(9600);
      Serial1.begin(9600);
    
      wert_1=0;
      wert_2=0;
      wert_3=0;
      wert_4=0;
    
      summe_1;
      summe_2;
      summe_3;
      summe_4;
    
      zaehler_1=0;
      zaehler_2=0;
      zaehler_3=0;
      zaehler_4=0;
    
    }
    
    void loop() 
    {
      wert_1=digitalRead(encoder_1);
      wert_2=digitalRead(encoder_2);
      wert_3=digitalRead(encoder_3);
      wert_4=digitalRead(encoder_4);
      
      
       if (summe_1 <= 9 && zaehler_1 == 0)
      {
        motor_1.setSpeed(150);
        motor_1.run(FORWARD);
        zaehler_1 = 1;
        Serial.print(wert_1);
        Serial.print("    ");
        Serial.println(summe_1);
        Serial1.print(wert_1);
        Serial1.print("    ");
        Serial1.println(summe_1);
      }
    
      else if (summe_1 <= 9 && zaehler_1 == 1)
      {
        zaehler_1 = 0;
        summe_1 = (summe_1 + wert_1);
        Serial.print(wert_1);
        Serial.print("    ");
        Serial.println(summe_1);
        Serial1.print(wert_1);
        Serial1.print("    ");
        Serial1.println(summe_1);
        motor_1.setSpeed(0);
        motor_1.run(RELEASE);
      }
     
        if (summe_2 <= 9 && zaehler_2 == 0)
      {
        motor_2.setSpeed(150);
        motor_2.run(FORWARD);
        zaehler_2 = 1;
        Serial.print(wert_2);
        Serial.print("        ");
        Serial.println(summe_2);
        Serial1.print(wert_2);
        Serial1.print("        ");
        Serial1.println(summe_2);
      }
    
      else if (summe_2 <= 9 && zaehler_2 == 1)
      {
        zaehler_2 = 0;
        summe_2 = (summe_2 + wert_2);
        Serial.print(wert_2);
        Serial.print("        ");
        Serial.println(summe_2);
        Serial1.print(wert_2);
        Serial1.print("        ");
        Serial1.println(summe_2);
        motor_2.setSpeed(0);
        motor_2.run(RELEASE);
      }
     
      if (summe_3 <= 9 && zaehler_3 == 0)
      {
        motor_3.setSpeed(150);
        motor_3.run(FORWARD);
        zaehler_3 = 1;
        Serial.print(wert_3);
        Serial.print("            ");
        Serial.println(summe_3);
        Serial1.print(wert_3);
        Serial1.print("            ");
        Serial1.println(summe_3);
      }
    
      else if (summe_3 <= 9 && zaehler_3 == 1)
      {
        zaehler_3 = 0;
        summe_3 = (summe_3 + wert_3);
        Serial.print(wert_3);
        Serial.print("            ");
        Serial.println(summe_3);
        Serial1.print(wert_3);
        Serial1.print("            ");
        Serial1.println(summe_3);
        motor_3.setSpeed(0);
        motor_3.run(RELEASE);
      }
      
        if (summe_4 <= 9 && zaehler_4 == 0)
      {
        motor_4.setSpeed(150);
        motor_4.run(FORWARD);
        zaehler_4 = 1;
        Serial.print(wert_4);
        Serial.print("                ");
        Serial.println(summe_4);
        Serial1.print(wert_4);
        Serial1.print("                ");
        Serial1.println(summe_4);
      }
    
      else if (summe_4 <= 9 && zaehler_4 == 1)
      {
        zaehler_4 = 0;
        summe_4 = (summe_4 + wert_4);
        Serial.print(wert_4);
        Serial.print("                ");
        Serial.println(summe_4);
        Serial1.print(wert_4);
        Serial1.print("                ");
        Serial1.println(summe_4);
        motor_4.setSpeed(0);
        motor_4.run(RELEASE);
      }
     
    }

    brachte aber ergebnisse, die so nicht bleiben können:
    Code:
    0    0 
    0        0 
    0            0 
    0                0 
    0    0 
    0        0 
    0            0 
    0                0 
    0    0 
    1        0 
    0            0 
    0                0 
    0    0 
    1        1 
    1            1 
    0                0 
    1    0 
    1        1 
    0            1 
    0                0 
    0    0 
    1        2 
    0            1 
    0                0 
    0    0 
    0        2 
    0            1 
    0                0 
    1    1 
    1        3 
    1            2 
    0                0 
    0    1 
    1        3 
    0            2 
    1                0 
    0    1 
    1        4 
    0            2 
    0                0 
    0    1 
    0        4 
    0            2 
    0                0 
    1    2 
    0        4 
    1            3 
    0                0 
    0    2 
    0        4 
    0            3 
    0                0 
    1    3 
    1        5 
    0            3 
    0                0 
    0    3 
    0        5 
    0            3 
    1                0 
    0    3 
    0        5 
    1            4 
    1                1 
    1    3 
    0        5 
    1            4 
    0                1 
    1    4 
    1        6 
    0            4 
    0                1 
    1    4 
    1        6 
    1            4 
    1                1 
    0    4 
    0        6 
    0            4 
    0                1 
    0    4 
    0        6 
    0            4 
    0                1 
    0    4 
    0        6 
    0            4 
    1                2 
    0    4 
    1        6 
    1            4 
    0                2 
    0    4 
    1        7 
    0            4 
    0                2 
    0    4 
    0        7 
    0            4 
    0                2 
    0    4 
    0        7 
    0            4 
    0                2 
    0    4 
    1        7 
    0            4 
    1                2 
    0    4 
    0        7 
    1            5 
    0                2 
    1    4 
    1        7 
    0            5 
    0                2 
    0    4 
    0        7 
    0            5 
    0                2 
    0    4 
    1        7 
    0            5 
    0                2 
    0    4 
    0        7 
    1            6 
    1                3 
    0    4 
    0        7 
    1            6 
    0                3 
    0    4 
    0        7 
    0            6 
    0                3 
    0    4 
    0        7 
    0            6 
    0                3 
    0    4 
    1        8 
    1            7 
    0                3 
    0    4 
    0        8 
    1            7 
    0                3 
    0    4 
    0        8 
    0            7 
    0                3 
    0    4 
    1        8 
    0            7 
    0                3 
    0    4 
    0        8 
    1            8 
    0                3 
    1    4 
    0        8 
    1            8 
    0                3 
    1    5 
    1        9 
    0            8 
    1                4 
    0    5 
    0        9 
    0            8 
    0                4 
    0    5 
    0        9 
    0            8 
    1                5 
    0    5 
    0        9 
    0            8 
    0                5 
    1    6 
    1        10 
    1            9 
    0                5 
    0    6 
    1            9 
    0                5 
    1    7 
    1            10 
    0                5 
    0    7 
    0                5 
    0    7 
    1                6 
    1    7 
    0                6 
    1    8 
    0                6 
    1    8 
    1                6 
    0    8 
    0                6 
    0    8 
    0                6 
    0    8 
    0                6 
    0    8 
    0                6 
    0    8 
    1                7 
    1    8 
    0                7 
    0    8 
    1                8 
    0    8 
    0                8 
    0    8 
    1                9 
    0    8 
    0                9 
    0    8 
    0                9 
    0    8 
    1                9 
    1    9 
    0                9 
    0    9 
    1                9 
    0    9 
    0                9 
    1    9 
    0                9 
    0    9 
    0                9 
    0    9 
    0                9 
    0    9 
    1                10 
    0    9 
    0    9 
    1    9 
    0    9 
    0    9 
    0    9 
    0    9 
    1    10
    die räder laufen unterschiedlich an, bleiben umterschiedlich stehen...

    ich bin sicher, dass das an der struktur des vervierfachten codes liegt, an den einzelnen abfragen des zustandes der vier encoder und der davon abhängigen reaktionen. So kann die struktur also nicht bleiben, ich habe aber absolut keinen plan wie es anders sein könnte?

    Ist der ansatz überhaupt richtig? Geht sowas überhaupt ohne interrupts? Wäre mir schon lieber, weil ich mich damit nicht gut auskenne und denke auch, dass das auslesen von 4 encodern und das gleichzeitige betreiben von vier motoren schon recht unkompliziert(?) ist und mit "normalem" code machbar sein müsste...
    Geändert von inka (15.12.2015 um 12:56 Uhr) Grund: foto hinzu
    gruß inka

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Ich habe ein wenig in deinem Code geschmökert, ohne allzuviel zu verstehen (liegt an meinen fehlenden Kenntnissen).
    Was mir aber auffiel sind einerseits die fehlende explizite Initialisierung der Variablen 'summe_n', andererseits die endlos vielen serial.print-Befehle. Das dauert doch alles "ewig", zumindest im Zeitmaßstab eines Controllers.

    Überschlage mal deine Zykluszeit der Hauptschleife - im Wesentlichen abhängig von Baudrate und Anzahl der übertragenen Zeichen - und schätze ab, ob das Programm bei der auftretenden Raddrehzahl und Encoderteilung überhaupt eine Chance hat, alle Zustände an den Radencodern wahrzunehmen.
    Lass' alle serial.print aus der Schleife weg und dokumentiere lediglich den Zieleinlauf, wenn der erste Encoder bei 10 angekommen ist.

    Wenn der Controller jemals auch noch andere Aufgaben als die Encoderauswertung machen soll - z.B. Übermittlung der Ergebnisse oder gar "höhere" Aufgaben wie eine Regelung oder ein Bedienmenü, dann wirst du kaum um die Verwendung eines Interrupts - Timer oder Pin-Change - herumkommen.

    P.S.: Dass die Motoren - bei einheitlichem PWM-DutyCycle unterschiedlich schnell anlaufen/abbremsen, ist aber ganz normal und abhängig von der Streuung bei den Reibungsverhältnissen der einzelnen Antriebsexemplare, zumal bei derart billig gemachten Komponenten (soll keine Verunglimpfung sein; ich denke, das ist konsensfähig).
    Geändert von RoboHolIC (08.11.2015 um 21:37 Uhr) Grund: Nachtrag zur Reibung

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    55
    Beiträge
    2.208
    Man kann die Zeit eines Durchlaufs auch leicht messen.
    http://forum.arduino.cc/index.php?topic=292794.0
    Sehr hilfreich bei diversen Anwendungen...
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

  4. #4
    HaWe
    Gast
    ein sehr gut funktionierender Code für AVR Arduinos ist dieser hier - er läuft über Timer Interrupts.
    Alles andere über normale loops ist zu langsam!

    Code:
    /************************************************************
    *
    * Demo-Programm zur Auswertung eines händisch betriebenen
    * Drehencoders (Quadraturencoder) mit dem Arduino im
    * Timer-Interrupt mit einer Abfragefrequenz von rd. 1kHz
    *
    * Kann von jederman frei verwendet werden, aber bitte den
    * Hinweis: "Entnommen aus http://www.meinDUINO.de" einfügen
    *
    ************************************************************/
    
    // An die Pins 2 und 3 ist der Encoder angeschlossen
    #define encoderA 2
    #define encoderB 3
    
    // Globale Variablen zur Auswertung in der
    // Interrupt-Service-Routine (ISR)
    volatile int8_t altAB = 0;
    volatile int encoderWert = 0;
    
    // Die beiden Schritt-Tabellen für volle oder 1/4-Auflösung
    // 1/1 Auflösung
    //int8_t schrittTab[16] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
    
    // 1/2 Auflösung ergibt bei Lego-Motoren 1 tick pro Grad (standard wie bei Lego)
    int8_t schrittTab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};
    
    
    // 1/4 Auflösung
    //int8_t schrittTab[16] = {0,0,0,0,0,0,0,-1,0,0,0,0,0,1,0,0};
    
    
    /*************************************************************
    *
    * Interrupt Service Routine
    *
    * Wird aufgerufen, wenn der entsprechende Interrupt
    * ausgelöst wird
    *
    *************************************************************/
    ISR(TIMER1_COMPA_vect) {
      altAB <<= 2;
      altAB &= B00001100;
      altAB |= (digitalRead(encoderA) << 1) | digitalRead(encoderB);
      encoderWert += schrittTab[altAB];
    }
    
    
    /*************************************************************
    *
    * void setup()
    *
    * Wird einmal beim Programmstart ausgeführt
    *
    *************************************************************/
    void setup() {
      pinMode(encoderA, INPUT);
      pinMode(encoderB, INPUT);
     
      noInterrupts(); // Jetzt keine Interrupts
      TIMSK1 |= (1<<OCIE1A);  // Timer 1 Output Compare A Match Interrupt Enable
    
      TCCR1A = 0; // "Normaler" Modus
    
      // WGM12: CTC-Modus einschalten (Clear Timer on Compare match)
      //        Stimmen OCR1A und Timer überein, wird der Interrupt
      //        ausgelöst
      // Bit CS12 und CS10 setzen = Vorteiler: 1024
      TCCR1B = (1<<WGM12) | (1<<CS12) | (1<<CS10);
    
      // Frequenz = 16000000 / 1024 / 15 = rd. 1kHz Abtastfrequenz;
      // Überlauf bei 14, weil die Zählung bei 0 beginnt
      OCR1A = 14;
     
      interrupts(); // Interrupts wieder erlauben
    
      Serial.begin(115200);
    }
    
    
    /*************************************************************
    *
    * void loop()
    *
    * Wird immer wieder durchlaufen
    *
    *************************************************************/
    void loop() {
     
      while(true) {
        Serial.println(encoderWert);
        delay(100);
      }
    }

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    danke für euere antworten...

    @ HaWe,

    den code kenne ich bereits von meinduino, habe aber das problem, dass die encoder keine zwei datenanschlüsse haben, sondern nur einen...

    @ Rabenauge,

    danke für den tipp mit dem millis() - werde ich mir anschauen


    @ RoboHoliC,

    - habe die "summen" mit "=0" versehen - kein einfluss auf den ablauf

    - habe sämtliche printanweisungen entferrnt - geschockt - die räder 3 & 4 zuckten nur kurz, das wars...

    - der controler soll nur der "motorfahrer" sein, es kommt dann noch kommunikation über IIc (wieder nur befehle für den motortreiber) mit dem RP6 - der RP6 soll den rest machen...

    - das unterschiedliche anlaufen und abbremsen kann m.e. nach nicht alleine durch die chinesischen/billigen teile bedingt sein, es variiert um mehrere umdrehungen und wechselt von mal zu mal auch die reihenfolge der räder...
    gruß inka

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Hallo Inka.

    Zitat Zitat von inka Beitrag anzeigen
    - habe die "summen" mit "=0" versehen - kein einfluss auf den ablauf
    Hatte ich auch nicht wirklich erwartet, weil die Zählungen ansich ja ganz vernünftig aussahen.

    Zitat Zitat von inka Beitrag anzeigen
    - habe sämtliche printanweisungen entferrnt - geschockt - die räder 3 & 4 zuckten nur kurz . . . das unterschiedliche anlaufen und abbremsen . . . variiert um mehrere umdrehungen und wechselt von mal zu mal auch die reihenfolge der räder...
    Uiii. da liegt aber noch was ganz im Argen. digitalRead(encoder_n) klingt sehr nach Bibliotheksfunkion. Hast du die Doku dazu studiert? Wechselwirkungen im Einsatz mit anderen Funktionen? Evtl. Überschneidungen bei den Controllerpins?
    'Encoder' klingt für mich auch nach mehreren Spuren für die Richtungserkennung (Quadraturencoder) oder Absolutposition. Passen Sensor und Auswertungscode wirklich zusammen?

    Ich habe mich ein wenig vertieft in deinen Code, habe die Idee dahinter aber noch nicht verstanden (vllt. auch deswegen, weil es mir schwer fällt, mich auf andere Programmiergewohnheiten einzustellen):
    - Steckt da an irgend einer Stelle die Erkennung einer Flanke (dunker --> hell) drin? Zehnmal "hell" gemessen müssen ja keine zehn Zählpulse sein!
    - Sperrzeit nach der Flankenerkennung oder Schmitt-Trigger-Eingang, damit nicht mechanische Vibrationen aus einem Übergang mehrere Pulse machen können.
    - Warum werden die Motoren nicht bestmöglich zeitgleichgestartet? Und ?immer wieder? gestartet - auch wenn das vielleicht nicht schadet.

    Zitat Zitat von inka Beitrag anzeigen
    "motorfahrer" . . . kommunikation über IIc
    Das sind klassisch zwei verschiedene Aufgaben auf einem Controller: Eine zeitkritische, nämlich die Encoderauswertung - und eine zeitUNkritische, nämlich die I2C-Kommunikation.
    Wenn du die beiden pollend in einer gemeinsamen Schleife bearbeitest, mag das zu Anfang funktionieren. Kommt dann mehr und mehr Code hinzu, steigt die Zykluszeit evtl. so weit an (vgl. deine seriellen Ausgaben!), dass der Controller bei der gewählten Drehzahl nicht mehr alle Inputs der Radsensoren mitkriegt. Besser ist es, die Encoderauswertung in einen Interrupt zu packen - dort kann sie mit Vorrang (ggf. in festem Zeitraster) abgearbeitet werden. Die Kommunikation und der ganze Rest darf meist innerhalb gewisser Grenzen mal ein wenig früher oder später in der Schleife passieren, ohne dass gleich das System aus dem Tritt gerät.

    Mut zum Interrupt - das ist meine Devise. Keines meiner Projekte arbeitet ohne.

    Gruß
    Christian.

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    Hi RoboHolIC,

    Zitat Zitat von RoboHolIC Beitrag anzeigen
    Uiii. da liegt aber noch was ganz im Argen. digitalRead(encoder_n) klingt sehr nach Bibliotheksfunkion. Hast du die Doku dazu studiert? Wechselwirkungen im Einsatz mit anderen Funktionen? Evtl. Überschneidungen bei den Controllerpins?
    'Encoder' klingt für mich auch nach mehreren Spuren für die Richtungserkennung (Quadraturencoder) oder Absolutposition. Passen Sensor und Auswertungscode wirklich zusammen?
    also: als encoder wird das teil vom hersteller/lieferanten bezeichnet, hat die anschlüsse Vcc / GND und OUT und ist eher eine lichtschranke mit einer lochscheibe, die 20x pro umdrehung hell und dunkel unterscheidet. Es ist noch eine rote LED und irgendein IC auf der platine, dessen funktion nicht klar ist. Die bibliothek für die motoren ist die von Adafruit, studiert habe ich sie nicht, die befehle aus einem beispiel so übernommen...

    Zitat Zitat von RoboHolIC Beitrag anzeigen
    Ich habe mich ein wenig vertieft in deinen Code, habe die Idee dahinter aber noch nicht verstanden (vllt. auch deswegen, weil es mir schwer fällt, mich auf andere Programmiergewohnheiten einzustellen)
    ich habe hier meinen code (den teil mit dem ersten motor) kommentiert, mir ist durchaus bewusst, dass bei einer 20er teilung und der relativ langsamen drehung des motors mehrere dutzend positive wie negative signale (null oder 1) beim arduino-pin ankommen bevor ein echter wechsel in der hardware passiert, habe also versucht nur das jeweils erste signal zu cashen (zaehler_1) und die abfrage damit zu steuern...

    Code:
    void(loop)
    {
      wert_1=digitalRead(encoder_1); //wert des encoders einlesen und speichern, 0 oder 1, hell oder dunkel
      
      if (summe_1 <= 19 && zaehler_1 == 0) // wenn summe <= "19" UND keine "0-impulse" gezählt
     
      {
        motor_1.setSpeed(150); //geschwindigkeit auf 150 stellen (0 bis 250 möglich)
        motor_1.run(FORWARD); // forwärts fahren
        zaehler_1 = 1; //, zähler der "0-impulse" auf "1" stellen
      }
    
      else if (summe_1 <= 19 && zaehler_1 == 1) // wenn summe < als 19 UND der zähler der "0-impulse" = "1"
      {
        zaehler_1 = 0; // zähler der "0-impulse" wieder auf "0" stellen
        summe_1 = (summe_1 + wert_1); // summe um "1" (den wert des encoders) erhöhen
        motor_1.setSpeed(0); // geschwindigkeit auf "0" stellen
        motor_1.run(RELEASE); // motor freigeben (kein antrieb, kein bremsen)
      }
    }
    vielleicht wird das jetzt klarer, welcher gedanke dahintersteckt, habe aber bereits zweifel angekündigt, ob der ansatz so ok ist - bei einem motor funktioniert es ja halbwegs...

    Zitat Zitat von RoboHolIC Beitrag anzeigen
    - Steckt da an irgend einer Stelle die Erkennung einer Flanke (dunker --> hell) drin? Zehnmal "hell" gemessen müssen ja keine zehn Zählpulse sein!
    - Sperrzeit nach der Flankenerkennung oder Schmitt-Trigger-Eingang, damit nicht mechanische Vibrationen aus einem Übergang mehrere Pulse machen können.
    siehe oben...


    Zitat Zitat von RoboHolIC Beitrag anzeigen
    - Warum werden die Motoren nicht bestmöglich zeitgleichgestartet? Und ?immer wieder? gestartet - auch wenn das vielleicht nicht schadet.
    Du meinst bei allen motoren im setup die geschwindigkeit festlegen und auch dort nacheinader starten? Oder teilen: geschwindigkeit im setup, start alle kurz hintereinander im loop? Ich hatte angst, dass die dann schon zu weit/zu lange drehen bis die abfrage nach dem signal kommt, ist aber wohl unbegründet...Muss ich probieren...

    Zitat Zitat von RoboHolIC Beitrag anzeigen
    Das sind klassisch zwei verschiedene Aufgaben auf einem Controller: Eine zeitkritische, nämlich die Encoderauswertung - und eine zeitUNkritische, nämlich die I2C-Kommunikation.
    Wenn du die beiden pollend in einer gemeinsamen Schleife bearbeitest, mag das zu Anfang funktionieren. Kommt dann mehr und mehr Code hinzu, steigt die Zykluszeit evtl. so weit an (vgl. deine seriellen Ausgaben!), dass der Controller bei der gewählten Drehzahl nicht mehr alle Inputs der Radsensoren mitkriegt. Besser ist es, die Encoderauswertung in einen Interrupt zu packen - dort kann sie mit Vorrang (ggf. in festem Zeitraster) abgearbeitet werden. Die Kommunikation und der ganze Rest darf meist innerhalb gewisser Grenzen mal ein wenig früher oder später in der Schleife passieren, ohne dass gleich das System aus dem Tritt gerät.
    ich möchte erstmal den zeitkritischen teil bearbeiten, das mit dem IIc ist noch weit, weit weg

    Zitat Zitat von RoboHolIC Beitrag anzeigen
    Mut zum Interrupt - das ist meine Devise. Keines meiner Projekte arbeitet ohne.
    Du hast gut reden. Aber auch recht...
    gruß inka

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Hallo inka.

    Ich sehe da keine Flankenerkennung. Die IF-Anweisungen enthalten keinerlei Abhängigkeit vom Encodersignal. Stattdessen wird zaehler_1 im ersten IF auf 1 erhöht, erfüllt damit die Teil-Bedingung zaehler_1 ==1 im zweiten IF, wo dieselbe Variable sofort wieder auf Null gesetzt und der eigentliche Counter summe_1 erhöht wird.
    Das bedeutet doch, dass in den ersten 19 Durchläufen die Bedingungen immer erfüllt sind und der rein zufällige Zustand des Encoders zu summe addiert wird. Das ist vielleicht ganz lustig, zählt aber keine Flanken, obwohl die Summe früher oder später 19 überschreitet. Das passiert nämlich selbst dann, wenn das Rad im Encoderzustand 1 (oder eben "H") blockiert.

    Flanken erkennt man z.B., indem man pro Durchlauf den Input der vorherigen Runde mit dem aktuellen vergleicht, ggf. den Zähler erhöht (oder ein Flag setzt) und anschließend den aktuellen Input als "neuen alten" Vergleichswert für die nächste Runde speichert.

    Warum in aller Welt die ständige Umschaltung zwischen Antrieb und Leerlauf? Das Teil soll doch fahren und nicht parken.

    Und wo fährt wohl ein Rollstuhlfahrer hin, wenn er aus der Ruhe zunächst nur mit der Linken antreibt, mit der Rechten aber erst noch ein wenig UARTelefoniert, bevor er dann doch auch diese zum Vortrieb verwendet? Sicher übertrieben skizziert, könnte aber zur Erhellung beitragen.


    Gruß
    Christian.

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    Hi Rabenauge,

    bevor ich mich mit den motoren und den encodern weiter beschäftige, wollte ich die zyklusmessung anschauen/ausprobieren,

    dort ist folgender code aufgeführt:
    Code:
    /*********************************************************************************
    ** LoopTiming() v06 by GuntherB & Doc_Arduino @ german Arduino Forum            **
    **********************************************************************************
    ** Funktion um die Dauer der Loop-Zeiten zu ermitteln                **
    ** wird in der Loop am Anfang und Ende aufgerufen                **
    ** benötigt ca (AL * 4 + 16) Byte RAM                        **
    *********************************************************************************/
    
    void LoopTiming()
    {
      const int AL = 100;        // Arraylänge, NUR GERADE Zahlen verwenden!
      static unsigned long LoopTime[AL];
      static unsigned int Index=0, Messung=0, Min=0xFFFF, Max, Avg;
      
      if (Messung % 2 == 0)     // wenn Messung X gerade (0,2,4,6 usw.), entspricht immer Anfang der Loop
        {
         LoopTime[Index] = millis();
         Messung++;
         Index++;    
         return;                // Funktion sofort beenden, spart bestimmt Zeit
        }
    
      if (Messung % 2 == 1)     // wenn Messung X ungerade (1,3,5,7 usw.), entspricht immer Ende der Loop
        {
         LoopTime[Index] = millis();
         LoopTime[Index-1] = LoopTime[Index] - LoopTime[Index-1];      // Loopdauer einen Index niedriger einspeichern wie aktuell
         Messung++;
        }    
            
      if (Index >= AL)     // Array voll, Daten auswerten
        {  
         for (int i = 0; i<AL; i++)
           {
            Min = min(Min, LoopTime[i]);
            Max = max(Max, LoopTime[i]);
            Avg += LoopTime[i];
           }
        
         Avg = Avg / AL;
         SERIAL_IMPL.print(F("Minimal       "));SERIAL_IMPL.print(Min);SERIAL_IMPL.println(" ms");
         SERIAL_IMPL.print(F("Durchschnitt  "));SERIAL_IMPL.print(Avg);SERIAL_IMPL.println(" ms");
         SERIAL_IMPL.print(F("Maximal       "));SERIAL_IMPL.print(Max);SERIAL_IMPL.println(" ms");
         Min = 0xFFFF;
         Max = 0;
         Avg = 0;
         Messung = 0;
         Index = 0;
        }
    }
    um den jetzt zum messen aufrufen zu können, muss ich den ja am ende meines programm als funktion einfügen und am anfang und am ende meines "loops" aufrufen. Beim kompilieren kommt dann aber:

    LoopTiming.ino:54:6: error: ‘SERIAL_IMPL’ was not declared in this scope
    wie deklariere ich denn das? Oder muss ich irgendwelche besondere lib einbinden? Darüber steht in dem thread leider nichts drinn...

    danke...
    gruß inka

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    Hallo inka,

    diese SERIAL_IMPL ist eine andere Implemetierung von Serial.

    Du kann die Zeilen
    Code:
     SERIAL_IMPL.print(F("Minimal       "));SERIAL_IMPL.print(Min);SERIAL_IMPL.println(" ms");
     SERIAL_IMPL.print(F("Durchschnitt  "));SERIAL_IMPL.print(Avg);SERIAL_IMPL.println(" ms");
     SERIAL_IMPL.print(F("Maximal       "));SERIAL_IMPL.print(Max);SERIAL_IMPL.println(" ms");
    nach
    Code:
    Serial.print("Minimal       ");Serial.print(Min);Serial.println(" ms");
    Serial.print("Durchschnitt  ");Serial.print(Avg);Serial.println(" ms");
    Serial.print("Maximal       ");Serial.print(Max);Serial.println(" ms");
    ersetzen, dann sollte es funktionieren.

    Nachtrag: Noch eine Frage: sind die Pins 18-21 schon an deinem Board belegt bzw. kannst Du die Encoder auf diese Pins legen? Dann wäre das interruptgesteuerte Zählen der Ticks nicht so schwierig zu implementieren.


    Gruß
    Chris
    Geändert von botty (11.11.2015 um 17:09 Uhr)

Seite 1 von 7 123 ... LetzteLetzte

Ähnliche Themen

  1. Vier PWM-Lüfter steuern
    Von Bammer im Forum AVR Hardwarethemen
    Antworten: 22
    Letzter Beitrag: 22.10.2010, 11:21
  2. Vier Servos steuern
    Von Brantiko im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 10
    Letzter Beitrag: 15.04.2008, 00:17
  3. Wie vier Motoren ansteuern???
    Von cinhcet im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 9
    Letzter Beitrag: 29.06.2006, 13:37
  4. vier L297 und VREF
    Von schmek im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 01.12.2005, 20:47
  5. Bot mit vier Rädern
    Von themaddin im Forum Mechanik
    Antworten: 17
    Letzter Beitrag: 06.11.2005, 22:39

Berechtigungen

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

LiFePO4 Speicher Test