-         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 16 von 16

Thema: Wie kann ich mit i2c-Sensoren für Nibo2 kommunizieren?

  1. #11
    Neuer Benutzer Öfters hier
    Registriert seit
    02.02.2020
    Ort
    Harz
    Alter
    70
    Beiträge
    8
    Anzeige

    Praxistest und DIY Projekte
    Hallo Hannes,
    große Freude - ich kann den Sensor lesen!!! Habe deine Ratschläge beachtet, funktioniert so gut. Dass das MSB und das LSB im Datenblatt des Sensors in der umgekehrten Rehenfolge steht und nicht wie bei dem Arduino-Scetch-Beispiel, war mir gar nicht aufgefallen. Also nochmals vielen Dank für deine Hilfe!
    So, nun gehts weiter, nun muss ich mir etwas einfallen lassen, wie ich aus den Sensorwerten die Gradzahl des Winkels bekomme.
    Mein Vorhaben ist, wenn der Nibo2 im Labyrinth eine 90°-Drehung nach links machen soll, dann soll er das so lange machen, bis der Kompass-Sensor sagt, dass er die 90° erreicht hat. Ohne den Sensor, nur über die Umdrehungszahl der Motoren, wird alles zu ungenau, weil der Nibo2 auf dem Untergrund auch rutscht.
    Übrigens bin ich auch deiner Meinung, dass es ungünstig ist, den i2c-Bus über mehrere Libs anzusprechen, die sich stören könnten.
    Ich denke mir, es müsste doch möglich sein, die Routinen aus der i2cmaster.h-Datei, die du mir empfohlen hast, mit in die originale i2cmaster.h-Datei des Nibo2 zu übernehmen. Beim Syntax dürften die sich doch eigentlich nicht stören, so dass der nds3 weiter funktioniert und ich aber meine zusätzlichen Sensoren mit den neuen Routinen anspreche. Der Befehl i2c_init() wird dann natürlich nur einmal gegeben.
    Was hältst du von meiner Idee? Oder hast du einen besseren Vorschlag?
    Ich wünsche dir noch einen schönen Abend.
    Gruß
    Klaus

  2. #12
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    31
    Beiträge
    4.857
    Schön das es jetzt funktioniert.

    Ich würde mich auf eine Lib beschränken.

    Entweder versuchen den Kompass mit der Nibo Lib oder den NDS3 (und andere Komponenten falls vorhanden) mit der Lib von Peter Fleury.

    Die Adresse des NDS3 könntest du versuchen mit dem Simulator herauszufinden.
    Du startest den Simulator mit einem Programm das den NDS3 anspricht (z.B. Entfernung auslesen). Diesen Programmteil lässt du dann Schritt für Schritt abarbeiten. Die Initialisierung kannst du überspringen, indem du vor dem Kommando klickst (rechte Maustaste) und dann wählst du "Run to Cursor".
    Wenn der gelbe Pfeil dort angezeigt wird, drückst du F11 (Step Into) und schaust was in das TWI Datenregister geschrieben wird.
    Wenn du die vermeintliche Adresse hast könntest du es mit der Peter Fleury Lib testen, die einzelnen Kommandos und das Protokoll sind hier zu finden http://www.nibo-roboter.de/wiki/NDS3
    Du könntest dann eine eigene Library schreiben, die diese Funktionen enthält. Also eine eigene "NDS3.h" erstellen.

    Ich würde die Peter Fleury Lib nehmen, da du diese auch für andere Projekte (also wenn du den Nibo nicht verwendest) verwenden kannst. Die Nibo Lib ist speziell auf den Nibo zugeschneidert und ist dadurch nur schwer für andere Dinge zu gebrauchen.

    Ich wünsche dir ebenfalls einen schönen Abend
    MfG Hannes

  3. #13
    Neuer Benutzer Öfters hier
    Registriert seit
    02.02.2020
    Ort
    Harz
    Alter
    70
    Beiträge
    8
    Hallo Hannes,
    will mich mal wieder melden. Ich war nicht untätig, habe den Kompass-Sensor nun in mein eigentliches Nibo2-Programm eingebaut.
    Und - es funktioniert wirklich, dass der Roboter, wenn er um 90° nach links drehen soll, da auch tut. Und das mit deutlich besserer Genauigkeit als vorher, wo ich sozusagen nur die Umdrehungszahl der Räder als Maß hatte, ob der Roboter nun gerutscht ist oder nicht, also ob er seine Zielrichtung erreicht hat oder nicht.
    Jetzt kommt aber ein ABER - aber komischerweise klappt das 2 bis 3 mal gut im Labyrinth, und plötzlich hört er nach 90° nicht auf, macht mehrere volle 360°-Drehungen, um dann anschließend wieder ordentlich zu reagieren.
    Ich weiß beim besten Willen nicht, woran das liegt!?! Ob das Probem am Lesen der Sensordaten über den i2c-Bus liegt?
    Schau bitte nochmals auf meine Routine, die in der while-Hauptschleife liegt:
    Code:
    /********************** Registereinstellungen für Kompass-Sensor ************************************/
    void kompass_init()
    {
    	i2c_start(KOMPASS_ADR+I2C_WRITE);       	// set device address and write mode
    	i2c_write(0x09);                       		// write address = 9
        i2c_write(0x1D);                       		// Define OSR = 512, Full Scale Range = 8 Gauss, ODR = 200Hz, set continuous measurement mode)
        i2c_write(0x0A);                       		// write address = 10
        i2c_write(0x40); 							// The I2C data pointer will automatically roll, 6.Bit = 1 setzen
    	i2c_write(0x0B);                       		// write address = 11
        i2c_write(0x01); 							// Define Set/Reset period
    	i2c_stop();                            		// set stop conditon = release bus
    }
    								
    /********************** Kommpasswerte lesen *********************************************************/
    int16_t kompass_lesen()
    {
    	int16_t winkel;
    	i2c_start_wait(KOMPASS_ADR+I2C_WRITE);     	// set device address and write mode
    	i2c_write(0x00);                        	// write Register = 0 = welcher Wert aus welchem Register soll zuerst gelesen werden
    	i2c_rep_start(KOMPASS_ADR+I2C_READ);       	// set device address and read mode
    	x = i2c_readAck();                   		// read one byte from address 0	LSB  x 
    	x |= i2c_readAck()<<8;                  	//  "    "    "    "     "    1	MSB  x (um 8 Bit nach links verschieben und addieren)
    	y = i2c_readAck();                   		//  "    "    "    "     "    2	LSB  y
    	y |= i2c_readAck()<<8;                  	//  "    "    "    "     "    3	MSB  y (um 8 Bit nach links verschieben und addieren)
    	z = i2c_readAck();                    		//  "    "    "    "     "    4	LSB  z
    	z |= i2c_readNak()<<8;                  	//  "    "    "    "     "    5	MSB  z (um 8 Bit nach links verschieben und addieren)
    	i2c_stop();                            		// set stop condition = release bus
    	winkel = atan2 (-y, x) * 180 / PI;
    	if (winkel < 0)
    		{
    			winkel += 360;
    		}
    	deklination = (3 + (33 / 60)) / (180 / PI); // Deklination für Gernrode (+3° 33')
    	winkel += deklination;
    	return winkel;
    }
    Im Datenblatt des Sensors lese ich:

     Check status register 06H[0] ,”1” means ready.
     Read data register 00H ~ 05H.

    Vielleicht muss ich ja das Register 06H checken, ob das 0. Bit gesetzt ist?!?
    Kannst du mir erklären, wie ich dies in meiner Routine realisieren kann?
    Oder hast du evtl. noch eine andere Idee?

    Viele Grüße aus dem Harz sendet
    Klaus

  4. #14
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    31
    Beiträge
    4.857
    Ich würde zuerst das Statusregister lesen. Dieses hat 3 Bits (Bit 0 - Bit 2). Bit 0 bedeutet neue Daten vorhanden. Das 2te Bit ist auch sehr wichtig, es sagt dir ob eine oder mehrere Achsen überlastet sind (magnetische Feld zu groß). Das 3te Bit ist nicht so wichtig, es sagt nur das du einen Messwert übersprungen hast (nicht ausgelesen).

    Ich würde also das Statusbyte lesen und nur wenn Daten vorhanden sind (Bit 0 = 1) und du keine Achse überlastet hast (Bit 1 = 0) die Sensordaten auslesen. Wenn Bit 0 = 0 oder Bit 1 = 1 einfach die Messwerte ignorieren.


    Was mir auch noch auffällt. Du lässt deinen Ort mit in die Berechnung einfließen, warum? Du benötigst keine Absoluten Winkel sondern nur einen relativen zum vorhergehenden.

    MfG Hannes

  5. #15
    Neuer Benutzer Öfters hier
    Registriert seit
    02.02.2020
    Ort
    Harz
    Alter
    70
    Beiträge
    8
    Hallo Hannes,
    irgendwie habe ich mir das alles einfacher vorgestellt mit meinem Kompass-Sensor:
    Wenn eine Drehung durchgeführt werden soll, wird zuerst der augenblickliche Startwinkel ermittelt, dann der gewünschte Drehwinkel berücksichtigt und dann der Zielwinkel berechnet. Während der Drehung wird ständig der aktuelle Winkel ermittelt, und wenn der gleich dem Zielwinkel ist, wird die Drehung beendet.
    Soweit, so gut - in der Theorie. Praktisch klappt das mal, mal nicht. Ich fand heraus, dass beim Ermitteln des aktuellen Winkels immer mal wieder ein Wert ausgelassen wrd. Und wenn das zufällig der gewünschte Zielwinkel ist, habe ich eben Pech!
    Hier ist mein Code:
    Code:
    /********************** Kommpasswerte lesen *********************************************************/
    void kompass_lesen()
    {
    	int8_t status;
    	i2c_start_wait(KOMPASS_ADR+I2C_WRITE);     	// set device address and write mode
    	i2c_write(0x06);                        	// Statusregister 06H setzen
    	i2c_rep_start(KOMPASS_ADR+I2C_READ);		// set device address and read mode
    	do{											// warten, bis Statusregister Bit0 = 1 ist, dann Winkeldaten lesen
    		delay(20);
    		status = i2c_readNak() && 1;			// Statusregister lesen
    	}while (status == 0);
    		i2c_start_wait(KOMPASS_ADR+I2C_WRITE);  // set device address and write mode
    		i2c_write(0x00);                       	// write Register = 0 = welcher Wert aus welchem Register soll zuerst gelesen werden
    		i2c_rep_start(KOMPASS_ADR+I2C_READ);    // set device address and read mode
    		x = i2c_readAck();                   	// read one byte from address 0	LSB  x 
    		x |= i2c_readAck()<<8;                  //  "    "    "    "     "    1	MSB  x (um 8 Bit nach links verschieben und addieren)
    		y = i2c_readAck();                   	//  "    "    "    "     "    2	LSB  y
    		y |= i2c_readNak()<<8;                  //  "    "    "    "     "    3	MSB  y (um 8 Bit nach links verschieben und addieren)
    		i2c_stop();                            	// set stop condition = release bus
    		winkel_aktuell = atan2 (-y, x) * 180 / PI;
    		if (winkel_aktuell < 0)					// Winkelangabe in den Bereich 0° bis 360° bringen
    		{
    			winkel_aktuell += 360;
    		}
    }
    
    /************************* Soll-Drehwinkelberechnung ************************************************/
    void drehwinkel_soll(int16_t winkel)
    {
    	kompass_lesen();							// winkel_aktuell gibt die augenblickliche Fahrtrichtung an	
    	winkel_start = winkel_aktuell;				// winkel_start berechnen
    	winkel_ziel = winkel_start + winkel;		// winkel_ziel berechnen
    	if (winkel_ziel < 0)						// Winkelwert in Bereich 0° bis 360° bringen
    	{
    		winkel_ziel += 360;
    	}
    	else if (winkel_ziel > 360)
    	{
    		winkel_ziel -= 360;
    	}
    }
    Ich habe es auch ohne delay(20) in der kompass_lesen()-Routine versucht, bringt aber auch nichts.
    Mache ich etwas verkehrt? Hast du wieder einen Tipp für mich, vielleicht auch Erfahrungswerte?
    Bin gespannt.
    Gruß
    Klaus

  6. #16
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    31
    Beiträge
    4.857
    Deine Kompass Lesefunktion funktioniert glaube ich nicht so wie du willst. Speziell die do/while Schleife.

    Vergleiche mein I2C Lese Ablauf von Post 4 und deinen Ablauf. Du ließt den Status aus (nach dem delay(20)), verwendest aber ein NACK, danach sollte aber ein I2C-Stopp kommen. Ein NACK bedeutet das keine weiteren Daten gelesen werden, du ließt aber danach (nach 20ms) noch ein Byte.

    Ich würde es eher so machen:
    Code:
    I2C Start (Adresse + schreiben)
    I2C schreibe (0x06)
    I2C rep Start (Adresse + lesen)
    status = I2C Lese NACK
    I2C Stopp
    
    wenn Status OK (Daten vorhanden und keine Fehler)
    {
    X, Y und Z Daten auslesen
    }

    Was du auch noch machen kannst ist eine Hysterese einbauen, also nicht auf exakt 90° drehen, sondern wenn der Bereich zwischen z.B. 89 und 91° ist, ist er OK.

    Eine weitere Funktion wäre die Geschwindigkeit der Motoren im Bereich um den Zielwinkel zu reduzieren (z.B. Winkelabweichung > 45° => PWM=100%, Winkelabweichung > 25° => PWM = 50%,...)

    Beim Messen könntest du auch versuchen die Motoren abzuschalten. Also Motoren stoppen, Messwert auslesen, Ziel berechnen, Motoren wieder einschalten, delay

    MfG Hannes

Seite 2 von 2 ErsteErste 12

Ähnliche Themen

  1. Suche Microcontroller welcher mit Android kommunizieren kann
    Von Mr.P. im Forum PC-, Pocket PC, Tablet PC, Smartphone oder Notebook
    Antworten: 10
    Letzter Beitrag: 04.10.2012, 12:13
  2. Antworten: 3
    Letzter Beitrag: 17.12.2010, 23:03
  3. Wie kann Mega8 mit ProfiLab Expert kommunizieren?
    Von mikro-VIIV im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 15.12.2007, 15:54
  4. Welche Sensoren kann ich dafür verwenden?
    Von blue_man im Forum Sensoren / Sensorik
    Antworten: 12
    Letzter Beitrag: 20.05.2005, 19:53
  5. Sensoren kommunizieren miteinander
    Von Andreas im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 01.05.2004, 00:51

Stichworte

Berechtigungen

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