Hilfe beim Auslesen eines Sensors

OP #3266547
Lesenswert?

Hallo,

Ich versuche schon seit einiger Zeit einen MS5611 Drucksensor mit meinem 
TI Launchpad MSP4302553 auszulesen. Dabei muss man zuerst 
Kalibrierungsdaten auslesen, mit deren Hilfe kann man die danach 
gelesenen Temeratur- und Druckwerte errechnen. Soweit funktioniert auch 
alles nur stimmt der errechnete Druck nicht mal annaehernd mit dem 
meiner Wetterstation ueberein. Die Temperatur passt so einigermassen und 
die Kalibrierungsdaten entsprechen auch etwa denen im Datenblatt.

Woran kanns also liegen das der Druck nicht stimmt. Vielleicht koennte 
sich mal jemand meine Funktion ms5611_get_pressure() anschaun, denke 
dass es an der Berechnung liegt.

Hier die Ausgabe via uart_printf:
1
-------------------------- START ------------------------------
2

3
Pres. sensitivity:                      65437 (0xFF9D)
4
Pres. offset:                           65495 (0xFFD7)
5
Temp. coefficient of pres. sensitivity: 65431 (0xFF97)
6
Temp. coefficient of pres. offset:      65484 (0xFFCC)
7
Reference temperature:                  30471 (0x7707)
8
Temp. coefficient of the temperature:   27753 (0x6C69)
9

10
ms5611_get_raw() : rxb[0]=123 rxb[1]=65438 rxb[2]=52
11
ms5611_get_temperature() : raw=8035892 dT=235316
12
temp = 2778
13
ms5611_get_raw() : rxb[0]=65411 rxb[1]=67 rxb[2]=65434
14
ms5611_get_pressure() : raw=8602522 off=117699218 sens=1
15
pres = 141287
16
ms5611_get_raw() : rxb[0]=123 rxb[1]=65456 rxb[2]=30
17
ms5611_get_temperature() : raw=8040478 dT=239902
18
temp = 2793
19
ms5611_get_raw() : rxb[0]=65411 rxb[1]=61 rxb[2]=118
20
ms5611_get_pressure() : raw=8600950 off=120045387 sens=1
21
pres = 141312
22
ms5611_get_raw() : rxb[0]=123 rxb[1]=65472 rxb[2]=65448
23
ms5611_get_temperature() : raw=8044712 dT=244136
24
temp = 2807
25
ms5611_get_raw() : rxb[0]=65411 rxb[1]=56 rxb[2]=70
26
ms5611_get_pressure() : raw=8599622 off=122211475 sens=1
27
pres = 141339

Im Datenblatt auf der Seite 7 wird die Berechnung genau beschrieben:
http://www.meas-spec.com/product/t_product.aspx?id=8503#

Danke Max
Angehängte Dateien:
Gast #3269351
Lesenswert?

Hallo;
wenn handwerklich kein Fehler vorliegt:

Dein Sensor misst den physikalischen Luftdruck.
Deine Wetterstation verwendet vermutlich die "barometrische" 
Höhenformel"
Wen n du ein  bischen suchst, gibt es bestimmt auch codebeispiel zur 
Anpassung.

Gruß
OP #3270051
Lesenswert?

Die barometrische Hoehenformel kommt erst spaeter ins Spiel, jetzt gehts 
mir mal in erster Linie um den aboluten Luftdruck, doch der passt ja 
schon nicht.

Aber passt diese Berechnung grunsaetzlich:
1
off = (((int64_t)MS5611_CAL_OFF) << 16) + ((((int64_t)MS5611_CAL_TCO) * dT) >> 7);
2
sens = (((int64_t)MS5611_CAL_SENS) << 15) + ((((int64_t)MS5611_CAL_TCS) * dT) >> 8);
3
pres = (((raw * sens) >> 21) - off) >> 15;
#3270130
Lesenswert?

Deine Ausgaben sind nichts wert
1
    uint32_t raw;  // Raw, uncompensated pressure
2
    int64_t off;   // Offset at actual temperature
3
    int64_t sens;  // Sensitivity at actual temperature
4

5

6
....
7
    uart_printf("ms5611_get_pressure() : raw=%l off=%l sens=%l\r\n", raw, off, sens);

raw ist ein uint32_t
off ist ein int64_t

Für beides benutzt du aber im Formatstring ein %l. Das kann nicht 
stimmen.

1
uint32_t ms5611_get_raw( const char* command )
2
{
3
    volatile char rxb[3];    // 3 Byte receive buffer
4
    
5
    uart_printf("ms5611_get_raw() : rxb[0]=%u rxb[1]=%u rxb[2]=%u\r\n", rxb[0], rxb[1], rxb[2]);
1
ms5611_get_raw() : rxb[0]=123 rxb[1]=65438 rxb[2]=52

Ein char, der den Wert 65438 hat?
Das glaub ich jetzt eher nicht.

1
    return ( (uint8_t)rxb[0] * 65536 ) +
wenn auf deinem System ein int nicht zufällig eine Größe von 4 Bytes 
hat, dann hast du hier bereits deinen ersten Overflow.


1
volatile char rxb[3];

halte dich an eine einfache Regel.
Es gibt 3(!) Character Datentypen
1
  int8_t    für kleine Integer, mit Vorzeichen (signed char)
2
  uint8_t   für kleine Integer, ohne Vorzeichen. Das ist das, was
3
            man gemeinhin unter 'Byte' versteht (unsigned char)
4
  char      für alles was mit Textverarbeitung zu tun hat. (char)

Benutze den richtigen Datentyp in der richtigen Umgebung, und zwar 
bereits bei den Variablendefinitionen!, und du hast weniger Probleme. 
Auf deinem System scheinen plain vanilla char ein Vorzeichen zu haben. 
char ist bei dir gleichzusetzen mit signed char. Ein Teil deiner 
Probleme in ms5611_get_raw stammen daher.
OP #3302058
Lesenswert?

Sodala, ich hab mich jetzt wieder mal an meinem alten Problem, dem 
Auslesen des Sensors MS5611 beschäftigt ... bin wieder ein Stückerl 
weitergekommen und mittlerweile kenn ich mich auch schon ein bisserl mit 
dem debuggen des MSP430ers aus.

Das Auslesen der Temperatur funktioniert schon korrekt und stimmt mit 
der Zimmertemperatur meiner Wetterstation überein, nur beim Luftdruck 
sind sich die beiden noch ziemlich uneinig, leider hat die Wetterstation 
recht. Ich lese vom Sensor so um die 1400 hPa (=mbar) es sollten aber so 
an die 950 sein. Und da komm ich nicht mehr weiter und bitte um Hilfe.

folgender Codeabschnitt führt die Berechnung durch:

1
raw = ms5611_get_raw(MS5611_CMD_D1_4096);
2
 
3
off = (((int64_t)MS5611_CAL_OFF) << 16) + ((((int64_t)MS5611_CAL_TCO) * (int64_t)dT) >> 7);
4
sens = (((int64_t)MS5611_CAL_SENS) << 15) + ((((int64_t)MS5611_CAL_TCS) * (int64_t)dT) >> 8);
5
pres = (((raw * sens) >> 21) - off) >> 15;

Die MS5611_CAL_xxx Werte sind Kalibrierungswerte die einmal zu beginn 
gelesen werden und in der Variable pres steht der endgültige Luftdruck.

Da ich mir long long nicht korrekt via uart ausgeben kann, hab ich off 
und sens mit dem debugger angeschaut:

1
(gdb) print/x ms5611_get_raw::rxb
2
$4 = {0x84, 0xa9, 0x48}
3
(gdb) print ms5611_get_pressure::raw
4
$5 = 8694088
5
(gdb) print ms5611_get_pressure::off
6
$6 = 4332879376
7
(gdb) print ms5611_get_pressure::sens
8
$7 = 2164522714
9
(gdb) print ms5611_get_pressure::pres
10
$8 = 141616

Und wenn ich das mit dem Taschenrechner nachrechne, komm ich auf die 
selben Werte. Bzw hab ich mir dafür ein kleines Bashscript geschrieben, 
dem man die drei raw und den dT wert übergint und dann die Berechnung 
macht, siehe Anhang.

Also ich steh wieder mal an und bin für jede Anregung dankbar.

lG,
Max
Angehängte Dateien:
OP #3316294
Lesenswert?

Mittlerweile funktioniert alles soweit ... mein einziges Problem ist 
nur, dass ich beim Auslesen des Sensors ein delay vom mindestens 6000 
Zyklen einbauen muss, damit eine korrete Antwort vom Drucksensor gelesen 
wird. Bei 1MHz Taktung sind das ca. 100ms. Laut Datenblatt benötigt er 
aber max 9.4ms für die Wandlung. Das ist für mich jetzt ein Problem da 
ich gerne schnell mehrere Werte lesen und dann mitteln will.

Andere Sourcebeispile im Netz warten auch nur ca.10ms, sollte also 
funktionieren.

Jetzt meine Frage. Ich hab die I2C Routinen von TI verwendet (siehe 
Anhang), kann sein es daran liegen kann. Kann man das noch 
besser/schneller machen? Vielleicht könnte sich mal jemand "meine" i2c.c 
anschaun.

Das Auslesen selbst mach ich so:
1
uint32_t ms5611_get_raw( const char* command )
2
{   
3
    volatile char rxb[3];    // 3 Byte receive buffer
4
    uint32_t raw;
5
    
6
    // Command to initiate a pressure conversion (OSR=4096, typ=D2)
7
    i2cSetupTx( MS5611_ADDR_CSB_LOW );
8
    i2cTransmit( command, 1 );
9
    
10
    // Wait to finish conversion, 0.096 sec@1MHz, ~100ms (should be max 9.4ms)
11
    __delay_cycles(6000);
12
    
13
    // ADC read sequence
14
    i2cSetupTx( MS5611_ADDR_CSB_LOW );
15
    i2cTransmit( MS5611_CMD_ADC_READ, 1 );
16
    
17
    // Receive 3 byte answer from MS5611-01BA
18
    i2cSetupRx( MS5611_ADDR_CSB_LOW );
19
    i2cReceive( rxb, 3 );
20
    
21
    raw = (uint8_t)rxb[0];
22
    raw = raw << 8;
23
    raw |= (uint8_t)rxb[1];
24
    raw = raw << 8;
25
    raw |= (uint8_t)rxb[2];
26
    
27
    return raw;
28
}

Danke,
MAX
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren