C Temperatursensor (STS3x)

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
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
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;
}
 
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?
 
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.
 
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)
 
Ich starte die Messung und lese dann die Temperatur. Also so zu sagen SingleShot und kein ständiges bit raus geballer..
 
Ich starte die Messung und lese dann die Temperatur. Also so zu sagen SingleShot und kein ständiges bit raus geballer..



CodeBox 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
 
Nach diesem Kommando sendest du ein START dann SlaveAdress+R. Antwortet der Slave mit NACK, sind keine Daten vorhanden und die Kommunikation wird abgebrochen[/B].
Ist die Messung fertig und sind Daten vorhanden antwortet der Slave mit ACK. Nun kannst du MSB+LSB+CRC lesen.

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..!?
 
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:
 
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

  • master_i2c.jpg
    master_i2c.jpg
    431,9 KB · Aufrufe: 3
Zuletzt bearbeitet:
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.
 
Müsste dann aber nicht trodzdem der CRC fehlschlagen?

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.
 
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.

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.
Damit nicht jeder suchen muss: Datasheet STS3X

EDIT:
Poste vielleicht auch noch mal deinen aktuellen Code.
 
Zuletzt bearbeitet:
Moin,

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


CodeBox 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
}

 
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
/**
@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);
 
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.

4.6 Readout of Measurement Results for Periodic Mode
Transmission of the measurement data can be initiated
through the fetch data command shown in Table 9. If no
measurement data is present the I2C read header is
responded with a NACK (Bit 9 in Table 9) and the
communication stops. After the read out command fetch
data has been issued, the data memory is cleared, i.e.
no measurement data is present.
upload_2017-8-8_15-37-3.png
 
Moin Dirk.

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


CodeBox 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
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.
 
eim Lesen der Temperaturdaten bei periodischer Messung hältst du dich nicht an das Protokoll.

Was meinst du damit? Das ich die einmalige Initialisierung nicht mache?
 
Was meinst du damit? Das ich die einmalige Initialisierung nicht mache?

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:
 
Nabend,

habe MIch noch mal an den Sensor dran gesetzt. Da jetzt das lesen / schreiben / Temperatur berechenen klappt, bin Ich schon mal sehr froh das Ich soweit gekommen bin..
Jedoch verstehe Ich einen Punkt noch nicht ganz.

Der Chip hat einen "Alarm Pin" dieser schaltet wohl sobald die Schwelle für "Luftfeuchtigkeit / Temperatur" über bzw unterschritten werden.
Nun habe ich an dem Ausgang eine LED (high active). Diese leuchtet die ganze Zeit! Das liegt wohl daran das die Schwellen nicht richtig konfiguriert wurden?!

Wie bekomme Ich diese LED aus, ohne den Vorwiderstand oder die LED zu entfernen :D?
 
Im Datenblatt steht:
The pin switches high, when alert conditions are met.
Und nirgendwo steht, daß man da irgendwas einstellen kann.
Da ich Deinen Schaltplan nicht kenne, gehe ich davon aus, daß Du die LED falsch angeschlossen hast.
Und wenn Du sie nur aus haben willst, brauchst Du sie nur vom Pin abzuklemmen. :D
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)