Forum: Mikrocontroller und Digitale Elektronik BMP180 I2C Problem?


von Jan (Gast)


Lesenswert?

Hallo,

ich versuche jetzt schon seit einiger Zeit den "BMP180" unter Kontrolle 
zu bekommen. Leider klappt das noch nicht 100 % ig...

Was funktionert?

Ich kann die Temperatur und den Druck auslesen...
Leider nur getrent.

sieht so aus..
1
    //int16_t tmp_temp = BMP180_read_temperature();  
2
    long temp_pressure = BMP180_read_pressure(0);

Möchte ich wieder beides zusammen auslesen, ändern sich meine Werte 
komplett in den Falschen Bereich (einzelnd passt Temperatur wie auch 
Druck).

Ich vermute mal das ich irgendwas am abholen der Werte falsch mache...
Habt ihr eine Idee?

Hier die Routinen...

1
int16_t BMP180_read_temperature()
2
{
3
  long UT; // holds the raw temperature value read from BMP180
4
  long X1, X2;
5
  long truetemperature, B5;
6
7
  i2c_start(BMP180_address+I2C_WRITE);
8
  i2c_write(0xF4);
9
  i2c_write(0x2E);
10
  i2c_stop();
11
  _delay_ms(5);
12
  
13
  i2c_start(BMP180_address+I2C_WRITE);
14
  i2c_write(0xF6);
15
  i2c_stop();
16
17
  i2c_start(BMP180_address+I2C_READ);
18
  UT  = (long)i2c_readAck()<<8;
19
  UT |= (long)i2c_readNak();
20
  i2c_stop();
21
  
22
  X1 = ((long)(UT - AC6)) * ((long)(AC5)) >> 15;
23
   X2 = ((long)MC << 11) / (X1 + MD); 
24
   B5 = (long)X1 + X2; 
25
  truetemperature = (long)((B5 + 8) >> 4);
26
  
27
  truetemperature = truetemperature / 10;
28
29
  return truetemperature;
30
}
31
32
unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
33
{
34
  long      B6, X1, X2, X3, B3;
35
  unsigned long  B4,B7;  
36
  long      UP, B5;   
37
  unsigned long  truepressure;
38
  
39
  i2c_start(BMP180_address+I2C_WRITE);
40
  i2c_write(0xF4);
41
  i2c_write(0xF4);  
42
  i2c_stop();
43
  _delay_ms(40);
44
  
45
  i2c_rep_start(BMP180_address+I2C_WRITE);
46
  i2c_write(0xF6);
47
  
48
  i2c_rep_start(BMP180_address+I2C_READ);
49
  UP  = (long)i2c_readAck()<<8;
50
  UP |= (long)i2c_readNak();
51
  //i2c_stop();
52
53
54
#if sample_calibration_test == 1
55
    
56
  /*sample calibrations*/   
57
  oversampling_setting = 0;  
58
  AC1 = (short)408;
59
  AC2 = (short)-72;
60
  AC3 = (short)-14383;
61
  AC4 = (unsigned short) 32741;
62
  AC5 = (unsigned short)32757;
63
  AC6 = (unsigned short)23153;
64
  B1 = (short)6190;
65
  B2 = (short)4;
66
  MB = (short)-32768;
67
  MC = (short)-8711;
68
  MD = (short)2868;
69
   
70
  UP = 23843;  
71
  B5 = 2399;
72
73
#endif
74
75
76
    B6 = B5 - 4000;
77
   X1 = (B2 * (B6 * B6 / 4096)) / 2048;
78
   X2 = (AC2 *  B6) / 2048;
79
   X3 = X1 + X2;
80
   B3 = (((AC1 * 4 + X3) << oversampling_setting) + 2) / 4;
81
   X1 = AC3 * B6 / 8192;
82
   X2 = (B1 * (B6 * B6 / 4096)) / 65536;
83
   X3 = ((X1 + X2) + 2) / 4;
84
   B4 = AC4 *(unsigned long) (X3 + 32768) / 32768;
85
   B7 = ((unsigned long)UP-B3) * (50000 >> oversampling_setting);
86
 
87
  if(B7 < 0x80000000)
88
  {
89
     truepressure = (B7 * 2) / B4;
90
   }
91
   else
92
  {
93
     truepressure = (B7 / B4) *2;
94
   }   
95
   
96
   X1 = (truepressure / 256) * (truepressure / 256);
97
  X1 = (X1 * 3038) / 65536;    
98
   X2 = (-7357 * truepressure) / 65536;
99
   truepressure = truepressure + (X1 + X2 + 3791) / 16;
100
101
  truepressure = truepressure * 0.01;
102
  return (unsigned long)truepressure;
103
}

von Joe F. (easylife)


Lesenswert?

Warum hast du in BMP180_read_pressure() das i2c_stop() auskommentiert?
Ausserdem solltest du zwischen den beiden Abfragen vermutlich auch ein 
paar ms warten.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Joe F. schrieb:
> Warum hast du in BMP180_read_pressure() das i2c_stop()
> auskommentiert?
> Ausserdem solltest du zwischen den beiden Abfragen vermutlich auch ein
> paar ms warten.

- Ich habe schon überall gewartet > 50 ms... hat leider auch nichts 
gebracht.

- das Stop habe ich nur testeshalber mal raus genommen (bringt leider 
auch nichts).


ich weiß nicht mehr an was das liegen kann...

von Joe F. (easylife)


Lesenswert?

Dein start, stop, repeated start conditions sind etwas chaotisch.
Die Zeit für die pressure conversion kann auch lt. Datenblatt je nach 
Mode bis zu 76.5ms dauern.
Ich denke es müsste so aussehen:

1
int16_t BMP180_read_temperature()
2
{
3
  long UT; // holds the raw temperature value read from BMP180
4
  long X1, X2;
5
  long truetemperature, B5;
6
7
  i2c_start(BMP180_address+I2C_WRITE);
8
  i2c_write(0xF4);
9
  i2c_write(0x2E);
10
  i2c_stop();
11
  _delay_ms(5);
12
  
13
  i2c_start(BMP180_address+I2C_WRITE);
14
  i2c_write(0xF6);
15
//  i2c_stop();
16
17
  i2c_rep_start(BMP180_address+I2C_READ); // <--- hier repeated start
18
  UT  = (long)i2c_readAck()<<8;
19
  UT |= (long)i2c_readNak();
20
  i2c_stop();
21
22
  _delay_ms(1); // <--- mal sicherheitshalber ausprobieren...
23
24
  
25
  X1 = ((long)(UT - AC6)) * ((long)(AC5)) >> 15;
26
   X2 = ((long)MC << 11) / (X1 + MD); 
27
   B5 = (long)X1 + X2; 
28
  truetemperature = (long)((B5 + 8) >> 4);
29
  
30
  truetemperature = truetemperature / 10;
31
32
  return truetemperature;
33
}
34
35
unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
36
{
37
  long      B6, X1, X2, X3, B3;
38
  unsigned long  B4,B7;  
39
  long      UP, B5;   
40
  unsigned long  truepressure;
41
  
42
  i2c_start(BMP180_address+I2C_WRITE);
43
  i2c_write(0xF4);
44
  i2c_write(0xF4);  
45
  i2c_stop();
46
//  _delay_ms(40);
47
  _delay_ms(80); // <--- hier mal laenger warten
48
  
49
//  i2c_rep_start(BMP180_address+I2C_WRITE);
50
  i2c_start(BMP180_address+I2C_WRITE); // <--- hier NICHT rep_start
51
  i2c_write(0xF6);
52
  
53
  i2c_rep_start(BMP180_address+I2C_READ);
54
  UP  = (long)i2c_readAck()<<8;
55
  UP |= (long)i2c_readNak();
56
  //i2c_stop();
57
58
  i2c_stop();   // <--- diese stop condition brauchst du mit Sicherheit
59
  _delay_ms(1); // <--- auch ausprobieren
60
61
  (...)

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Das ändert leider auch nichts... Hier habe ich mal einen Auszug aus 
meinem TeraTerm...

Kommentiere ich die einzelnen Funktionen aus, scheint es zu klappen...

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

So schlecht sieht das doch nicht aus!
1000 mbar sind plausibel, mit der Berechnung der Temperatur ist wohl 
noch etwas falsch, aber immerhin schwanken die Werte nicht total absurd.

von Jan H. (janiiix3)


Lesenswert?

Joe F. schrieb:
> So schlecht sieht das doch nicht aus!
> 1000 mbar sind plausibel, mit der Berechnung der Temperatur ist wohl
> noch etwas falsch, aber immerhin schwanken die Werte nicht total absurd.

Wieso denkst du, dass da was falsch ist ? Wenn ich alles einzelnd 
ausgebe, passt es...

von Karl H. (kbuchegg)


Lesenswert?

Mit welchem Code fährst du jetzt.

Ich würde mal sagen, du bist zu schnell dir das vermeintliche Ergebnis 
abzuholen.

Wenn du nur eine Größe abfragst, dann kommst du damit durch, weil dann 
immer wieder nur die Temperatur in die Ausgangsregister geschrieben 
werden. D.h. du startest dann zwar eine neue Messung (die auch 
irgendwann fertig wird), aus dem Ausgangsregister kriegst du aber das 
Ergebnis einer vorhergehenden Messung. Da du zwischendurch nicht den 
Messtypus umschaltest, sind die Werte dann auch plausibel.

Wie könnte man das abklären?

Ich würde mir mal die Bytes ausgeben lassen. So wie sie vom Sensor 
kommen.
Einmal nur bei Temperatur. Einmal nur bei Druck. Und dann beides 
gemeinsam. Wenn alles so läuft wie spekuliert, dann wirst du bei deiner 
Temperaturmessung Bytewerte sehen, die dich an die Druckwerte erinnern.

(Ich bin überhaupt ein Fan davon, mit dir rohen Bytes erst mal anzusehen 
und nicht gleich rumzurechnen. Ich hab das Gefühl, da sieht man 
Zusammenhänge einfach viel besser, als bei offensichtlich falschen 
Resultaten, von denen keiner erklären kann wie sie zustande kommen)

von Joe F. (easylife)


Lesenswert?

Wo werden denn die Variablen/Konstanten AC6, AC5, MC, MD für die 
Funktion  BMP180_read_temperature() definiert?
Kann es sein, dass du hier andere Werte hast, als die, die dann in 
BMP180_read_pressure() gesetzt werden, und dadurch 
BMP180_read_temperature() nach einem Aufruf von BMP180_read_pressure() 
nicht mehr funktioniert?
Poste mal bitte den gesamten Code, und zwar als Dateianhang.

: Bearbeitet durch User
von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Joe F. schrieb:
> Wo werden denn die Variablen/Konstanten AC6, AC5, MC, MD für die
> Funktion  BMP180_read_temperature() definiert?
> Kann es sein, dass du hier andere Werte hast, als die, die dann in
> BMP180_read_pressure() gesetzt werden, und dadurch
> BMP180_read_temperature() nach einem Aufruf von BMP180_read_pressure()
> nicht mehr funktioniert?
> Poste mal bitte den gesamten Code, und zwar als Dateianhang.

Hier habt ihr mal den gesamten Code...

P.S

Danke schon mal für eure schnelle Hilfe!

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

@ Karl Heinz...

Du scheinst Recht zu haben. Leider klappt es auch mit Wartezeit > 100 ms 
nicht.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> @ Karl Heinz...
>
> Du scheinst Recht zu haben. Leider klappt es auch mit Wartezeit > 100 ms
> nicht.


Wie hoch bist du gegangen?
Geh mal ins Extrem. 1 Sekunde oder so. Nicht kleckern. Klotzen! Wir sind 
auf Fehlersuche und nicht beim Wettbewerb.

(ps: mit %x, genauer %04x anstelle von %i oder %u kannst du dir im 
sprintf eine hexadezimale Anzeige geben lassen. Hex ist es meist 
einfacher Bytes zu vergleichen.)

Blöde Frage: die 8Mhz stimmen aber schon?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Blöde Frage: die 8Mhz stimmen aber schon?


Der Optimizer vom Compiler ist eingeschaltet?

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> @ Karl Heinz...
>>
>> Du scheinst Recht zu haben. Leider klappt es auch mit Wartezeit > 100 ms
>> nicht.
>
> Wie hoch bist du gegangen?
> Geh mal ins Extrem. 1 Sekunde oder so. Nicht kleckern. Klotzen! Wir sind
> auf Fehlersuche und nicht beim Wettbewerb.
>
> (ps: mit %x, genauer %04x anstelle von %i oder %u kannst du dir im
> sprintf eine hexadezimale Anzeige geben lassen. Hex ist es meist
> einfacher Bytes zu vergleichen.)
>
> Blöde Frage: die 8Mhz stimmen aber schon?


Ich bin schon auf 2,5 sec. das klappt nicht.

Ich habe in der "main" 16 MHz definiert.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> @ Karl Heinz...
>>
>> Du scheinst Recht zu haben. Leider klappt es auch mit Wartezeit > 100 ms
>> nicht.
>
>
> Wie hoch bist du gegangen?
> Geh mal ins Extrem. 1 Sekunde oder so.

Und das bei beidem: Temperatur UND Druck.

Nach dem Kommando 'Messen' gibst du dem Sensor mal alle Zeit der Welt in 
Ruhe und gemütlich seine Messung zu machen.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:

> Ich habe in der "main" 16 MHz definiert.

IN deinen BMP Routinen steht aber 8Mhz?

Wenn dein µC mit 16Mnz taktet, dann ist klar, dass ein
1
   _delay_ms( 5 );

keine 5 Millisekunden dauert, wenn der als Berechnungsgrundlage von 8Mhz 
ausgeht.

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>
>> Ich habe in der "main" 16 MHz definiert.
>
> IN deinen BMP Routinen steht aber 8Mhz?
>
> Wenn dein µC mit 16Mnz taktet, dann ist klar, dass ein   _delay_ms( 5 );
>
> keine 5 Millisekunden dauert, wenn der als Berechnungsgrundlage von 8Mhz
> ausgeht.

Habe das #define dort mal raus geschmissen. Nun müsste der Compiler doch 
mit meinen "16MHz" von der "main" rechnen oder?

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> Jan H. schrieb:
>>
>>> Ich habe in der "main" 16 MHz definiert.
>>
>> IN deinen BMP Routinen steht aber 8Mhz?
>>
>> Wenn dein µC mit 16Mnz taktet, dann ist klar, dass ein   _delay_ms( 5 );
>>
>> keine 5 Millisekunden dauert, wenn der als Berechnungsgrundlage von 8Mhz
>> ausgeht.
>
> Habe das #define dort mal raus geschmissen. Nun müsste der Compiler doch
> mit meinen "16MHz" von der "main" rechnen oder?

Nein.

Jedes C File wird für sich selbst und unabhängig von allen anderen 
übersetzt.

Wenn der Compiler die BMP180.c übersetzt, dann interessiert es niemanden 
was in einem main.c steht.
Jedes C-File steht ganz allein auf weiter Flur und erst im Linker werden 
die teilübersetzten Ergebnisse dann zum kompletten Programm 
zusammenmontiert. Da ist es aber schon zu spät.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Jan H. (janiiix3)

>Habe das #define dort mal raus geschmissen. Nun müsste der Compiler doch
>mit meinen "16MHz" von der "main" rechnen oder?

Nö. Poste deine originalen Quelltext als Anhang!

von Jan H. (janiiix3)


Lesenswert?

Was ich auch nicht verstehe...

Laut Datenblatt, wird "B5" für die Berechnung vom Druck benötigt.
Deßhalb habe ich "B5" global deklariert. Tue ich genau dies, passt der 
Druck nicht mehr.

Deklariere ich "B5" jedes mal in der jeweiligen Funktion "neu"... Habe 
ich aufeinmal einen Aktzeptablen Druck...

Muss man das verstehen?

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Falk Brunner schrieb:
> @ Jan H. (janiiix3)
>
>>Habe das #define dort mal raus geschmissen. Nun müsste der Compiler doch
>>mit meinen "16MHz" von der "main" rechnen oder?
>
> Nö. Poste deine originalen Quelltext als Anhang!


Nicht wundern, ist nicht sonderlich aufgeräumt :(d

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:

> Muss man das verstehen?

Ja das sollte man als C-Programmierer
Deine Funktionen sind voller Fehler.

Aber solange die Bytewerte nicht stimmen ist alles andere sinnlos.
Eines nach dem anderen. Erst mal wollen wir vom Sensor die richtigen 
Bytewerte zum richtigen Zeitpunkt.
Dann kommt der Rest.

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>
>> Muss man das verstehen?
>
> Ja das sollte man als C-Programmierer
> Deine Funktionen sind voller Fehler.
>
> Aber solange die Bytewerte nicht stimmen ist alles andere sinnlos.
> Eines nach dem anderen. Erst mal wollen wir vom Sensor die richtigen
> Bytewerte zum richtigen Zeitpunkt.
> Dann kommt der Rest.

Ich bin jetzt auch nicht so der "Pro" Programmierer. Fange ja erst 
richtig an.

Wo sind denn Fehler?

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> Jan H. schrieb:
>>
>>> Muss man das verstehen?
>>
>> Ja das sollte man als C-Programmierer
>> Deine Funktionen sind voller Fehler.
>>
>> Aber solange die Bytewerte nicht stimmen ist alles andere sinnlos.
>> Eines nach dem anderen. Erst mal wollen wir vom Sensor die richtigen
>> Bytewerte zum richtigen Zeitpunkt.
>> Dann kommt der Rest.
>
> Ich bin jetzt auch nicht so der "Pro" Programmierer. Fange ja erst
> richtig an.
>
> Wo sind denn Fehler?

Zum Beispiel das B5 in der Druck Lesefunktion.
Welchen Wert hat es, wenn die Berechnungen starten?
1
unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
2
{
3
  long      UP, B5;   
4
....
5
    B6 = B5 - 4000;
6
....

richtig. Wir wissen es nicht. Irgendeinen. Zufällig. Was halt gerade im 
Speicher stand, als die Funktion betreten wurde.

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Zum Beispiel das B5 in der Druck Lesefunktion.
> Welchen Wert hat es, wenn die Berechnungen starten?
> unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
> {
>   long      UP, B5;
> ....
>     B6 = B5 - 4000;
> ....
>
> richtig. Wir wissen es nicht. Irgendeinen. Zufällig. Was halt gerade im
> Speicher stand, als die Funktion betreten wurde.

Ich sollte die Variablen vorher "auf null" setzen, richtig ?

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> Zum Beispiel das B5 in der Druck Lesefunktion.
>> Welchen Wert hat es, wenn die Berechnungen starten?
>> unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
>> {
>>   long      UP, B5;
>> ....
>>     B6 = B5 - 4000;
>> ....
>>
>> richtig. Wir wissen es nicht. Irgendeinen. Zufällig. Was halt gerade im
>> Speicher stand, als die Funktion betreten wurde.
>
> Ich sollte die Variablen vorher "auf null" setzen, richtig ?

Was steht denn im Datenblatt?
0 wird wohl nicht so prickelnd sein.
Denn dann würde man wohl kein B5 in der Vorlage von Bosch finden, 
sondern dann würde dort wohl gleich
1
    B6 = -4000;
stehen. Wäre doch um einiges einfacher. Oder nicht?

Du fängst zur raten an. Kein gutes Zeichen.

von Falk B. (falk)


Lesenswert?

Ja. Der Compiler müsste eigentlich eine Warnung ausgeben.

von Falk B. (falk)


Lesenswert?

@Jan H. (janiiix3)

>    read_BMP180.zip (5,73 MB, 0 Downloads)

Das 8MB Datenblatt hättest du uns ersparen können.
Dann wären es nur noch schlappe 99kB gewesen . . .

>Nicht wundern, ist nicht sonderlich aufgeräumt :(d

Die #define F_CPU sind in bmp180.c und read_bmp180.c richtig. Aber so 
sollte man es dennoch nicht tun, denn man muss die gleiche Information 
an zwei Orten aktuell halten.

Entweder im AVR Studio in den Projektoptionen einstellen, dann wird 
daraus ein automatisches #define beim Compilieren

Oder EINMALIG in EINER main.h das #define reinschreiben. Diese wird dann 
in allen anderen Dateien über #inlcude "main.h" genutzt.

Für deine Fehlersuche bringt das jetzt aber nicht viel.

von Joe F. (easylife)


Lesenswert?

Du hast an vielen Stellen sowas hier:

  i2c_stop();
  i2c_rep_start(BMP180_address+I2C_READ);

z.B. in BMP180_read_i16()
Das macht keinen Sinn.
Nach einer stop condition braucht man eine start condition.
repeated start nur ohne vorherige stop condition.

So wäre es richtig:
1
int16_t BMP180_read_i16(uint8_t reg)
2
{
3
  int16_t tmp_cal;
4
  
5
//  i2c_rep_start(BMP180_address+I2C_WRITE);
6
  i2c_start(BMP180_address+I2C_WRITE);   // <--- hier start
7
8
  i2c_write(reg);
9
//  i2c_stop();     // <--- vor repeated start kein stop
10
  
11
  i2c_rep_start(BMP180_address+I2C_READ);
12
  tmp_cal  = i2c_readAck()<<8;
13
  tmp_cal |= i2c_readNak();
14
  i2c_stop();
15
  
16
  return tmp_cal;
17
}

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> Karl Heinz schrieb:
>>> Zum Beispiel das B5 in der Druck Lesefunktion.
>>> Welchen Wert hat es, wenn die Berechnungen starten?
>>> unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
>>> {
>>>   long      UP, B5;
>>> ....
>>>     B6 = B5 - 4000;
>>> ....
>>>
>>> richtig. Wir wissen es nicht. Irgendeinen. Zufällig. Was halt gerade im
>>> Speicher stand, als die Funktion betreten wurde.
>>
>> Ich sollte die Variablen vorher "auf null" setzen, richtig ?
>
> Was steht denn im Datenblatt?
> 0 wird wohl nicht so prickelnd sein.
> Denn dann würde man wohl kein B5 in der Vorlage von Bosch finden,
> sondern dann würde dort wohl gleich    B6 = -4000;
> stehen. Wäre doch um einiges einfacher. Oder nicht?
>
> Du fängst zur raten an. Kein gutes Zeichen.

Ich habe doch weiter oben schon geschrieben, dass ich "B5" global 
deklariert habe, da dieses mit in die Rechnung für den "Druck" 
einfließt.

Nun tu ich das so, passt mein Druck in keiner weise mit dem aktuellen 
Druck zusammen.

Deklariere ich die Variable in jeder Funktion neu, kommt der Druck 
ungefähr hin...

von Karl H. (kbuchegg)


Lesenswert?

Hier

1
#if sample_calibration_test == 1
2
    
3
...   
4
  UP = 23843;  
5
  B5 = 2399;
6
7
#endif

hast du jedenfalls nicht 0 genommen.
Aber das gilt jetzt nichts, da ja
1
#define sample_calibration_test 0

dieser Wert nicht zum Zug kommt.


Können wir uns jetzt bitte erst mal auf das Teilproblem konzentrieren 
'die richtigen Ergebnisbytes zur richtigen Messung vom Sensor'?

Du verzettelst dich sonst (gut, das hat du sowieso schon. Aber ich sehe 
es als meine Aufgabe an, dich wieder zurückzubringen und dein 
rumgestochere in geordnete Bahnen zu lenken).

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:

> Ich habe doch weiter oben schon geschrieben, dass ich "B5" global
> deklariert habe, da dieses mit in die Rechnung für den "Druck"
> einfließt.
>
> Nun tu ich das so, passt mein Druck in keiner weise mit dem aktuellen
> Druck zusammen.
>
> Deklariere ich die Variable in jeder Funktion neu, kommt der Druck
> ungefähr hin...

Wollen wir jetzt wirklich noch einen Grundlagenkurs
"C, lokale Variablen und wie werden sie initialisiert"
oben draufsetzen?

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Können wir uns jetzt bitte erst mal auf das Teilproblem konzentrieren
> 'die richtigen Ergebnisbytes zur richtigen Messung vom Sensor'?

Die A/D Werte habe ich doch oben schon gepostet.

von Karl H. (kbuchegg)


Lesenswert?

Joe F. schrieb:
> Du hast an vielen Stellen sowas hier:

Ich hätt auch gesagt:
schmeiss die 85 unterschiedlichen Read und Write Funktionen raus. Im 
gegenständlichen Fall bringen sie sowieso nichts, weil sie kein Aas 
benutzt.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> Können wir uns jetzt bitte erst mal auf das Teilproblem konzentrieren
>> 'die richtigen Ergebnisbytes zur richtigen Messung vom Sensor'?
>
> Die A/D Werte habe ich doch oben schon gepostet.


Da waren wir aber noch im F_CPU Dilemma.

Deine Wartezeiten haben nicht gestimmt.
Insbesondere waren deine 5ms nur 2.5ms. Laut Bosch zuwenig für eine 
Temperaturmessung

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

Das gleiche auch in BMP180_read_u16().
Ausserdem macht es keinen Sinn, 2 Funktionen hierfür zu haben.

BMP180_read_u16() reicht völlig aus.
Wenn deine Variable, der du den Rückgabewert von BMP180_read_u16 zuweist 
ein int16_t ist, castet dir der Compiler das hin.

Oder du machst es eben explizit:

int16_t AC1;
AC1 = (int16_t)(BMP180_read_u16(0xAA));

von Falk B. (falk)


Lesenswert?

Nur mal so. Wenn man das Prpjekt einfach mal compiliert, kommen 8 
Warnungen! Die sollte man intelligenterweise NICHT ignorieren. U.a.

Warning  6  'B5' is used uninitialized in this function 
[-Wuninitialized]  D:\download\read_BMP180\read_BMP180\BMP180.c  164  8 
read_BMP180


Ausserdem wird hier anfängertypisch ganz schön rumgewurschtelt, u.a. mit 
globalen Variabeln in verteilten .c Dateien. Das geht meist schief ;-)

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

So, nun noch mal die aktuellen A/D Werte.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> So, nun noch mal die aktuellen A/D Werte.

Das sieht doch schon mal viel freundlicher aus. Zumindest unterscheidet 
sich der vom Sensor als Temperatur ausgewiesene Wert schon mal vom 
Druckwert.

Kaum macht mans richtig, funktioniert es auch.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Da
1
  X1 = (UT - AC6) * AC5 >> 15;
2
   X2 = MC << 11 / (X1 + MD);

fehlen doch mit Sicherheit ein paar Klammern.

Mal bei Bosch nachsehen, wie das wirklich berechnet wird.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Da
>
1
>   X1 = (UT - AC6) * AC5 >> 15;
2
>    X2 = MC << 11 / (X1 + MD);
3
>
>
> fehlen doch mit Sicherheit ein paar Klammern.

Jep.
Und zwar hier
1
    X2 = ( MC << 11 ) / (X1 + MD);

und der anderen Zeile würde es auch nicht schaden, wenn man eine Klammer 
einführt, auch wenn sie technisch nicht notwendig ist. Dem Verständnis 
würde es IMHO zugute kommen
1
   X1 = ( (UT - AC6) * AC5 ) >> 15;

von Frank F. (frank_f49)


Lesenswert?

>  X1 = (UT - AC6) * AC5 >> 15;
>   X2 = MC << 11 / (X1 + MD);


>fehlen doch mit Sicherheit ein paar Klammern.
>Mal bei Bosch nachsehen, wie das wirklich berechnet wird.

Alder,  wenn bei einmaligem Aufruf  der Funktion
korrekte  Druck - und Termperaturwerte  rauskommen
dann wird  das Problem  sicher  nicht  von fehlenden Klammern
verursacht.

Zugegeben, der Code  sieht  ohne Klammern  scheisse
aus,  aber  man muss keine Klammern setzen wenn
man  sie  nicht braucht.

Klammern  sind was  für  Leute  die die Punkt-vor Strich-Regel
nicht kennen.

von Karl H. (kbuchegg)


Lesenswert?

Was weiss man eigentlich über AC6 bzw. AC5 vom Zahlenwert her?
Stimmen die in etwa mit den Werten aus dem Datenblatt überein?

Der rohe Datenwert für die Temperatur ist ja nicht so weit weg vom 
Datenblatt. Im Datenblatt ergibt sich im Beispiel aus 27898 eine 
Temperatur von 15.0°C. Ich weiss jetzt nicht, wie warm oder kalt es bei 
dir ist, aber 28830 ist von den 27898 nicht so weit weg. Das könnte 
hinkommen, wenn die Werte für AC5 und AC6 in etwa mit dem Datenblatt 
vergleichbar sind.

von Karl H. (kbuchegg)


Lesenswert?

Frank Fahrenheit schrieb:
>>  X1 = (UT - AC6) * AC5 >> 15;
>>   X2 = MC << 11 / (X1 + MD);
>
>
>>fehlen doch mit Sicherheit ein paar Klammern.
>>Mal bei Bosch nachsehen, wie das wirklich berechnet wird.
>
> Alder,

Alder.
Ein << unterscheidet sich von einem / nun mal durch die Operator 
Precedence.

>  wenn bei einmaligem Aufruf  der Funktion
> korrekte  Druck - und Termperaturwerte  rauskommen
> dann wird  das Problem  sicher  nicht  von fehlenden Klammern
> verursacht.

So, so.
Du glaubst also, dass es bei ihm wirklich -17°C hat?

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Karl Heinz schrieb:
> Frank Fahrenheit schrieb:
>>>  X1 = (UT - AC6) * AC5 >> 15;
>>>   X2 = MC << 11 / (X1 + MD);
>>
>>
>>>fehlen doch mit Sicherheit ein paar Klammern.
>>>Mal bei Bosch nachsehen, wie das wirklich berechnet wird.
>>
>> Alder,
>
> Alder.
> Ein << unterscheidet sich von einem / nun mal durch die Operator
> Precedence.

Aber ich lad dich gerne ein, dir im Datenblatt die korrekte Formel 
anzusehen und mit dem zu vergleichen, was er draus gemacht hat

Alder

von Frank F. (frank_f49)


Lesenswert?

>  wenn bei einmaligem Aufruf  der Funktion
> korrekte  Druck - und Termperaturwerte  rauskommen
> dann wird  das Problem  sicher  nicht  von fehlenden Klammern
> verursacht.

Guckst Du  mal  beim Posting  von 16:46

von Karl H. (kbuchegg)


Lesenswert?

Frank Fahrenheit schrieb:
>>  wenn bei einmaligem Aufruf  der Funktion
>> korrekte  Druck - und Termperaturwerte  rauskommen
>> dann wird  das Problem  sicher  nicht  von fehlenden Klammern
>> verursacht.
>
> Guckst Du  mal  beim Posting  von 16:46


Ja ich sehs.
Ein Raum, der sich in ... na so ca. 300ms von 43 Grad auf 19 Grad 
abkühlt und dann wieder auf 23 Grad aufheizt.

Genau.

Aber ... du kannst ihm gerne helfen, wenn du magst.
(Das Bild mit der Formel aus dem Datenblatt schon gesehen?)

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Karl Heinz schrieb:

> Aber ... du kannst ihm gerne helfen, wenn du magst.
> (Das Bild mit der Formel aus dem Datenblatt schon gesehen?)


Guckst du (siehe Bild)

Und jetzt das Suchbild: Wodurch unterscheidet sich das von
1
  X1 = (UT - AC6) * AC5 >> 15;
2
  X2 = MC << 11 / (X1 + MD);

von Frank F. (frank_f49)


Lesenswert?

>Ein Raum, der sich in ... na so ca. 300ms von 43 Grad auf 19 Grad
>abkühlt und dann wieder auf 23 Grad aufheizt.

Und fehlende Klammern erklären diese  merkwürdigen Trends?

von Joe F. (easylife)


Lesenswert?

Die Klammer spielt eine entscheidende Rolle:
1
        AC5 = 32757;
2
        AC6 = 23153;
3
        MC = -8711;
4
        MD = 2868;
5
6
        UT = 27898;
7
8
9
        X1 = (UT - AC6) * AC5 >> 15;
10
        X2 = MC << 11 / (X1 + MD);
11
        B5 = X1 + X2;
12
        truetemperature = (B5 + 8) >> 4;
13
14
        printf("%ld\n", truetemperature);

Ausgabe: -248
1
X2 = (MC << 11) / (X1 + MD);

Ausgabe: 150


Aufpassen auch bei negativen Zahlen.
Da ist Bitshiften etwas anderes wie Multiplizieren/Teilen...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Frank Fahrenheit schrieb:
>>Ein Raum, der sich in ... na so ca. 300ms von 43 Grad auf 19 Grad
>>abkühlt und dann wieder auf 23 Grad aufheizt.
>
> Und fehlende Klammern erklären diese  merkwürdigen Trends?


Weisst was. Studier eine operator precedence table.
Dann weisst du was der entscheidende Unterschied zwischen Rechts 
Schieben und Multiplizieren ist. WEnn Bosch multiplizeren will, dann 
kann man das nicht einfach so mir nichts dir nichts durch schieben 
ersetzen.

Und da ist das Problem des Vorzeichens noch gar nicht inkludiert. Danke 
Joe.

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

Deswegen besser so:

X1 = ((UT - AC6) * AC5) / 32768;
X2 = (MC * 2048) / (X1 + MD);
B5 = X1 + X2;
truetemperature = (B5 + 8) / 16;

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Joe F. schrieb:
> Deswegen besser so:

Geeeeenau.
Das ist sowieso die beste Version.

Auf negative Temperaturen hätt ich jetzt nämlich auch vergessen.

von drama (Gast)


Lesenswert?

Und ich frag mich hier wieder, warum keiner den offiziellen Code nutzt:

https://github.com/BoschSensortec/BMP180_driver

von Karl H. (kbuchegg)


Lesenswert?

drama schrieb:
> Und ich frag mich hier wieder, warum keiner den offiziellen Code nutzt:

Wär natürlich gegangen.
Aber auch den müsste man (nach einem ersten Eindruck beim 
Drüberscrollen) noch ein wenig von Linux auf AVR anpassen.

von Karl H. (kbuchegg)


Lesenswert?

So.
Wie siehts in der Zwischenzeit am realen Sensor aus?
Stimmen jetzt die Temperaturwerte?

von Wolfgang (Gast)


Lesenswert?

Da gibt es natürlich noch mehr
Beitrag "Re: BMP180 Library"

Aber manchem C-Anfänger tut es gut, wenn er seinen Code nicht nur aus 
Libraries zusammenbaut, sondern sich auch mal mit den Bits und Bytes 
hinter den Kulissen beschäftigt.

von drama (Gast)


Lesenswert?

Karl Heinz schrieb:
> Wär natürlich gegangen.
> Aber auch den müsste man (nach einem ersten Eindruck beim
> Drüberscrollen) noch ein wenig von Linux auf AVR anpassen.

Der Code ist nicht speziell für Linux o.ä., der ist sehr generisch. Man 
muss nur ein paar Funktionspointer in einem struct setzen, damit der 
Zugriff auf I2C-Hardware klappt.

von Karl H. (kbuchegg)


Lesenswert?

drama schrieb:
> Karl Heinz schrieb:
>> Wär natürlich gegangen.
>> Aber auch den müsste man (nach einem ersten Eindruck beim
>> Drüberscrollen) noch ein wenig von Linux auf AVR anpassen.
>
> Der Code ist nicht speziell für Linux o.ä., der ist sehr generisch. Man
> muss nur ein paar Funktionspointer in einem struct setzen, damit der
> Zugriff auf I2C-Hardware klappt.

Hab ich gesehen.
Und du denkst, das kriegt er hin?

:-)

von Joe F. (easylife)


Lesenswert?

Sein Code ist ja einigermaßen korrekt. Kein Grund alles umzubauen.
Die Temperaturberechnung muss gefixed werden (Bitshifts raus, Mathe 
rein), und vor allem auch die I2C Kommunikation (start, stop, 
repeated-start).

Kann ja sein, dass die total kaputte Kommunikation vielleicht sogar 
irgendwie gerade eben funktioniert, nur entspricht sie absolut nicht der 
Spezifikation.
Dass der Chip offenbar nach einem stop mit einem repeated-start klar 
kommt ist reiner Zufall.
Wenn Bosch da irgendwann mal was am Chip ändert knallt es.

von Karl H. (kbuchegg)


Lesenswert?

Schade nur, dass es keine Rückmeldung mehr gibt, ob die Temperatur-Werte 
jetzt stimmen.
Der nächste Schritt wäre jetzt gewesen, den ominösen Wert B5 von der 
Temperaturmessung in die Druckmessung zu übernehmen. Denn der Wert ist 
dort Teil der Berechnung.

: Bearbeitet durch User
von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Hallo,

sorry das ich mich gestern nicht mehr gemeldet habe. Musste leider 
dringend weg.

So, ich habe den Ratschlag mit dem Bitschifting befolgt und diesen 
Codeteil umgebaut.

Nun habe ich mal die aktuellen "A/D Werte" mit "B5" ausgelesen.

Hier das Ergebninss.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Hallo,
>
> sorry das ich mich gestern nicht mehr gemeldet habe. Musste leider
> dringend weg.
>
> So, ich habe den Ratschlag mit dem Bitschifting befolgt und diesen
> Codeteil umgebaut.
>
> Nun habe ich mal die aktuellen "A/D Werte" mit "B5" ausgelesen.

Alles schön.
Nur kann man ohne Kenntnis der zuvor ausgelesenen Koeffizienten AC5 und 
AC6, UT, MC und MD nicht nachvollziehen, wie das Ergebnis zustande 
kommt.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> Hallo,
>>
>> sorry das ich mich gestern nicht mehr gemeldet habe. Musste leider
>> dringend weg.
>>
>> So, ich habe den Ratschlag mit dem Bitschifting befolgt und diesen
>> Codeteil umgebaut.
>>
>> Nun habe ich mal die aktuellen "A/D Werte" mit "B5" ausgelesen.
>
> Alles schön.
> Nur kann man ohne Kenntnis der zuvor ausgelesenen Koeffizienten AC5 und
> AC6, UT, MC und MD nicht nachvollziehen, wie das Ergebnis zustande
> kommt.


UT natürlich nicht. Das ist einfach nur die Zusammensetzung der beiden 
Bytes vom Sensor

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Die Kalibrationsparameter haben sich nicht verändert. Hier noch mal im 
Anhang.

"UT" entspricht "A/D Temperatur".

von Falk B. (falk)


Lesenswert?

Ich glaube aber nicht, dass bei dir am Platz 36°C sind. Also stimmt es 
noch nicht so ganz.

von Jan H. (janiiix3)


Lesenswert?

Ich muss noch dazu sagen, dass ich die Muster Kalibrationswerte vom 
Datenblatt mit dem Algo. umgerechnet habe ( also mein µC hat es 
umgerechnet ) und ich kam genau auf das Ergebniss wie im Datenblatt. 
Also sollte die Umrechnung funktionieren.

von Jan H. (janiiix3)


Lesenswert?

Falk Brunner schrieb:
> Ich glaube aber nicht, dass bei dir am Platz 36°C sind. Also
> stimmt es
> noch nicht so ganz.

Stimmt!
Habe hier im Raum ca. 18 - 20°C.

von Falk B. (falk)


Lesenswert?

Poste deine aktuellen Quelltexte als Anhang. Und bitte kein Monster-Zip, 
die .c und .h Datei für die Sensorroutinen reicht!

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Falk Brunner schrieb:
> Poste deine aktuellen Quelltexte als Anhang. Und bitte kein
> Monster-Zip,
> die .c und .h Datei für die Sensorroutinen reicht!

von Karl H. (kbuchegg)


Lesenswert?

Sind 18.9°C als Temperatur in deiner Umgebung realistisch?

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Sind 18.9°C als Temperatur in deiner Umgebung realistisch?

Ja, durchaus!

von Karl H. (kbuchegg)


Lesenswert?

> uint16_t AC4, AC5, AC6;

sollten int32_t sein, wenn du deine Berechnung nicht quer durch die Bank 
mit Casts nach long spicken willst.

von Falk B. (falk)


Lesenswert?

Ich kenne den Sensor und das Datenblatt nicht. Aber hier könnte ein 
Fehler stecken.

  UT  = (long)i2c_readAck()<<8;
  UT |= (long)i2c_readNak();

Damit wird man NIE negative Zahlen erhalten. Es fehlt die 
Vorzeichenerweiterung. Der Cast macht das glaube ich nicht. Da fehlt 
hinterher noch ein
1
  if (UT & 0x8000) UT |= 0xFFFF0000;

Bei Druck könnte/sollte man das Gleiche machen.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> Sind 18.9°C als Temperatur in deiner Umgebung realistisch?
>
> Ja, durchaus!


OK.
Das sind deine Zwischenergebnisse
1
X1: 5791
2
X2: -2764
3
B5: 3027
4
Temp: 189

mit diesem Code
1
#include "stdafx.h"
2
3
int main()
4
{
5
  int AC5 = 24808;
6
  int AC6 = 20872;
7
  int MC = -11782;
8
  int MD = 2937;
9
10
  int UT = 28522;
11
12
  int X1 = (( UT - AC6 ) * AC5 ) >> 15;
13
  int X2 = ( MC << 11 ) / ( X1 + MD );
14
  int B5 = X1 + X2;
15
16
  int Temp = ( B5 + 8 ) >> 4;
17
18
  printf( "X1: %d\n", X1 );
19
  printf( "X2: %d\n", X2 );
20
  printf( "B5: %d\n", B5 );
21
  printf( "Temp: %d\n", Temp );
22
23
  return 0;
24
}

lass dich nicht von den int täuschen. Ich hab das auf dem PC gemacht, da 
ist ein int 4 Byte gross. Auf einem AVR sind das alles long bzw. int32_t

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> printf( "B5: %d\n", B5 );

Also meinst du es liegt an meinem "uint16_t AC4, AC5, AC6;"?

von Karl H. (kbuchegg)


Lesenswert?

Das hier

>   int X2 = ( MC << 11 ) / ( X1 + MD );

ist natürlich extrem fies von Bosch.
Wenn bei der Multiplikation mit 2 hoch 11 der falsche Datentyp steht, 
dann werden die Bits nicht korrekt an der 32 Bit Grenze abgeschnitten, 
wie es vorausgesetzt wird.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:
> Karl Heinz schrieb:
>> printf( "B5: %d\n", B5 );
>
> Also meinst du es liegt an meinem "uint16_t AC4, AC5, AC6;"?

Ja.
Denn der Bosch-Code beruht heftig darauf, dass die Ergebnisse in 32 Bbit 
darstellbar sind. Multiplizierst du aber 16 Bit mit 16 Bit, dann kriegst 
du auch nur ein 16 Bit Ergebnis und keines mit 32 Bit.

Du hast die Werte, setz sie in deinen Code ein, lass dir die 
Zwischenergebnisse ausgeben und sieh dir an, wo du Abweichungen hast.

von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> Karl Heinz schrieb:
>>> printf( "B5: %d\n", B5 );
>>
>> Also meinst du es liegt an meinem "uint16_t AC4, AC5, AC6;"?
>
> Ja.
> Denn der Bosch-Code beruht heftig darauf, dass die Ergebnisse in 32 Bbit
> darstellbar sind. Multiplizierst du aber 16 Bit mit 16 Bit, dann kriegst
> du auch nur ein 16 Bit Ergebnis und keines mit 32 Bit.
>
> Du hast die Werte, setz sie in deinen Code ein, lass dir die
> Zwischenergebnisse ausgeben und sieh dir an, wo du Abweichungen hast.

Kannst du mal dein Programm für den PC mit anhängen?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>> Karl Heinz schrieb:
>>> printf( "B5: %d\n", B5 );
>>
>> Also meinst du es liegt an meinem "uint16_t AC4, AC5, AC6;"?
>
> Ja.

und auch MC und MD.

Das ist allerdings auch nur die halbe Miete.
Wenn du da auf int32_t hochgehst, musst du beim Zusammensetzen der Bytes 
aufpassen, wie Falk korrekt einwendet.

von Karl H. (kbuchegg)


Lesenswert?

Jan H. schrieb:

> Kannst du mal dein Programm für den PC mit anhängen?

Hab ich doch!

Ich hab keinen Sensor.
Ich nehm deine Kalbrierwerte, deinen Sensorwert, definier mir dafür die 
Variablen und häng die Berechnungsvorschrift von Bosch rein.

und dann krieg ich 18.9 Grad Celsius raus, wenn ich alles in signed 32 
Bit rechne.

Beitrag "Re: BMP180 I2C Problem?"

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Karl Heinz schrieb:
> Jan H. schrieb:
>
>> Kannst du mal dein Programm für den PC mit anhängen?
>
> Hab ich doch!
>
> Ich hab keinen Sensor.
> Ich nehm deine Kalbrierwerte, deinen Sensorwert, definier mir dafür die
> Variablen und häng die Berechnungsvorschrift von Bosch rein.
>
> und dann krieg ich 18.9 Grad Celsius raus, wenn ich alles in signed 32
> Bit rechne.
>
> Beitrag "Re: BMP180 I2C Problem?"

Okay, ich werde es nacher dirkt noch einmal ausprobieren.

von Alex D. (allu)


Lesenswert?

Karl Heinz schrieb:
> lass dich nicht von den int täuschen. Ich hab das auf dem PC gemacht, da
> ist ein int 4 Byte gross. Auf einem AVR sind das alles long bzw. int32_t

Die Temperatur- und Druckberechnung lässt sich auch mit Fließkommazahlen 
ausführen, dem C-Compiler wird es egal sein. Oder spricht etwas dagegen?

von Karl H. (kbuchegg)


Lesenswert?

Alex D. schrieb:
> Karl Heinz schrieb:
>> lass dich nicht von den int täuschen. Ich hab das auf dem PC gemacht, da
>> ist ein int 4 Byte gross. Auf einem AVR sind das alles long bzw. int32_t
>
> Die Temperatur- und Druckberechnung lässt sich auch mit Fließkommazahlen
> ausführen, dem C-Compiler wird es egal sein. Oder spricht etwas dagegen?

Weiss ich noch nicht.

Die Bosch Leute sind da .... etwas seltsam unterwegs.

Die Casten da in ihrem eigenen Code hemmungslos rum
(Hier die Temperatur)
1
s16 bmp180_get_temperature(u32 v_uncomp_temperature_u32)
2
{
3
  s16 v_temperature_s16 = C_BMP180_ZERO_U8X;
4
  s32 v_x1_s32, v_x2_s32 = C_BMP180_ZERO_U8X;
5
  /* calculate temperature*/
6
  v_x1_s32 = (((s32) v_uncomp_temperature_u32 -
7
  (s32) p_bmp180->calib_param.ac6) *
8
  (s32) p_bmp180->calib_param.ac5) >> BMP180_SHIFT_15_POSITION;
9
  if (v_x1_s32 == C_BMP180_ZERO_U8X && p_bmp180->calib_param.md
10
  == C_BMP180_ZERO_U8X) {
11
    return C_BMP180_ZERO_U8X;
12
  } else {
13
    v_x2_s32 = ((s32) p_bmp180->calib_param.mc
14
    << BMP180_SHIFT_11_POSITION) /
15
    (v_x1_s32 + p_bmp180->calib_param.md);
16
  }
17
  p_bmp180->param_b5 = v_x1_s32 + v_x2_s32;
18
  v_temperature_s16 = ((p_bmp180->param_b5 + C_BMP180_EIGHT_U8X)
19
  >> BMP180_SHIFT_4_POSITION);
20
21
  return v_temperature_s16;
22
}

AC5 und AC6 sind eigentlich unsigned Werte, werden aber zur Berechnung 
auf signed 32 hochgecastet.

Im Moment hab ich noch keinen Überblick, wann und wo es zu einer 
Vorzeichenerweiterung kommen muss und wo nicht (falls letzteres 
überhaupt irgendwo der Fall sein sollte).

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

>
1
> s16 bmp180_get_temperature(u32 v_uncomp_temperature_u32)
2
> {
3
>

dafür ist der Eingangswert wieder ein unsigned mit 32 Bit, der von 16 
Bit vom Sensor stammmt.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Karl Heinz schrieb:
>
>>
1
>> s16 bmp180_get_temperature(u32 v_uncomp_temperature_u32)
2
>> {
3
>>
>
> dafür ist der Eingangswert wieder ein unsigned mit 32 Bit, der von 16
> Bit vom Sensor stammmt.

Der zur Rechnerei
1
  v_x1_s32 = (((s32) v_uncomp_temperature_u32 -
wieder auf einen signed mit 32 Bit umgecastet wird :-)


Ganz ehrlich: Ruhmesblatt ist das alles nicht.

von Karl H. (kbuchegg)


Lesenswert?

Schön langsam denke ich echt, drama hat hier
Beitrag "Re: BMP180 I2C Problem?"
recht.

Nimm die Umrechnungsfunktionen und die Strukturdefinition von Bosch her 
wie sie sind. Definier dir entsprechende typedef, nimm deine I2C 
Funktionen setz die Bytes entsprechend zusammen aber nimm um Himmels 
Willen die Bosch Funktionen um die Werte umzurechnen.
Da stecken so viele Datentypfallen drinn, dass geht auf keine Kuhhaut.

Denn Bosch Code kann man vereinfachen, der ist dort natürlich in der 
Version 'passt überall, wenn man die richtigen #define setzt'. Das kann 
man abspecken. Aber ausser, dass der Pointer auf die Struktur rausfliegt 
und durch eine direkte Adressierung ersetzt wird, greif die eigentliche 
Berechnung bloss nicht an.
:-)

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>Da stecken so viele Datentypfallen drinn, dass geht auf keine Kuhhaut.

Naja, bei Bosch arbeiten auch genügend Praktikanten. Dazu der bekannte 
Spruch "Guten Leuten muss man absagen".

Und dieses Beispiel ist mal wieder ein "schönes" zum Thema "int 
Datenbreit und C".
Mit int32_t wär das nicht passiert, 16 Jahre nach C99 . . .

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Was ich nicht verstehe...

Wenn ich die Musterwerte in die umrechnung haue... Kommt doch das 
richtige Ergebniss raus (laut Datenblatt : Seite 15)...

Also kann es doch nicht an der Umrechnung liegen? Sehe ich da etwas 
falsch?

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.