-
        

Ergebnis 1 bis 8 von 8

Thema: GoTurn () Winkel und Strecke

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    15.05.2008
    Beiträge
    7

    GoTurn () Winkel und Strecke

    Anzeige

    Hallo
    ich habe die GoTurnfunktion ausprobiert und fand es schade, dass man entweder einen Winkel oder eine Strecke eingeben konnte, aber nicht beides zusammen. Deshalb versuche ich grade ein Quelltext zu schreiben, bei dem (erstmal mit anderen Bezeichnungen) dann beides in Abhängigkeit berechnet wird.

    Ich hab dabei nur folgendes Problem ... ich will erstmal experimentel ermitteln, welchen Wert ich für X einsetzen muss, damit er genau grade einen Meter fährt.

    Auf ähnliche weise will ich dann auch später die nötigen Verrechnungsfaktoren für die Winkel und den damit zusammenhängenden Speed ermitteln. Nun hab ich den Quellcode soweit geschreiben, allerdings fährt er, wenn X ca. 1-20 ist immer etwas schneller, wie ers soll, dann hört er auf und bleibt stehen, ich sehe aber über IR dass er die X weiter ausführt. Bei 90-100 macht er dann genau das selbe, mit den selben strecken wie am anfang und hört dann wieder auf.

    Code:
    #include "asuro.h"
    
    int main(void)
    {
    	Init();
    	int distance = 1000;
    	int degree = 0;
    	int x, c;
    	unsigned char speed = 200, speedd;
    	unsigned char speedl = speed;
    	unsigned char speedr = speed;
    	
    	for (x=0;x<500;x++)
    	{
    		c = PollSwitch();
    		
    		if (distance > 0)
    		{
    			MotorDir (FWD,FWD);
    		}
    		else
    		{
    			MotorDir (RWD,RWD);
    		}
    		
    		if (degree == 0)
    		{
    			speedl = speed;
    			speedr = speed;
    		}
    		
    
    		if (degree < 0)
    		{
    			speedd = degree / distance;
    			speedl = speed + speedd;
    			speedr = speed - speedd;
    		}
    		if (degree > 0)
    		{
    			speedd = degree / distance;
    			speedl = speed - speedd;
    			speedr = speed + speedd;
    		}
    		if (speedl > 255)
    		{
    			speedl = 255;
    			speedr = speedr - (speedl + 255);
    		}
    		if (speedr > 255)
    		{
    			speedl = speedl - (speedr + 255);
    			speedr = 255;
    		}
    
    		SerPrint ("\n\rX: ");
    		PrintInt (x);
    		SerPrint ("\n\rWinkel: ");
    		PrintInt (degree);
    		SerPrint ("\n\rWeg: ");
    		PrintInt (distance);
    		SerPrint ("\n\rGeschwindigkeit: ");
    		PrintInt (speed);
    		SerPrint ("\n\rGeschwindigkeit Rechts: ");
    		PrintInt (speedr);
    		SerPrint ("\n\rGeschwindigkeit Links: ");
    		PrintInt (speedl);
    		SerPrint ("\n");
    
    		Msleep (200);
    		MotorSpeed (speedl,speedr);
    		Msleep (distance * x / speed);
    		MotorSpeed (0,0);
    		Msleep (200);
    		if (c >= 0) {Msleep (1000);}
    	}
    	BackLED (ON,ON);
    	while (1);
    	return 0;
    }

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    02.01.2008
    Alter
    26
    Beiträge
    239
    hallo Wo2le,

    bei deinem programm habe ich eine stelle gefunden, die ich nicht verstehe:
    Code:
          if (speedl > 255)
          {
             speedl = 255;
             speedr = speedr - (speedl + 255);
          }
    du setzt doch zuerst speedl auf 255, dann addierst du zu speedl 255, das ergibt 510, ziehst diesen wert von speedr ab und speicherst ihn in speedr

    dh. in speedr steht dann ein wert, der speedr -510 ist, also zwischen -510 und -255. diese zahl kann man doch nicht in ein unsigned char speicher, und hatt in dienem programm auch keinen sinn.

    oder habe ich dein programm falsch verstanden?
    mfg hai1991

    P.S.: wer großbuchstaben oder rechtschreibfehler findet darf sie behalten

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    15.05.2008
    Beiträge
    7
    Danke ... das war ein Denkfehler. Ich wollte damit absichern, dass er wenn der eine Motor durch diese Speedd größer als 255 wird, beide Werte um die Selbe zahl nach unten gehen, damit dann das Verhältnis in etwa wieder stimmt ... muss dann mal schauen ob das proportional bleibt. Ist ja aber eh erst im Anfangsstadium. Ich hab das jetzt folgendermaßen geändert, obwohl das zurzeit keine Rolle spielt, weil die beiden Motoren mit einer konstanten Geschwindigkeit von 200 in diesem Fall fahren.

    Code:
    		if (speedl > 255)
    		{
    			speedd = speedl - 255;
    			speedr = 255 - speedd;
    			speedl = 255;
    		}
    		if (speedr > 255)
    		{
    			speedd = speedr - 255;
    			speedl = 255 - speedd;
    			speedr = 255;
    		}
    Seltsamerweise geht das erste Intervall nun bis 32 bevor der Motor stoppt, obwohl das X nur etwas mit dem Msleep zutun hat und die Geschwindigkeit konstant ist!

    Ich finde da wirklich keinen Fehler

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    15.02.2008
    Ort
    Bremen
    Alter
    38
    Beiträge
    119
    Wenn die ganzen Variablen immer noch "unsigned char" (= 1 Byte) sind, dann geht sowieso nur max. 0xFF = 255 hinein und eine Abfrage wie "if speed1 > 255" wird niemals true.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo Wo2le,
    erst einmal ein willkommen im Forum.

    Das mit den 'unsigned char'-Variablen solltest du auf alle Fälle austauschen. Variable als 'int'-Typ definieren gibt zwar ein paar Compilerwarnings, aber damit kann man erst einmal leben.


    Versuche doch mal die Anweisung
    - Msleep (distance * x / speed);

    zu ersetzen mit:
    - NeueIntVariable = (int)((float)distance * (float)x / (float)speed);
    - Msleep (NeueIntVariable);

    Eventuell hilft es dem Compiler vor allem die Division mit Nachkommaanteil zu erzwingen, damit zum Schluß hoffentlich etwas funktionierendes raus kommt.

    Gruß Sternthaler

    P.S.: Ansonsten kann ich auch keine Stelle finden die mir fehlerhaft vorkommen würde.
    Lieber Asuro programieren als arbeiten gehen.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    15.05.2008
    Beiträge
    7
    Ersteinmal ... findet ihr es realistisch, das man ein Program schreiben kann, wobei man erstmal die Variablen für die Strecke und den Winkel auf jeden Asuro individuell Kallibrieren kann, sodass die Werte immer ziemlich genau sind und dass man dann nurnoch die Strecke und den Winkel eingeben muss?

    Danke für die Tipps. Ich habe sie versucht einzubauen und will die Zahlen jezt nur zum testen sozusagen die Werte über IR senden. Ich weis, dass die Werte bei SerRead nur unsigned char sind und ich das auf int oder float eingeben können muss. hat vielleicht jemand eine idee wie ich das machen kann?

    ich hab schoneinmal solchein Programtext versucht, allerdings funktioniert dies nicht aus besagten Gründen.

    Hier einmal der Quelltext

    Code:
    
    #include "asuro.h"
    
    int main (void)
    {
    	Init();
    	int x, c, n, r, k = 0, o;
    	int degree;
    	int distance;
    	int speed;
    	int speedd;
    	int sl, sr;
    	unsigned char speedl;
    	unsigned char speedr;
    	char emfangene_daten [1];
    	degree = 90;
    	distance = 500;
    	speed = 200;
    	o = 25;
    	do
    	{
    		for (x=0;x<50;x++)
    		{
    
    			r = x * 10;
    
    			c = PollSwitch();
    			sr = speed;
    			sl = speed;
    			
    			switch (c)
    			{
    // Tasten um zum ermitteln der Werte bestimmte Werte einzugeben.
    // Problem mit unsigned char und int ???
    
    case 1: SerPrint ("X (49 = Ende) Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			x = emfangene_daten [0] * 10;
    			SerPrint ("X (49 = Ende) Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			x = x + emfangene_daten [0];
    			break;
    
    case 2: SerPrint ("R (Winkelkalibrierung) Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			r = emfangene_daten [0] * 10;
    			SerPrint ("R (Winkelkalibrierung) Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			r = r + emfangene_daten [0];
    			break;
    			
    case 4: SerPrint ("O (Streckenkalibrierung (~25)) Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			o = emfangene_daten [0] * 10;
    	SerPrint ("O (Streckenkalibrierung (~25)) Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			o = o + emfangene_daten [0];
    			break;
    					
    case 8: SerPrint ("Winkel Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			degree = emfangene_daten [0] * 10;
    			SerPrint ("Winkel Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			degree = degree + emfangene_daten [0];
    			break;
    					
    case 16:SerPrint ("Strecke Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			distance = emfangene_daten [0] * 10;
    			SerPrint ("Strecke Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			distance = 10 * (distance + emfangene_daten [0]);
    			break;
    					
    case 32:SerPrint ("Geschwindigkeit Erste Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			sr = emfangene_daten [0] * 100;
    			SerPrint ("Geschwindigkeit Zweite Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			sl = emfangene_daten [0] * 10;
    			SerPrint ("Geschwindigkeit Dritte Zahl: \n\r: ");
    			SerRead (emfangene_daten, 1, 0);
    			speed = emfangene_daten [0] + sl + sr;
    			break;
    			}
    			sr = speed;
    			sl = speed;
    
    			r = x * 10;
    		
    			if (speed > 255)
    			{
    				speed = 255;
    			}
    
    			if (speed < 0)
    			{
    				speed = 0;
    			}
    		
    			if (distance >= 0)
    			{
    				MotorDir (FWD,FWD);
    				k = 1;
    			}
    
    			if (distance < 0)
    			{
    				MotorDir (RWD,RWD);
    				k = 2;
    			}
    		
    			if (degree < 0)
    			{
    				speedd = degree * r / distance;
    				sl = speed + speedd;
    				sr = speed - speedd;
    			}
    			if (degree > 0)
    			{
    				speedd = degree * r / distance;
    				sl = speed - speedd;
    				sr = speed + speedd;
    			}
    
    			if (speedl > 255)
    			{
    				speedd = sl - 255;
    				sr = 255 - speedd;
    				sl = 255;
    			}
    			if (speedr > 255)
    			{
    				speedd = sr - 255;
    				sl = 255 - speedd;
    				sr = 255;
    			}
    
    			SerPrint ("\n\rX: ");
    			PrintInt (x);
    			SerPrint ("\n\rWinkel: ");
    			PrintInt (degree);
    			SerPrint ("\n\rWeg: ");
    			PrintInt (distance);
    			SerPrint ("\n\rGeschwindigkeit: ");
    			PrintInt (speed);
    			SerPrint ("\n\rGeschwindigkeit Rechts: ");
    			PrintInt (speedr);
    			SerPrint ("\n\rGeschwindigkeit Links: ");
    			PrintInt (speedl);
    			SerPrint ("\n\rC: ");
    			PrintInt (c);
    			SerPrint ("\n\rO: ");
    			PrintInt (o);
    			SerPrint ("\n\rR (Winkelkalibrierung): ");
    			PrintInt (r);
    			SerPrint ("\n");
    
    			if (c > 0) {Msleep (10000);}
    
    			speedr = sr;
    			speedl = sl;
    	
    			n = distance * o / speed;
    
    			Msleep (200);
    			MotorSpeed (speedl,speedr);
    			for (c=0;c<n;c++) {Msleep (30);}
    			MotorSpeed (0,0);
    			Msleep (200);
    
    			if (k == 1)
    			{MotorDir (RWD,RWD);}
    			if (k == 2)
    			{MotorDir (FWD,FWD);}	
    
    			MotorSpeed (speedl,speedr);
    			for (c=0;c<n;c++) {Msleep (30);}
    			MotorSpeed (0,0);
    		}
    	}
    	while (1);
    	return 1;
    	BackLED (ON,ON);
    }
    Ich hab die Zeit, also für die Distanz, auch in eine Schleife gesetzt, da es jetzt nicht bei einer bestimmten Zahl abbricht und wieso würdest du fload statt int nehmen? Ich hab das Problem, dass mein einer Motor schneller als der andere läuft und deshalb müsste noch eine Odemerie-messung mit eingebaut werden, oder man kann es im Programm am anfang Kallibrieren. Hat jemand eine Idee?

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo Wo2le,

    nein, realistisch ist es nicht über eine Zeitvorgabe den Weg vorzugeben.
    Du hast ja schon den Ansatz mit der Odometrie angeführt. Nicht umsonst macht das die GoTurn()-Funktion schon lange.

    Ging das mit der NeueIntVariable?

    Gruß
    Lieber Asuro programieren als arbeiten gehen.

  8. #8
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    15.02.2008
    Ort
    Bremen
    Alter
    38
    Beiträge
    119
    Wenn du es einigermaßen genau haben möchtest, wirst du um die Odometrie wohl nicht herumkommen.

    Zum einlesen von Zahlen musst du deren ASCII-Darstellung (also den String) nach int (etc.) wandeln. Bspw. könntest du die einzelnen Bytes in ein Array einlesen bis du einen Zeilenumbruch bekommst, danach hängst du eine 0 an und steckst den Zeiger auf das Array in die Funktion atoi(char*). Schon hast du dein Int

    Wenn du noch ein wenig Fehlerüberprüfung machen willst, kannst du die Funktion auch selbst schreiben - die Ansätze dazu hast du in deinem Code oben ja schon:

    Code:
    int iVal = 0;
    char c;
    int count=0;
    const int MAX_COUNT = 6;
    char multiplier = 1;
    
    for (SerRead(&c,1,0); 
          ((c >= '0') && (c <= '9')) || (c=='-'); //nur Zahlen und Minus
          SerRead(&c,1,0))
    {
        count++;
        if ( count > MAX_COUNT )
            break; //Zu viele Zeichen
        else if ( c=='-' ) 
        {
            if (count == 1)
                multiplier = -1;
            else break; // Minus an der falschen Position
        else
        {
            iVal *= 10;
            iVal += c-'0';
        } 
    }
    iVal *= multiplier; //evtl. Vorzeichen beachten
    
    //iVal enthält jetzt ein signed int
    Code da oben ist ohne Gewähr, aber ich denke man sieht ungefähr, wie es funktionieren sollte ... Wenn man will, kann man noch auf Überlauf prüfen und vorne bspw. ein Plus-Zeichen zulassen etc.pp.

Berechtigungen

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