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

Thema: RP6 Master-Slave Einstellung

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    @Mac80,

    ok, vielleicht hatte ich eben dein Problem noch nicht richtig verstanden ...

    Das mit dem "Überdenken" hatte ich so gemeint:

    1. Du hast ja ein I2C-Bussystem mit einem Master (M32) und 4 Slaves (Base + 3x SRF08 ).
    2. Der Master kann mit den 4 Slaves kommunizieren und Daten abfragen.
    3. Normalerweise dient die M32 ja dann dazu, als "Gehirn" des Roboters zu funktionieren.
    4. Das heißt: Die M32 braucht die SRF08-Daten, um die Base wie gewünscht zu steuern.
    5. Das heißt auch: Die Base braucht die Sensordaten eigentlich nicht selbst, denn sie wird ja durch die M32 "ferngesteuert".
    6. Das Fernsteuern wird erreicht, indem in der Base das I2C-Slave-Programm läuft und in der M32 ein passender Master.

    Davon war ich ausgegangen. Willst du das irgendwie anders machen?
    Gruß
    Dirk

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2011
    Ort
    Hannover
    Beiträge
    9
    Hallo,
    ja so hatte ich mir das vorgestellt, dass der I2C-Master alle Daten abfragt. Da die Base ursprünglich die Sensordaten abgefragt hatte (Beispielprogramm), wollte ich das erstmal auch so lassen. Da aber der I2C-Master nun auf dem M32 läuft, musste ich das anpassen. Von der Leistung her sollte das für den M32 kein Problem darstellen.
    Mein neuer Ansatz wäre jetzt, auf dem Base (Slave) alle Sensordaten zu entfernen, außer den Definitionen und dem Registeranhang, wenn dies nötig ist. Über die Funktion "void I2C_requestedDataReady(uint8_t dataRequestID)" im M32-Master sollten dann I2C Abfragekollisionen vermieden werden können. Momentan hängen 5 Slaves am I2C Bus (Base, 3x Sensor SRF08 und ein inaktiver TSL2561 Lichtsensor). Wenn die Abfragen der SRF08 Sensoren störungsfrei funktionieren, dann kommt der TSL2561 dazu. Abfragen auch über den Master.
    Momentan muss ich nochmal die Ansteuerung der SRF Sensoren überarbeiten, da sei scheinbar nur messen, wenn die IR Sensoren ein Objekt detektieren. Ansonsten wird immer noch der Startwert 0 zugewiesen.


    Gruß
    Mac80

  3. #3
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Hallo Mac80
    ich gebe folgendes zu bedenken. So lange die Base die Sensoren auslesen soll und keine M32 aufsitzt, müsste alles funktionieren wie geplant. Sobald aber die M32 aufsitzt muss die Base als Slave laufen. Liest die Base aber dabei Sensoren aus, würde sie als Master auf dem Bus agieren und es wäre ein Multimaster System bzw die Base müsste Master und Slave Mode können. Dagegen ist technisch so nichts einzuwenden, jedoch hat die CPU angeblich Hardwareseitig ein Problem bei der Erkennung von Buskollisionen
    (http://www.robotroom.com/Atmel-AVR-T...r-Problem.html)
    und obendrein funktioniert die Busarbitierung mit der RP6Lib Software so nicht und es gibt auch sonst noch ein paar Schwierigkeiten.

    Allein ein System mit Base als "dummer" Slave, Slave-Sensoren und M32 als Master ist mit Boardmitteln denkbar aber leider relativ instabil. Mit der M128 lässt sich das entsprechend noch weiter spinnen - wobei die auch nur Funktionen vergleichbar mit der Feury Lib bietet und eher nicht Multimaster tauglich ist. (http://homepage.hispeed.ch/peterfleu...ware.html#libs)

    Wenn Dich die Hintergründe interssieren:
    https://www.roboternetz.de/community...-RP6Lib-Bugfix
    Ich habe jedoch die Arbeit daran magels Interesse & Feedback eingestellt. Wenn weiterhin Interesse an einem Multimastersystem besteht, empfehle ich Dir die Libs vom Arduino Projekt, dort insbesondere wire.cpp und twi.c/.h.
    Damit ist zumindest ein stabiler Multimasterslave Betrieb möglich.

    Leider macht das Gefummel mit den Interrupts in der RP6 Lib ein stabilen Betrieb der Base Slave schwierig - eigentlich bräuchte man auf der Base ein stabiles Core System wenn man mit der M32 anfängt zu experimentieren. Ich habe diesbezüglich mal mit Nano OS (http://sourceforge.net/projects/nanoos/ und http://www.mikrocontroller.net/topic/190388) experimentiert, aber bin bisher nicht zu vorzeigbaren Ergebnissen gekommen. Leider konnte ich auch noch niemand dazu bewegen, das als Team gemeinsam anzugehen und um das allein zu machen issses mir zu Aufwendig. Das I2C aber allgemein beim RP6 problematisch ist, erfährst du schon wenn du hier nach I2C suchst. Echte Lösungen findet man aber kaum - nur Minimallkompromisse und Provisorien.
    LG Rolf
    Geändert von RolfD (14.04.2012 um 14:35 Uhr)
    Sind Sie auch ambivalent?

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    04.09.2011
    Ort
    Hannover
    Beiträge
    9
    Hallo Rolf,
    ich habe jetzt das Erweiterungsmodul M32 stillgelegt, bis bei mir da eine bessere Lösung funktioniert. Bis dahin verwende ich nur das RP6 Base als Master, womit auch alle SRF Sensoren funktionieren.
    Da ich schon mit dem Arduino Mega 2560 die einzelnen Bauteile getestet hatte und mit Wire.h gut zu rande kam, stellten sich schon die ersten Probleme mit der I2C Umstellung beim RP6 ein.
    Wobei mich da jetzt das nächste Problem einholt. Mit dem Arduino konnte ich den TSL2561 ganz gut ansprechen, aber mit der jetzigen Lib (RP6I2CmasterTWI.h) habe ich so meine Probleme.

    Der (Beispiel) Code im Arduino:
    Code:
    #include <Wire.h>
    
    void setup()
    {
      Wire.begin();                // join I2C bus (address optional for master)
      Serial.begin(9600);          // start serial communication at 9600bps
    }
    
    int reading = 0;
    
    void loop()
    {
      Wire.beginTransmission(115);                            
      Wire.write(byte(0x00));    
      Wire.write(byte(0x51));      
      Wire.endTransmission();     
      delay(70);  
      Wire.beginTransmission(115);
      Wire.write(byte(0x02));     
      Wire.endTransmission();      
      Wire.requestFrom(115, 2); 
    
      if(2 <= Wire.available())    // if two bytes were received
      {
        reading = Wire.read(); 
        reading = reading << 8;   
        reading |= Wire.read();
        Serial.println(reading); 
      }
    
      delay(500); 
    }


    Übertragung (Kurzform) auf RP6I2CmasterTWI.h im RP6 Base:

    Code:
    #include "RP6RobotBaseLib.h" 	
    #include "RP6I2CmasterTWI.h"
    
    #define SRF_LEFT_ADR  0xE6
    #define SRF_MIDDLE_ADR 0xE4
    #define SRF_RIGHT_ADR 0xE2
    #define TSL_2561_ADR 0x39
    
    #define MEASURE_US_LEFT_LOW 	0
    #define MEASURE_US_LEFT_HIGH 	1
    #define MEASURE_US_RIGHT_LOW 	2
    #define MEASURE_US_RIGHT_HIGH 	3
    #define MEASURE_US_MIDDLE_LOW 	4
    #define MEASURE_US_MIDDLE_HIGH 	5
    #define MEASURE_TSL_DATA_LOW	6
    #define MEASURE_TSL_DATA_HIGH	7
    
    uint16_t distance_left = 0;
    uint16_t distance_right = 0;
    uint16_t distance_middle = 0;
    uint16_t lux = 0;
    
    //I2C Bus Werteabfrage auf Adressen
    void I2C_requestedDataReady(uint8_t dataRequestID)
    {
    	uint8_t messageBuf[8];
    	static uint8_t dist_tmp;
    	switch(dataRequestID)
    	{
    		case MEASURE_US_LEFT_HIGH:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			dist_tmp = messageBuf[0];
    			I2CTWI_transmitByte(SRF_LEFT_ADR, 3);
    			I2CTWI_requestDataFromDevice(SRF_LEFT_ADR, MEASURE_US_LEFT_LOW, 1);
    		break;
    		case MEASURE_US_LEFT_LOW:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			distance_left = messageBuf[0] + (dist_tmp << 8);
    			writeString_P("SRF_L: ");
    			writeInteger(distance_left, DEC);
    			writeString_P(" cm ");
    		break;
    		case MEASURE_US_RIGHT_HIGH:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			dist_tmp = messageBuf[0];
    			I2CTWI_transmitByte(SRF_RIGHT_ADR, 3);
    			I2CTWI_requestDataFromDevice(SRF_RIGHT_ADR, MEASURE_US_RIGHT_LOW, 1);
    		break;
    		case MEASURE_US_RIGHT_LOW:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			distance_right = messageBuf[0] + (dist_tmp << 8);
    			writeString_P("\tSRF_R: ");
    			writeInteger(distance_right, DEC);
    			writeString_P(" cm");
    		break;
    		case MEASURE_US_MIDDLE_HIGH:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			dist_tmp = messageBuf[0];
    			I2CTWI_transmitByte(SRF_MIDDLE_ADR, 3);
    			I2CTWI_requestDataFromDevice(SRF_MIDDLE_ADR, MEASURE_US_MIDDLE_LOW, 1);
    		break;
    		case MEASURE_US_MIDDLE_LOW:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			distance_middle = messageBuf[0] + (dist_tmp << 8);
    			writeString_P("\tSRF_M: ");
    			writeInteger(distance_middle, DEC);
    			writeString_P(" cm\n");
    		break;
    		case MEASURE_TSL_DATA_HIGH:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			dist_tmp = messageBuf[0];
    			I2CTWI_transmitByte(TSL_2561_ADR, 3);
    			I2CTWI_requestDataFromDevice(TSL_2561_ADR, MEASURE_TSL_DATA_LOW, 1);
    		case MEASURE_TSL_DATA_LOW:
    			I2CTWI_getReceivedData( messageBuf, 2 );
    			lux = messageBuf[0] + (dist_tmp << 8);			//
    			writeString_P("\tTSL: ");
    			writeInteger(lux, DEC);
    			writeString_P(" lux\n");
    		break;
    	}
    }
    
    //I2C Bus Fehlerausgabe
    void I2C_transmissionError(uint8_t errorState)
    {
    	writeString_P("\nI2C ERROR --> TWI STATE IS: 0x");
    	writeInteger(errorState, HEX);
    	writeChar('\n');
    }
    
    //SRF08 Sensorenfunktion
    void task_SRF(void)
    {
    	static uint8_t measureInProgress = false;
    	static uint8_t channel = 0;
    	if(!measureInProgress) // Start measurement ONCE only
    	{
    		if(TWI_operation == I2CTWI_NO_OPERATION) // Busverkehrüberwachung, freie Transfermöglichkeit
    		{
    			if(channel == 0)
    				I2CTWI_transmit2Bytes(SRF_LEFT_ADR, 0, 81);
    			else if(channel == 1)
    				I2CTWI_transmit2Bytes(SRF_RIGHT_ADR, 0, 81);
    			else if(channel == 2)
    				I2CTWI_transmit2Bytes(SRF_MIDDLE_ADR, 0, 81);
    			measureInProgress = true;
    			setStopwatch1(0);
    		}
    	}
    	else if(getStopwatch1() > 500) // 500ms Messverzögerung
    	{
    		if(channel == 0)
    		{
    			I2CTWI_transmitByte(SRF_LEFT_ADR, 2);
    			I2CTWI_requestDataFromDevice(SRF_LEFT_ADR, MEASURE_US_LEFT_HIGH, 1);
    			channel = 1;
    		}
    		else if(channel == 1)
    		{
    			I2CTWI_transmitByte(SRF_RIGHT_ADR, 2);
    			I2CTWI_requestDataFromDevice(SRF_RIGHT_ADR, MEASURE_US_RIGHT_HIGH, 1);
    			channel = 2;
    		}
    		else if(channel == 2)
    		{
    			I2CTWI_transmitByte(SRF_MIDDLE_ADR, 2);
    			I2CTWI_requestDataFromDevice(SRF_MIDDLE_ADR, MEASURE_US_MIDDLE_HIGH, 1);
    			channel = 0;
    		}
    		measureInProgress = false;
    		setStopwatch1(0);
    	}
    }
    
    int task_TSL()
    {
    	static uint8_t measureInProgress = false;
    	static uint8_t channel = 0;
    	uint8_t DataLow = 0;
    	uint8_t DataHigh = 0;
    	uint8_t Channel3 = 0;
    	
    	if(!measureInProgress)
    	{
    		if(TWI_operation == I2CTWI_NO_OPERATION)
    		{
    		if(channel == 3)
    				I2CTWI_transmit2Bytes(TSL_2561_ADR, 140, DataLow);
    				I2CTWI_transmit2Bytes(TSL_2561_ADR, 141, DataHigh);
    			measureInProgress = true;
    			setStopwatch2(0);
    		}
    	else if(getStopwatch2() >500)
    	I2CTWI_transmitByte(TSL_2561_ADR, 2);
    	I2CTWI_requestDataFromDevice(TSL_2561_ADR, MEASURE_TSL_DATA_HIGH, 1);
    	}
    	measureInProgress = false;
    	setStopwatch2(0);
    	Channel3 = DataHigh*256+DataLow;
    	return(Channel3);
    }
    
    
    
    int main(void)
    {
    	initRobotBase();
    	
    	I2CTWI_initMaster(100);
    	I2CTWI_setRequestedDataReadyHandler(I2C_requestedDataReady);
    	I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);
    
    	setLEDs(0b111111);
    	mSleep(500);	   
    	setLEDs(0b000000);
    	
    	powerON();
    		
    	
    	startStopwatch1();	//SRF
    	startStopwatch2();	//TSL2561
    	startStopwatch3();
    	
    	while(true)  
    	{
    		task_TSL();			//kommt noch...
    		task_SRF();
    		task_I2CTWI();
    		task_RP6System();
    	}
    	return 0;
    }

    Klappt noch nicht.

    Nach dem Chip Hersteller soll man die Struktur beachten:
    Read ADC Channels Using Read Byte Protocol

    Address = 0x39 //Slave addr − also 0x29 or 0x49
    Command = 0x8C //Address the Ch0 lower data register
    ReadByte (Address, Command, DataLow) //Result returned in DataLow
    Command = 0x8D //Address the Ch0 upper data register
    ReadByte (Address, Command, DataHigh) //Result returned in DataHigh
    Channel0 = 256 * DataHigh + DataLow //Shift DataHigh to upper byte
    Command = 0x8E //Address the Ch1 lower data register
    ReadByte (Address, Command, DataLow) //Result returned in DataLow
    Command = 0x8F //Address the Ch1 upper data register
    ReadByte (Address, Command, DataHigh) //Result returned in DataHigh
    Channel1 = 256 * DataHigh + DataLow //Shift DataHigh to upper byte


    Da bräuchte ich Hilfe.

    Gruß
    Mac80

  5. #5
    Erfahrener Benutzer Roboter-Spezialist Avatar von RolfD
    Registriert seit
    07.02.2011
    Beiträge
    414
    Da Du mit der Arduino Software vertraut bist sollte es dir möglich sein, die TWI funktionen aus der RP6 Lib rauszuwerfen (oder einfach nicht zu includieren) und statt dessen die Arduino Funktionen zu portieren.. das ist etwas arbeit aber es lohnt sich. Die twi.c/.h müsste man fast komplett so übernehmen können, evtl. auf sowas wie Frequenzen achten und so... die wire.c ist zwar in c++ geschrieben aber recht simpel - eigentlich ist es nicht kompliziert sie in ein normalen c code zu übertragen. Da könnte auch der GCC präprozessor bzw. g++ helfen. Ich halte es auch für machbar, einen Wrapper zu schreiben der die Aufrufe aus den Demoprogrammen gegen die RP6 TWI Libs austauscht gegen Aufrufe der Arduino Lib - so das man dann die noramlen RP6Lib Aufrufe weiter verwenden kann. Das wär aber dann schon Schritt 2.
    Dann wird jedenfalls auch dein TSL2561 und die Srfs wieder so funktionieren wie getestet. Ich habe diese Woche leider keine Zeit am Source zu arbeiten aber ich bin an den Ergebnissen interssiert und werde mich nächste Woche evtl. mal mit dran setzen.
    LG Rolf
    Geändert von RolfD (16.04.2012 um 02:54 Uhr)
    Sind Sie auch ambivalent?

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    40
    Beiträge
    1.516
    @Mac80:
    Zu dem TSL Code.
    Erstmal glaube ich das da ein paar Klammern in Deiner task_TSL nicht so ganz richtig gesetzt sind.
    Eine if Bedingung ohne klammer führt nur genau EINE direkt darauf folgende Zeile aus.
    Die Einrückung spielt in C anders als in Python keine Rolle

    Und was if(channel == 3) da überhaupt zu suchen hat ist mir auch nicht ganz klar.

    Also strukturier es doch zunächst etwas einfacher und versuch erst danach es so zu machen
    wie es für die SRFs gelöst wurde.

    Du musst ja nicht die requestedDataReady Funktion verwenden.
    Das ist nur um mehr Dinge nebenläufig erledigen zu können eingeführt worden.
    Es geht auch normal blockierend.

    Im Beispiel RP6Base_I2CMaster_04.c siehst Du wie man beide Arten auch miteinander mischen kann.

    Dann reduziert sich ein Zugriff auf so einen Sensor z.B. auf


    Code:
    #define PCF8591_4LDRS_ADR  0x90
    
    /**
     * Read 4x PCF8591 LDRs - we do not take advantage of the method we use for
     * the SRF Sensors above!
     */
    void task_ext_LDRs(void)
    {
        if(getStopwatch2() > 200) 
        {
            I2CTWI_transmitByte(PCF8591_4LDRS_ADR, 0b01000100 );  // 64 + 4); 
            
            uint8_t results[6];
            I2CTWI_readBytes(PCF8591_4LDRS_ADR,results,5);
            // Byte 0 contains last conversion result - thus we skip it and
            // begin with results[1]:
            writeString_P(" | LDR1:"); writeInteger(results[1], DEC); 
            writeString_P(" | LDR2:"); writeInteger(results[2], DEC); 
            writeString_P(" | LDR3:"); writeInteger(results[3], DEC); 
            writeString_P(" | LDR4:"); writeInteger(results[4], DEC); 
            writeChar('\n');
            setStopwatch2(0);
        }
    }
    Hier ein PCF8591 4 Kanal ADC auslesen - musst Du natürlich noch an den Sensor anpassen.
    Probiers doch erstmal so.

    MfG,
    SlyD

  7. #7
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    40
    Beiträge
    1.516
    Jetzt noch kurz eine Vermutung warum Du oben mit der Lib auf dem M32 Probleme hast.
    Du hast da einfach nicht bedacht das die RP6Control_I2CMasterLib mit eingebunden ist.
    Der Code gehört natürlich mit zum Programm!

    #define INT0_STATUS_CHECK 0

    und


    #define MEASURE_US_LEFT_LOW 0

    sind hier beide auf derselben Request ID.
    --> Schlecht.
    Also bitte alle Deine eigenen request IDs um 1 erhöhen.


    Dann noch folgendes aus einem der Beispielprogramme lesen:

    Code:
    /**
     * The I2C_requestedDataReady Event Handler is now a lot smaller. 
     * It is free for your own request routines. 
     * You can put them in the Block of the if condition.
     * (similar to the RP6 Base Example programs...)
     */
    void I2C_requestedDataReady(uint8_t dataRequestID)
    {
        // We need to check if this is an INT0 Request from the Robot Base unit.
        // The Function call inside the if condition returns true if it was an
        // interrupt request, so we have to negate it here and if it was NOT
        // an interrupt request from the Robot base we can check any other sensors
        // from which you may have requested data...
    
        if(!checkRP6Status(dataRequestID)) 
        {
            // Here you can Check other sensors/microcontrollers with their own
            // request IDs - if there are any... 
        }
    }


    Dein Code gehört also eigentlich in die If Bedingung rein.
    Nicht davor.
    Das alleine wäre aber nicht so schlimm, problematischer
    ist da schon das mit der doppelt belegten request ID.

    Das kommt sich natürlich in die Quere da ja beides gleichzeitig läuft...



    Ob das das einzige Problem ist oder noch an anderer Stelle irgendwas nicht stimmt habe ich jetzt nicht genauer untersucht.
    Aber ändere erstmal das und teste es dann nochmal.

    Hattest Du am Slave Code von der RP6Base irgendwas geändert?
    (Ich frage nur weil Du den Code hier gepostet hattest, auf den ersten blick sieht der unverändert aus)

    MfG,
    SlyD

Ähnliche Themen

  1. Master & Slave AVR
    Von Tonyy im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 30.09.2010, 20:14
  2. Slave-Master-Slave übertragung geht nicht
    Von Dämmi im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 16
    Letzter Beitrag: 26.11.2008, 00:08
  3. I²C Master und Slave, Problem bei Master Reset
    Von ACU im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 01.03.2007, 11:07
  4. LPT-Master <=> SPI <=> AVR-Slave
    Von BlueNature im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 17.04.2006, 20:38
  5. 2 x I2C Master und 1 x Slave
    Von Anubisbot im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 29.12.2005, 13:27

Stichworte

Berechtigungen

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

LiFePO4 Speicher Test