- 3D-Druck Einstieg und Tipps         
Seite 1 von 4 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 34

Thema: SRF02. Wie ohne Timer Messwert-Abfrage steuern

  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652

    SRF02. Wie ohne Timer Messwert-Abfrage steuern

    Anzeige

    Powerstation Test
    Hallo alle,

    ich habe meine Probleme, aktuell mit dem SRF02, meinem Englisch und der Bedienungsanleitung des SRF02. Dort steht nämlich zu Checking for Completion of Ranging:
    Zitat Zitat von robot-electronics-co-uk
    ... ... Therefore, if you try to read from the SRF02 ... then you will get 255 (0xFF) whilst ranging ... As soon as the ranging is complete ... its not 255 (0xFF) anymore ... ...
    Also programmiere ich unbedarft:
    Code:
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //      Messung starten auf Sensor Sadd
    // - - - - - - - - - - - - - - -
      if (!(i2c_start( Sadd + I2C_WRITE ))) // Slave bereit zum schreiben?
      {                                     //   dann Werte schreiben
        i2cdmy  =  i2c_write (  00 );       // Buffer Startadresse setzen     
        i2cdmy  =  i2c_write ( 0x51 );      // Startbefehl SRF02
                   i2c_stop();              // Zugriff beenden
      }                                     //
      else                  // Weiter mit if (!(i2c_start( Sadd + I2C_WRITE )))
      {                                     //
        uputs0("\r\n\t## SRF_rdat\r\n");
        wms ( 1000);
        return 9901;                        // Return mit Fehlercode
      }                     // Ende if (!(i2c_start( Sadd + I2C_WRITE )))
    
      cli(); tmr1    =   0 ; sei();
    
      while ( 1 )
      {                             //
      i2c_start( Sadd + I2C_WRITE );  // Starte Slave lesen
      i2c_write( 0x00 );               // write address = das angepeilte Byte
            i2c_stop();             //
    
      i2c_start ( Sadd + I2C_READ );        // Slave bereit zum Lesen?
      byte_0  = i2c_readAck();      // Byte 0 lesen... ab laddr = 0
      byte_1  = i2c_readNak();      // Byte 1 lesen... NAK
            i2c_stop();             //
    
      if ( byte_0 == 0 ) break;    // Messung beendet
      }                     // Ende while ( 1 )
    
      cli(); Timer1  =  tmr1; sei();
      uputs0 ("\r\t####\t Timer1 [tupsi] =  "); uputs0u ( Timer1 );
    
      uputs0 ("\r\tbyte_0 =  "); uputs0u ( byte_0 );
    ... um die Messung abzuwarten UND um mir zu Testzwecken den Timerwert für die Messdauer ausgeben zu lassen. Pustekuchen. Je nach Abwandlung des Codes : der Controller hängt sich auf, eine Variation der Abfrage ergibt den WErt 6 - vermutlich die Versionsnummer (so stehts in der Dokumentation) - aber eine Abfrage z.B. auf 255 führt zum Koma. Wenn ich in einer Variante die Abfrage hinkriege, dann steht der Timer auf 0, das heißt bei diesem Timer: Zeitbedarf <50 µs -- bei einem Messabstand von rund 150 cm nicht glaubhaft weil viel zu wenig. Ich kann also den SRF02 nicht ohne Timer betreiben, wie es in der Bedienungsanleitung in Aussicht gestellt wird.

    Fragen:
    Erkennt jemand meine Fehler?
    Hat jemand ne Lösung mit der er den Busystatus - oder den Readystatus - eines SRF02 abfragen kann?

    Danke im Voraus für die Hilfe.
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Der Text ist für mich etwas widersprüchlich. Ich versuche mal zu interpretieren.

    Es wird gesagt, der SRF02 reagiert nicht auf den I2C, solange er misst. Das klingt erstmal einfach. Dann wird aber gesagt, man solle den Chip, am besten ein Register mit bekanntem Wert auslesen, und solange der 0xFF sei (der Bus wenn er nicht getrieben wird) ist der Chip noch nicht fertig.

    Wenn der SRF nicht auf I2C Kommandos reagiert, solange er misst, kann man aber eigentlich auch kein Register auslesen. Er liefert dann nämlich kein ACK auf das Adressbyte. Ich kann nur vermuten, daß der Schreiber des Textes davon ausgeht, daß der Anwender einfach blind den I2C Bus liest und keine Fehlerauswertung macht. Ob aber die jeweils verwendete I2C Library oder HW das 0xFF des Buses liefert, oder der Wert bei einem NACK undefiniert ist, kann ich nicht sagen.

    Ich würde es mal so probieren (wie es auch in Anleitungen zu anderen Bausteinen beschrieben wird): solange bis der SRF mit ACK antwortet die Adresse mit Write senden. Reagiert er, kann man dann auch Register auslesen.

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

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Zitat Zitat von Klebwax Beitrag anzeigen
    ... für mich etwas widersprüchlich. ... solange er misst, kann man aber eigentlich auch kein Register auslesen ...
    Danke, so hatte ich auch gedacht/vermutet - mit leichtem Kopfwiegen und der Hoffnung, dass die devantech-Leute mehr von I2C verstehen als ich.

    Dann werd ich das Ganze mal wieder hervorholen.
    Ciao sagt der JoeamBerg

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    ... Dann werd ich das Ganze mal wieder hervorholen.
    Tja. Wenn ich dieses Detail nur kapieren würde.

    Im Internet hatte ich folgende Anleitung gefunden:
    Code:
    Busy Test geht so: 
    1. Start senden 
    2. Adresse + W senden 
    3. ACK lesen 
    4. if ACK gehe zu 7. 
    5. Stop senden 
    6. gehe zu 1. 
    7. Stop senden 
    Ende
    Mein Code lautet (und ich bin sicher, dass ich damit die Anleitung NICHT realisiert habe (sorry):
    Code:
      cli(); tmr1  = 0; sei();      // Timer 1 starten
                 //
      i2c_start (Sadd + I2C_WRITE); // Starte Slave lesen
      i2c_write ( 0x00 );           // write address = dieses Byte soll gelesen werden
            i2c_stop();             //
    
      i2c_start (Sadd + I2C_READ);  // Slave bereit zum Lesen?
      lobyte  = i2c_readNak();      // Byte lesen... NAK
            i2c_stop();             //
    
      cli(); Timer1  =  tmr1; sei();
      uputs0 ("\r\t## Timer1 =  "); uputs0u ( Timer1 );
      uputs0 ("\r\tlobyte =  "); uputs0u ( lobyte );
    mit i2c_readAck/~Nak laut PFleury
    Code:
    /*************************************************************************
     Read one byte from the I2C device, request more data from device 
    
     Return:  byte read from I2C device
    *************************************************************************/
    unsigned char i2c_readAck(void)
    {
        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
        while(!(TWCR & (1<<TWINT)));    
    
        return TWDR;
    
    }/* i2c_readAck */
    
    
    /*************************************************************************
     Read one byte from the I2C device, read is followed by a stop condition 
     
     Return:  byte read from I2C device
    *************************************************************************/
    unsigned char i2c_readNak(void)
    {
        TWCR = (1<<TWINT) | (1<<TWEN);
        while(!(TWCR & (1<<TWINT)));
        
        return TWDR;
    
    }/* i2c_readNak */
    mit dem Ergebnis:
    Code:
        ## Timer1 =  2
        lobyte =  6
    Das Ergebnis bedeutet, dass ich a) mehr als zwischen 100 µs und 150 µs fürs abarbeiten gebraucht habe und dass b) das gelesene Byte die ominöse 6 ist. Der Fall a) würde bedeuten, dass die zum Lesen vom SRF02 benötigten 75 ms (MILLI !) nicht erreicht wurden. In < 150 µs läuft der Schall ganz grob 5 cm, der Sensor hat aber rund 2 m bis zum Echo . . .

    Daher bitte ich um weitere Hilfe, danke.

    Nachtrag/Erklärung: Wieso steht da
    Code:
      lobyte  = i2c_readNak();      // Byte lesen... NAK
    Weil sich der controller aufhängt, wenn ich ein i2c_readAck(); reinschreibe (ich hab ja geschrieben, dass ich das nicht kapiere :-/ )
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo oberallgeier,

    mir fallen 3 Dinge auf.

    1)
    Im deinem oben angegebenen ersten Code liest du in der while(1)-Schleife immer ZWEI Bytes aus.
    Laut Doku bzw. Musterprogramm aus dem PDF von Robotikhardware (http://www.robotikhardware.de/download/srf02doku.pdf) Seite 8 wird dort aber nur das Register 0 gelesen. (Auch so im Text erwähnt.)

    Dein Code mit meinen Kommentaren:

    Code:
      while ( 1 )
      {
        i2c_start( Sadd + I2C_WRITE );
        i2c_write( 0x00 );                  // HIER OK. Adresse 0 anzusprechen
        i2c_stop();
    
        i2c_start ( Sadd + I2C_READ );
        byte_0  = i2c_readAck();            // OK, um das Firmware-Register geht es
        byte_1  = i2c_readNak();            // NICHT OK, ein weiteres Byte zu lesen?
        i2c_stop();
    
        if ( byte_0 == 0 )
          break;
      }
    2)
    In deiner while(1)-Schleife ist KEIN wait enthalten.
    In dem Beispiel ist ein 'Wait' mit Bascom als "Waitms 1" angegeben.
    Ich bin nicht sicher, aber ein "Dauerfeuer" auf dem Bus ist nicht erlaubt.
    Hier solltest du doch eines deiner eigentlich zu sparenden waits auch mal einbauen.


    3)
    In deinem "... NICHT realisierten ..." Codestück liest du zwar nicht mehr das zweite Byte vom Register, aber dort loopst du auch nicht mehr.
    Warum?


    Viele Grüße und vor allem Erfolg
    Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Tja. Wenn ich dieses Detail nur kapieren würde.

    Im Internet hatte ich folgende Anleitung gefunden:
    Code:
    Busy Test geht so: 
    1. Start senden 
    2. Adresse + W senden 
    3. ACK lesen 
    4. if ACK gehe zu 7. 
    5. Stop senden 
    6. gehe zu 1. 
    7. Stop senden 
    Ende
    Soo schwer ist I2C nicht. Ich benutze dazu keine Libraries, die "paar" Zeilen mach ich selber (dann sind auch Fehler im Code meine eigenen).

    Ich versuch mal eine Erklärung:
    Für jedes Byte werden 9 Bit übertragen. Wenn der Master schreibt, schickt er die ersten 8 Bit (die Daten) und der Slave quitiert beim 9. Takt mit ACK, bzw. quitiert nicht also NAK.

    Wenn der Master liest, taktet er 8 Bit ein (der Master gibt immer den Takt vor) und liefert mit dem 9. Takt entweder ACK oder NAK.

    Dann kann der Master auf dem Bus noch eine Startkondition oder eine Stopkondition anlegen. Das sind feste Zustände. Und als letztes: treibt der Master den Bus nicht und sind SCL und SDA high, ist der Bus idle.

    Die passenden Timingdiagramme gibt es zuhauf in den diversen Datenblättern von I2C Chips oder hier. Das ist eigentlich schon alles über den Datentransfer auf dem I2C Bus.

    Und jetzt zu dem Ablauf von oben:

    Busy Test geht so:
    1. Start senden

    Eigentlich sollte man zuerst prüfen, ob der Bus idle ist, also SDA und SCL == 1. Wenn ja, eine Startkondition erzeugen. Ist häufig einfach ein Bit im Controler setzen.
    2. Adresse + W senden
    Das erste Byte nach dem Start muß das Adressbyte sein, oberste 7 Bit die I2C-Adresse des Slave, unterste Bit das R/W bit. Das wird typisch ins Datenregister des Chips geschrieben, der erzeugt dann die erforderlichen 9 Takte und liefert das ACK bzw. NAK in einem Bit zurück. Bei einem NAK muß die Übertragung mit Stop abgebrochen werden
    3. ACK lesen
    4. if ACK gehe zu 7.
    5. Stop senden

    Das ist hier passiert
    6. gehe zu 1.
    Slave not ready, weiter probieren. Es könnte aber auch bedeuten, Slave garnicht da, hat sich ausgelötet , Adresse ist falsch etc
    7. Stop senden
    Das müßte man nicht machen, der Slave ist da und bereit, man könnte jetzt die Registeradresse schreiben und dann erst Stop anlegen.

    Ein "I2C read" ist hier nicht vorgekommen, daher halte ich die Verwendung einer Funktion mit "read" im Namen für falsch (ich kenne die Library nicht). Ich vermute aber mal so ins Blaue: die Funktion i2c_start() liefert als Returnwert den Status des ACK-Bits.

    Ich hoffe, das hilft etwas weiter.

    @Sternthaler
    In deiner while(1)-Schleife ist KEIN wait enthalten.
    In dem Beispiel ist ein 'Wait' mit Bascom als "Waitms 1" angegeben.
    Ich bin nicht sicher, aber ein "Dauerfeuer" auf dem Bus ist nicht erlaubt.
    Ein "Dauerfeuer" wie du es nennst, ist selbstverständlich erlaubt. Man muß sich nur an die Setup und Holdzeiten der Chips halten und das sind ganz wenige µs eher Nanosekunden. So schnell kann dein Programm garnicht laufen. Und Chips, die eine lange Leitung haben, quitieren nicht (was dann ein NAK ist) solange sie nicht fertig sind.

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

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Zitat Zitat von oberallgeier Beitrag anzeigen
    ## Timer1 = 2
    lobyte = 6

    Das Ergebnis bedeutet, dass ich a) mehr als zwischen 100 µs und 150 µs fürs abarbeiten gebraucht habe und dass b) das gelesene Byte die ominöse 6 ist. Der Fall a) würde bedeuten, dass die zum Lesen vom SRF02 benötigten 75 ms (MILLI !) nicht erreicht wurden. In < 150 µs läuft der Schall ganz grob 5 cm, der Sensor hat aber rund 2 m bis zum Echo . . .
    Hallo oberallgeier,
    nochmals ich.

    Ich rechne mal etwas anders als du.
    Wenn der Schall 300 Meter pro Sekunde schafft, dann sind das 300 * 100cm / 1000ms * 75ms-Messdauer = 2250 cm Weg.

    Unser Schall muss hin und zurück laufen. Somit vom SRF02 zum Hinderniss die Hälfte: 1125 cm Weg.
    Die Reichweite vom Sensor wird mit 600 cm angegeben und entspricht somit ca. der Hälfte 'meiner' Rechnung.

    Wenn also der Piepston mit einer Dauer von NULL erzeugt würde, könnte der Sensor in der Zeit die doppelte Entfernung schaffen.
    Ich gehe also davon aus, dass auch das Piepen selbst schon Zeit benötigt
    Evenuell wird auch zwei mal 'gepiept' um eine Mittelwertmessung zu machen.

    cu Sternthaler

    - - - Aktualisiert - - -

    Zitat Zitat von Klebwax Beitrag anzeigen
    Ein "Dauerfeuer" wie du es nennst, ist selbstverständlich erlaubt. Man muß sich nur an die Setup und Holdzeiten der Chips halten und das sind ganz wenige µs eher Nanosekunden. So schnell kann dein Programm garnicht laufen. Und Chips, die eine lange Leitung haben, quitieren nicht (was dann ein NAK ist) solange sie nicht fertig sind.
    Hallo Klebwax,

    jepp, du hast Recht mit deinen Zeitangaben.
    Ich hatte im Hinterkopf, dass im dicken AVR-Handbuch so eine Zeitangabe zwischen STOP und nächstem START angegeben ist.

    Nun wiedergefunden im Kapitel "Electrical Characteristics" und Unterkapitel "Two-wire Serial Interface Characteristics" aus einer Atmel-Doku zum ATmega48A bis 328P:

    Bus free time between a STOP and START condition
    fSCL < 100kHz 4.7 – μs
    fSCL > 100kHz 1.3 – μs


    oberallgeier ist beim I2C mit 400 kHz unterwegs und somit sind 1.3 μs nun nicht wirklich die Welt. Aber trotzdem schaffen seine 20 MHz dann schon 26 1-Takt Befehle!
    Und nun könnte man mal schauen, was zwischen i2c_stop() und dem nächsten i2c_start() an Maschinenbefehlen steht. (In der Loop gibt es das 2 mal.)

    Gruß Sternthaler
    Lieber Asuro programieren als arbeiten gehen.

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Erstmal vielen Dank Klebwax und Sternthaler für eure Geduld und Ausdauer.
    Soo schwer ist I2C nicht. Ich benutze dazu keine Libraries, die "paar" Zeilen mach ich selber ...
    Klar, das ist der richtige Ansatz. Bisher hatte ich die Anleitungen dazu in der Dokumentation von Fleury undoder von Atmel schon nach den ersten Zeilen wegen massiven Nichtverstehens weggelegt. Sorry. Das hatte mir schon vor vielen Monaten Schwierigkeiten gemacht - damals konnte ich nie schnellere I2C-Taktraten als 100 kHz störungsfrei fahren :-/ Hier bin ich mittlerweile mit so ner Art full speed (ok ok, da gibts natürlich Bremser vom Slave) störungsfrei *lichtblick*

    Grundlagen: Dokumentation zum mega1284 : 8272D–AVR–05/12 und die verwendete Bibliothek von PFleury : i2cmaster.zip

    Euer Entgegenkommen nutze ich mal noch mehr aus und versuche mal langsam mein Nicht-Verständnis abzubauen. Es fängt ja schon mit der von mir verwendeten Bibliothek an (Peter Fleurys I2C Master library).

    Code:
    Erklärung in der Dokumentation zur Bibliothek (siehe obigen Link "... Master lib..") :
    unsigned char i2c_start     (      unsigned char      addr      )      
    
    Issues a start condition and sends address and transfer direction.
    
    Parameters:
            addr     address and transfer direction of I2C device
    
    Return values:
            0     device accessible
            1     failed to access device 
    
    Hier die Startsequenz, stimmt im Wesentlichen mit der Dokumentation zum mega1284 überein.
    /*************************************************************************    
      Issues a start condition and sends address and transfer direction.
      return 0 = device accessible, 1= failed to access device
    *************************************************************************/
    unsigned char i2c_start(unsigned char address)
    {
        uint8_t   twst;
    
        // send START condition
        TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
    
        // wait until transmission completed
        while(!(TWCR & (1<<TWINT)));
    
        // 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)));
    
        // 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 */
    
    /*************************************************************************
    Hier fehlt >für mich< schon mal der Wert für TW_STATUS. In der Atmeldokumentation steht dazu TWSR z.B. auf Seite 220 bei Check value of TWI Status Register :

    Code:
    if ((TWSR & 0xF8) != START)
    ERROR();
    und pfleury schreibt dazu
    Code:
        // check value of TWI Status Register. Mask prescaler bits
        twst = TW_STATUS & 0xF8;
    In myfile.lls finde ich dazu:
    Code:
        // check value of TWI Status Register. Mask prescaler bits.
        twst = TW_STATUS & 0xF8;
         25c:    80 91 b9 00     lds    r24, 0x00B9
         260:    88 7f           andi    r24, 0xF8    ; 248
        if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
         262:    88 30           cpi    r24, 0x08    ; 8
         264:    21 f0           breq    .+8          ; 0x26e <i2c_start+0x22>
         266:    80 31           cpi    r24, 0x10    ; 16
         268:    11 f0           breq    .+4          ; 0x26e <i2c_start+0x22>
         26a:    81 e0           ldi    r24, 0x01    ; 1
         26c:    08 95           ret
    und weiter oben:
    Code:
    void i2c_init(void)
    {
      /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
      
      TWSR = 0;                         /* no prescaler */
         240:    10 92 b9 00     sts    0x00B9, r1
      TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
         244:    8c e0           ldi    r24, 0x0C    ; 12
         246:    80 93 b8 00     sts    0x00B8, r24
    
    }/* i2c_init */
         24a:    08 95           ret
    Und da setzts bei mir aus - ob das TWIStatusregister TWSR richtig angegeben ist. Und .. ich finde in den Quellen kein define für das TWSR . . .

    Einfach wäre es jetzt im fleury-code das TWI_TW_STATUS durch TWSR zu ersetzen. Aber es wäre eben experimentelle Softwareentwicklung :-/

    Danke im Voraus!

    Nachtrag:
    in der m1284def.inc steht bei "... TWI ..." nur:
    Code:
    ; TWSR - TWI Status Register
    .equ    TWPS0    = 0    ; TWI Prescaler
    .equ    TWPS1    = 1    ; TWI Prescaler
    .equ    TWS3    = 3    ; TWI Status
    .equ    TWS4    = 4    ; TWI Status
    .equ    TWS5    = 5    ; TWI Status
    .equ    TWS6    = 6    ; TWI Status
    .equ    TWS7    = 7    ; TWI Status
    Geändert von oberallgeier (30.09.2014 um 09:53 Uhr) Grund: Auszug aus der m1284def.inc zitiert
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    Meine Fehler sind ja noch schlimmer - im R N Wiki steht ein Beispielprogramm für den SRF02 MIT der Sequenz Warteaufmessung (in Bascom) die wohl genau das tut, was ich eigentlich suche:
    Code:
    '------------- Hilfsfunktionen für SRF02 ----------
    Function Srf02_firmware(byval Slaveid As Byte) As Byte
      Local Firmware As Byte
      Local Slaveid_read As Byte
      slaveid_read = Slaveid + 1
      I2cstart
      I2cwbyte Slaveid
      I2cwbyte 0 'Leseregister festlegen
      I2cstop
      I2cstart
      I2cwbyte Slaveid_read
      I2crbyte Firmware , Nack
      I2cstop
      Srf02_firmware = Firmware
    End Function
    
    Function Srf02_entfernung(byval Slaveid As Byte) As Integer
      Local Lob As Byte
      Local Hib As Byte
      Local Firmware As Byte
      Local Temp As Byte
      Local Slaveid_read As Byte
    
      slaveid_read = Slaveid + 1
    
      'Messvorgang in starten
      I2cstart
      I2cwbyte Slaveid
      I2cwbyte 0
      I2cwbyte 81 'in Zentimetern messen
      I2cstop
    
      Warteaufmessung:
        Waitms 1
        Firmware = Srf02_firmware(slaveid)
      If Firmware = 255 Then Goto Warteaufmessung
    
      I2cstart
      I2cwbyte Slaveid
      I2cwbyte 2 'Leseregister festlegen
      I2cstop
      I2cstart
      I2cwbyte Slaveid_read
      I2crbyte Hib , Ack
      I2crbyte Lob , Nack
      I2cstop
      Srf02_entfernung = Makeint(lob , Hib)
     End Function
    End
    Ciao sagt der JoeamBerg

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Ich mache mit PICs rum und kenne mich daher mit AVR nicht so aus. Ich hab mir daher das Datenblatt von Atmel mal angesehen. Dafür hat Atmel weder einen Preis für Didaktik noch für Chipdesign verdient. Jetzt kann ich verstehen, weswegen viele I2C für kompliziert halten.

    Aber in deinem geposteten Code findet sich das wieder, was ich oben geschrieben habe. In i2c_start() wird alles nötige gemacht.

    also:
    Code:
    if(i2c_start(Adresse und Write) == 0) {
            Chip ist fertig mit der Messung und bereit zum Lesen
    	i2c_write(Registeradresse)
    	i2c_stop()
    	if(i2c_start(Adresse und Read) != 0) {
    		eben war der Chip doch noch bereit, was soll das jetzt? Selbstzerstörung einleiten??
    	}
    	ErsteByte = i2c_readAck()
    	ZweiteByte = i2c_readAck()
            .  .  .  .
    	LetzteByte = i2c_readNak()
    	i2c_stop()
    } else {
    	Chip noch nicht bereit, mach erstmal was anderes und versuchs später noch einmal
    }
    So sollte es gehen.

    Und zu deinem Problem mit TW_STATUS: wenn es nicht definiert wäre, würde der Compiler maulen. In dem meisten IDEs kann man sich irgendwie die Macroexpansion anzeigen lassen, da findet man dann auch wo das steht. Aber man kann da natürlich auch TWSR schreiben, das ist kein Experiment sondern aus dem Datenblatt. TW_STATUS hat sich auch nur jemand ausgedacht (weil es sich schöner liest?).

    etwas OT:
    Das ganze ist halt ein muchtiges Design. Das eigentlich Statuswort steht in den 5 oberen Bits von TWSR, kann man so machen, ist halt die Hardware. Aber in der Status-Codeliste immer die unteren Bits mitzuschleppen ist Krampf.

    Eigentlich müßte man schreiben:

    TwiStatus = TWSR >> 3

    Und dann kann man mit if oder case die Auswertung auf TwiStatus machen.

    Aber trotzdem schaffen seine 20 MHz dann schon 26 1-Takt Befehle!
    Da Start und Stop in Hardware erzeugt werden und im Code darauf gewartet wird, das sich der Status ändert, spielt das keine Rolle.

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

Seite 1 von 4 123 ... LetzteLetzte

Ähnliche Themen

  1. [ERLEDIGT] Probleme mit IF-Abfrage / Timer
    Von sammler im Forum C - Programmierung (GCC u.a.)
    Antworten: 11
    Letzter Beitrag: 25.04.2011, 11:41
  2. SRF02 über RS232 Beispielcode ohne Funktion?
    Von TobiasBlome im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 10.05.2009, 14:21
  3. problem mit button-abfrage im timer (c#)
    Von Roboman93 im Forum Open Source Software Projekte
    Antworten: 4
    Letzter Beitrag: 29.12.2008, 17:40
  4. SRF02 Messwert in Millimeter ermitteln
    Von Stiffer im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 29.03.2008, 12:00
  5. Messwert Diagramm erstellen... aber wie?
    Von raptor_79 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 15.11.2007, 08:30

Berechtigungen

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

12V Akku bauen