Forum: Mikrocontroller und Digitale Elektronik Hilfe beim Auslesen eines Sensors


von Markus M. (mmax)


Angehängte Dateien:

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

von Marc Rupprath (Gast)


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ß

von Markus M. (mmax)


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;

von Karl H. (kbuchegg)


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.

von Markus M. (mmax)


Lesenswert?

Danke fuer die Tipps ... dann werd ich mal die Datentypen ueberarbeiten

von Markus M. (mmax)


Angehängte Dateien:

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

von Markus M. (mmax)


Angehängte Dateien:

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.