- LiTime Speicher und Akkus         
Ergebnis 1 bis 10 von 10

Thema: Sensoren blockieren I2C Bus

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    Sensoren blockieren I2C Bus

    Anzeige

    Powerstation Test
    Einen schönen guten Morgen zusammen:

    ich habe eine Frage zum I2C Bus.
    Da ja viele Sensoren mit diesem Bus ausgestattet sind, habe ich hier gepostet.

    Meine Idee war folgende:
    Da sich mehrere Chips auf dem Bus befinden können, wollte ich nach einem Reset
    den Bus mit "allen" Adressen scannen, um festzustellen welche Adressen bzw. Chips ansprechbar sind.

    1.Dazu sende ich lediglich eine Startcondition
    2.dann das Adressbyte mit dem R/W Bit (READ=High)
    3.und dann wieder die Stop Condition

    Das 9te Bit nach dem Adressbyte ist das Ack oder Nack vom Slave.
    Bekomme ich ein Ack, weis ich, dass sich die Adresse bzw. der Chip auf dem Bus
    befindet und ansprechbar ist.

    Das habe ich dann gleich mal ausprobiert und das klappte wunderbar.
    Dann habe ich einen Barometer Chip vom Type BMP180 an den Bus gehangen
    Er reagierte auch korrekt mit einem ACK, aber dann hielt er die SDA Leitung auf Low.
    Auch nachdem ich die Stop Condition gesetzt habe, blieb die Datenleitung Low.
    Der Bus ist damit komplett blockiert.

    Dann habe ich im Adressbyte das R/W Bit auf WRITE=Low gesetzt
    und den Versuch wiederholt.
    Nun funktioniert es korrekt: Slave sendet sein Ack und
    die Datenleitung geht wieder auf High, der Bus ist wieder frei.

    Also zurück und wieder mit Read probiert.
    So hatte ich endlich mal die Gelegenheit "gezielt" zu testen
    wie ich bei Fehlern den Bus zurücksetzten kann.

    Ich habe bei einem Fehler (Datenleitung bleibt Low)
    nun auf Portmode umgeschaltet und einzelne Clocks erzeugt.
    Nach 3 oder 8 Clocks gaben die Chips den Bus wieder frei.

    Diese Problem wunderte mich jetzt und ich habe diverse I2C Chips
    ausprobiert wie sie sich verhalten.


    #define ADXL345_ADDRESS 0x53 // OKAY Accelerometer Beschleunigung
    #define L3G4200_ADDRESS 0x69 // OKAY Gyroskop Drehraten
    #define HMC5883_ADDRESS 0x1E // OKAY Kompas/Magnetometer
    #define BMP180_ADDRESS 0x77 // Problem Barometer problem bei Read dann 8 clocks
    #define BMP280_ADDRESS 0x76 // Problem Barometer problem bei raed dann 8 clocks
    #define ADS1110_ADDRESS 0x48 // Problem AD Converter problem bei raed dann 8 clocks
    #define MPU9250_ADDRESS 0x68 // OKAY wenn AD= auf Masse liegt, sonst 0x69
    #define MPU6050_ADDRESS 0x68 // OKAY wenn AD0 = Low sonst 0x69
    #define PCA9685_LED_ALL 0x70 // Problem bei read dann 3 Clock

    Jetzt kommt meine Frage:
    Muss nach einer Stop Condition nicht der Bus generell vom Slave freigegeben werden ?
    Und warum verhalten sich nur einige Chips derart und dann auch nur im Read Modus ?

    Ich hatte die Idee, dass es eventuell durch den 10 Bit Adressmodus wäre
    und manche Chips halt ein 2tes Byte benötigen für die Adresse
    aber das müsste dann bei Read und bei Write identisch sein,
    der Fehler tritt aber nur bei Read auf.

    Achja, zur Info:
    Ich habe bei den Versuch generell nur EINEN Chip am Bus gehabt um das Verhalten zu prüfen.
    Die beiden Pullups sind natürlich dran. 3K3 an 3,3V

    Also solange man mit Write arbeitet scheint es ein gute Methode zu sein
    um den Bus bzw. die angeschlossenen Slaves zu prüfen.
    Sollte der Bus tatsächlich mal blockiert werden, wird ja generell empfolen
    9 Clocks zu erzeugen.

    Ich könnte natürlichh auch generell noch ein Byte einlesen, dann müsste es auch immer funktionieren bei Read
    das probiere ich grade.....
    Jo, das scheint sich zu bestätigen.
    Fazit: Erst mich anquatschen und dann nix von mir wollen mögen einige Chips nicht und reagieren erbost mit Blockade

    Vielleicht habt Ihr dazu etwas Information für mich.
    Siro
    Geändert von Siro (27.01.2018 um 09:15 Uhr)

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Siro Beitrag anzeigen
    ich habe eine Frage zum I2C Bus.
    Da ja viele Sensoren mit diesem Bus ausgestattet sind, habe ich hier gepostet.

    .....

    Jetzt kommt meine Frage:
    Muss nach einer Stop Condition nicht der Bus generell vom Slave freigegeben werden ?
    Und warum verhalten sich nur einige Chips derart und dann auch nur im Read Modus ?
    Deine Beobachtungen sind völlig richtig. Hier ein paar Erklärungen. Im Write-Mode ist SDA immer (Ausnahme ACK) unter Kontrolle des Masters. Beim Read hat aber der Slave die Kontrolle über SDA. Da gibt es dann Situationen, bei denen der Master gar keinen Stop erzeugen kann, der Slave hält SDA auf low. Manchmal reicht es, solange Takte auf SCL auszugeben, bis SDA frei (high durch den Pullup) ist und dann einen STOP zu erzeugen. Spätestens nach 8 (9?) Takten ist das erreicht, die Übertragung eines Bytes abgeschlossen. Es ist also am einfachsten, immer 8 Takte zu erzeugen und dann einen STOP.

    Wie kommt man in die Situation mit dem klemmenden Bus? Zuallerst beim Debuggen. Mitten in der Übertragung wird gestoppt, der Master resettet, bevor ein STOP erzeugt hat etc. Es ist also hilfreich, am Anfang der Initialisierung des I2C Controlers SCL 8 mal zu takten und dann ein STOP zu generieren.

    Der nächste Fall ist eine Adresse mit READ ohne zu lesen. Manche Slaves übernehmen die Kontrolle über SDA beim READ gleich nach dem ACK. Wenn sie dann eine 0 liefern wollen, kann der Master kein STOP erzeugen und der Bus klemmt. Daher sollte man einen I2C Bus nur mit einem WRITE scannen.

    Eine weitere Situation entsteht, wenn man das letzte Byte eines READS nicht mit einem NAK quitiert. Auch das bringt manche Slaves dazu, den Bus zu blockieren.

    Die Fälle lassen sich aber in der Software leicht vermeiden.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hab erstmal vielen Dank für deine Informationen Klebwax

    Okay, dann sind also meine Messungen richtig und das Verhalten ist tatsächlich etwas unterschiedliche bei den Chips.
    Dann werde ich generell mit einem Write "scannen"

    Beim Debuggen hab ich auch schon so einige Chips aus der Ruhe bringen können, ja das ist oft kritisch....

    Eine weitere Situation entsteht, wenn man das letzte Byte eines READS nicht mit einem NAK quitiert. Auch das bringt manche Slaves dazu, den Bus zu blockieren.
    Genau das ist mir schon passiert. Ich hatte ein EEPROM am Bus und das lief Jahrelang einwandfrei,
    dann habe ich es ausgetauscht von einem anderen Hersteller und plötzlich lief es nicht mehr richtig.

    Beim letzten Byte lesen hatte ich kein NACK gesendet und das "alte" EEPROM hatte damit kein Problem und hat sich anscheinend wieder
    mit dem STOP synchronisiert. Das neue EEPROM jedoch wollte unbedingt ein NACK haben.

    Siro
    Geändert von Siro (27.01.2018 um 12:41 Uhr)

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    .. Der Bus ist damit komplett blockiert. .. Vielleicht habt Ihr dazu etwas Information für mich ..
    Vor etlichen Jahren verstand ich von I²C/TWI so ziemlich nix, hatte aber auch mal mit der Zeitdehnung des Slaves zu kämpfen. Damals hatte ich mit - zugebenermassen - unanständigen Mitteln mich aus der Affaire gezogen: ich hatte in den I²C-Routinen eine for-Schleife eingebaut. Aus meinen alten Beständen (nach mühevoller Suche) mal ein Beispiel zur Verdeutlichung :
    Code:
    unsigned char i2c_start(unsigned char address)
    {                               //
        uint8_t   twst;             //
        uint8_t   tggl;             //
        uint8_t   tttt = TWBR;      //
    
        // send START condition
        TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
        // wait until transmission completed
    //    while(!(TWCR & (1<<TWINT)));    // ##################
        for (uint16_t m = 0; m<=60000; m++) 
            { if ((TWCR & (1<<TWINT))) break;       // I2C-Device hat sich gemeldet
              for (uint8_t n = 0; n<= tttt; n++)    // wenn nicht 
              { tggl    = 29 + 2; }                 //      => Zeit schinden
            }
    
        // check value of TWI Status Register. Mask prescaler bits.
        twst = TW_STATUS & 0xF8;
        if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
    
        // send device address
        TWDR = address;
        TWCR = (1<<TWINT) | (1<<TWEN);
    
        // wail until transmission completed and ACK/NACK has been received
    //    while(!(TWCR & (1<<TWINT)));    // ##################
        for (uint16_t m = 0; m<=60000; m++) 
            { if ((TWCR & (1<<TWINT))) break;       // I2C-Device hat sich gemeldet
              for (uint8_t n = 0; n<= tttt; n++)    // wenn nicht 
              { tggl    = 29 + 2; }                 //      => Zeit schinden
            }
    
        // check value of TWI Status Register. Mask prescaler bits.
        twst = TW_STATUS & 0xF8;
        if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
    
        return 0;
    
    }/* i2c_start */
    Ich bin nicht sicher ob genau dieser Code gelaufen war, aber in die Richtung gings dann mal richtig gut. Mittlerweile lebe ich problemlos mit dem Stetching . . *gg*. Aber es war mir immerhin die Erfahrung wert.

    .. Muss nach einer Stop Condition nicht der Bus generell vom Slave freigegeben werden ? ..
    Am besten der alte Ratschlag: RTFM, z.B. die Application Note AVR311, Atmel-2565E-Using-the-TWI-Module-as-I2C-Slave_AVR311_Application Note-03/2016 oder so. Dazu natürlich auch die AVR315: Using the TWI module as I2C master (meine ist Rev. 2564B-AVR-09/04).
    Geändert von oberallgeier (27.01.2018 um 11:40 Uhr) Grund: AppNote
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Meine ersten Funktionen sahen nicht viel anders aus, als ich mit dem I2C Bus angefangen habe:

    Code:
    /******************************************************************************/
    /* tested OKAY */
    /* wait max 5 ms that the SI bit in the I2C0CONSET Register becomes High */
    /* return TRUE if Bit is or goes High in this time */
    /* return FALSE if SI Bit never set in this time */
    /* normaly after clearing the SI bit in the I2CCONSET register, the */
    /* shift transfer startet. 9 clock cycles, 8 data, 1 acknowlwdge. if all */
    /* bits shifted out and the Ackbit received the SI bit sets automatically by */
    /* the hardware. */
    /* shift clock is 100Khz = 10us per bit * 9 = 90 usec. */
    /* timeout was set to 5ms */
    /* !!!! after a stop condition, this bit is alwas zero and never set. */
    /* info: the SystemTickCount increments every milli second TIMER0 Interrupt */ 
    
    BOOL wait_i2c_SI()
    { U32  time;
      
      time = SystemTickCount + 2;         /* 07.11.2011   wait max 2 ms (timeout) */
    
      do 
      {  
        if (LPC_I2C0CONSET & I2CONSET_SI) /* if SI bit is set */
             return TRUE;                 /* return with TRUE */
      } while (SystemTickCount < time);   /* else wait */
     
      /* if the above lines are interrupted, maybe an timout occure */
      /* so we test the SI flag again, after timeout */
      if (LPC_I2C0CONSET & I2CONSET_SI)   /* if SI bit is set after timeout */
             return TRUE;                 /* return with TRUE */  
    
      return FALSE;                       /* else time out return FALSE */
      
    }
    /******************************************************************************/
    
    
    BOOL ee_read(U32   EE_Address,
                  void *DataAddress,
                  U32   DataSize)
    { U32 time;
      volatile U8* dataptr = DataAddress;
    
      /* the EEPROM write cycle time is max 20ms for byte and page write */
      /* maybe we must wait, because the last write is not ready now */
      /* other interrupts may occur, so we set the max waittime to 100ms */
    
      time = SystemTickCount + EE_WRITE_CYCLE_TIME; /* set max waittime to 100 ms*/
      while (ee_busy(EE_Address))
      {
         if ((SystemTickCount > time) && (ee_busy(EE_Address)))
            return FALSE; /* EE BUSY Time Out Error */
      }
    
      LPC_I2C0CONSET = I2CONSET_STA;    /* Set Start flag */
      if (!wait_i2c_SI()) return FALSE;     /* wait until SI Flag is set */
      LPC_I2C0CONCLR = I2CONCLR_STAC;    /* Clear the Start flag */  
    
      LPC_I2C0DAT =  EE_SLAVE_ADDRESS | ((EE_Address >> 8) << 1); /* send Slave Address and the 3 Upper Adressbits */
      LPC_I2C0CONCLR = I2CONCLR_SIC;         /* clear the SI Flag */
                                   /* starts the shift out Device Address */
      if (!wait_i2c_SI()) return FALSE;     /* wait until SI Flag is set */
    
      LPC_I2C0DAT = (U8)(EE_Address);        /* EEPROM Address */
      LPC_I2C0CONCLR = I2CONCLR_SIC;         /* clear the SI Flag */
                                             /* starts the shift out EEPORM Address */
      if (!wait_i2c_SI()) return FALSE;      /* wait until SI Flag is set */
    
      /* reading:  first set the control byte (Slave Address) with RD bit=1 */
      /* include the 3 Upper Adressbits from the eeprom address */
    
      LPC_I2C0CONSET = I2CONSET_STA;    /* Set Start flag, repeated start condition  */
      LPC_I2C0CONCLR = I2CONCLR_SIC;        /* clear the SI Flag, start shift out repeatetd start condition */  
      if (!wait_i2c_SI()) return FALSE;     /* wait until SI Flag is set */
      LPC_I2C0CONCLR = I2CONCLR_STAC;    /* Clear the Start flag */  
    
      LPC_I2C0DAT = EE_SLAVE_ADDRESS | ((EE_Address >> 8) << 1) | I2C_RD_BIT; 
      LPC_I2C0CONCLR = I2CONCLR_SIC;         /* clear the SI Flag */
                                             /* starts the shift out the control byte with RD Bit=1*/
      if (!wait_i2c_SI()) return FALSE;      /* wait until SI Flag is set */
    
      LPC_I2C0CONSET = I2CONSET_AA;      /* assert ACK after every received data byte */
    
      /* start READ LOOP:  */
      while (DataSize--) /* read all data bytes from EEPROM with always ACK */
      {
    
        /* after the last byte the master must send "NACK" to end the sequential read 02.03.2011 */
        if (!DataSize) LPC_I2C0CONCLR = I2CONSET_AA;      /* assert NACK after last byte received 02.03.2011 */
        
        LPC_I2C0CONCLR = I2CONCLR_SIC;         /* clear the SI Flag */
                                               /* starts the shift in data byte */
        if (!wait_i2c_SI()) return FALSE;      /* wait until SI Flag is set */
        *dataptr++ = LPC_I2C0DAT;              /* save received data byte */
      }  
      /* end READ LOOP */
      
      LPC_I2C0CONSET = I2CONSET_STO;         /* set STOP condition, sets SDA-Pin to Low NOW */
      LPC_I2C0CONCLR = I2CONCLR_SIC;         /* clear the SI Flag */
                                             /* starts the shift out STOP Condition */
                                             /* clears the STOP bit */
    /* !!!!!!! SI are never set , dont wait here */
      
      return TRUE;
    }
    2011 habe ich anscheinend das neue EEPROM benutzt und merkte, dass ich ein NACK beim letzten Byte brauche....
    Das war/ist ein CAT24C08 EEPROM
    Geändert von Siro (27.01.2018 um 12:45 Uhr)

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    Das Beispiel von Oberallgeier kann man noch erweitern indem man den Bus Status abfragt oder wenn mehrere Anfragen fehlschlagen einfach mal einen Bus reset durchführt.
    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    @damfino:
    ja, das habe ich zum probieren auch so gemacht mit den Status Abfragen, da ich das ganze dann im Interrupt verarbeiten möchte.
    so kann ich schön mit Breakpoints gucken wie der interne Status vom Controller steht.

    Code:
    //----------------------------------------------------------
    BOOL i2c_check(U8 address, U8 ReadWriteMode)
    { volatile U8 stat;
      BOOL result;
    
    // stat mueste 0xF8 sein
      stat = I2C_STAT;
    
    //  setze das Startflag
      I2C_CONSET = CON_STA;      // STA Set Start flag
      // Start Condition wird sofort ausgeschoben
    
      // warte auf das SI Flag, dann ist Startcondition fertig
      if (! i2c_waitSI())
      {
        i2c_stop();
        return FALSE;
      }
    
    // stat muesste nun 0x08 sein
      stat = I2C_STAT;
      I2C_CONCLR = CON_STAC;  // loesche das Start Flag
    //  set address and read/write bit to the dat register
      I2C_DAT = (address << 1 ) | ReadWriteMode;
      // loesche SI Flag startet das Ausschieben der Adresse und RW Bit
      I2C_CONCLR = CON_SIC;
    
      // warte auf das SI Flag
      if (! i2c_waitSI())
      {
        i2c_stop();
        return FALSE;
      }
    
      stat = I2C_STAT;
    // stat muesste nun 0x18 sein wenn ACK gesendet wurde vom Slave
    // oder 0x20 Adresse transmitted, no ACK received, kein Slave antwortet
    // wenn ReadMode also RW Bit = 1 dann wird der status 0x40 oder 0x48
      result = FALSE;
      if ((ReadWriteMode == I2C_WRITE) && (stat == 0x18)) result = TRUE;
      if ((ReadWriteMode == I2C_READ ) && (stat == 0x40)) result = TRUE;
    
    
      // neu 27.01.2018 , wir lesen ein Byte ein, damit sich die Chips wieder
      // synchronisieren können. Einige brauchen das anscheinend
      I2C_CONCLR = CON_AAC;   // clear the Ackflag // wir wollen danach nichts weiter lesen NACK
      I2C_CONCLR = CON_SIC;   // loesche SI Flag startet das Ausschieben der Adresse und RW Bit
    
      // warte auf das SI Flag
      if (! i2c_waitSI())
      {
        i2c_stop();
        return FALSE;
      }
    
      stat = I2C_STAT;
    
      // STOP condition
      I2C_CONCLR = CON_STAC;  // clear the Start flag
      I2C_CONCLR = CON_AAC;   // clear the Ackflag
      I2C_CONSET = CON_STO;   // set STO
    
      // loesche SI Flag startet, das Ausschieben der Stop condition
      I2C_CONCLR = CON_SIC;
    
    // stat mueste wieder 0xF8 sein
      stat = I2C_STAT;
    
      return result;
    }
    Geändert von Siro (27.01.2018 um 13:05 Uhr)

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Das Beispiel von Oberallgeier kann man noch erweitern ..
    Die aktuelle Abfragen des I²C-Busses beim Start von archie - > 1 m lang - erzeugen die folgenden Ausgaben auf UART/Terminal und LCD (bessere Auflösungen im Bild verlinkt ) . Angezeigt werden also drei (von mehreren Slaves), hier MotorController, KopfController und ArmRechtsCOntroller. Üblicherweise wird aber auch der ALCo (ArmLinksController) angezeigt :

    ......Bild hier  

    ......Bild hier  

    In der kompletten UART-Aufzeichnung (im Bild verlinkt) trennt der rote Strich zwei Zustände. Wenn die I²C-Leitung mit einem nicht-stromführenden Slave verbunden ist (Beispiel unterhalb rot - korrig.28.1.´18x) dann hängt das Programm beim ersten I²C-Aufruf. Ist "nur" die I2C-Leitung vom Bus abgeklemmt worden, dann kommen die kompletten Suchergebnisse, siehe oben.

    Der dazugehörige Code steht unten. Dem fehlt offenbar ne Abfrageschleife, die im main von archie den Fehler abfängt (existiert derzeit nicht) :
    Code:
    // ============================================================================= =
    // ============================================================================= =
     void i2clook (void)            // Welche I²C-Devices existieren? Liste ?
     {                              //                              Aufruf     main =>
    // Teste I²C-Schreibadressen von 0x70hex bis 0xAC, 112 - 254 (früher bis 0xFC)
    //   ##>> Testbereich einschränken auf 112 - 159 bzw x70 - x9F
    //      Erfolgsmeldung(en) ausgeben mit Adresse dez und hex, Fehlsuche mit "-"
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //              B E A C H T E   bei   S T O E R U N G
    //      https://www.roboternetz.de/community/threads/71534-Uhrschalt
    //      plan-%C3%BCberpr%C3%BCfen-MOSFET-und-MAG3110?p=642024&view
    //      full=1#post642024
    ////        Dazu lässt man SDA aus Sicht des Masters offen und erzeugt 9 mal einen
    ////            Takt auf SCL. Danach erzeugt man ein Stop. Das sollte die
    ////            Statemachine im Slave zurück setzen
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      uint8_t jaflag = 0;           // Ja-Flag
    // - - - - - - - - - - - - - - -
    
      uputs0 ("\r\tSuche I²C-Devices im Bereich 0x70/112dez - 0xFE/254dez"); 
      uputs0 ("\r\tJedes '-' bedeutet: Slave/s nicht vorhanden oder defekt\r\t");
                                    // war 0x70 - 0xAC
                                    // bzw 0x70/112dez - 0x9F/159dez bzw 0x70 - 0xAC
      Line2();                      // LCD vorbereiten für Anzeige
      lcd_string("                ");       // Zeile 2 löschen
    
      for ( u8 such=0x70; such <= 0xF0; such = such + 2 )   // Adressenbereich
      {                             // Teste den I2C-Adressbereich gemäß for-Schleife
        if(!(i2c_start(such)))      // Slave bereit zum schreiben?
        {                           // 
          i2c_stop();               // Zugriff beenden
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //##25Jun14,14h01    uputs0 ("\r\t\tSlave addr\t"); // Melde zugriffbereiten Slave
    //      =: SetCursor (2, 10) heisst SetCursor (x,y), x=zeile {1,2}, y=Pos {0, 15}
          uputs0 ("\r\t\tSlave addr\t");      // Melde zugriffbereiten Slave
          uputs0i (such); uputs0hex (such); //   .. mit dezimaler und Hex-Adresse
          // Hilfsschema zur Anordnung von Text am LCD     0123456789012345
          //                                               MoC KoC ARC ALC 
          if (such==130)            //
          { uputs0("\tMoCo"); SetCursor (2,  8); lcd_string("MoC "); }
          if (such==132)            //
          { uputs0("\tKoCo"); SetCursor (2,  4); lcd_string("KoC "); }
          if (such==134)            //
          { uputs0("\tARCo"); SetCursor (2,  0); lcd_string("ARC "); }
          if (such==136)            //
          { uputs0("\tALCo"); SetCursor (2, 12); lcd_string("ALC "); }
          jaflag = 55;              //
        }                   // ist if(!(i2c_start(such)))
        else                        // Melde: Kein Byte geschrieben
        {                           //      und Fehlermelde-Strich
          i2c_stop();               // Zugriff bei Fehlerfall beenden, sonst SDA low
          if ( jaflag == 55 )       // Flag "Slave erkannt" ??
          {                         //
            uputs0 ("\r\t");          //
          }                 // Ende if ( jaflag = 55; )
            jaflag    =  0;         // Flag zurücksetzen
          uputs0 ("-");             //
        }                   // Ende if(!(i2c_start(such)))
      }             // Ende for (uint8_t such=0x70..; Alle Slaveadressen sind getestet
     }              // Ende Ende void i2csuch (void)
    // ===  Ende Routine i2clook
    // ============================================================================= =
    Geändert von oberallgeier (28.01.2018 um 09:46 Uhr) Grund: Bilderupload komplett
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    06.08.2008
    Ort
    Graz
    Beiträge
    521
    i2c_start liefert 0 oder 1 zurück. Wird aber vom Programm nicht ausgewertet da nur mit if(!(i2c_start(such))) abgefragt wird. Wenn jetzt der Bus hängt kommt man auch nicht mehr raus. Ein eventueller Stop Befehl hat gar keine Wirkung
    Wenn man aber bei 1 einen Bus reset macht, wird die nächste Abfrage an einen andere Slave funktionieren.

    Ich hatte das gleich in die library eingebaut, zB:


    zB:
    Code:
    void i2c_stop(void){
    unsigned short timeout=0;
     //uint8_t   twst;
        /* send stop condition */
        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
       // wait until stop condition is executed and bus released
    
        while((TWCR & (1<<TWSTO))&& ++timeout);
    
        if( TW_STATUS & 0xF8 == TW_BUS_ERROR) 
            { // TWI aus, Pause, wiedereinschalten.
            TWCR &= ~((1 << TWSTO) | (1 << TWEN));
            _delay_ms(2);
            TWCR |= (1<<TWEN);            
            } 
    
    
    
    
        _delay_us(5);
    
    
    
    }/* i2c_stop */

    alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    14.02.2018
    Beiträge
    15
    Deshalb verwendet man in sicherheitskritischen Systemen keine solchen Busse sondern packt jeden Sensor an eine eigene Leitung und multiplext sie.

Ähnliche Themen

  1. Lift für Riesenglotze - Gasdruckfeder elektronisch blockieren (oder andere Lösung)?
    Von matzrh im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 3
    Letzter Beitrag: 04.10.2019, 23:57
  2. Blockieren vom Steppermotor erkennen
    Von skywalker1979 im Forum Motoren
    Antworten: 11
    Letzter Beitrag: 01.08.2013, 09:39
  3. Kann ein Nabenmotor blockieren?
    Von Daniel002 im Forum Motoren
    Antworten: 5
    Letzter Beitrag: 24.07.2012, 13:44
  4. Zerstörung von Servos durch blockieren?
    Von avrrobot im Forum Motoren
    Antworten: 1
    Letzter Beitrag: 08.01.2012, 21:52
  5. [ERLEDIGT] IR-Sensoren
    Von highlow im Forum Sensoren / Sensorik
    Antworten: 0
    Letzter Beitrag: 25.10.2005, 16:57

Berechtigungen

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

LiFePO4 Speicher Test