Forum: Mikrocontroller und Digitale Elektronik Drucksensor MS5837-30BA liefert unplausible Werte


von Marc P. (marc_p649)


Lesenswert?

Hallo,

hat irgend jemand Erfahrung mit dem Drucksensor MS5837-30BA?
Das Datenblatt gibt's unter folgendem Link:
https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Data+Sheet%7FMS5837-30BA%7FC2%7Fpdf%7FEnglish%7FENG_DS_MS5837-30BA_C2.pdf%7FMS583730BA01-50

Ich kämpfe gerade damit die richtigen Temperatur- und Druckwerte des 
Sensors zu bestimmen. Allerdings stoße ich auf zwei Probleme:

1. hat meine Temperatur sowohl nach oben als auch nach unten einen 
Offset. Ich habe einen Klimaschrank zur Verfügung. Wenn ich diesen auf 
50 °C einstelle, dann komm ich mit dem Sensor auf ca. 49 °C (damit 
könnte ich leben). Wenn ich den Klimaschrank auf -15 °C einstelle, dann 
komm ich irgendwo bei ca. -11 °C raus. Mir ist bewusst, dass 
Temperaturmessungen öfters mal nicht ganz genau sind und man nicht zu 
viel erwarten darf, aber die 4 °C sind doch schon ein wenig viel, oder?

2. Ich kann mir die Hex-Werte der Druck- und Temperaturwerte über 
Docklight anschauen. Mir ist aufgefallen, dass der Druckwert teilweise 
um 500 mBar schwankt.

Hat hier jemand ähnliche Erfahrung gemacht? Ich habe es sowohl mit der 
Kompensierung 1. Ordnung als auch mit der Kompensierung 2. Ordnung 
probiert. Beides ohne Erfolg.

Ich möchte nicht ausschließen, dass es an meiner Programmierung liegt.
1
void calculatePressure(int32_t dT) {
2
  static uint16_t CalibrationParameters[4];
3
  volatile uint32_t D1;
4
  volatile int64_t off, sens, SENSi, sens2, OFFi, OFF2, Ti, temp_square;
5
  static volatile uint32_t D1_1;
6
  static volatile int64_t off_1, sens_1;
7
  static volatile int32_t dT_1;
8
  
9
  if(!CalibrationParameters[C1]) {
10
    initSensorParametersPressure(CalibrationParameters);
11
  }
12
  
13
  I2C_0_read(I2C_ADDR_PRESSENSE, I2C_CMD_PRESSENSE_READ, 3);
14
  D1 = (au8_msgBuf[0]<<16 | au8_msgBuf[1]<<8 | au8_msgBuf[2]);
15
16
  off = ((int64_t)(CalibrationParameters[C2] << 16)) + ((int64_t)((CalibrationParameters[C4]*dT) >> 7));
17
  sens = ((int64_t)(CalibrationParameters[C1] << 15)) + ((int64_t)((CalibrationParameters[C3]*dT) >> 8));
18
  
19
  temp_square = (presSensor.temperature - 2000)*(presSensor.temperature - 2000);
20
21
  if(presSensor.temperature < 2000) {
22
    Ti = (int64_t)((3*dT*dT) >> 33);
23
    OFFi = 3*(temp_square >> 1);
24
    SENSi = 5*(temp_square >> 3);
25
    
26
    if(presSensor.temperature < - 1500) {
27
      temp_square = (presSensor.temperature + 1500)*(presSensor.temperature +1500);
28
      OFFi = OFFi + 7*temp_square;
29
      SENSi += 4*temp_square;
30
    }
31
  } else {
32
    Ti = (int64_t)((2*dT*dT) >> 37);
33
    OFFi = (temp_square >> 4);
34
    SENSi = 0;
35
  }
36
  
37
  presSensor.temperature2Order = presSensor.temperature - Ti;
38
  presSensor.pressure2Order = (((((uint64_t)D1*(uint64_t)(sens - SENSi)) >> 21) - (off-OFFi)) >> 13);
39
}
40
41
void initSensorParametersPressure(uint16_t sensorParameters[]) {
42
  for(int i = 0; i < 4; i++) {
43
    I2C_0_read(I2C_ADDR_PRESSENSE, I2C_REG_PRESSENSE_C1 + 2*i, 2);
44
    *(sensorParameters + i) = ((au8_msgBuf[0]<<8 | au8_msgBuf[1])); //compare Datasheet page 11
45
  }
46
}
47
48
int32_t calculateTemperatureAndReturnDifferentialTemperatur() {
49
  volatile int32_t dT;
50
  volatile uint32_t D2;
51
  volatile int64_t shift; 
52
  static uint16_t CalibrationParameters[2];
53
54
  if(!CalibrationParameters[C5]) {
55
    initSensorParametersTemperature(CalibrationParameters);
56
  }
57
  I2C_0_read(I2C_ADDR_PRESSENSE, I2C_CMD_PRESSENSE_READ, 3);
58
  
59
  D2 =  (au8_msgBuf[0]<<16|au8_msgBuf[1]<<8|au8_msgBuf[2]);
60
  dT = (int32_t)((D2 - (int32_t)(CalibrationParameters[C5] * 256)));
61
  shift =  ((int64_t)dT*(int64_t)CalibrationParameters[C6])/8388608;
62
  presSensor.temperature = 2000 + shift;
63
  
64
  return dT;
65
};
66
67
68
void initSensorParametersTemperature(uint16_t sensorParameters[]) {
69
  for(int i = 0; i < 2; i++) {
70
    I2C_0_read(I2C_ADDR_PRESSENSE, I2C_REG_PRESSENSE_C5 + 2*i, 2);
71
    *(sensorParameters + i) = ((au8_msgBuf[0]<<8 | au8_msgBuf[1])); //compare Datasheet page 11
72
  }
73
}
74
75
// Die Routine wird alle 5 Millisekunden aufgerufen. Der Sensor benötigt circa 3 ms zum Wandeln der Werte und sollte genug Zeit haben. 
76
void pressureSensorRoutine() {
77
  static volatile uint8_t state = 0;
78
  static volatile int32_t dT;
79
  switch (state)
80
  {
81
    case 0:
82
      resetPresSens();
83
      state = 1;
84
    break;
85
    case 1:
86
      calculatePressure(dT);
87
      startTemperatureConversion();
88
      state = 2;
89
    break;
90
    case 2:
91
      dT = calculateTemperatureAndReturnDifferentialTemperatur();
92
      startPressureConversion();
93
      state = 1;
94
    break;
95
    default:
96
    state = 0;
97
    break;
98
  }
99
}

Vielen Dank schon mal für die Hilfe.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Marc P. schrieb:
> Wenn ich den Klimaschrank auf -15 °C einstelle, dann komm ich irgendwo
> bei ca. -11 °C raus
Und welche Temperatur hat der Sensor in diesem Augenblick? Denn die 
Lufttemperatur des Klimaschranks hat ja nur annähernd was mit der 
Temperatur eines Prüflings zu tun...

von Marc P. (marc_p649)


Lesenswert?

Ich kann leider keinen genauen Wert nennen. Ich versuche die 
Sensortemperatur heute Abend oder Montagmorgen zu messen ohne viel 
Fehler einzubauen. Auf der Platine befinden sich aber keine 
Nennenswerten Heizquellen und der Sensor lag deutlich länger als eine 
Stunde im Klimaschrank. Da ist quasi nur ein Gyro drauf (welches nicht 
abgefragt wird) und ein Microcontroller.

von PittyJ (Gast)


Lesenswert?

Wird alle 5 Millisekunden aufgerufen... Dann ist der ja nur am arbeiten.

Ich messe maximal einmal die Sekunde. Schneller ändert sich die 
Temperatur selten.
Nur wird so nur noch 1/200stel an Leistung verbraten.

von Wolfgang (Gast)


Lesenswert?

Marc P. schrieb:
> Auf der Platine befinden sich aber keine
> Nennenswerten Heizquellen und der Sensor lag deutlich länger als eine
> Stunde im Klimaschrank. Da ist quasi nur ein Gyro drauf (welches nicht
> abgefragt wird) und ein Microcontroller.

Dann guck mal, wieviel Strom auf der Versorgung fließt. Multipliziert 
mit der Spannung kennst du deinen Wärmeeintrag und zusammen mit dem 
Wärmeübergangswiderstand zur Kammerluft auch die Temperaturüberhöhung.
Miss mal alle 10s, 1s, 100ms, 10ms und legen zwischen den Messungen 
möglichst alles schlafen. Damit bekommst du ein Gefühl dafür, wie hoch 
die Eigenerwärmung auf Grund deiner Messfrequenz ist.

von Marc P. (marc_p649)


Lesenswert?

Danke für eure Tipps. Ich probier am Montag aus, wie sich die 
Temperaturabweichung mit den unterschiedlichen Abtastraten verändert und 
meld mich mit den Ergebnissen.

von Jefe (Gast)


Lesenswert?

Wo misst den der Prüfschrank die Temperatur? Und in der Regel ist da ein 
Ventilator verbaut. Also schon mal schlecht für Druckmessungen.

von Wolfgang (Gast)


Lesenswert?

Jefe schrieb:
> Und in der Regel ist da ein
> Ventilator verbaut. Also schon mal schlecht für Druckmessungen.

Für eine Temperaturmessung wird es trotzdem funktionieren. Die ist 
unabhängig von der Druckmessung und dankbar für eine vernünftige 
Durchmischung in der Kammer.

Marc P. schrieb:
> Wenn ich den Klimaschrank auf -15 °C einstelle, dann
> komm ich irgendwo bei ca. -11 °C raus.

von Marc P. (marc_p649)


Lesenswert?

Jefe schrieb:
> Wo misst den der Prüfschrank die Temperatur?

Das habe ich vergessen zu schreiben. Der Klimaschrank hat einen 
Temperaturfühler, den ich neben die Platine gelegt hab (beides liegt auf 
einer Styroporschale, umgedreht nach oben, sodass alle Bauteile auf dem 
"Boden" der Schale und die Schale auf den Seitenwänden stehen). Daneben 
habe ich noch ein Thermometer gestellt, das ich von außen beobachten 
kann. Das Thermometer misst sehr ähnliche Temperaturen wie der 
Klimaschrank.

: Bearbeitet durch User
von Marc P. (marc_p649)


Angehängte Dateien:

Lesenswert?

Ich habe heute nochmal Messungen gemacht. Es ist tatsächlich besser 
geworden in dem ich die Abfragen nur noch sekündlich mache. Danke 
schonmal für den Tipp.

Mit der Druckmessung bin ich allerdings nicht weiter gekommen. 
Allerdings habe ich etwas beobachtet. Ich führe wie oben geschrieben 
jede Sekunde eine Messung durch und sende das Ergebnis über die serielle 
Schnittstelle. Die Nachricht besteht aus einer Startsequenz (4 Byte), 
dem Druckwert (6 Byte), dem Temperaturwert (6 Byte) und einem Endbyte. 
Der Messwert setzt sich aus den zweiten 4 Bit des jeweiligen Byte 
zusammen, also ist der Druckwert in der ersten Zeile 0x244F, der 
Temperaturwert 0x0EB8. In dem Angehängten Bild sieht man beispielhaft 
die "Druckänderung" (Rx5 und Rx6). Hier springt die 2 auf die 3.

Ich hab mit dem Debugger festgestellt, dass die Werte nicht bei der 
Übertragung, sondern bei der Berechnung des Druckwertes entstehen, die 
serielle Schnittstelle schließe ich deshalb aus.

Der I2C-Bus läuft mit einer Übertragungsrate von 400 kbit/s. Eine 
geringere Übertragungsrate von 100 kbit/s hat leider keine Verbesserung 
gebracht.

Hat vielleicht irgendjemand eine Idee woran das liegen könnte?

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.