BMP180 Luftdruck Sensor

OP #5361034
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
}
Angehängte Dateien:
(Firma: Brainit GmbH) #5362028
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.
OP #5362038
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
}
Gast #5362061
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.
OP #5362064
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.

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