- 3D-Druck Einstieg und Tipps         
Seite 6 von 7 ErsteErste ... 4567 LetzteLetzte
Ergebnis 51 bis 60 von 64

Thema: fahrzeug mit vier motoren und vier encodern

  1. #51
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    56
    Beiträge
    2.210
    Anzeige

    Praxistest und DIY Projekte
    Du kannst deine If()'s ja mal debuggen: schreib einfach in jedes if() ne spezielle Ausgabe und lass dir die auf die Konsole geben. Ggf. zusammen mit nen paar Variablen. Dann siehst du ja, wo er eventuell hängen bleibt.
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

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

    mir fallen mehrere Sachen in Deinen Beispielen auf.
    Erstmal konkurieren die "run()" Aufrufe damit die Motoren laufen mit Deinen Aufrufen für die Sensormessungen.
    Egal welche Variante der Sensormessungen die Du uns gezeigt hast, beide blockieren den Rest des Systems während der Messung, weil Du auf das Ergebnis wartest. Und nicht nur das, Du hast die Sache noch verschärft, da in den Funktionen "delay(500)" drin steht. Sprich jedes Mal wenn Du die Messfunktion aufrufst vergehen 1/2sec plus der Zeit für die Messung. Deine Stepper könnten also gerade mal einen Step/sec machen.
    Sicher nicht was Du willst. Die Messfunktion muss also so geschrieben sein, daß sie nicht blockiert. Die NewPing-Lib kann das s.u.

    Die andere Sache, womit der Code klarer werden würde, ist die Verwendung von zwei Schleifen in der Loop-Funktion. Die äußere Schleife sorgt für den Fortschritt Deiner Fahrkommandos und die innere Schleife führt sie aus. In Pseudocode sähe das in etwa so aus (hab's nicht durch den Compiler gejagt!):

    Code:
    void loop() {
      while(1) {
         // Kommando auswählen
         // Motoren konfigurieren z.B.
         geradeaus_unendlich();
    
         do {
           // Fortschritt der Motoren
           stepper_VL.run();
           stepper_HL.run();
           stepper_HR.run();
           stepper_VR.run();
    
          // Bis die Aufgabe erledigt ist
         } while ( ! (stepper_VL.isDone() && stepper_HL.isDone() && stepper_VR.isDone() && stepper_HR.isDone()) );
      }
    
    }
    wie immer Du die Auswahl der Fahrkommandos organisierst, hast Du so eine klare Trennung zwischen Auswahl und Ausführung!

    Jetzt weiß ich nicht was Dein Roboter alles können soll. Ich nehme hier mal an er soll immer geradeaus fahren und wenn ein Hinderniss erkannt wird nach Rechts drehen. Beim Drehen soll er den Sensor ignorieren. Dann erweitert sich das Bsp. so:
    Code:
    void loop() {
      bool sensor_benutzen = true;
    
      while(1) {
         // Kommando auswählen
         // Motoren konfigurieren z.B.
         geradeaus_unendlich();
    
         sensor_benutzen = true;
    
         do {
            if(sensor_benutzen && hindernis_vorh()) {
                motoren_stop();
                drehen_rechts(); // Konfiguriert die Motoren um und wird so lange
                                       // ausgeführt bis die innere Schleife abbricht.
                sensor_benutzen = false;
            }
    
           // Fortschritt der Motoren
           stepper_VL.run();
           stepper_HL.run();
           stepper_HR.run();
           stepper_VR.run();
    
          // Bis die Aufgabe erledigt ist
         } while ( ! (stepper_VL.isDone() && stepper_HL.isDone() && stepper_VR.isDone() && stepper_HR.isDone()) );
      }
    }
    Die NewPing-Lib stellt Dir die Funktion "ping()" zur Verfügung, leider blockiert die das System, kommt also nicht in Frage.
    Statt dessen müssen wir "ping_timer()" und "check_timer()" benutzen.
    "hindernis_vorh()" soll uns immer den letzten gültigen Wert liefern und dafür sorgen, daß der Sensor immer wieder neu mißt.
    Also gibt uns die Funktion einen bool zurück:
    Code:
    bool hindernis_vorh() {
    }
    wir müssen uns merken ob der Sensor läuft "sensor_misst" und was das letzte Ergebnis war "erg_vorher", beide sollen nur lokal sichtbar sein. Ausserdem sollen die Werte erhalten bleiben, sprich die Variablen dürfen nicht auf dem Stack liegen sondern müssen ins Datensegment. Dafür gibt's "static".
    Dann brauchen wir eine Dummy Funktion,weil "ping_timer()" 'nen Funktionspointer als Argument haben will.
    Das Ganze sollte dann so aussehen (nicht durch den Compiler gejagt!):
    Code:
    void sonarDummyFunc() { return; }
    
    bool hindernis_vorh() {
       static bool sensor_misst = false; // Beim Prg Start läuft der Sensor noch nicht 
       static bool erg_vorher = false; // Beim Start noch keine Messung vorhanden
    
       if(sensor_misst) {
          if(sonar.check_timer()) {
             erg_vorher = (sonar.ping_result / US_ROUNDTRIP_CM) < 4; // Oder welche Entfernung auch immer
             sensor_misst = false;
          }
       } else {
         sonar.timer_stop();
         sonar.ping_timer(sonarDummyFunc);
         sensor_misst = true;
       }
    
       return erg_vorher;
    }
    jetzt läßt sich "hindernis_vorh()" immer wieder aufrufen und startet den Sensor immer wieder neu und liefert das letzte Ergebnis zurück.

    Ein anderes Beispiel findest Du sonst noch https://bitbucket.org/teckel12/ardui...ping/wiki/Home in der Mitte ist ein Beispiel das den Callback-Mechanismus benutzt aber eine globale Variable verwendet,wovon ich kein Freund bin.

    Hoffe die Ideen bringen Dich ein bischen weiter.

    Gruß

    Chris
    Geändert von botty (28.12.2015 um 16:30 Uhr)

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

    solltest Du momentan diese Variante
    Code:
    void alle_stepper_vorwaerts()
    {
    
    
      hindernis_vorh();
      if (hindernis == true)
      {
         Serial.print("hindernisabfrage in - alle_stepper_vorwärts -");
         alle_stepper_rueckwaerts();
      }
      // !!! Im Fall das hinderniss == false ist führt das zu einer Rekursion ohne Widerkehr !!!
      else alle_stepper_vorwaerts();
    
    
      
      vorwaerts = true;
      stepper_VL.setRPM(12);
      stepper_HL.setRPM(12);
      stepper_HR.setRPM(12);
      stepper_VR.setRPM(12);
    
    
      stepper_VL.setSPR(4075.7728395);
      stepper_HL.setSPR(4075.7728395);
      stepper_HR.setSPR(4075.7728395);
      stepper_VR.setSPR(4075.7728395);
    
    
      stepper_VL.setDirection(CW);
      stepper_VL.rotate(1);
      stepper_HL.setDirection(CW);
      stepper_HL.rotate(1);
      stepper_HR.setDirection(CW);
      stepper_HR.rotate(1);
      stepper_VR.setDirection(CW);
      stepper_VR.rotate(1);
      //vorwaerts = true;
    }
    
    
    void alle_stepper_rueckwaerts()
    {
      Serial.print("fahre rückwärts nach hindernisabfrage in - alle_stepper_vorwärts -");
      rueckwaerts = true;
      stepper_VL.setRPM(12);
      stepper_HL.setRPM(12);
      stepper_HR.setRPM(12);
      stepper_VR.setRPM(12);
    
    
      stepper_VL.setSPR(4075.7728395);
      stepper_HL.setSPR(4075.7728395);
      stepper_HR.setSPR(4075.7728395);
      stepper_VR.setSPR(4075.7728395);
    
    
      stepper_VL.setDirection(CCW);
      stepper_VL.rotate(1);
      stepper_HL.setDirection(CCW);
      stepper_HL.rotate(1);
      stepper_HR.setDirection(CCW);
      stepper_HR.rotate(1);
      stepper_VR.setDirection(CCW);
      stepper_VR.rotate(1);
      //rueckwaerts = true;
    }
    im Einsatz haben, landest Du für den Fall das kein Hindernis erkannt wird in einer endlos Rekursion. Dein Program hängt sich schlicht auf und ich vermute das System rebootet immer wieder. Prüfen könntest Du das, wenn Du in die setup-Funktion am Ende mal ein "Serial.println("setup ende")" oder so schreiben würdest. Das sollte dann mehrfach in der Console zwischen den "Ping: xxx cm" erscheinen.

    Falls Du noch die NewPing lib benutzt gibt es bei "ping()" einen Sonderfall zu berücksichtigen:
    Wenn der US-Sensor ins Unendliche zeigt, liefert die Funktion eine Null zurück. In Deiner Funktion:
    Code:
    void hindernis_vorh(void)
    {
      if (start_ping == false) ping_distanz();
    
    
      if (((uS / US_ROUNDTRIP_CM) <= 10))
        hindernis = true;
    }
    kann "hindernis" also auch "true" sein. Daher muß eine weitere Abfrage da hinein:
    Code:
    void hindernis_vorh(void)
    {
      if (start_ping == false) ping_distanz();
    
    
      if(uS > 0) {
        if (((uS / US_ROUNDTRIP_CM) <= 10))
          hindernis = true;
      } else {
          hindernis = false;
      }
    }
    meine Funktion funktionert so leider auch nicht. Weil mir "check_timer()" bei einem Blick hinter die Sensorreichweite keine Info darüber gibt, dass ein Time-Out stattgefunden hat. Muss man sich also selbst merken.
    Code:
    void sonarDummyFunc() { return; }
    
    bool hindernis_vorh() {
       static bool sensor_misst = false; // Beim Prg Start läuft der Sensor noch nicht 
       static bool erg_vorher = false; // Beim Start noch keine Messung vorhanden
       static unsigned long start_zpkt = 0; // Fuer's timeout
    
       if(sensor_misst) {
          if(sonar.check_timer()) {
             erg_vorher = (sonar.ping_result / US_ROUNDTRIP_CM) <= 10; // Oder welche Entfernung auch immer
             sensor_misst = false;
          } else if( (start_zpkt - millis()) >= 50 ) { // Falls Distanz hinter Sensorreichweite,
                                                                 // nach 50ms erneut messen ermöglichen.
             erg_vorher = false;
             sensor_misst = false;
          }
       } else {
         sonar.timer_stop();
         sonar.ping_timer(sonarDummyFunc);
         sensor_misst = true;
         start_zpkt = millis();
       }
    
       return erg_vorher;
    }
    Gruß

    Chris

  4. #54
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    hallo botty,
    Zitat Zitat von botty Beitrag anzeigen
    solltest Du momentan diese Variante
    Code:
    void alle_stepper_vorwaerts()
    {
    
    
      hindernis_vorh();
      if (hindernis == true)
      {
         Serial.print("hindernisabfrage in - alle_stepper_vorwärts -");
         alle_stepper_rueckwaerts();
      }
      // !!! Im Fall das hinderniss == false ist führt das zu einer Rekursion ohne Widerkehr !!!
      else alle_stepper_vorwaerts();
    
    
      
      vorwaerts = true;
      stepper_VL.setRPM(12);
      stepper_HL.setRPM(12);
      stepper_HR.setRPM(12);
      stepper_VR.setRPM(12);
    
    
      stepper_VL.setSPR(4075.7728395);
      stepper_HL.setSPR(4075.7728395);
      stepper_HR.setSPR(4075.7728395);
      stepper_VR.setSPR(4075.7728395);
    
    
      stepper_VL.setDirection(CW);
      stepper_VL.rotate(1);
      stepper_HL.setDirection(CW);
      stepper_HL.rotate(1);
      stepper_HR.setDirection(CW);
      stepper_HR.rotate(1);
      stepper_VR.setDirection(CW);
      stepper_VR.rotate(1);
      //vorwaerts = true;
    }
    
    
    void alle_stepper_rueckwaerts()
    {
      Serial.print("fahre rückwärts nach hindernisabfrage in - alle_stepper_vorwärts -");
      rueckwaerts = true;
      stepper_VL.setRPM(12);
      stepper_HL.setRPM(12);
      stepper_HR.setRPM(12);
      stepper_VR.setRPM(12);
    
    
      stepper_VL.setSPR(4075.7728395);
      stepper_HL.setSPR(4075.7728395);
      stepper_HR.setSPR(4075.7728395);
      stepper_VR.setSPR(4075.7728395);
    
    
      stepper_VL.setDirection(CCW);
      stepper_VL.rotate(1);
      stepper_HL.setDirection(CCW);
      stepper_HL.rotate(1);
      stepper_HR.setDirection(CCW);
      stepper_HR.rotate(1);
      stepper_VR.setDirection(CCW);
      stepper_VR.rotate(1);
      //rueckwaerts = true;
    }
    im Einsatz haben,
    nein habe ich nicht...

    Zitat Zitat von botty Beitrag anzeigen
    Falls Du noch die NewPing lib benutzt gibt es bei "ping()" einen Sonderfall zu berücksichtigen:

    ........Daher muß eine weitere Abfrage da hinein:
    Code:
    void hindernis_vorh(void)
    {
      if (start_ping == false) ping_distanz();
    
    
      if(uS > 0) 
    {
        if (((uS / US_ROUNDTRIP_CM) <= 10))
          hindernis = true;
      } else {
          hindernis = false;
      }
    }
    habe ich berücksichtigt, danke für den tipp...

    - - - Aktualisiert - - -

    hi botty,

    ich habe jetzt eine einigermassen funktionierende version in der ich ein paar sachen die Du hier erwähnst auch schon drin habe:

    - das delay(500) im ping distanz habe ich entfernt, geht auch ohne
    - die schleife do - while bei dem run() der Stepper habe ich eingefügt, meine aber das wäre doppelt gemoppelt hier, oder?

    der roboter:
    - prüft erstmal ob vor ihm ein hindernis ist
    - fährt entsprechend nach vorne, oder zurück
    - nach vorne arbeitet er die (zunächstmal vorgegeben kommandor links, rechts usw) ab
    - nach hindernis wird immer nur im voraus geprüft, ausgewichen nach links (warum auch immer)

    hier der code (habe auch einen ohne "enum, idx" und was sonst noch zu der elegenteren lösung gehört "

    Code:
    #include <CustomStepper.h>
    #include <NewPing.h>
    
    
    #define TRIGGER_PIN  8  // Arduino pin tied to trigger pin on the ultrasonic sensor. //12
    #define ECHO_PIN     7  // Arduino pin tied to echo pin on the ultrasonic sensor. //11
    #define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
    
    
    NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
    
    
    uint8_t idx;
    uint16_t distanz;
    uint16_t uS;
    //uint8_t hindernis, start_ping;
    
    
    
    
    enum stepper_e
    { stepper_VL, stepper_HL, stepper_VR, stepper_HR, stepper_MAX };
    
    
    
    
    CustomStepper stepper[stepper_MAX]
    {
      CustomStepper(23, 25, 27, 29),
      CustomStepper(31, 33, 35, 37),
      CustomStepper(47, 49, 51, 53),
      CustomStepper(46, 48, 50, 52)
    };
    
    
    
    
    boolean rotate_li;
    boolean rotate_deg_li;
    boolean rotate_re;
    boolean rotate_deg_re;
    boolean vorwaerts;
    boolean rueckwaerts;
    boolean start_ping;
    boolean hindernis;
    boolean stepper_stop;
    
    
    void setup()
    {
    
    
      rotate_li = false;
      rotate_deg_li = false;
      rotate_re = false;
      rotate_deg_re = false;
      vorwaerts = false;
      rueckwaerts = false;
      start_ping = false;
      hindernis = false;
      stepper_stop = false;
    
    
      Serial.begin(115200);
      Serial.println("setup_ende");
    }
    
    
    void loop()
    {
    
    
      hindernis_vorh();
      /****************************************/
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        if (stepper[idx].isDone() &&  rueckwaerts == false && hindernis == true)
        {
          Serial.println("start - Stepper rückwärts- if-abfrage_1");
          alle_stepper_rueckwaerts();
    
    
        }
        else if (stepper[idx].isDone() &&  vorwaerts == false && hindernis == false)
        {
          Serial.println("start - Stepper vorwärts- else-abfrage_1");
          alle_stepper_vorwaerts();
    
    
        }
      }
      /*************************************/
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        if (stepper[idx].isDone() &&  rueckwaerts == true && rotate_li == false)
        {
          Serial.println("loop - rotiere_links - if-abfrage_2");
          rotieren_links();
        }
      }
    
    
    
    
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        if (stepper[idx].isDone() &&  rotate_li == true && vorwaerts == false)
        {
          Serial.println("loop - alle_stepper_vorwärts - if-abfrage_3");
          alle_stepper_vorwaerts();
        }
      }
    
    
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        if (stepper[idx].isDone() &&  vorwaerts == true && rotate_re == false)
        {
          Serial.println("loop - rotiere_rechts - if-abfrage_4");
          rotieren_rechts();
        }
    
    
      }
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        if (stepper[idx].isDone() &&  rotate_re == true && vorwaerts == true)
        {
          Serial.println("loop - alle_stepper_vorwärts - if-abfrage_5");
          alle_stepper_vorwaerts();
        }
      }
    
    
      /*****************************************/
      do
      {
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          stepper[idx].run();
        }
      } while ( ! (stepper[idx].isDone()));
    }
    
    
    /***********************************************************/
    
    
    
    
    void ping_distanz(void)
    {
      //delay(500);// Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
      uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
      Serial.print("Ping: ");
      Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
      Serial.println(" cm");
      start_ping = true;
    }
    
    
    
    
    void hindernis_vorh(void)
    {
      if (start_ping == false) ping_distanz();
      if (uS > 0)
      {
        if (((uS / US_ROUNDTRIP_CM) <= 10))
          hindernis = true;
      } else
      {
        hindernis = false;
      }
    }
    void alle_stepper_stop()
    {
      stepper_stop = true;
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(0);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(STOP);
      }
    }
    
    
    
    
    void alle_stepper_vorwaerts(void)
    {
      if (start_ping == true) ping_distanz();
      //Serial.print(hindernis);
      if (hindernis == true)
      {
        rueckwaerts = true;
    
    
        Serial.print(hindernis);
        Serial.println("  hindernis - true - alle_stepper_rückwärts - if-abfrage_6");
        hindernis = false;
        //alle_stepper_rueckwaerts();
    
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          stepper[idx].setRPM(12);
          stepper[idx].setSPR(4075.7728395);
          stepper[idx].setDirection(CCW);
          stepper[idx].rotate(1);
        }
    
    
      }
      else
      {
        vorwaerts = true;
    
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          stepper[idx].setRPM(12);
          stepper[idx].setSPR(4075.7728395);
          stepper[idx].setDirection(CW);
          stepper[idx].rotate(1);
        }
      }
    }
    
    
    
    
    
    
    void alle_stepper_rueckwaerts(void)
    {
      rueckwaerts = true;
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CCW);
        stepper[idx].rotate(1);
      }
    }
    
    
    
    
    void rotieren_links(void)
    {
      rotate_li = true;
    
    
      for (idx = stepper_VL; idx < stepper_VR; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CCW);
        stepper[idx].rotate(1);
      }
    
    
      for (idx = stepper_VR; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CW);
        stepper[idx].rotate(1);
      }
    }
    
    
    
    
    void rotieren_rechts(void)
    {
    
    
      rotate_re = true;
    
    
      for (idx = stepper_VL; idx < stepper_VR; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CW);
        stepper[idx].rotate(1);
      }
    
    
      for (idx = stepper_VR; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CCW);
        stepper[idx].rotate(1);
      }
    }
    Zitat Zitat von botty Beitrag anzeigen
    Die NewPing-Lib stellt Dir die Funktion "ping()" zur Verfügung, leider blockiert die das System, kommt also nicht in Frage.
    Statt dessen müssen wir "ping_timer()" und "check_timer()" benutzen.
    hier stellt sich mir die frage warum ist es ein problem, wenn - hier sogar beide wesentlichen funktionen - ping() und run() der Stepper blockierend sind? Der roboter fährt, sogar recht zügig, misst zwischendurch und weicht auch hindernissen aus, wo ist das problem? Kannst Du es mir bitte erklären?
    In einem würde ich Dir recht geben: Der roboter fährt nach der messung seine strecke die er vorgegeben bekommen hat noch ab, bleibt also noch der fsetstellung - da vorne ist ein hindernis - nicht sofort stehen. Das kann man aber über die gemessene entfernung lösen, oder?


    Zitat Zitat von botty Beitrag anzeigen
    Ein anderes Beispiel findest Du sonst noch https://bitbucket.org/teckel12/ardui...ping/wiki/Home in der Mitte ist ein Beispiel das den Callback-Mechanismus benutzt aber eine globale Variable verwendet,wovon ich kein Freund bin.
    das muss ich noch lesen...
    gruß inka

  5. #55
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    Grüß Dich inka,

    ich fange mal Hinten an.

    "ping()" würde "run()" blockieren, nicht umgekehrt. die "run()" Funktionen müssen nachdem die Stepper konfiguriert sind immer wieder aufgerufen werden und das so schnell wie möglich, sonst hakt es.

    Sowie Du Dein Programm aufgebaut hast, gibt's zwei kritische Dinge zu beachten:
    Nachdem Du "gepingt" hast, fährst Du los. Wenn jetzt plötzlich etwas vor dem Roboter auftaucht - Eure Katze, Deine Füße oder die Schienbeine Deiner Liebsten - bekommt das das System nicht mit, sondern fährt einfach weiter - schlimmstenfalls "Aua" .
    Das andere Problem hast Du schon richtig erkannt, die gemessene Distanz vom Sensor muss größer sein als der Fahrweg.
    Du legst im Moment bei gerade Fahren immer eine Umdrehung zwischen den "pings" zurück. Dein Grenzwert zum potentiellen Hinderniss sind aktuell 10cm. Das ist zu wenig, denn ich schätze Dein Raddurchmesser wird größer als 10cm/pi sein, oder?
    Rechne mal nach Raddurchmesser * pi - dann muss "hindernis_vorh()" so aussehen:
    Code:
    {
      if (start_ping == false) ping_distanz();
    
    
      if(uS != NO_ECHO) 
    {
        /* richtige Werte einsetzen */
        if (((uS / US_ROUNDTRIP_CM) <= (Raddurchmesser * M_PI))
          hindernis = true;
      } else {
          hindernis = false;
      }
    }
    eine weitere Möglichkeit wäre statt "rotate(1)" "rotateDegrees(180)" oder mit anderen Werten kleinere Schritte zu machen. Das könnte dann zum Stottern führen. Momentan, vermute ich, bewegt die Trägheit den Robbi während des "pings" weiter, so das man das mit bloßem Auge nicht wahr nimmt. Einfach mal kleinere Werte mit "rotateDegrees()" ausprobieren.

    Zum Thema "do{...}while()" und "doppelt gemoppelt":
    Deine "loop()" sah auszugsweise so aus:
    Code:
    void loop() {
    
        if (stepper[idx].isDone() &&  rueckwaerts == false && hindernis == true)
        {
          Serial.println("start - Stepper rückwärts- if-abfrage_1");
          alle_stepper_rueckwaerts();
    
    
        }
        else if (stepper[idx].isDone() &&  vorwaerts == false && hindernis == false)
        {
          Serial.println("start - Stepper vorwärts- else-abfrage_1");
          alle_stepper_vorwaerts();
    
    
        }
    
    // andere if's
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          stepper[idx].run();
        }
     }
    Du testes zwangsweise am Anfang immer ab, ob die Stepper schon das letzte Kommando ausgeführt haben oder nicht.
    Dadurch mischt Du inhaltlich "Sind die Stepper fertig?" mit "Wie wähle ich das nächste Kommando aus?".
    Führst Du jetzt die innere Schleife ein egal ob "while(){}" oder "do{...}while()":
    Code:
    void loop() {
    
        // Kommando Auswahl treffen
        if (rueckwaerts == false && hindernis == true)
        {
          Serial.println("start - Stepper rückwärts- if-abfrage_1");
          alle_stepper_rueckwaerts();
    
    
        }
        else if (vorwaerts == false && hindernis == false)
        {
          Serial.println("start - Stepper vorwärts- else-abfrage_1");
          alle_stepper_vorwaerts();
    
    
        }
    
    // andere if's
    
        // Stepper ausführen lassen
        // Es muessen alle Stepper gleichzeitig getestet werden, sonst ist's falsch!
        while( ! (stepper[stepper_VL].isDone() && stepper[stepper_HL].isDone() 
                    && stepper[stepper_VR].isDone() && stepper[stepper_HR].isDone() ) )
        {
           for (idx = stepper_VL; idx < stepper_MAX; idx++)
          {
            stepper[idx].run();
          }
        }
     }
    dann ist nach der inneren Schleife und vor dem nächsten "loop()" Ablauf absolut sicher, dass die Stepper ihre angewiesene Arbeit getan haben.
    Dadurch reduzieren sich Deine "if()" Ausdrücke, die sich nur noch mit der Auswahl beschäftigen und sind meiner Meinung nach einfacher lesbar.
    Das Konzept der CustomStepper-Lib basiert darauf 1) die Stepper zu konfigurieren was sie tun sollen "rotate()", "setDirection()" etc. und dann 2) sie solange mit "run()" in Schwung zu halten, bis "isDone()" wahr wird. Genau das spiegelt sich in letzterem Aufbau wieder.
    Ich hoffe ich hab's verständlich erklärt?

    Gruß

    Chris

  6. #56
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    ein gutes neues jahr 2016 allen,

    hallo botty,

    Deinen erklärungen konnte ich folgen, danke...

    irgendwie funktioniert bei mir die erkennung ob die Stepper mit der vorgesehen einen drehung fertig sind aber nicht und ich finde keinen unterschied zu Deinen codebeispielen in meinem loop:

    Code:
    void loop()
    {
        hindernis_vorh();
        /****************************************/
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (rueckwaerts == false && hindernis == true)
          {
            Serial.println("start - Stepper rückwärts- if-abfrage_1");
            alle_stepper_rueckwaerts();
    
          }
          else if (vorwaerts == false && hindernis == false)
          {
            Serial.println("start - Stepper vorwärts- else-abfrage_1");
            alle_stepper_vorwaerts();
    
          }
        }
        /*************************************/
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
    if (rueckwaerts == false && rotate_li == false)
          {
            Serial.println("loop - rotiere_links - if-abfrage_2");
            rotieren_links();
          }
        }
    
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (rotate_li == true && vorwaerts == false)
          {
            Serial.println("loop - alle_stepper_vorwärts - if-abfrage_3");
            alle_stepper_vorwaerts();
          }
        }
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (vorwaerts == true && rotate_re == false)
          {
            Serial.println("loop - rotiere_rechts - if-abfrage_4");
            rotieren_rechts();
          }
        }
    
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (rotate_re == true && vorwaerts == true)
          {
            Serial.println("loop - alle_stepper_vorwärts - if-abfrage_5");
            alle_stepper_vorwaerts();
          }
        }
      /*****************************************/
    
    
      while ( ! (stepper[stepper_VL].isDone() && stepper[stepper_HL].isDone()
                 && stepper[stepper_VR].isDone() && stepper[stepper_HR].isDone() ) )
      {
        for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          stepper[idx].run();
         // delay(1);
        }
      }
    }
    hier noch die ausgabe im terminal, wie man sehen kann werden zwar die if abfragen mit "rotiere links" und "rotiere rechts" erreicht, die befehle selbst aber nicht ausgeführt, daraus würde ich schliessen, dass die Stepper eben noch nicht fertig sind?

    Code:
    setup_ende
    Ping: 83 cm
    start - Stepper vorwärts- else-abfrage_1
    Ping: 71 cm
    loop - rotiere_links - if-abfrage_2
    loop - rotiere_rechts - if-abfrage_4
    loop - alle_stepper_vorwärts - if-abfrage_5
    Ping: 82 cm
    loop - alle_stepper_vorwärts - if-abfrage_5
    Ping: 82 cm
    ergänze ich einer dieser if abfragen mit der afrage ob z.b. der "stepper_VL" fertig ist, wird der printbefehl auch übersprungen, die abfrage 2 also gar nicht ausgeführt...

    Code:
    for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {    
         if (stepper[stepper_VL].isDone())
          if (rueckwaerts == false && rotate_li == false)
          {
            Serial.println("loop - rotiere_links - if-abfrage_2");
            rotieren_links();
          }
        }
    gruß inka

  7. #57
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Ich versuche mich grad mal wieder am lesen von C-Code. Dabei tauchen Fragen auf, die eventuell den Weg zum Fehler weisen ...:
    Warum wird der Funktionsaufruf "alle_stepper_vorwaerts();"in der Funktion hindernis_vorh() in eine for-Schleife über alle vorhandenen Stepper verpackt? Ist der Namensanteil "alle_..." irreführend? Ist im Augenblick nur ein Stepper dem Programm bekannt? Falls es mehrere sind - warum erscheint die serielle Ausgabe "start - Stepper vorwärts- else-abfrage_1" trotz Motor-unabhängiger boolescher Aussage nur ein einziges mal auf dem Terminal?

  8. #58
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    es sind vier stepper. "alle" im funktionsnamen deshalb, weil ja evtl. auch nur zwei laufen sollen...


    es sind hier aufrufe zweier verschiedener funktionen:

    1) hindernis_vorh() - prüft ob hindernis vorne (funktion selbst ist im codebeispiel nicht zu sehen - ist ausserhalb von loop())

    2) in dieser schleife

    Code:
    for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (rueckwaerts == false && hindernis == true)
          {
            Serial.println("start - Stepper rückwärts- if-abfrage_1");
            alle_stepper_rueckwaerts();
    
          }
          else if (vorwaerts == false && hindernis == false)
          {
            Serial.println("start - Stepper vorwärts- else-abfrage_1");
            alle_stepper_vorwaerts();
    
          }
        }
    wird eine andere funktion aufgerufen - alle_stepper_rueckwaerts() - wenn hindernis vorne

    oder alle_stepper_vorwaerts() - wenn kein hindernis

    serial.print soll nur einmal melden wo man gerade ist...

    und die funktionen "alle_stepper***" sind natürlich auch ausserhalb von loop()...
    gruß inka

  9. #59
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    OK, bei "hindernis_vorh();"hab ich übersehen, dass das der Aufruf einer Funktion ist und das Nachfolgende weiterer Code.

    Trotzdem:
    Zitat Zitat von inka Beitrag anzeigen
    es sind vier stepper. "alle" im funktionsnamen deshalb, weil ja evtl. auch nur zwei laufen sollen...
    Dann müssten es angesichts der for-Parameter dennoch vier Schleifendurchläufe und vier serielle Meldungen werden, oder ??

    Zitat Zitat von inka Beitrag anzeigen
    serial.print soll nur einmal melden
    We das? Es wird doch viermal aufgerufen, oder? Das ist ja mein Zweifel, ob an dieser Stelle der Programmfluss anders als gewünscht verläuft.

    Ich gestehe, dass ich nicht heimisch bin in diesem Thread und deinen Arbeiten. Ich hab halt mal versucht, den gelieferten Programmausschnitt auf Auffälligkeiten hin zu studieren.
    Wenn ich hier neben der Spur sein sollte, darfst du gerne deine Zeit sparen und meine Beiträge ignorieren.

  10. #60
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    jetzt hast Du mich etwas verunsichert (ist nicht schwierig )...

    hier in diesem
    Code:
    for (idx = stepper_VL; idx < stepper_MAX; idx++)
        {
          if (rueckwaerts == false && hindernis == true)
          {
            Serial.println("start - Stepper rückwärts- if-abfrage_1");
            alle_stepper_rueckwaerts();                                   <-----hier
    
          }
          else if (vorwaerts == false && hindernis == false)
          {
            Serial.println("start - Stepper vorwärts- else-abfrage_1");
            alle_stepper_vorwaerts();
    
          }
        }
    springt er hierhin:
    Code:
    void alle_stepper_rueckwaerts(void)
    {
      rueckwaerts = true;
    
    
      for (idx = stepper_VL; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CCW);
        stepper[idx].rotate(1);
      }
    }
    
    
    
    
    void rotieren_links(void)
    {
      rotate_li = true;
    
    
      for (idx = stepper_VL; idx < stepper_VR; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CCW);
        stepper[idx].rotate(1);
      }
    
    
      for (idx = stepper_VR; idx < stepper_MAX; idx++)
      {
        stepper[idx].setRPM(12);
        stepper[idx].setSPR(4075.7728395);
        stepper[idx].setDirection(CW);
        stepper[idx].rotate(1);
      }
    }
    und dann wieder, nach dem er diese funktion abgearbeitet hat, zurück, ignoriert die else-if abfrage und geht weiter. Und muss die schleife noch 3x durchlaufen?
    Die serialprint meldung kommt wirklich nur einmal! ich muss es noch ohne die schleife mit den "idx" testen...
    gruß inka

Seite 6 von 7 ErsteErste ... 4567 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
  •  

12V Akku bauen