Czujniki ciśnienia i temperatury BMP085 / BMP180
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: https://www.jarzebski.pl/datasheets/BMP085.pdf
Pełna karta katalogowa BMP180: https://www.jarzebski.pl/datasheets/BMP180.pdf
Obliczanie wysokości na podstawie pomiaru ciśnienia atmosferycznego
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
Połączenie z Arduino
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.
Przykładowy program
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
Wizualizacja
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.
Materiały dodatkowe
Biblioteka dla Arduino: https://www.jarzebski.pl/arduino/BMP085/BMP085.zip
Przykłady z powyższego wpisu: https://www.jarzebski.pl/arduino/BMP085/BMPxxx_examples.zip
Pełna karta katalogowa BMP085: https://www.jarzebski.pl/datasheets/BMP085.pdf
Pełna karta katalogowa BMP180: https://www.jarzebski.pl/datasheets/BMP180.pdf
Reklama
Komentarze
z dużym zainteresowaniem przeczytałem, troszku przez przypadek trafiłem na Twoją stronę - szukając czujnika ciśnienia atmosferycznego, 180 - jest za mało dokładna dla mnie, a może istnieją bardziej dokładne
mikro - czujniki tylko ja źle szukam ?
Z pełnym podziwem
Henryk
Bardzo ciekawe rozwiązanie, gratulacje dla autora.
Interesuje mnie czy czujniki BMP pracują także pod typiowy oprogramowaniem np, LogTemp, se sterownikami Maxima?
Jeśli mogę poproszę odpowiedź na moją pocztę.
Pozdrowienia.
Witaj, nic mi na ten temat nie wiadomo - technicznie rzecz biorąc pójdzie pod wszystkim co obsłuży i2c, kwestia oprogramowania
Mam pytanie.
Chcialem polaczyc 2 przyklady w jeden tzn aby Arduino Pro Mini pobieral dane z DHT22 i BMP180. Czy połączone oba przyklady z Pana strony zamieszczone ponizej bedzie OK ??? czy moze cos inaczej zrobic aby korzystac z 2 czujnikow
====================================================================
#include "DHT.h" // biblioteka DHT
#define DHTPIN 2 // numer pinu sygnałowego
#define DHTTYPE DHT22 // typ czujnika (DHT11). Jesli posiadamy DHT22 wybieramy DHT22
#include
#include
Adafruit_BMP085 bmp;
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on \'168/\'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on \'168/\'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here
DHT dht(DHTPIN, DHTTYPE); // definicja czujnika
void setup()
{
Serial.begin(9600); // otworzenie portu szeregowego
dht.begin(); // inicjalizacja czujnika
// 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()
{
// Odczyt temperatury i wilgotności powietrza
float t = dht.readTemperature();
float h = dht.readHumidity();
// Sprawdzamy czy są odczytane wartości
if (isnan(t) || isnan(h))
{
// Jeśli nie, wyświetlamy informację o błędzie
Serial.println("Blad odczytu danych z czujnika");
} else
{
// Jeśli tak, wyświetlamy wyniki pomiaru
Serial.print("Wilgotnosc: ");
Serial.print(h);
Serial.print(" % ");
Serial.print("Temperatura (DHT22): ");
Serial.print(t);
Serial.println(" *C");
Serial.println();
}
// BMP180
// 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);
}
Najprościej będzie skompilować i sprawdzić :) Pamiętaj, aby czujniki nie korzystały z tych samych pinów
Witam,
czujnik dziala bezproblemowo ...oprócz dokładności. 1012hPa a on pokazuje 992... Pod czym jest skompilowane program wizualizacyjny?
Pozdrawiam
Krzysztof
Skąd bierzesz wartość 1012hPa? Może nie bierzesz pod uwagę wysokości na jakiej się znajdujesz? Czujnik podaje Ci faktyczne ciśnienie, zaś ciśnienie "meteo" jest zredukowane do poziomu morza...
Mam identyczny problem i sam juz nie wiem czy to wina czujnika czy może programu.
Dzięki za fajny artykuł. Być może ktoś tu jeszcze trafi i będzie walczył z tym samym co ja, czyli by ciśnienie wyglądało jak w pogodynce. Należy wyliczyć ciśnienie zredukowane na podstawie wysokości stacji, temperatury i ciśnienia zmierzonego:
[code]
//funkcja wylicza cisnienie zredukowane do poziomu morza i dla 0oC (takie jak na mapach pogody) na podstawie zmierzonego cisnienia atmosferycznego na danej wysokosci npm i zmierzonej temperatury
//temperatura w oC, ciśnienie w Pa, wysokość npm w m
uint32_t cisnieniezredukowaneNPM(int16_t temperatura, uint32_t cisnieniebezw, uint32_t wysokosc_pomiaru)
{
//stopien baryczny
uint16_t stopienbaryczny=(800000*(1000+4*temperatura)/(cisnieniebezw+1)); //dodaje 1 w mianowniku bo czasami wychodzi jajo jak jest blisko 0
//przyblizone cisnienie
uint32_t cisnienie1=cisnieniebezw+(100000*wysokosc_pomiaru/(stopienbaryczny+1));
// cisnienie srednie
uint32_t Psr=(cisnieniebezw+cisnienie1)/2;
//temperatura poziomu morza
int16_t tpm=temperatura+((6*wysokosc)/1000);
//srednia temperatura
int16_t tsr=(temperatura+tpm)/2;
//kolejne przyblizenie stopnia barycznego
stopienbaryczny=(800000*(1000+4*tsr)/(Psr+1)); //wyliczamy ponownie dla wartosci srednich
//zwracamy cisnienie zredukowane w Pa, ewentualnie mozna przeliczyc na hPa poza funkcja
return cisnieniebezw+(100000*wysokosc_pomiaru/(stopienbaryczny+1));
}
[/code]
Funkcja w fazie testów, tę 1 z mianowników można pewnie wywalić i mieć bardziej precyzyjny wynik, trzeba tylko zabezpieczyć się IFami przed brakiem odczytu z czujnika i dzieleniem przez 0. Formułka na ciśnienie zredukowane z forum o pogodzie przerobiona na liczby całkowite.
Pozdr
Kacza
Dzięki za bardzo pomocne przykłady.
Pytanie: jak mogę podłączyć dwa czujniki do pomiaru ciśnienia do arduino? Czy w funckcji >> bmp.readPressure() jako parametr podaję numer czujnika?
BMP będą posiadać ten sam adres na I2c, dlatego musiałbyś skorzystać z tego: http://www.nxp.com/documents/data_sheet/PCA9548A.pdf
hmmmmm wyższa szkoła jazdy, chyba zastosuje drugie mini pro do drugiego bmp.
myślałem, że wszystkie urządzenia na i2c mają unikalne adresy...?
WItam, czujnik działa bezproblemowo ale jest "duży" problem z dokładnościa odnośnie wysokości pokazujue ci około też 300 metrów nad poziomem morza ja sprawdziłem u siebie pokazuje mi na pomiarze z czujnika też około 300 metrów a moje miasto znajduję sie na około 50 metrów jak poradzić sobie i rozwiązać ten problem.
Podajesz dobre, aktualne ciśnienie na poziomie morza do sealevelPressure?
cisnienie podaje dokladne sprawdz u siebie czy ci dobrze działa ?
Witam, jakiego programu uzywa pan do wizualizacji wynikow pomiaru?
BMP180 to bardzo dobry czujnik, sam użyłem go w jednym z moich projektów. Ostatnio znalazłem w Elektronice Praktycznej artykuł o polskim portalu typu chmura dla urządzeń pomiarowych. BMP180 jest tam pokazany jako przykład, pracuje razem z czujnikiem wilgotności HTU21D i to wszystko nadaje do chmury za pomocą ESP8266. Fajna sprawa, marzy mi się własna stacja pogodowa z wykreseami w necie, warto się nad tym zastanowić, tylko ja osobiście nie miałem jeszcze do czynienia z ESP i w ogóle zagadnieniami sieciowymi.
stronka tutaj https://skizi.net/blog/show/22
Prawie wszystko można zbudować w oparciu o moduł ESP8266. Obecnie własnie buduje stacje pogodowa na tym mikrokontrolerze, zbierając dane z areometru, kierunkowskazu i DHT22 a pozniej wysyłając do internetu. Polecam do nauki: https://learn.adafruit.com/esp8266-temperature-slash-humidity-webserver (przykładowy poradnik, na stronie adafruit jest ich wiecej) Sam jeszcze sie uczę ;)
Wszytko pięknie kolego, tylko problem polega na tym że DHT22 to mega słaby czujnik, a DHT11 to już w ogóle porażka. Od kilku miesięcy mam uruchiony testowo taki układ DHT22 + DS18B20 obok stoi jeszcze czujnik stacji pogodowej Bioterm i zwykły termometr. Wszystkie trzy łącznie z DS18B20 pokazują zgodnie tą samą temperaturę +/- 0,5stopnia (co dla domowej stacji pogodowej jest jak najbardziej do przyjęcia), a DHT22 odwala takie bzdury że szkoda gadać.
W temperaturze pokojowej DHT22 jako tako sobie radzi, ale gdy temperatura spada poniżej zera potrafi pokazywać -6 gdy jest -10. Druga sprawa to bardzo wolna reakcja na zmianę temperatury. Ogólnie czujniki DHT nie nadają się do niczego poza nauką arduino.
Dlatego myślę nad zakupem BME280 bo generalnie DS18N20 jest najlepszy, ale brak mi wilgotności :(
Dzięki, szczególnieza graficzną prezentację pomiarów, zastosowałem czujnik BME280, temperatura, ciśnienie i wilgotność powietrza, działa wyśmienicie.
Podpiąłem BMP180 + DTH22 i wszystko pięknie działa. Jedynie rozbieżność przy odczycie temperatur z obu czujników wynosi 0,4oC. Przydała by się kalibracja czujników.
Teraz czas zrobić wizualizację.
Dziękuję.
Jeśli odchyłka jest stała dla szerszego zakresu tempepratur :) odejmin/dodaj te 0.4C
Proszę o pomoc . Zrobiłem ten przykład i niestety wyświetla - nie wykryto czujnika ......... Na przykładach z biblioteki arduino czujnik normalnie działa . Użyłem arduino nano , Bmp 180 . Piny podłączone do A4 i A5 .
Gwarantuję że musiałeś coś źle podłączyć. Na Nano działa taki zestaw poprawnie - podłączenie SCL do A5 oraz SDA do A4.
Czy spotkał się ktoś z warjacjami w odczytach? Raz otrzymuje odczyt w normie 993 po czym za jakiś czas dostaje odczyt 1700 nawet do 2000 po czym znowu odczyt jest w porządku.
Easy ESP v120 + BMP180
sprawdź połączenia, szczególnie czy masa dobrze styka