- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 31

Thema: Neuling: Odometrie

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #26
    Neuer Benutzer Öfters hier
    Registriert seit
    23.12.2007
    Ort
    AC
    Beiträge
    23
    Das war leider nicht das Problem. Ich habe jetzt an mehreren Stellen Sleep Funktionen zum beschleunigen eingebaut, damit er Zeit zum Beschleunigen hat und erst dann anfängt zu messen.
    Das klappt auch ganz gut. Manchmal korrigiert er was, fährt ein stück relativ gerade aus, doch dann - wie die meiste Zeit - fährt er wieder ne Kurve.
    Daher habe ich den Eindruck dass irgendwas mit meiner Logik nicht funktioniert - vielleicht ist es aber auch nur das Finetuning der Werte, ihr habt da mehr Erfahrung. Zur Logik habe ich mal kurz eine Skizze gemacht.

    Das folgende Programm wurde an einigen Stellen überarbeitet, also besser dieses anschauen : ). Ich wäre euch sehr dankbar wenn ihr mir helfen könntet diese Hürde endlich mal zu bewältigen ; )!

    Danke und Gruß!

    Code:
    #include "asuro.h"      // Konfigurationsdateien laden
    #define MITTER 155      // Die ca. Hälfte der Amplitude
    #define MITTEL 140      // für die ersten Anpassungen
    
    /* Funktionen definieren */
    
    /* Globale Variablen */
    unsigned char i;		// Zähler
    unsigned char alr=0;			// schon (already) gelaufen?
    unsigned char alr2=0;			// schon (already) gelaufen?
    unsigned int cntsL=0;			// Zähler (counts)
    unsigned int cntsR=0;			// Zähler
    unsigned int cnts=0;			// Zähler
    unsigned int odoData[2];     	// Array für Odo Werte
    unsigned int lrHi[2]={MITTEL, MITTER};          // left right highest
    unsigned int lrLo[2]={MITTEL, MITTER};          // left right lowest
    unsigned int spd0=190; 		// Geschwindigkeit (speed)
    unsigned int spd1=190; 		// Geschwindigkeit
    unsigned int odoMemL[3];      	// Ododaten zwischenspeichern (ododmetrie memory)
    unsigned int odoMemR[3];      	// Ododaten zwischenspeichern
    unsigned int testErg[2];      	// Ergebnisse des Durchlaufes (test ergebnis)
                                  	// 0=low, 1=hi
    
    void schlafen(unsigned int wert){
       for(i=0; i<=wert; i++){
       Sleep(72);}
    }
    
    /* Geradeausfahren */
    
    char InitFwd(void){
    
     schlafen(250);
     StatusLED(RED);
     schlafen(250);
     StatusLED(YELLOW);
    
       MotorDir(FWD,FWD);   // zunächst gasgeben damit er fährt und Werte sammelt, Vortest
       MotorSpeed(190,190);
       schlafen(250);
    
       while(cnts<500){       // 200 mal zählen
          OdometrieData(odoData);
    
          for(i=0; i<3; i++){  // 3 durchläufe für OdoWerte
          OdometrieData(odoData);
          
          odoData[0]=odoMemL[i];
          odoData[1]=odoMemR[i];
    
             if(odoData[0]>lrHi[0]){       // die Höchstwerte ermitteln LINKS
                lrHi[0]=odoData[0];}
             else if(odoData[0]<lrLo[0]){  // die Tiefstwerte ermitteln
                lrLo[0]=odoData[0];}
    
             if(odoData[1]>lrHi[1]){       // die Höchstwerte ermitteln RECHTS
                lrHi[1]=odoData[1];}
             else if(odoData[1]<lrLo[1]){  // die Tiefstwerte ermitteln
                lrLo[1]=odoData[1];}
          }
          
           testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
           testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
    
          /* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
          /* links */
          if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
          cntsL++;}
          else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
          cntsL++;}
    
          /* rechts */
          if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
          cntsR++;}
          else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
          cntsR++;}
    
          if(cntsL>420 && cntsR>420){
          alr=1;
           StatusLED(RED);
           schlafen(250);
           StatusLED(GREEN);}
       cnts++;
       }//while cnts
    
     MotorDir(BREAK,BREAK);
     MotorSpeed(0,0);
    
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
    
    return alr;
    
    }
    
    
    void Forward(void){
    
    if(alr2 == 0){            // Beschleunigen damit er in Fahrt Werte sammelt
       MotorDir(FWD,FWD);   
       MotorSpeed(spd0,spd1);
       schlafen(250);
       alr2 = 1;}
    
    
    if(alr == 1){    // Falls Vorprüfung stattgefunden hat, ausführen
          
          for(i=0; i<3; i++){  // 3 durchläufe für OdoWerte
          OdometrieData(odoData);
          
          odoData[0]=odoMemL[i];
          odoData[1]=odoMemR[i];
    
             if(odoData[0]>lrHi[0]){       // die Höchstwerte ermitteln LINKS
                lrHi[0]=odoData[0];}
             else if(odoData[0]<lrLo[0]){  // die Tiefstwerte ermitteln
                lrLo[0]=odoData[0];}
    
             if(odoData[1]>lrHi[1]){       // die Höchstwerte ermitteln RECHTS
                lrHi[1]=odoData[1];}
             else if(odoData[1]<lrLo[1]){  // die Tiefstwerte ermitteln
                lrLo[1]=odoData[1];}
          }
    
     testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
     testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
    
          /* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
          /* links */
          if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
          cntsL++;}
          else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
          cntsL++;}
    
          /* rechts */
          if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
          cntsR++;}
          else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
          cntsR++;}
    
    
    if(spd1==255 || spd0==255){  // Falls Maximalspd erreicht Spielraum schaffen
       spd1=spd1-10;
       spd0=spd0-10;}
    
    if(cntsL>cntsR){	// Korrektur!
       spd1++;
       StatusLED(RED);}
    
    if(cntsL<cntsR){
       spd0++;
       StatusLED(GREEN);}
    
    if((cntsR > 10000 || cntsL > 10000) && (cntsR>7000 && cntsL>7000)){ // aufpassen dass Variable nicht überläuft
       cntsL=cntsL-7000;
       cntsR=cntsR-7000;}
    
       MotorDir(FWD,FWD);   // und go!!
       MotorSpeed(spd0,spd1);
    
    }// if alr
    }
    
    /* Beginn des Hauptprogramms */
    
    int main (void){
    
    Init();            //Prozessor initialisieren
    InitFwd();	   // Odo Initialisieren
    
    while(1)         // Endlosschleife
    {
      Forward();
    }
    
    /* Schluss ! */
    
    return 0;
    }
    // EDIT:
    Mittlerweile bin ich mir relativ sicher dass das Problem beim Messen liegt. Durch die Schleife
    Code:
          for(i=0; i<3; i++){  // 3 durchläufe für OdoWerte
          OdometrieData(odoData);
          
          odoData[0]=odoMemL[i];
          odoData[1]=odoMemR[i];
    wird der Fall wie in der Skizze dargestellt nur sehr selten auftreten. Ein neuer Algorithmus muss her

    // EDIT die 2.:

    So, jetzt habe ich einen neuen Algorithmus entwickelt. ASURO arbeitet jetzt mit durchlaufenden Werten und es sollten daher alle Übergänge verzeichnet werden.
    Code:
          /* Neuer Algorithmus: "Durchlaufende Werte" */
          OdometrieData(odoData);
          
          odoMemL[0]=odoMemL[1];
          odoMemL[1]=odoMemL[2];
          odoMemL[2]=odoData[0];
          
          odoMemR[0]=odoMemR[1];
          odoMemR[1]=odoMemR[2];
          odoMemR[2]=odoData[1];
    Klappen tut es allerdings noch nicht.... Ein bisschen Sorgen macht es mir, dass er bei folgender Kontrollfunktion auch niemals etwas ans Terminal sendet!!
    Code:
    if(cntsL>cntsR){	// Korrektur!
       spd1++;
       StatusLED(RED);
       SerWrite("L groesser R",12);}
    else if(cntsL<cntsR){
       spd0++;
       StatusLED(GREEN);
       SerWrite("R groesser L",12);}
    else if(cntsL==cntsR){
       spd0++;
       StatusLED(GREEN);
       SerWrite("R gleich L",10);}
    Irgendeine Idee warum es immer noch nicht klappt? Hier nochmal das komplette Program:
    Code:
    #include "asuro.h"      // Konfigurationsdateien laden
    #define MITTER 155      // Die ca. Hälfte der Amplitude
    #define MITTEL 140      // für die ersten Anpassungen
    
    /* Funktionen definieren */
    
    /* Globale Variablen */
    unsigned char i;		// Zähler
    unsigned char alr=0;			// schon (already) gelaufen?
    unsigned char alr2=0;			// schon (already) gelaufen?
    unsigned int cntsL=0;			// Zähler (counts)
    unsigned int cntsR=0;			// Zähler
    unsigned int cnts=0;			// Zähler
    unsigned int odoData[2];     	// Array für Odo Werte
    unsigned int lrHi[2]={MITTEL, MITTER};          // left right highest
    unsigned int lrLo[2]={MITTEL, MITTER};          // left right lowest
    unsigned int spd0=190; 		// Geschwindigkeit (speed)
    unsigned int spd1=190; 		// Geschwindigkeit
    unsigned int odoMemL[3];      	// Ododaten zwischenspeichern (ododmetrie memory)
    unsigned int odoMemR[3];      	// Ododaten zwischenspeichern
    unsigned int testErg[2];      	// Ergebnisse des Durchlaufes (test ergebnis)
                                  	// 0=low, 1=hi
    
    void schlafen(unsigned int wert){
       for(i=0; i<=wert; i++){
       Sleep(72);}
    }
    
    /* Geradeausfahren */
    
    char InitFwd(void){
    
     schlafen(250);
     StatusLED(RED);
     schlafen(250);
     StatusLED(YELLOW);
    
       MotorDir(FWD,FWD);   // zunächst gasgeben damit er fährt und Werte sammelt, Vortest
       MotorSpeed(190,190);
       schlafen(250);
    
       while(cnts<500){       // XXX mal zählen
    
          /* Neuer Algorithmus: "Durchlaufende Werte" */
          OdometrieData(odoData);
          
          odoMemL[0]=odoMemL[1];
          odoMemL[1]=odoMemL[2];
          odoMemL[2]=odoData[0];
          
          odoMemR[0]=odoMemR[1];
          odoMemR[1]=odoMemR[2];
          odoMemR[2]=odoData[1];
    
             if(odoData[0]>lrHi[0]){       // die Höchstwerte ermitteln LINKS
                lrHi[0]=odoData[0];}
             else if(odoData[0]<lrLo[0]){  // die Tiefstwerte ermitteln
                lrLo[0]=odoData[0];}
    
             if(odoData[1]>lrHi[1]){       // die Höchstwerte ermitteln RECHTS
                lrHi[1]=odoData[1];}
             else if(odoData[1]<lrLo[1]){  // die Tiefstwerte ermitteln
                lrLo[1]=odoData[1];}
               
           testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
           testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
    
          /* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
          /* links */
          if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
          cntsL++;}
          else if(((odoMemL[0]<odoMemL[1]) && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/MITTEL)<1.05) && ((odoMemL[1]/MITTEL)>0.95))){
          cntsL++;}
    
          /* rechts */
          if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
          cntsR++;}
          else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/MITTER)<1.05) && ((odoMemR[1]/MITTER)>0.95))){
          cntsR++;}
    
          if(cntsL>420 && cntsR>420){
          alr=1;
           StatusLED(RED);
           schlafen(250);
           StatusLED(GREEN);}
       cnts++;
       }//while cnts
    
     MotorDir(BREAK,BREAK);
     MotorSpeed(0,0);
    
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
     StatusLED(YELLOW);
     schlafen(250);
     StatusLED(GREEN);
     schlafen(250);
    
    return alr;
    
    }
    
    
    void Forward(void){
    
    if(alr2 == 0){            // Beschleunigen damit er in Fahrt Werte sammelt
       MotorDir(FWD,FWD);   
       MotorSpeed(spd0,spd1);
       schlafen(250);
       alr2 = 1;}
    
    
    if(alr == 1){    // Falls Vorprüfung stattgefunden hat, ausführen
          
          /* Neuer Algorithmus: "Durchlaufende Werte" */
          OdometrieData(odoData);
          
          odoMemL[0]=odoMemL[1];
          odoMemL[1]=odoMemL[2];
          odoMemL[2]=odoData[0];
          
          odoMemR[0]=odoMemR[1];
          odoMemR[1]=odoMemR[2];
          odoMemR[2]=odoData[1];
    
             if(odoData[0]>lrHi[0]){       // die Höchstwerte ermitteln LINKS
                lrHi[0]=odoData[0];}
             else if(odoData[0]<lrLo[0]){  // die Tiefstwerte ermitteln
                lrLo[0]=odoData[0];}
    
             if(odoData[1]>lrHi[1]){       // die Höchstwerte ermitteln RECHTS
                lrHi[1]=odoData[1];}
             else if(odoData[1]<lrLo[1]){  // die Tiefstwerte ermitteln
                lrLo[1]=odoData[1];}
          
     testErg[0]=(lrHi[0]+lrLo[0])/2; // Test Ergebnisse zuweisen,
     testErg[1]=(lrHi[1]+lrLo[1])/2; // Mitte der Funktion bei Hälfte der Amplitue
    
          /* Hier wird geschaut, ob die Schwelle übertreten wird, falls ja hat Umdrehung stattgefunden */
          /* links */
          if((odoMemL[0]>odoMemL[1] && odoMemL[1]>odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
          cntsL++;}
          else if((odoMemL[0]<odoMemL[1] && odoMemL[1]<odoMemL[2]) && (((odoMemL[1]/testErg[0])<1.05) && ((odoMemL[1]/testErg[0])>0.95))){
          cntsL++;}
    
          /* rechts */
          if((odoMemR[0]>odoMemR[1] && odoMemR[1]>odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
          cntsR++;}
          else if((odoMemR[0]<odoMemR[1] && odoMemR[1]<odoMemR[2]) && (((odoMemR[1]/testErg[1])<1.05) && ((odoMemR[1]/testErg[1])>0.95))){
          cntsR++;}
    
    
    if(spd1==255 || spd0==255){  // Falls Maximalspd erreicht Spielraum schaffen
       spd1=spd1-10;
       spd0=spd0-10;}
    
    if(cntsL>cntsR){	// Korrektur!
       spd1++;
       StatusLED(RED);
       SerWrite("L groesser R",12);}
    else if(cntsL<cntsR){
       spd0++;
       StatusLED(GREEN);
       SerWrite("R groesser L",12);}
    else if(cntsL==cntsR){
       spd0++;
       StatusLED(GREEN);
       SerWrite("R gleich L",10);}
    
    if((cntsR > 10000 || cntsL > 10000) && (cntsR>7000 && cntsL>7000)){ // aufpassen dass Variable nicht überläuft
       cntsL=cntsL-7000;
       cntsR=cntsR-7000;}
    
       MotorDir(FWD,FWD);   // und go!!
       MotorSpeed(spd0,spd1);
    
    }// if alr
    }
    
    /* Beginn des Hauptprogramms */
    
    int main (void){
    
    Init();            //Prozessor initialisieren
    InitFwd();	   // Odo Initialisieren
    
    while(1)         // Endlosschleife
    {
      Forward();
    }
    
    /* Schluss ! */
    
    return 0;
    }
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken prinzip_odometrie.jpg  

Berechtigungen

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

Solar Speicher und Akkus Tests