Willkommen in unserer Community

Werde Teil unserer Community und registriere dich jetzt kostenlos ...

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

C Temperatursensor (STS3x)

Dieses Thema im Forum "Software" wurde erstellt von Janiiix3, 4. August 2017.

  1. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Moin Moin,

    da bin ich mal wieder..
    Habe gerade einen neuen Temperatursensor vor mir liegen, den (STS3x)..
    Der sendet mir seine Temperatur in 3 Bytes zurück.

    Byte 1: Temperatur MSB
    Byte 2: Temperatur LSB
    Byte 3: CRC

    Nun kommt es ab und zu mal vor, dass die Temperatur von gut und böse liegt.
    Ich muss dazu sagen, dass ich jeweils den jeh kleinsten gemessenen Wert speichere sowie den jeh größte Wert.

    Ab und zu sehe ich auf dem Display (7 Segment) das die Temperatur (die jeh größte) deutlich größer als 40° angeblich sein soll.. Und das mit CRC..

    Mache ich was falsch?
    Wie unterdrücke ich das am besten?

    Hier mal meine Routine zum auslesen des Sensors mit CRC..



    CodeBox C und C++
    uint8_t tmp[3]={0x00,0x00,0x00};
    int16_t sts3x_read(void){
       
        #define MSB 0
        #define LSB 1
        #define CRC 2
    
       
           
        i2c_start_wait((0x4a<<1)+I2C_WRITE);
        i2c_write(0x20);
        i2c_write(0x2f);   
        i2c_rep_start((0x4a<<1)+I2C_READ);
        tmp[MSB]=i2c_readAck();
        tmp[LSB]=i2c_readAck();
        tmp[CRC]=i2c_readNak();
        i2c_stop();
       
        crc_glob = tmp[CRC]; // only for debug (usart output)
       
        uint8_t crc=0xff;
        crc=_crc8_ccitt_update(crc,tmp[0]);
        crc=_crc8_ccitt_update(crc,tmp[1]);
       
        /* data correct received? */
        if (crc==tmp[2]){
            return (uint16_t)tmp[0]<<8|tmp[1];
        }
        return -1;
    }
    
     
  2. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.668
    Zustimmungen:
    37
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Du hast kein Datenblatt des Sensors verlinkt, deswegen mal nur 'n Schuß ins Blaue:
    Bist Du sicher, daß das Auslesen der Bytes bezüglich der Wandlungen atomar erfolgt? Also daß der Sensor die Register selbst während des Auslesens gegen neue Ergebnisse blockt/puffert, und Du Dich nicht selbst kümmern mußt, sicherzustellen, während eines potentiellen Updates nicht zu lesen?
     
  3. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Ja. Ich sperre die Interrupts in der Zeit. Es kommt ja auch meistens der gleiche Wert raus. Es sind meistens 45 Grad. Sonst klappt das auslesen gut und die Genauigkeit ist auch inordnung. Werde das Datenblatt nach reichen.
     
  4. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.668
    Zustimmungen:
    37
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Nein, zu Deinem C-Code müssen Dirk, Hemi & co. was sagen, ich meinte ob Du sicher bist, daß Du nicht zufällig gerade während eines neuen Ergebnisses auf den Sensor zugreifst, und MSB und LSB zu zwei unterschiedlichen (aufeinanderfolgenden) Messungen gehören. (also ob der Sensor-IC selbst sowas ausschließt, indem er während des Lesens neue Updates blockt, oder den Lesezugriff puffert)
     
  5. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Ich starte die Messung und lese dann die Temperatur. Also so zu sagen SingleShot und kein ständiges bit raus geballer..
     
  6. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map


    CodeBox C und C++
    i2c_start_wait((0x4a<<1)+I2C_WRITE); 
    i2c_write(0x20); 
    i2c_write(0x2f);


    Mit 0x202F sendest du das Kommando für periodische Messung, nicht für "Single Shot" Messung.

    Nach diesem Kommando sendest du ein START dann SlaveAdress+R. Antwortet der Slave mit NACK, sind keine Daten vorhanden und die Kommunikation wird abgebrochen.
    Ist die Messung fertig und sind Daten vorhanden antwortet der Slave mit ACK. Nun kannst du MSB+LSB+CRC lesen.

    EDIT:
    Damit nicht jeder suchen muss: Datasheet STS3X
     
  7. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Das kann es wohl sein. Das Nack kann ich doch auch irgendwie abfragen oder? Ich benutze ja schon lange die fertigen Routinen für die Mega Serie.
    Das Nack muss dann wahrscheinlich im Status Register stehen..!?
     
  8. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map
    Ja, das sollte dann im TWI Statusregister TWSR stehen, ob nach MasterRead SLAVEADDR+R ein ACK oder NACK empfangen wurde, schau mal in das Datenblatt des Mikrocontrollers.

    Dirk :ciao:
     
  9. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Müsste dann aber nicht trodzdem der CRC fehlschlagen?

    Sehe ich das richtig, dass es dann der Statuscode "$40" sein müsste?

    Woher weiß ich jetzt ob es ein NACK oder ein ACK war?
     

    Anhänge:

    #9 Janiiix3, 6. August 2017
    Zuletzt bearbeitet: 6. August 2017
  10. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map
    Ja, ich denke
    0x40 für ACK
    und
    0x48 für NACK

    Achtung in TWSR sind ggf. noch Prescaler bits, die müssen maskiert werden, sie sind nicht in dem Statuscode berücksichtigt.
     
  11. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Was ist hier mit? Wenn solch eine Temperatur angezeigt wird, die überhaupt nicht passt scheint der CRC aber trodzdem richtig zu sein. Das kann doch nicht angehn.
     
  12. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map
    Ich kann das nun auch nicht genau sagen, soweit habe ich mir das Datenblatt nicht angesehen.

    Aber:

    Du sendest immer ein Kommando "periodische Messung" und vermutest es ist ein Kommando für Einzelmessung.
    Danach liest du sofort (irgendwelche) Daten aus, ohne auf das Timing zu achten oder ohne darauf zu achten, ob gültige Temperaturdaten vorhanden sind.

    Ich nehme an, daran liegt es.

    Vielleicht kann aber auch mal ein anderer User in das Datenblatt schauen. Ich habe leider nicht so die Zeit.
    EDIT:
    Poste vielleicht auch noch mal deinen aktuellen Code.
     
    #12 Dirk, 6. August 2017
    Zuletzt bearbeitet: 7. August 2017
  13. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Moin,

    Habe es bis heute nicht hin bekommen, das NACK auszuwerten.


    CodeBox C und C++
    uint16_t sts3x_read(void){
    
    #define MSB 0
    #define LSB 1
    #define CRC 2
    
    i2c_start_wait((0x4a<<1)+I2C_WRITE);
    i2c_write(0x21);
    i2c_write(0x30);
    
    
    i2c_rep_start((0x4a<<1)+I2C_READ);
    Temperature.Rx[MSB]=i2c_readAck();
    Temperature.Rx[LSB]=i2c_readAck();
    Temperature.Rx[CRC]=i2c_readNak();
    i2c_stop();
    
    uint8_t crc=0xff;
    crc=_crc8_ccitt_update(crc,Temperature.Rx[MSB]);
    crc=_crc8_ccitt_update(crc,Temperature.Rx[LSB]);
    
    
    /* data correct received? */
    if (crc==Temperature.Rx[CRC]){
    return (uint16_t)Temperature.Rx[MSB]<<8|Temperature.Rx[LSB];
    }
    
    return 17000; // ad value for 0
    }
    
    
     
  14. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Die Funktionen liefern mir zwar Werte zurück, dass hat doch aber nichts damit zu tun, dass der Sensor gerade keine neuen Daten für mich hat oder? Viel mehr das der Chip nicht Antwortet oder nicht da ist..



    CodeBox C und C++
    /**
    @brief Issues a repeated start condition and sends address and transfer direction
    @param addr address and transfer direction of I2C device
    @retval 0 device accessible
    @retval 1 failed to access device
    */
    extern unsigned char i2c_rep_start(unsigned char addr);
    
     
  15. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map
    Du sendest nun ein Kommando (0x2130) für periodische Messung. Das solltest du nur einmalig machen, zum Initialisieren der periodischen Messung, nicht permanent bevor du auslesen möchtest.

    Beim Lesen der Temperaturdaten bei periodischer Messung hältst du dich nicht an das Protokoll.

    Du wirst aktuell ggf. zwar irgenwas zurückbekommen, bei dem CRC stimmt. Dies schützt aber sicher nur gegen Übertragungsfehler auf dem I2C Bus und wird dir nicht bestätigen, dass die empfangenen Daten richtig sind und diese sind, welche du erwartest.

     
  16. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Moin Dirk.

    Ich hatte in der main() schon einmal die Initalisierung vorgenommen (0x2130)..


    CodeBox C und C++
    i2c_start_wait((0x4a<<1)+I2C_WRITE);
    i2c_write(0x21);
    i2c_write(0x30);
    i2c_stop();
    


    Wenn ich nun zyklisch meine Daten auslese, sende ich ihn vorher..


    CodeBox C und C++
    uint16_t sts3x_read(void){
    
    #define MSB 0
    #define LSB 1
    #define CRC 2
    
    i2c_start_wait((0x4a<<1)+I2C_WRITE);
    i2c_write(0xe0);
    i2c_write(0x00);
    
    i2c_rep_start((0x4a<<1)+I2C_READ);
    Temperature.Rx[MSB]=i2c_readAck();
    Temperature.Rx[LSB]=i2c_readAck();
    Temperature.Rx[CRC]=i2c_readNak();
    i2c_stop();
    
    uint8_t crc=0xff;
    crc=_crc8_ccitt_update(crc,Temperature.Rx[MSB]);
    crc=_crc8_ccitt_update(crc,Temperature.Rx[LSB]);
    
    
    /* data correct received? */
    if (crc==Temperature.Rx[CRC]){
    return (uint16_t)Temperature.Rx[MSB]<<8|Temperature.Rx[LSB];
    }
    
    return 17000; // ad value for 0
    }
    


    Und danach warte ich auf die Daten. Das hat leider gar nicht funktioniert. So bekomme ich wenigstens Gültige Daten.
     
  17. Janiiix3

    Janiiix3 Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    976
    Zustimmungen:
    4
    Ort:
    Hannover
    Sprachen:
    C#
    Map
    Was meinst du damit? Das ich die einmalige Initialisierung nicht mache?
     
  18. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.044
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C#, Assembler, Pascal, C++, PHP, Java
    Map
    Nein, in deinem Code zuvor in diesem Beitrag führst du die Initialisierung für periodische Messung permanent aus und sendest auch kein Kommando 0xE000, sondern versuchst sofort Daten zu lesen.

    Dein Code danach macht das ja besser. Es wäre gut, wenn hier mal jemand mit I2C und C Erfahrungen helfen könnte.

    Dirk :ciao:
     

Diese Seite empfehlen

  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)