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

Thema: Odometrie die 1002te(Problem gelöst)

  1. #1

    Odometrie die 1002te(Problem gelöst)

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hi,
    Ich habe mich mal an einem Programm zur synchronisation der Drehzahlen versucht. Nach langem probieren war es dann vorgestern endlich soweit, dass mein Asuro geradeaus fuhr und nicht immer nur Linkskurven. Habe mich gefreut und ersteinmal das Programm etwas gerafft (Überflüssige Schleifen und Variablen entfernt alles etwas schöner gemacht).
    Das dumme ist nur, es funktioniert jetzt nicht mehr. Das Programm in der Form in der es funktionierte habe ich nicht mehr und ich finde den Fehler nicht.
    Vielleicht hat ja jemand Zeit mal drüber zu schauen, und etwas zu entdecken das immer übersehe. Oder das Ganze mal auf den eigenen Asuro laden um zu schauen wie es sich da benimmt.
    Vielen Dank schon mal.
    Code:
    #include <asuro.h>
    
    #define STARTSPEEDL 180
    #define STARTSPEEDR 180
    #define STARTODOZYKLEN 1000
    #define ODOZYKLEN 1000
    #define MITTELWERTPUFFER 0
    #define TRUE 1
    #define FALSE 0
    int n;                                                             //zählvariable
    int Lmotorspeed=STARTSPEEDL,Rmotorspeed=STARTSPEEDR;               //motorgeschw.
    unsigned long int odomittelwertL,odomittelwertR;//mittlere helligkeit der ododaten      
    unsigned long int odosummeL=0,odosummeR=0;//aufsummierte ododaten eines zyklus
    unsigned int ododata[2];                                //nimmt die ododaten auf 
    short int Luebermittelwert=FALSE,Ruebermittelwert=FALSE;
    
    
    void start()                                     //initialisiere
    {
      Init();
      StatusLED(RED);
      MotorSpeed(Lmotorspeed,Rmotorspeed);
      for(n=0;n<STARTODOZYKLEN;n++)       //erstmal werden die ododaten 
      {                                                         //aufsummiert  
        OdometrieData(ododata);                   
        odosummeL=odosummeL+ododata[0];          				
        odosummeR=odosummeR+ododata[1];          				
      }
      odomittelwertL=(odosummeL/STARTODOZYKLEN);//erster Mittelwert wird ermittelt
      odomittelwertR=(odosummeR/STARTODOZYKLEN);
              
      odosummeL=0;              //...wir wollen ja gleich eine neue summe bilden
      odosummeR=0;	  
             
      if (ododata[0]>odomittelwertL)  //weisses oder schwarzes Feld vor dem Sensor
        Luebermittelwert=TRUE;
      if (ododata[1]>odomittelwertR)
        Ruebermittelwert=TRUE;
      
      StatusLED(GREEN);         
    }
    
    void reglespeed()
    {
      unsigned int Lswcount=0,Rswcount=0;//zähler für schwarzweissÜbergänge
         
      //Schleife um Übergänge zu zählen
      //FOR SCHLEIFE BEGINN+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      for(n=0;n<ODOZYKLEN;n++)
      {
        OdometrieData(ododata);
        //****************************************LINKE SEITE
        if ( (ododata[0]>(odomittelwertL+MITTELWERTPUFFER)) && (Luebermittelwert!=TRUE) )                 //wenn ein schwarzes feld vor dem sensor ist...
    	{			                         //..und eben nicht auch schon war..
          Lswcount++;                             // zähle einen übergang
          Luebermittelwert=TRUE;             //und merke dirs für nächste runde
        }
    	 
        if ( (ododata[0]<(odomittelwertL-MITTELWERTPUFFER)) && (Luebermittelwert!=FALSE) )               
        {																						
    	  Lswcount++;                                                                        
    	  Luebermittelwert=FALSE;
        }
          
        //****************************************RECHTE SEITE
    	if ( (ododata[1]>(odomittelwertR+MITTELWERTPUFFER)) && (Ruebermittelwert!=TRUE) )
        { 	  
          Rswcount++;
          Ruebermittelwert=TRUE;
        }	
    	
    	if ( (ododata[1]<(odomittelwertR-MITTELWERTPUFFER)) && (Ruebermittelwert!=FALSE) )
        {
    	  Rswcount++;
    	  Ruebermittelwert=FALSE;
        }
        //***************************************Aufsummieren
        odosummeL=odosummeL+ododata[0];
        odosummeR=odosummeR+ododata[1];
      }
      //FORSCHLEIFE ENDE+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       
      odomittelwertL=odosummeL/ODOZYKLEN;     //neuer Mittelwert wird ermittelt
      odomittelwertR=odosummeR/ODOZYKLEN;
      odosummeL=0;                                        //...nächste runde neue summe
      odosummeR=0;	
      
      //Geschwindigkeit des rechten Motors wird angepasst
      //(der rechte meines Asuros ist stärker) 
      //der Linke bleibt immer auf Anfangsgeschw.
      if (Lswcount>Rswcount) Rmotorspeed=(Rmotorspeed+5);
      if (Lswcount<Rswcount) Rmotorspeed=(Rmotorspeed-5);
      
      if (Rmotorspeed<100) Rmotorspeed=100;            //obere und untere grenze
      if (Rmotorspeed>250) Rmotorspeed=250;
      
      MotorSpeed(Lmotorspeed,Rmotorspeed);
    }
    
    
    int main()
    {
      start();
      while(1)
      {
        reglespeed();
      }
      return(0);
    }
    Achja das Problem ist, dass der rechte Motor(den linken regle ich nicht) entweder konsequent schneller gemacht wird oder eben langsamer, abhängig davon wie der wert MITTELWERTPUFFER definiert ist. Für 0 wie im Code oben geht er auf maximalspeed für werte ab 40 wird er langsamer. Auch werte dazwischen bringen keine abhilfe, der Fehler muss woanders sein. Dankeschön.
    EDIT:meine kommentare etwas an die größe des codefensters angepasst und Titel geändert

  2. #2
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Milda
    Alter
    38
    Beiträge
    4.064
    hmm... ich kann spontan keine fehler finden. weisst du ungefähr welche "überflüssigen schleifen" du entfernt hast? war evtl eine nicht so ganz überflüssige dabei?
    Read... or die.
    ff.mud.de:7600
    Bild hier  

  3. #3
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Das sieht ja auf den ersten Blick recht ordentlich aus. Hier mal meine Kommentare:

    Wie viele hell/dunkel-Wechsel erkennst du bei 1000 Messzyklen?

    Ein MotorDir(FWD,FWD) ist zwar überflüssig, weils so in Init() gesetzt wird, würde aber auch nicht schaden.

    Ich glaube, der generelle Denkfehler ist folgender:

    Die hell/dunkel-Verteilung ist nicht gleichmässig, soll heisen, dein Mittelwert den du bildest, liegt nicht in der Mitte der möglichen Werte.

    Ob das dein Problem ist, kann ich dir noch nicht sagen, ich muss deinen Code erst noch etwas "verinnerlichen"

    Ich löse das etwa so:

    Eine Kalibrierungsfahrt mit default-Startwerten speichert die Min- und Max-Werte je Seite(bei dir (start()). Die Differenz zwischen Max und Min teile ich durch drei und lege die Schwelle für low auf min+diff/3, für high auf max-diff/3. Neu eingelesene Werte vergleiche ich dann mit meinen Schwellwerten und zähle in Äbhängigkeit vom letzten Pegel bei Bedarf den jeweiligen Zähler hoch. Ein Wert im mittleren Drittel wird generell ignoriert. Das ist quasi ein Filter, der Fehllesungen ausfiltert.

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    18.03.2007
    Beiträge
    62
    Also was mir da nur einfällt als Tipp:
    Erhöhe die Anzahl der Zyklen. Ich glaub, 1000 Zyklen sind zu wenig.
    Ich würde jeden Zyklus die LED blinken lassen. So kannst du sehen wann ein Zyklus vorbeigeht. Wenn die zu oft blinkt, können starke Messungenauigkeiten auftreten.

    Wieso es früher funktioniert hat:
    Früher hattest wohl mehr Schleifen, mehr unnötigen Code -> ein Zyklus dauerte länger, wodurch du virtuell die Zyklenzahl grösser hattest.
    18.März '07- mein erster ASURO

  5. #5
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Milda
    Alter
    38
    Beiträge
    4.064
    naja da die 1000 zyklen ohne zeitverzögerung durchgeführt werden, dürfte die haupt-bremse wohl der ADwandler sein. trotzdem wird man von der led nicht viel sehen. 1000 zyklen gehen SEHR schnell vorbei. vielleichtg ist gerade das das problem, weil dann nur ein bis 2 felder des odo-rades gemessen werden. tu mal in den initialisierungs-for-schleife (die mit den 1000 zyklen) ein Sleep(72) rein, dann dauert die initialisierung etwa eine sekunde und in dieser zeit ziehen mehr felder am sensor vorbei. so werden zwar nicht mehr, aber wenigstens "verschiedenere" punkte der odo scheibe vermessen.
    Read... or die.
    ff.mud.de:7600
    Bild hier  

  6. #6
    Vielen Dank schon mal.
    Eine Erhöhung der Messungen für eine Zählung führt zu keiner Verbesserung. Ich werde dann heute abend mal versuchen ein paar Daten von Asuro zu bekommen was er den da eigentlich zählt. Auserdem gefällt mir Radbruchs Methode die unsicheren Werte in der Mitte herauszufiltern.
    Gruß ADR

  7. #7
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    die unsicheren Werte in der Mitte herauszufiltern
    Hier liegt wohl auch der "Fehler" in deinem Programm. Nachdem ich nun noch etwas darüber nachgedacht habe, halte ein mehrfaches Zählen ein und derselben Flanke für die Ursache der Fehlfunktion. Generell sollten vielleicht die Ausrutscher rausgefiltert werden. (z.B. mittelwerte der letzten drei..)

    Ich hab früher schon mal versucht die Flanken zu erkennen. Dabei habe ich mehrere Werte auf steigende oder sinkende Folge (odo0<odo1<odo2<odo3 bzw. odo0>odo1>odo2>odo3) geprüft. Ab einem Vergleich mit 4-5 Werten funktionierte das gut:

    Code:
        OdometrieData(data);
        if ((data[0]<o1_l) && (o1_l<o2_l) && (o2_l<o3_l)) {
            if (!odo_bit_l) {
                count_l ++;
                odo_bit_l=(1==1);
                StatusLED(YELLOW);
            }
        }
        if ((data[0]>o1_l) && (o1_l>o2_l) && (o2_l>o3_l)) {
            if (odo_bit_l) {
                count_l ++;
                odo_bit_l=(1==0);
                StatusLED(OFF);
           }
        }
        o3_l=o2_l;
        o2_l=o1_l;
        o1_l=data[0];
    Wenn sich das Rad dreht, blinkt die StatusLED im Rythmus der Flanken und der Counter wird erhöht.
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    01.02.2007
    Ort
    Ashausen
    Alter
    66
    Beiträge
    64
    Hi ADR,

    Versuche doch erst einmal Deine Odometriedaten zu analysieren. Das kanst Du z.B. so machen:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define POINTS 100
    #define SPEED  100
    
    
    int main(void)
    {
    	unsigned int data_array[2][POINTS] = {{0}};
    	unsigned char sw;
    	unsigned int data[2] = {0}, iLinks =0 , iRechts=0, i=0;
    	unsigned char cWert[25] = {0};
    	
    	Init();
    	
    	SerWrite("Odometrie Test\n\r",16);
    	
    	BackLED(OFF,OFF);
    	MotorDir(FWD,FWD);
    	MotorSpeed(SPEED,SPEED);
    	
    	for (i=0; i<500; i++)
    			Sleep(255);
    
    	for (i=0; i<POINTS; i++) {
    		OdometrieData(data);
    		data_array[0][i] = data[0];
    		data_array[1][i] = data[1];
    	}
    	MotorDir(BREAK,BREAK);
    	MotorSpeed(0,0);
    	BackLED(ON,ON);
    	
    	while(TRUE) {
    		sw = PollSwitch();
    		if (sw & 0xFF) {
    			for (i=0; i<POINTS; i++) {
    				iLinks  = data_array[0][i];
    				iRechts = data_array[1][i];
    				sprintf(cWert,"\n\rLinks %3u Rechts %3u",iLinks, iRechts);
    				SerWrite(cWert, strlen(cWert));
    			}
    		}
    	}
    	
    	return 0;
    }
    Damit kannst Du ASURO fahren lassen und danach durch Betätigung eines Tasters die gemessenen Werte mit HyperTerminal auslesen. Die Zahlenreihen dann mit Copy and Paste in Excel übernehmen und darstellen lassen. Du solltest saubere Sinusschwingungen bekommen - ohne "Ausrutscher". Mache den Test auch bei unterschiedlichem Umgebungslicht, um dessen Einfluß zu ermitteln.

    Ich habe meine Odometriesensoren mit kleinen, schwarzen Pappgehäusen umgeben und die Motoren entstört. Das hat sehr geholfen.
    Anhand der Excelkurven kannst Du dann auch einen oberen und unteren Wert für die Zählschwelle festlegen und brauchst sie dann nicht immer neu zu ermitteln.

    Viel Erfolg...

    Gruß,

    _HP_

  9. #9
    Hi,
    ich wollt mich wollt mich nur noch mal für eure hilfe bedanken hab mich ja damals aus verschiedensten Gründen nicht mehr gemeldet.
    Mein Asuro läuft jetzt wieder zu meiner vollsten zufriedenheit, mit dem Programm das ich damals hier reingestellt hab. War so wies aussieht ein hardwareproblem.
    Also vielen Dank nochmal

Berechtigungen

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

12V Akku bauen