Forum: Mikrocontroller und Digitale Elektronik BMP180 Luftdruck Sensor


von Simon X. (simon1720)


Angehängte Dateien:

Lesenswert?

Guten Tag ich habe den Druckluftsensor BMP180 in Betrieb genommen. Das 
Programm läuft einwandfrei bis auf einen groben Fehler. Bei der Zeile 
mit unsigned long B7 errechnet der uC B7 in einer höhe von ca 1650000000 
und in den nächsten schritten wird p also der Druck berechnet. Am 
Schluss ist p ca 25500. Dieser Wert ist ca. 4 mal zu klein. Bis an die 
Stelle wo B4 ausgerechnet wird habe ich alles nachgerechnet und 
überprüft auch mit dem Display. Ich vermute ev das es etwas mit den 
Datentypen auf sich hat. Vielleicht sieht jemand das Problem oder meinen 
Fehler.

Der Code ist im Anhang:
1
#include "Luftdruck.h"
2
#include "i2c.h"
3
#include "LCD.h"
4
5
6
void get_EPromData(short*AC1,short*AC2,short*AC3,unsigned short*AC4,unsigned short*AC5,unsigned short*AC6,short*B1,short*B2,short*MB,short*MC,short*MD)
7
{
8
  i2c_start(0xEE,0);
9
  i2c_write(0xAA);
10
  i2c_stop();
11
  
12
   i2c_start(0xEE,1);
13
   *AC1 = (i2c_read(1) << 8);
14
   *AC1 += i2c_read(1);
15
   
16
   *AC2 = (i2c_read(1) << 8);
17
   *AC2 += i2c_read(1);
18
   
19
  *AC3 = (i2c_read(1) << 8);
20
  *AC3 += i2c_read(1);
21
  
22
  *AC4 = (i2c_read(1) << 8);
23
  *AC4 += i2c_read(1);
24
  
25
  *AC5 = (i2c_read(1) << 8);
26
  *AC5 += i2c_read(1);
27
  
28
  *AC6 = (i2c_read(1) << 8);
29
  *AC6 += i2c_read(1);
30
  
31
  *B1 = (i2c_read(1) << 8);
32
  *B1 += i2c_read(1);
33
  
34
  *B2 = (i2c_read(1) << 8);
35
  *B2 += i2c_read(1);
36
  
37
  *MB = (i2c_read(1) << 8);
38
  *MB += i2c_read(1);
39
  
40
  *MC = (i2c_read(1) << 8);
41
  *MC += i2c_read(1);
42
  
43
  *MD = (i2c_read(1) << 8);
44
  *MD += i2c_read(0);
45
   i2c_stop();  
46
   
47
//    *AC1 = 408;
48
//    *AC2 = -72;
49
//    *AC3 = -14383;
50
//    *AC4 = 32741;
51
//    *AC5 = 32757;
52
//    *AC6 = 23153;
53
//    *B1 = 6190;
54
//    *B2 = 4;
55
//    *MB = -32768;
56
//    *MC = -8711;
57
//    *MD = 2868;
58
  
59
}
60
61
void get_Preasure(short AC1,short AC2,short AC3,unsigned short AC4,unsigned short AC5,unsigned short AC6,short B1,short B2,short MB,short MC,short MD)
62
{
63
64
   uint8_t oss = 0;  //Oversampling 4.5ms
65
   long p;
66
   
67
   //Temperatur auslesen
68
   i2c_start(0xEE,0);
69
   i2c_write(0xF4);
70
   i2c_write(0x2E);
71
   i2c_stop();
72
   _delay_ms(5);  //warten
73
   
74
   i2c_start(0xEE,0);
75
   i2c_write(0xF6);
76
   i2c_stop();
77
   i2c_start(0xEE,1);
78
   long UT = (i2c_read(1) << 8);
79
   UT = UT + i2c_read(0);
80
   i2c_stop();
81
   
82
   //Luftdruck auslesen
83
   i2c_start(0xEE,0);
84
   i2c_write(0xF4);
85
   i2c_write(0x34+(oss<<6));
86
   i2c_stop();
87
   _delay_ms(5);  //warten
88
   
89
   i2c_start(0xEE,0);
90
   i2c_write(0xF6);
91
   i2c_stop();
92
   
93
   
94
  
95
   i2c_start(0xEE,1);
96
   long MSB = (i2c_read(1) << 8);
97
   long LSB = (i2c_read(1) << 8);
98
   long XLSB = i2c_read(0);
99
   long UP = ((MSB<<8) + LSB + XLSB) >> (8-oss);
100
   i2c_stop();
101
102
   //Temperatur berechnen
103
   long X1 = ((UT- AC6) * AC5)>>15;
104
    long X2 = (long)MC * 2048 / (X1+ MD);
105
    long B5 = X1 + X2;
106
    long T = (B5+8)/16;
107
108
   //Berechnungen mit EEProm und Luftdruck für Luftdruck
109
    long B6 = B5 - 4000;
110
    X1 = ((long)B2 * (B6*B6/4096))/2048;
111
    X2 = (long)AC2 * B6/2048;
112
    long X3 = X1 + X2;
113
    
114
     unsigned long B3 = (((AC1 * 4 + X3)<<oss)+2)/4;
115
     X1 = AC3 * B6/8192;
116
     X2 = ((long)B1*(B6*B6/4096))/65536;
117
     X3 = ((X1 + X2)+2)/4;
118
     long B4 = (unsigned long)AC4 * (unsigned long)(X3 + 32768)/32768; //OK
119
     unsigned long B7 = ((unsigned long )UP - B3)*(50000 >> oss);          //Problem / ev. unsigned long long?
120
    
121
//   unsigned long XY = (33000*50000)/100000;
122
//   unsigned long Q = 2000111000;
123
 
124
       if (B7 < 0x80000000)
125
       {
126
         p = (B7*2)/B4;
127
       }
128
       else
129
       {
130
         p = (B7/B4)*2;
131
       }
132
133
      X1 = (p/256)*(p/256);
134
      X1 = (X1 * 3038)/65536;
135
      X2 = (-7357 * p)/65536;
136
      p = p + (X1 + X2 + 3791)/16;  
137
  
138
      set_cursor(1,4);
139
      write_zahl(p,7,0,0,0);
140
  _delay_ms(1000);
141
}

von Wolfgang (Gast)


Lesenswert?

Warum versuchst du, das Rad neu zu erfinden und verwendest nicht die von 
BoschSensortec veröffentlichten Routinen?
https://github.com/BoschSensortec/BMP280_driver

von Simon X. (simon1720)


Lesenswert?

Der Code Ablauf steht das meiste schon im Datenblatt. Der fertige Code 
ist sehr unübersichtlich und für meinen gebrauch ungeeignet. Ausserdem 
ist dies so zusagen dieser Ablauf.

von Stephan G. (Firma: privat) (morob)


Lesenswert?

sicher das deine datentypen stimmen?

von Simon X. (simon1720)


Lesenswert?

Ja diese habe ich mit dem Datenblatt überprüft.

von Dominic K. (domi1997)


Lesenswert?

Ist der Displaytreiber auf einen so langen Datentyp ausgelegt? 
https://en.wikipedia.org/wiki/C_data_types

von Simon X. (simon1720)


Lesenswert?

Der Display Treiber spielt keine Rolle, den ich teile am Schluss noch 
durch 100 so das es auf dem Display einen maximalen wert einer 4 
Stelligen Zahl ergib.

von Stephan G. (Firma: privat) (morob)


Lesenswert?

Simon X. schrieb:
> Ja diese habe ich mit dem Datenblatt überprüft.

welcher prozessor?
welche länge hat short bei dir?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Wolfgang schrieb:
> Warum versuchst du, das Rad neu zu erfinden und verwendest nicht die von
> BoschSensortec veröffentlichten Routinen?
> https://github.com/BoschSensortec/BMP280_driver

Weil der Bosch-Code Schrott ist?
Beitrag "Bosch BMP280: Umrechnungen vereinfachen?"

von Simon X. (simon1720)


Lesenswert?

Der Prozessor ist ein Atmega644PA
short hat eine Grösse von 8Bit.

von Simon X. (simon1720)


Lesenswert?

dies ist aber der Code zu dem BMP280

von Simon X. (simon1720)


Lesenswert?

Stephan G. schrieb:
> Simon X. schrieb:
>> Ja diese habe ich mit dem Datenblatt überprüft.
>
> welcher prozessor?
> welche länge hat short bei dir?

Hab noch einmal überprüft short ist bei dem 16Bit.

von Wolfgang (Gast)


Lesenswert?

Simon X. schrieb:
> dies ist aber der Code zu dem BMP280

Sorry
https://github.com/BoschSensortec/BMP180_driver

von Simon X. (simon1720)


Lesenswert?

Diese Treiber sind alle unbrauchbar. Ich schreibe diesen Code um in 150 
Zeilen und nicht 1500 mit unnötigen Berechnungen. Wer einen fertigen 
Treiber benützt hat es einfach nicht begriffen. Vor allem wen es sich um 
eine Grundstruktur handelt von einem Sensor!

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Simon X. schrieb:
> Diese Treiber sind alle unbrauchbar. Ich schreibe diesen Code um in 150
> Zeilen und nicht 1500 mit unnötigen Berechnungen. Wer einen fertigen
> Treiber benützt hat es einfach nicht begriffen. Vor allem wen es sich um
> eine Grundstruktur handelt von einem Sensor!

Mach mal, aber lass uns dann das Ergebnis sehen.

von Simon X. (simon1720)


Lesenswert?

Habe das Problem gefunden. Es lag an einem Datentypen bei der 
Verrechnung nach dem Auslesen aus dem I2C Bus von UP.
Hier ist der Funktionale Treiber für den BMP180. Die Stelle ist markiert 
wo das Problem lag. Man sieht also der Treiber mit über 1000 Zeilen ist 
überflüssig geht auch ohne und selber schreiben. Weiss man danach auch 
was man gemacht hat!
1
 
2
void get_EPromData(short*AC1,short*AC2,short*AC3,unsigned short*AC4,unsigned short*AC5,unsigned short*AC6,short*B1,short*B2,short*MB,short*MC,short*MD)
3
{
4
  i2c_start(0xEE,0);
5
  i2c_write(0xAA);
6
  i2c_stop();
7
  
8
   i2c_start(0xEE,1);
9
   *AC1 = (i2c_read(1) << 8);
10
   *AC1 += i2c_read(1);
11
   
12
   *AC2 = (i2c_read(1) << 8);
13
   *AC2 += i2c_read(1);
14
   
15
  *AC3 = (i2c_read(1) << 8);
16
  *AC3 += i2c_read(1);
17
  
18
  *AC4 = (i2c_read(1) << 8);
19
  *AC4 += i2c_read(1);
20
  
21
  *AC5 = (i2c_read(1) << 8);
22
  *AC5 += i2c_read(1);
23
  
24
  *AC6 = (i2c_read(1) << 8);
25
  *AC6 += i2c_read(1);
26
  
27
  *B1 = (i2c_read(1) << 8);
28
  *B1 += i2c_read(1);
29
  
30
  *B2 = (i2c_read(1) << 8);
31
  *B2 += i2c_read(1);
32
  
33
  *MB = (i2c_read(1) << 8);
34
  *MB += i2c_read(1);
35
  
36
  *MC = (i2c_read(1) << 8);
37
  *MC += i2c_read(1);
38
  
39
  *MD = (i2c_read(1) << 8);
40
  *MD += i2c_read(0);
41
   i2c_stop();    
42
}
43
44
void get_Preasure(short AC1,short AC2,short AC3,unsigned short AC4,unsigned short AC5,unsigned short AC6,short B1,short B2,short MB,short MC,short MD)
45
{
46
47
   uint8_t oss = 0;  //Oversampling 4.5ms
48
   long p;
49
  long p0 = 1013.25;
50
   
51
   //Temperatur auslesen
52
   i2c_start(0xEE,0);
53
   i2c_write(0xF4);
54
   i2c_write(0x2E);
55
   i2c_stop();
56
   _delay_ms(5);  //warten
57
   
58
   i2c_start(0xEE,0);
59
   i2c_write(0xF6);
60
   i2c_stop();
61
   i2c_start(0xEE,1);
62
   long UT = (i2c_read(1) << 8);
63
   UT = UT + i2c_read(0);
64
   i2c_stop();
65
   
66
   //Luftdruck auslesen
67
   i2c_start(0xEE,0);
68
   i2c_write(0xF4);
69
   i2c_write(0x34+(oss<<6));
70
   i2c_stop();
71
   _delay_ms(5);  //warten
72
   
73
   i2c_start(0xEE,0);
74
   i2c_write(0xF6);
75
   i2c_stop();
76
77
   i2c_start(0xEE,1);
78
   unsigned int MSB = (i2c_read(1) << 8);
79
   unsigned int LSB = i2c_read(1);
80
   unsigned int XLSB = i2c_read(0);
81
  unsigned int UP = MSB + LSB + XLSB; //Verrechnungsproblem!!
82
   i2c_stop();
83
   
84
   //Temperatur berechnen
85
   long X1 = ((UT- AC6) * AC5)>>15;
86
    long X2 = (long)MC * 2048 / (X1+ MD);
87
    long B5 = X1 + X2;
88
    long T = (B5+8)/16;
89
90
   //Berechnungen mit EEProm und Luftdruck für Luftdruck
91
    long B6 = B5 - 4000;
92
    X1 = ((long)B2 * (B6*B6/4096))/2048;
93
    X2 = (long)AC2 * B6/2048;
94
    long X3 = X1 + X2;
95
    
96
     unsigned long B3 = (((AC1 * 4 + X3)<<oss)+2)/4;
97
     X1 = AC3 * B6/8192;
98
     X2 = ((long)B1*(B6*B6/4096))/65536;
99
     X3 = ((X1 + X2)+2)/4;
100
     long B4 = (unsigned long)AC4 * (unsigned long)(X3 + 32768)/32768; 
101
     unsigned long B7 = ((unsigned long )UP - B3)*(50000 >> oss);    
102
103
    p = (B7*2)/B4;
104
  
105
        if (B7 < 0x80000000)
106
        {
107
          p = (B7*2)/B4;
108
        }
109
        else
110
        {
111
          p = (B7/B4)*2;
112
        }
113
114
       X1 = (p/256)*(p/256);
115
       X1 = (X1 * 3038)/65536;
116
       X2 = (-7357 * p)/65536;
117
       p = p + (X1 + X2 + 3791)/16;  
118
     p = p / 100;
119
     
120
    if ((p0 == 0) || (p0 < p)) p0 = 101325;
121
    float palt = pow (((double) p / p0), (1.0 / 5.255));
122
    palt = 1 - palt;
123
    palt = palt / 0.0000225577;
124
    int16_t alt = (int16_t) palt;
125
}

: Bearbeitet durch User
von Karl M. (Gast)


Lesenswert?

Hallo,

das stimmt aber nicht, Du hättest besser einen Cast angewendet.
1
unsigned int MSB = (i2c_read(1) << 8);
2
unsigned int LSB = i2c_read(1);
3
unsigned int XLSB = i2c_read(0);
4
unsigned int UP = MSB + LSB + XLSB; //Verrechnungsproblem!!

Hier werden 24 Bit gelesen!
Aber dieser Code liefert nur ein 16Bit Ergebnis, die Wertigkeiten 
stimmen nicht:
a2  | a1  | a0
MSB | LSB | XLSB

Erg = a2*8² + a1*8¹ + a0*8⁰

Ich habe gerade auch eine BMP180 Implementierung anhand des Datenblattes 
gemacht und könnte von meinen Erfahrungen berichten.

von Simon X. (simon1720)


Lesenswert?

Ja das Stimmt ich habe ein wenig ausprobiert. Da XLSB immer einen 0 
zurück bekommt habe ich dies vernachlässigt. Aber das Stimmt wen man OSS 
auch hinzufügt dan muss man dies anders lösen werde ich noch nachtragen. 
Aber so funktioniert dies auch mal. Stehe immer ein wenig auf Kriegsfuss 
mit Datentypen.

von Karl M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Simon X.,

dann caste bitte vorher das MSB nach long, wie im Datenblatt des BMP180 
beschrieben, dann passt das!

von Simon X. (simon1720)


Lesenswert?

Ja dies hatte ich auch mal am Anfang. Dies ist aber ein Problem, da mein 
Compiler das nicht verarbeiten will auch mit #pragma optimize 0. Er 
Speicherte mir den Wert UP nie und schrieb das Register mit FFFF... 
voll. Somit musste ich auf eine andere Lösung zurückgreifen.

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.