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.
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
Hilfreiche Links:
– mitat.tuu.fi/
– Bosch BMP085
– Datenblatt bei Adafruit
> Luftdruck und Temperatur als NMEA 0183 Datensatz ausgeben
von Matthias Busse
Pingback: Bosch BMP180 Luftdruck und Temperatur Sensor am Arduino Uno | Shelvin – Elektronik ausprobiert und erläutert
Pingback: Luftdruck und Temperatur als NMEA 0183 Datensatz ausgeben. | Shelvin – Elektronik ausprobiert und erläutert
Top-Programm:
BMP085 oder BMP180 an den Arduino anschließen, Programm hochladen und Luftdruck anzeigen lassen!!
LOB!