Bosch BMP180 / BMP085 Luftdruck und Temperatur Sensor am Arduino Uno

Der BMP085 Sensor wird von Bosch Sensortec nicht mehr hergestellt, dafür gibt es jetzt den neuen BMP180. Er ist deutlich kleiner geworden. Die technischen Daten sind aber größtenteils gleich. Ich habe nur Zusatzinformation im neuen Datenblatt gefunden die sich auf die relative Luftdruckmessung bezieht, die war im BMP085 Datenblatt nicht enthalten.

Der Grössenvergleich.

Links BMP085 und rechts BMP180

links BMP085 und rechts BMP180

Der Aufbau

Ich verwende hier folgende Anschlüsse:

Arduino > BMP180 Platine
3,3V > VCC
GND > GND
A5 > SCL
A4 > SDA

BMP180 am Arduino Uno

BMP180 am Arduino Uno

Der absolute Luftdruck wird mit einem max. Fehler -4 bis +2 hPa (typisch -1 hPa) gemessen, was einem Höhenunterschied von ca. 8m entspricht.
Der relative Luftdruck wird mit einem Fehler von +-0,12 hPa angegeben, was einem Höhenunterschied von ca. 1 m entspricht. Relative Messungen beziehen sich immer auf die vorherigen Messungen. Wenn der Luftdruck einmal abgeglichen ist, z.B. mit einer lokalen Wetterstation, ist die Höhenmessung mit 1m Genauigkeit möglich.

Die Software

Die Software kann 1:1 vom BMP085 übernommen werden. Ich habe nur die Namen der Funktionen geändert. Ansonsten ist alles gleich und läuft auf Anhieb.

// BMP180 Luftdruck und Temperatur Sensor
//
// Matthias Busse 20.6.2014 Version 1.0

#include < Wire.h>

// Einstellungen für den BMP180
#define I2C_ADDRESS 0x77
const unsigned char oversampling_setting = 3; //oversamplig:  0 ungenau (13ms) ... 3 genau (34ms)
const unsigned char pressure_waittime[4] = { 5, 8, 14, 26 };
int ac1, ac2, ac3, b1, b2, mb, mc, md;
unsigned int ac4, ac5, ac6;

int temp = 20, temp_mittel=200;
long druck = 1013, druck_mittel=101300;
float temp_offset=0.0, druck_offset=1.0; // Korrekturwerte
int mitteln=5;

void setup() {
  Serial.begin(38400);
  Serial.println("BMP180 Temperatur und Luftdruck auslesen.");
  Wire.begin();
  bmp180_get_cal_data();
  bmp180_read_temperature_and_pressure(&temp_mittel,&druck_mittel); // erstmal Mittelwerte lesen
}

void loop() {
  bmp180_read_temperature_and_pressure(&temp, &druck); // dauert ca. 34ms
  temp_mittel = ((temp_mittel * (mitteln-1)) + temp) / mitteln;
  druck_mittel = ((druck_mittel * (mitteln-1)) + druck) / mitteln;
  Serial.print("Temp.: ");
  Serial.print(((float)temp_mittel/10.0)+temp_offset, 1);
  Serial.print(" Druck: ");
  Serial.println(((float)druck_mittel/100.0)+druck_offset, 2);
//  delay(1000); // ms
}

void bmp180_read_temperature_and_pressure(int* temp, long* druck) {
int ut= bmp180_read_ut();
long up = bmp180_read_up();
long x1, x2, x3, b3, b5, b6, p;
unsigned long b4, b7;

  x1 = ((long)ut - ac6) * ac5 >> 15; //Temperatur berechnen
  x2 = ((long) mc << 11) / (x1 + md);
  b5 = x1 + x2;
  *temp = (b5 + 8) >> 4;

  b6 = b5 - 4000; //Druck berechnen
  x1 = (b2 * (b6 * b6 >> 12)) >> 11;
  x2 = ac2 * b6 >> 11;
  x3 = x1 + x2;

  if (oversampling_setting == 3) b3 = ((int32_t) ac1 * 4 + x3 + 2) << 1;
  if (oversampling_setting == 2) b3 = ((int32_t) ac1 * 4 + x3 + 2);
  if (oversampling_setting == 1) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 1;
  if (oversampling_setting == 0) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 2;

  x1 = ac3 * b6 >> 13;
  x2 = (b1 * (b6 * b6 >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
  b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting);
  p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;

  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  *druck = p + ((x1 + x2 + 3791) >> 4);
}

unsigned int bmp180_read_ut() {
  write_register(0xf4,0x2e);
  delay(5); //mehr als 4.5 ms
  return read_int_register(0xf6);
}

void bmp180_get_cal_data() {
  ac1 = read_int_register(0xAA);
  ac2 = read_int_register(0xAC);
  ac3 = read_int_register(0xAE);
  ac4 = read_int_register(0xB0);
  ac5 = read_int_register(0xB2);
  ac6 = read_int_register(0xB4);
  b1 = read_int_register(0xB6);
  b2 = read_int_register(0xB8);
  mb = read_int_register(0xBA);
  mc = read_int_register(0xBC);
  md = read_int_register(0xBE);
}

long bmp180_read_up() {
  write_register(0xf4,0x34+(oversampling_setting<<6));
  delay(pressure_waittime[oversampling_setting]);

  unsigned char msb, lsb, xlsb;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(0xf6);
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 3); 
  while(!Wire.available()) {} // warten
  msb = Wire.read(); 
  while(!Wire.available()) {} // warten
  lsb |= Wire.read(); 
  while(!Wire.available()) {} // warten
  xlsb |= Wire.read(); 
  return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting);
}

void write_register(unsigned char r, unsigned char v) {
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r); 
  Wire.write(v); 
  Wire.endTransmission();
}

char read_register(unsigned char r) {
unsigned char v;

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r); 
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1); 
  while(!Wire.available()) {} // warten
  v = Wire.read(); 
  return v;
}

int read_int_register(unsigned char r) {
unsigned char msb, lsb;

  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r); 
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 2);
  while(!Wire.available()) {} // warten
  msb = Wire.read(); 
  while(!Wire.available()) {} // warten
  lsb = Wire.read(); 
  return (((int)msb<<8) | ((int)lsb));
}

Die Ausgabe

Ausgabe

Vorherige Beiträge:
Luftdruck und Temperatur als NMEA 0183 Datensatz ausgeben
Der Luftdruck und Temperatur Sensor BMP085 am Arduino Uno.

von Matthias Busse

5 Gedanken zu „Bosch BMP180 / BMP085 Luftdruck und Temperatur Sensor am Arduino Uno

  1. Pingback: Barometer Display mit 1h / 3h Differenz und Temperatur Ausgabe. Mit dem 5110 Display, BMP-180, Uno | Shelvin – Elektronik ausprobiert und erläutert

  2. Pingback: Grafische PC Ausgabe der Arduino Daten mit Processing | Shelvin – Elektronik ausprobiert und erläutert

  3. cm

    in der Funktion „bmp180_read_temperature_and_pressure“ ist ein kleiner Fehler.
    Bei Temperaturen >34°C wird die Temp negativ. Und die Berechnung des Drucks ist dann falsch.
    Als Behebung kann der Datentyp der Variablen „ut“ von int auf long geändert werden:

    <> long ut= bmp180_read_ut();

    Antworten
  4. Wilhelm

    Hallo,
    super was Sie da machen mit dem Arduino.
    Frage: Für ein eigenes Projekt möchte ich einen BME280 einsetzen.
    Liegt da evtl. ein passender Sketch in der Schublade?
    Schönen Tag wünscht Wilhelm Freitag

    Antworten

Schreibe einen Kommentar zu cm Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.