mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik BMP180 I2C Problem?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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..
    //int16_t tmp_temp = BMP180_read_temperature();  
    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...


int16_t BMP180_read_temperature()
{
  long UT; // holds the raw temperature value read from BMP180
  long X1, X2;
  long truetemperature, B5;

  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF4);
  i2c_write(0x2E);
  i2c_stop();
  _delay_ms(5);
  
  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF6);
  i2c_stop();

  i2c_start(BMP180_address+I2C_READ);
  UT  = (long)i2c_readAck()<<8;
  UT |= (long)i2c_readNak();
  i2c_stop();
  
  X1 = ((long)(UT - AC6)) * ((long)(AC5)) >> 15;
   X2 = ((long)MC << 11) / (X1 + MD); 
   B5 = (long)X1 + X2; 
  truetemperature = (long)((B5 + 8) >> 4);
  
  truetemperature = truetemperature / 10;

  return truetemperature;
}

unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
{
  long      B6, X1, X2, X3, B3;
  unsigned long  B4,B7;  
  long      UP, B5;   
  unsigned long  truepressure;
  
  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF4);
  i2c_write(0xF4);  
  i2c_stop();
  _delay_ms(40);
  
  i2c_rep_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF6);
  
  i2c_rep_start(BMP180_address+I2C_READ);
  UP  = (long)i2c_readAck()<<8;
  UP |= (long)i2c_readNak();
  //i2c_stop();


#if sample_calibration_test == 1
    
  /*sample calibrations*/   
  oversampling_setting = 0;  
  AC1 = (short)408;
  AC2 = (short)-72;
  AC3 = (short)-14383;
  AC4 = (unsigned short) 32741;
  AC5 = (unsigned short)32757;
  AC6 = (unsigned short)23153;
  B1 = (short)6190;
  B2 = (short)4;
  MB = (short)-32768;
  MC = (short)-8711;
  MD = (short)2868;
   
  UP = 23843;  
  B5 = 2399;

#endif


    B6 = B5 - 4000;
   X1 = (B2 * (B6 * B6 / 4096)) / 2048;
   X2 = (AC2 *  B6) / 2048;
   X3 = X1 + X2;
   B3 = (((AC1 * 4 + X3) << oversampling_setting) + 2) / 4;
   X1 = AC3 * B6 / 8192;
   X2 = (B1 * (B6 * B6 / 4096)) / 65536;
   X3 = ((X1 + X2) + 2) / 4;
   B4 = AC4 *(unsigned long) (X3 + 32768) / 32768;
   B7 = ((unsigned long)UP-B3) * (50000 >> oversampling_setting);
 
  if(B7 < 0x80000000)
  {
     truepressure = (B7 * 2) / B4;
   }
   else
  {
     truepressure = (B7 / B4) *2;
   }   
   
   X1 = (truepressure / 256) * (truepressure / 256);
  X1 = (X1 * 3038) / 65536;    
   X2 = (-7357 * truepressure) / 65536;
   truepressure = truepressure + (X1 + X2 + 3791) / 16;

  truepressure = truepressure * 0.01;
  return (unsigned long)truepressure;
}


Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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:

int16_t BMP180_read_temperature()
{
  long UT; // holds the raw temperature value read from BMP180
  long X1, X2;
  long truetemperature, B5;

  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF4);
  i2c_write(0x2E);
  i2c_stop();
  _delay_ms(5);
  
  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF6);
//  i2c_stop();

  i2c_rep_start(BMP180_address+I2C_READ); // <--- hier repeated start
  UT  = (long)i2c_readAck()<<8;
  UT |= (long)i2c_readNak();
  i2c_stop();

  _delay_ms(1); // <--- mal sicherheitshalber ausprobieren...

  
  X1 = ((long)(UT - AC6)) * ((long)(AC5)) >> 15;
   X2 = ((long)MC << 11) / (X1 + MD); 
   B5 = (long)X1 + X2; 
  truetemperature = (long)((B5 + 8) >> 4);
  
  truetemperature = truetemperature / 10;

  return truetemperature;
}

unsigned long BMP180_read_pressure(uint8_t oversampling_setting)
{
  long      B6, X1, X2, X3, B3;
  unsigned long  B4,B7;  
  long      UP, B5;   
  unsigned long  truepressure;
  
  i2c_start(BMP180_address+I2C_WRITE);
  i2c_write(0xF4);
  i2c_write(0xF4);  
  i2c_stop();
//  _delay_ms(40);
  _delay_ms(80); // <--- hier mal laenger warten
  
//  i2c_rep_start(BMP180_address+I2C_WRITE);
  i2c_start(BMP180_address+I2C_WRITE); // <--- hier NICHT rep_start
  i2c_write(0xF6);
  
  i2c_rep_start(BMP180_address+I2C_READ);
  UP  = (long)i2c_readAck()<<8;
  UP |= (long)i2c_readNak();
  //i2c_stop();

  i2c_stop();   // <--- diese stop condition brauchst du mit Sicherheit
  _delay_ms(1); // <--- auch ausprobieren

  (...)

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl Heinz...

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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz schrieb:

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


Der Optimizer vom Compiler ist eingeschaltet?

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   _delay_ms( 5 );

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

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?
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.

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
    B6 = -4000;
stehen. Wäre doch um einiges einfacher. Oder nicht?

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

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Der Compiler müsste eigentlich eine Warnung ausgeben.

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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:
int16_t BMP180_read_i16(uint8_t reg)
{
  int16_t tmp_cal;
  
//  i2c_rep_start(BMP180_address+I2C_WRITE);
  i2c_start(BMP180_address+I2C_WRITE);   // <--- hier start

  i2c_write(reg);
//  i2c_stop();     // <--- vor repeated start kein stop
  
  i2c_rep_start(BMP180_address+I2C_READ);
  tmp_cal  = i2c_readAck()<<8;
  tmp_cal |= i2c_readNak();
  i2c_stop();
  
  return tmp_cal;
}

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hier

#if sample_calibration_test == 1
    
...   
  UP = 23843;  
  B5 = 2399;

#endif

hast du jedenfalls nicht 0 genommen.
Aber das gilt jetzt nichts, da ja
#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).

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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));

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, nun noch mal die aktuellen A/D Werte.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da
  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.

: Bearbeitet durch Moderator
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

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

Jep.
Und zwar hier
    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
   X1 = ( (UT - AC6) * AC5 ) >> 15;

Autor: Frank F. (frank_f49)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Frank F. (frank_f49)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?)

Autor: Karl H. (kbuchegg) (Moderator)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
  X1 = (UT - AC6) * AC5 >> 15;
  X2 = MC << 11 / (X1 + MD);

Autor: Frank F. (frank_f49)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Klammer spielt eine entscheidende Rolle:
        AC5 = 32757;
        AC6 = 23153;
        MC = -8711;
        MD = 2868;

        UT = 27898;


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

        printf("%ld\n", truetemperature);

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

Ausgabe: 150


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

: Bearbeitet durch User
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deswegen besser so:

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

: Bearbeitet durch User
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: drama (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und ich frag mich hier wieder, warum keiner den offiziellen Code nutzt:

https://github.com/BoschSensortec/BMP180_driver

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

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

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: drama (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

:-)

Autor: Joe F. (easylife)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

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

"UT" entspricht "A/D Temperatur".

Autor: Falk B. (falk)
Datum:

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

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

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

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind 18.9°C als Temperatur in deiner Umgebung realistisch?

Autor: Jan H. (janiiix3)
Datum:

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

Ja, durchaus!

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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
  if (UT & 0x8000) UT |= 0xFFFF0000;

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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

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


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

mit diesem Code
#include "stdafx.h"

int main()
{
  int AC5 = 24808;
  int AC6 = 20872;
  int MC = -11782;
  int MD = 2937;

  int UT = 28522;

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

  int Temp = ( B5 + 8 ) >> 4;

  printf( "X1: %d\n", X1 );
  printf( "X2: %d\n", X2 );
  printf( "B5: %d\n", B5 );
  printf( "Temp: %d\n", Temp );

  return 0;
}

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 Moderator
Autor: Jan H. (janiiix3)
Datum:

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

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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Jan H. (janiiix3)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex D. (allu)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)
s16 bmp180_get_temperature(u32 v_uncomp_temperature_u32)
{
  s16 v_temperature_s16 = C_BMP180_ZERO_U8X;
  s32 v_x1_s32, v_x2_s32 = C_BMP180_ZERO_U8X;
  /* calculate temperature*/
  v_x1_s32 = (((s32) v_uncomp_temperature_u32 -
  (s32) p_bmp180->calib_param.ac6) *
  (s32) p_bmp180->calib_param.ac5) >> BMP180_SHIFT_15_POSITION;
  if (v_x1_s32 == C_BMP180_ZERO_U8X && p_bmp180->calib_param.md
  == C_BMP180_ZERO_U8X) {
    return C_BMP180_ZERO_U8X;
  } else {
    v_x2_s32 = ((s32) p_bmp180->calib_param.mc
    << BMP180_SHIFT_11_POSITION) /
    (v_x1_s32 + p_bmp180->calib_param.md);
  }
  p_bmp180->param_b5 = v_x1_s32 + v_x2_s32;
  v_temperature_s16 = ((p_bmp180->param_b5 + C_BMP180_EIGHT_U8X)
  >> BMP180_SHIFT_4_POSITION);

  return v_temperature_s16;
}

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 Moderator
Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz schrieb:

>
> s16 bmp180_get_temperature(u32 v_uncomp_temperature_u32)
> {
> 

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

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

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

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


Ganz ehrlich: Ruhmesblatt ist das alles nicht.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 Moderator
Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht 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 . . .

Autor: Jan H. (janiiix3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.