BMP085 i BMP180 to dwa zgodne elektrycznie czujniki ciśnienia atmosferycznego i temperatury firmy Bosch.
CharakteryzujÄ… siÄ™ pomiarem ciÅ›nienia w zakresie od 300 do 1100 hPa, co daje nam możliwość okreÅ›lenia wysokoÅ›ci od +9000 do -500 metrów wzglÄ™dem poziomu morza. GÅ‚ównymi różnicami jakie wystÄ™pujÄ… pomiÄ™dzy BMP085 a BMP180 to rozmiar oraz dokÅ‚adność pomiaru w trybie wysokiej rozdzielczoÅ›ci pomiaru, w którym przewagÄ™ ma nowszy model oznaczony BMP180.
BMP085 | BMP180 | |
Zakres mierzonego ciśnienia | 300 - 1100 hPa | |
Napięcie zasilania | 1.8 - 3.6 V | |
Pobór prÄ…du | 5 µA / pomiar | |
Rozmiar | 5.0 mm x 5.0 mm | 3.6 mm x 3.8 mm |
Wysokość | 1.2 mm | 0.93 mm |
Dokładność (tryb niskiego poboru energii) | 0.06 hPa (0.5m) | |
Dokładność (tryb wysokiej rozdzielczości) | 0.03 hPa (0.25m) | 0.02 hPa (0.17m) |
Temperatura pracy | -40 to +85°C |
Pełna karta katalogowa BMP085: http://www.jarzebski.pl/datasheets/BMP085.pdf
Pełna karta katalogowa BMP180: http://www.jarzebski.pl/datasheets/BMP180.pdf
Znając ciśnienie jakie panuje na poziomie morza p0 (np.: 1013.25 hPa) oraz pomiar p, możemy określić aktualną wysokość, wyliczając ją z poniższego wzoru.
Zależność pomiÄ™dzy wysokoÅ›ciÄ… a ciÅ›nieniem przedstawia poniższa charakterystyka, z której wynika, że zmiana ciÅ›nienia Δp = 1 hPa odpowiada wysokoÅ›ci Δh = 8.43 m. Natomiast zmiana wysokoÅ›ci Δh = 10 m odpowiada zmianie ciÅ›nienia Δp = 1 2hPa
Na rynku istnieje kilka gotowych moduÅ‚ów z czujnikami BMP085 oraz BMP180. RóżniÄ… siÄ™ one przede wszystkim poziomem napiÄ™cia zasilania, które typowo wynosi 3.3V. W przypadku posiadanych przeze mnie moduÅ‚ów IMU GY-80 oraz IMU GY-87 zasilanie może być zarówno 5V jak i 3.3V. JeÅ›li zdecydujemy siÄ™ na zasilanie 5V należy zwrócić szczególnÄ… uwagÄ™ na podÅ‚Ä…czenie do odpowiedniego 5V pinu moduÅ‚u IMU, gdyż podÅ‚Ä…czenie do pinu 3.3V może go uszkodzić.
Pin oznaczony SCL (adapter) podłączamy do pinu A5 (Arduino), natomiast pin SDA (adapter) do pinu A4 (Arduino).
Nie zapomnijmy również o masie GND.
Na szczęście w przypadku czujników BMP085 i BMP180 możemy posÅ‚użyć siÄ™ gotowÄ… bibliotekÄ… przygotowanÄ… przez Adafruit: https://github.com/adafruit/Adafruit-BMP085-Library (lub mirror BMP085.zip). BibliotekÄ™ należy rozpakować do katalogu libraries.
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
void setup()
{
Serial.begin(9600);
// Jako parametr mozemy podav dokladnosc - domyslnie 3
// 0 - niski pobór energii - najszybszy pomiar
// 1 - standardowy pomiar
// 2 - wysoka precyzja
// 3 - super wysoka precyzja - najwolniejszy pomiar
if (!bmp.begin())
{
Serial.println("Nie odnaleziono czujnika BMP085 / BMP180");
while (1) {}
}
}
void loop()
{
// Odczytujemy temperaturÄ™
Serial.print("Temperatura = ");
Serial.print(bmp.readTemperature());
Serial.println(" *C");
// Odczytujemy cisnienie
Serial.print("Cisnienie = ");
Serial.print(bmp.readPressure());
Serial.println(" Pa");
// Obliczamy wysokosc dla domyslnego cisnienia przy pozimie morza
// p0 = 1013.25 millibar = 101325 Pascal
Serial.print("Wysokosc = ");
Serial.print(bmp.readAltitude());
Serial.println(" metrow");
// Jesli znamy aktualne cisnienie przy poziomie morza,
// mozemy dokladniej wyliczyc wysokosc, padajac je jako parametr
Serial.print("Rzeczywista wysokosc = ");
Serial.print(bmp.readAltitude(102520));
Serial.println(" metrow");
Serial.println();
delay(500);
}
Wynik działania
Spróbujmy jeszze pokazać na wykresie poszczególne parametry za pomocÄ… processingu. W tym przypadku skorzystamy nieco z zmodyfikowanego programu dla Arduino. Wyliczymy również wysokość samodzielnie, ponieważ funkcja readAltitude() ponownie bÄ™dzie odczytywaÅ‚a ciÅ›nienie do wyliczeÅ„, które już mamy.
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
float sealevelPressure;
void setup()
{
Serial.begin(9600);
if (!bmp.begin())
{
Serial.println("Nie odnaleziono czujnika BMP085 / BMP180");
while (1) {}
}
}
void loop()
{
// Odczytujemy temperature i cisnienie
float temp = bmp.readTemperature();
float pressure = bmp.readPressure();
// Sami wyliczamy wysokosc
sealevelPressure = 101325;
float altitude = 44330 * (1.0 - pow(pressure / sealevelPressure, 0.1903));
// Wyczucamy dane na port szeregowy
Serial.print("D:");
Serial.print(temp);
Serial.print(":");
Serial.print(pressure);
Serial.print(":");
Serial.print(altitude);
Serial.println();
}
Program wizualizacyjny:
import processing.serial.*;
Serial myPort;
boolean hasData = false;
int actualSample = 0;
int maxSamples = 300;
int sampleStep = 2;
float[] tempValues = new float[maxSamples+1];
int minTemp = 0;
int maxTemp = 0;
float[] pressureValues = new float[maxSamples+1];
int minPressure = 0;
int maxPressure = 0;
float[] altitudeValues = new float[maxSamples+1];
int minAltitude = 0;
int maxAltitude = 0;
void setup ()
{
size(670, 750);
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil(10);
background(0);
}
void drawChart(String title, float[] data, int minValue, int maxValue, int x, int y, int h, int ls, int fs)
{
strokeWeight(1);
noFill();
stroke(50,50,50);
rect(x, y, (maxSamples*sampleStep)+50, h+50);
strokeWeight(1);
stroke(90,90,90);
for (float t = minValue; t <= maxValue; t = t + ls)
{
float line = map(t, minValue, maxValue, 0, h);
line(x+40, y+h-line+16, x+(maxSamples*sampleStep)+40, y+h-line+16);
fill(200, 200, 200);
textSize(fs);
text(int(t), 5+x, h-line+20+y);
}
textSize(14);
String title2 = title + " " + nf(data[actualSample-1], 0, 2);
text(title2, ((maxSamples*sampleStep)/2)-(textWidth(title2)/2)+40, h+40+y);
strokeWeight(2);
stroke(204, 102, 0);
for (int i = 1; i < actualSample; i++)
{
float v0 = map(data[i-1], minValue, maxValue, 0, h);
float v1 = map(data[i], minValue, maxValue, 0, h);
line(((i-1)*sampleStep)+40+x, h-v0+16+y, (i*sampleStep)+40+x, h-v1+16+y);
}
}
void draw ()
{
if (!hasData) return;
background(0);
drawChart("Temperatura", tempValues, minTemp, maxTemp, 10, 10, 100, 1, 14);
drawChart("Cisnienie", pressureValues, minPressure, maxPressure, 10, 200, 200, 50, 10);
drawChart("Wysokosc", altitudeValues, minAltitude, maxAltitude, 10, 490, 200, 1, 12);
}
void nextSample()
{
if (actualSample == maxSamples)
{
float lastTemp = tempValues[maxSamples];
float lastPressure = pressureValues[maxSamples];
float lastAltitude = altitudeValues[maxSamples];
for (int i = 1; i <= (maxSamples-1); i++)
{
tempValues[i-1] = tempValues[i];
pressureValues[i-1] = pressureValues[i];
altitudeValues[i-1] = altitudeValues[i];
}
tempValues[(maxSamples-1)] = lastTemp;
pressureValues[(maxSamples-1)] = lastPressure;
altitudeValues[(maxSamples-1)] = lastAltitude;
} else
{
actualSample++;
}
}
void serialEvent (Serial myPort)
{
String inString = myPort.readStringUntil(10);
if (inString != null)
{
inString = trim(inString);
String[] list = split(inString, ':');
String testString = trim(list[0]);
if (list.length != 4) return;
float temp = float(list[1]);
float pressure = float(list[2]);
float altitude = float(list[3]);
if (actualSample == 0)
{
for (int i = 0; i <= maxSamples; i++)
{
tempValues[i] = temp;
pressureValues[i] = pressure;
altitudeValues[i] = altitude;
}
}
tempValues[actualSample] = temp;
pressureValues[actualSample] = pressure;
altitudeValues[actualSample] = altitude;
maxTemp = floor(max(tempValues))+1;
minTemp = ceil(min(tempValues))-1;
maxPressure = floor(max(pressureValues))+200;
minPressure = ceil(min(pressureValues))-200;
maxAltitude = floor(max(altitudeValues))+2;
minAltitude = ceil(min(altitudeValues))-2;
if (actualSample > 1)
{
hasData = true;
}
nextSample();
}
}
O ile pomiar ciÅ›nienia jest w miarÄ™ dokÅ‚adny na potrzeby meteorologiczne, to przeliczona za jego pomocÄ… wysokość może może wahać siÄ™ w zakresie ±1 m. Warto również podkreÅ›lić fakt, że wiÄ™ksza dokÅ‚adoność pomiaru ciÅ›nienia w czujniku BMP180 rozwiÄ…zywana jest programowo, a nie sprzÄ™towo - uÅ›redniany jest 3-krotny pomiar.
Biblioteka dla Arduino: http://www.jarzebski.pl/arduino/BMP085/BMP085.zip
Przykłady z powyższego wpisu: http://www.jarzebski.pl/arduino/BMP085/BMPxxx_examples.zip
Pełna karta katalogowa BMP085: http://www.jarzebski.pl/datasheets/BMP085.pdf
Pełna karta katalogowa BMP180: http://www.jarzebski.pl/datasheets/BMP180.pdf