Der Luftdruck und Temperatur Sensor BMP085 am Arduino Uno.

Ich habe hier den Luftdruck und Temperatur Sensor BMP085 von Bosch. Er wird seriell über den i²C Bus angesprochen und gibt dann die Temperatur und den Luftdruck aus.

Der Messbereich geht von 300 hPa bis 1100 hPa mit einer Genauigkeit von typisch +-1,0 hPa. Zwischen 700 und 1100 hPa mir der maximalen Auflösung von 0,01 hPa.
Die Temperatur misst er von 0 bis 65°C mit einer Genauigkeit von typisch +-1 Grad Celsius.

Das sind sehr gute Werte für einen preiswerten Sensor.

Die Hardware

Der BMP085 ist hier fertig auf einer Platine mit i²C Pull up Widerständen, Kondensatoren und einem Spannungsumsetzer. Ich schliesse ihn aber direkt an die 3,3V vom Arduino an. Bitte hier niemals die 5V verwenden, das kann den Sensor zerstören.

BMP085 Sensor am Arduino

Die Verbindungen Sensor > Arduino – Kabelfarbe im Bild
VCC > 3,3V – rot
GND > GND – blau
SCL > A5 – orange
SDA > A4 –  gebl

Die Software für den Arduino Uno

// BMP085 Luftdruck und Temperatur Sensor
//
// Matthias Busse 17.5.2014 Version 1.0

#include < Wire.h>

// Einstellungen für den BMP085
#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("BMP085 Temperatur und Luftdruck auslesen.");
  Wire.begin();
  bmp085_get_cal_data();
  bmp085_read_temperature_and_pressure(&temp_mittel,&druck_mittel); // erstmal Mittelwerte lesen
}

void loop() {
  bmp085_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 bmp085_read_temperature_and_pressure(int* temp, long* druck) {
int ut= bmp085_read_ut();
long up = bmp085_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 bmp085_read_ut() {
  write_register(0xf4,0x2e);
  delay(5); //mehr als 4.5 ms
  return read_int_register(0xf6);
}

void bmp085_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 bmp085_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));
}

Zu der Software und den Registern gibt es sehr viele Hinweise und Beispiele im Datenblatt und im Netz. Deshalb spare ich mir hier die Erklärungen.

Die Ausgabe

BMP 085 Ausgabe

Hilfreiche Links:
mitat.tuu.fi/
Bosch BMP085
Datenblatt bei Adafruit

> Luftdruck und Temperatur als NMEA 0183 Datensatz ausgeben

von Matthias Busse

3 Gedanken zu „Der Luftdruck und Temperatur Sensor BMP085 am Arduino Uno.

  1. Pingback: Bosch BMP180 Luftdruck und Temperatur Sensor am Arduino Uno | Shelvin – Elektronik ausprobiert und erläutert

  2. Pingback: Luftdruck und Temperatur als NMEA 0183 Datensatz ausgeben. | Shelvin – Elektronik ausprobiert und erläutert

Schreibe einen Kommentar

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.