Lekce 19 - Arduino a senzor tlaku BMP085

24.05.2013 21:07

Translate to English

   

 Před několika dny mi dorazil poštou senzor atmosférického tlaku BMP085 od firmy Bosch. Jedná se o již připravený modul o velikosti 20x15mm takže opravdu prcek. Nálézá se na něm 6 vývodů, všechny jsou na modulu popsané a vzhledem k tomu, že modul komunikuje protokolem I2C, stačí pro funkční zapojení pouze 4 vodiče (2 napájení a 2 pro I2C). Modul je napájený napětím 3V, což z Arduina není problém. S tímto modulem si můžeme postavit malou meteostanici i s předpovědí počasí, elektronický měřič nadmořské výšky a pod.

     Pro zprovoznění modulu máme 2 možnosti. Jedna obtížnější - po prozkoumání datasheetu napíšeme zdrojový kód a poté ta lehčí - najdeme již napsanou knihovnu modulu a importujeme ji do programu. Začneme, ale pro pochopení modulu tou težší.     

     Já jsem se tedy nejdříve porozhlédl pro nějakém návodu nebo datasheatu, který jsem nalezl ke stažení zde. Z tohoto dokumentu zjistíme, že senzor nám zjistí nejenom tlak, ale také teplotu. Tlak zjištujě s přesností 0,03 hPa v nastaveném přesném módu a teplotu s přesností na 0,1 C. Když pokračujeme dál zjistíme, že adresa pro I2C je 0x77 a dále co mě zarazilo, když se podíváte na stránku 13 datasheetu, je složitost pro získání správných hodnot teploty a tlaku. Já popíšu zhruba postup jak je k těhto hodnot dosaženo.

  1. Musíme získat tzv. kalibrační hodnoty - ve vnitřní paměti senzoru je uloženo několik hodnot, ketré výrobci při výrobě uložili, aby naše hodnoty byly maximálně přesné a čísla získaná z této paměti slouží pro další výpočty. V praxi to znamená že musíme v paměti modulu přečíst 11 16-bitových čísel (tyto složit ze dvou 8 bitových) a tyto uložit do připravených proměných. To jsme se již učili a postup je obdobný jako u čtení z EEPROM na I2C. 
    Každá hodnota má svoje dvě asdresy pro každou 8 bitovou hodnotu
  2. Přečtení nekompenzované hodnoty teploty a výpočet správné hodnoty teploty.
  3. Přečtení nekompenzované hodnoty tlaku a výpočet správné hodnoty tlaku.

Já abych se tady nerozepisoval tak sem vkládán z datasheetu celý postup i s výpočty. Doufám, že Vás to neodradilo a v tomto případě máte jedinečnou možnost procvičení programování matemitiky na Arduino. Nicméně nechápu, proč vyvojoví pracovníci ve fy. Bosch toto již nenaprogramovali do modulu :-). Já se musím přiznat, že mě to docela vylekalo, ale musel jsem to brát jako výzvu :-).

Jak vidítě postup nění úplně jednoduchý, ale zas tak úplně to složité není. V ukázce programu je to trošku rozděleno do funkcí pro větší přehled. Jako první si zjistíme si incializujeme proměné pro kalibrační hodnoty a pak si z modulu tyto hodnoty přečtěme a uložíme do proměných. Čteme 16 biitové číslo - tzn. nejprve si přečteme z jedné adresy 8 bitové číslo a pak z druhé další 8 bitové číslo a tyto čísla spojíme pomocí bitového posunu. Adresy hodnot najdeme v tabulce výše v textu. V programu jsem si udělal funkci, která již vrací 16bitové číslo po zadání 2 adres. Je to funkce "GetShort". Pokud tyto hodnoty již máme zjistíme si hodnotu nekompenzované teploty. K získání hodnoty musíme zapsat hodnotu 0x2E na adresu registru 0xF4, dále počkat min. 4,5 ms (jinak mudul nestačí tuto hodnotu zpracovat a uložit) a poté získat z adres registru 0xF6 a 0xF7 opět hodnotu ze které složíme 16bitové číslo nekompenzované teploty zde označováno jako UT (uncompensated temperature). Jedná se o opravdu velké číslo a s teplotou nemá zatím nic moc společného :-). Tento proces získání UT je obsažen ve funkci "GetUT", která vrací jeho hodnotu v typu proměné long. Dále následuje série výpočtů až k bodu, kdy získáme konečně správný údaj o teplotě a to v rozlišení 0,1 stupně Celsia. To číslo je vlastně násobeno 10. Správná hodnota je vždy teplota/10. (tzn. že T=224 je 22,4 st. Celsia). Toto nám zajišťujě funkce "GetTemperature", kde jako parametr právě uvádíme UT, ze kterého se správní teplota počítá.

Po získání údajů o teplotě si změříme atmosférický tlak. Postup je podobný. Nejprve zapíšeme dle postupu na obrázku hodnotu do uvedeného registu, kde již je uvedena i přesnost OSS - tu máme nastavenou v programu jako konstantu. (0 až 3), dále chvilku počkáme. Doba závisí na nastavené přesnosti a v programu je již zohledněna. Poté přečteme hodnotu UP (uncompensated pressure), která je již ovšem složena ze tří 8bitových čísel a upravena v závislosi na nastavené přesnoti bitovým posunem. To v programu zajištujě funkce "ReadUP". Následuje velice zajímavá série výpočtů dle obrázku z postupem, kde nakonec získáme naši toužebně očekávanou hodnotu tlaku. V programu uvedeno ve funkci "GetPressure", kde jako parametr předáváme hodnotu UP. Výsledná hodnota je samozřejmě uvedena v Pascalech. Pro převod do kPa (hektoPascalů vydělíme 100). 

Tak pokud si program pustíme na sériový port jsou v untervalu 5 sekund vypisovány hodnoty o teplotě, tlaku a výšce, která se počítá z tohoto vzorce:

Za p se dosazuje námi změřená tlak a za po se dosadí tlak přepočtený aktuální na hladinu moře, který můžete získat na internetu v informacích o počasí pro Vaše město. Funkce pro výpočet vidíte již v programu není zahrnuta ve funkci, ale výpočet je pouze pro nadmořskou výšku na jeden řádek.v baterii

Tak tady je k tomuto funkční program:

Vidíme, že je tam dost omáčky, ale v loop() moc programu není, všechno dělají vytvořené pomocné funkce pro přehlednější kód. Program, ale funguje dobře. Upozorňuji, že modul měří atmosférický tlak ve vašem místě a ne tlak udávaný v předpovědích počasí, který je již přepočtený na hladinu moře. Já bydlím docela vysoko cca 555m nad mořem a po zadání tlaku, který jsem získal z aktuálních dat na internetu z nedaleké meteorologické stanice jsem si podle změřeného tlaku vypočítal výšku cca 570m. Nepatrná odchylka tu je. Vy budete ale modul možná používat jako měřič barometrického tlaku. Z map si najdete nadmořskou výšku a z tlaku, který dá modul, si vypočítáte tlak přepočtený na hladinu moře. 

V programu si také můžete nastavit přesnost od 0 do 3. 0 je samozřejmě s nejmenší přesností, ale výpočet netrvá tak dlouho. Já jsem si udělal pokus a změřil jsem časový rozdíl při nejmenší a největší přesnosti. Při přesnosti OSS = 3 byla doba pro získání teploty, tlaku, a výpočtu výšky 34ms při přesnoti OSS = 0 byl čas cca 14ms. Myslím, že pro naše použití bude taková nepatrná doba nepodstatná. Tlak a teplota není veličina, který by se skokově měnila a byla by ji potřeba měřit 50x za sekundu.

Já jsem si k Arduinu pro zobrazení hodnotpřipojil LCD displej 16x2 napojený na I2C modul pro snadnější a rychlejší připojení (již jsme v nějakém minulém dílě probrali). Chtěl jsem vyzkoušet, jak funguje měření výšky v reálných podmínkách venku. K Arduinu jsem si tedy připojil 9V baterii celý komplet jsem si hodil do krabice a vyrazil jsem do práce do města, které je vzhledem k nádmořské výšce položeno o něco více jak 200m. Fungovalo to bezvadně. Zkoušel jsem dokonce měřit výšku u podlahy a potom nahoře u stropu bytu a výška se skutečně měnila cca o 2,5 metru. 

     Tak a teď ta lehčí metoda pro lenochy. Z tohoto zdroje si stáhneme knihovnu pro BMP085. Po otevření (je to ve formátu *.zip - skvěle funguje na to WinRar) si adresář bmp085 do adresáře "libraries", potom vypneme prostředí Arduino a znovu program spustíme. Již by se měla objevit v nabídce v menu "Sketch->Import Library-> ...." (postup jsme si ukázali v minulých dílech". Tak já hned uvedu nějaký program, který pracuje právě s touto knihovnou:

Já jsem trošku upravil a přeložil příklad uvedený s knihovnou. Jsou tam uvedeny tři možné inicializace senzoru. Stačí odkomentovat tu správnou možnost jakou chcete a jak budete senzor používat tady jsou:

  1. dps.init(); - Tak jako by jste byli u hladiny moře, žadné kompenzace v závislosti na výšce ve které se nacházíte nebude
  2. dps.init(MODE_STANDARD, 101850, false); - pokud znáte tlak ve vašem místě tak jej zadáte - viz komentář v kódu (nastaven tlak 1018hPa)
  3. dps.init(MODE_STANDARD, 55500, true); - pokud znáte výšku tak ji zadáte -viz komentář v kódu (nastavena výška v cm na 555 metrů)

Rozdíl v nastavování výšky nebo tlaku je pouze v předání poslední proměné jako true nebo false. Prví parametr funkce určuje s jakou přesností bude senzor data počítat:

  1. MODE_ULTRA_LOW_POWER    -->   přesnost 0,06hPa
  2. MODE_STANDARD    -->   přesnost 0,05hPa
  3. MODE_HIGHRES     -->   přesnost 0,04hPa
  4. MODE_ULTRA_HIGHRES     -->    přesnost 0,03hPa

Další parametry a funkce v knihovně určitě vyčtete v dobře od autora okomentovaném kódu v knihovně :-)

Nějaké tipy na stránky:

Aktuální informace o tlaku na území České republiky

Zjištění nadmořské výšky z mapy

Atmosférický tlak - Wikipedie

 

Zpět

Diskusní téma: Lekce 19 - Arduino a senzor tlaku BMP085

Datum
Vložil
Titulek

Pochvala

Pěkně zpracováno

Datum
Vložil
Titulek

Variometr

Ahoj, Dalo by se to nějak upravit na měření stoupavosti/klesavosti... rtesp. měšení změny výšky na čase?... jak velkou obnovovací frekvenci by to zvládlo.. dalo by se refreshovat alespon 2x za sekundu ? díky

Datum
Vložil
Titulek

Re: Variometr

Mělo by to stíhat 4x za sekundu :)
Taky dělám vario, mám na to trochu jinou knihovnu...

Datum
Vložil
Titulek

1 senzor pro více zařízení

Je vůbec možné využít tento nebo třeba senzor HC-SR04 ve více zařízeních Zapojit ho do kontatního pole a připojit do něj vodiče např. pro 2 arduina, raspberry apod ?

Datum
Vložil
Titulek

Re: 1 senzor pro více zařízení

Sám jsem to nezkoušel. Teoreticky by to šlo a mohlo fungovat pokud zařízení měli stejný potenciál napájení. Avšak i sběrnice I2C funguje v režimu master/slave a mít dva pány to není dobré. Chyby by vznikaly např. pokud by hodnoty žádaly najednou 2 Arduina. Zkuste a uvidíte. Praxe je taková, že se spíše zapojuje vice I2C zařízeních na jedno Arduino.

Datum
Vložil
Titulek

přesnost/stabilita

Jak jste na tom se stabilitou hodnot i když mi to leží na stole rozpětí je až 1m :((

Datum
Vložil
Titulek

Re: přesnost/stabilita

+- 1 metr je tak vzhledem k přesnosti zařízení akorát. Stačí že foukne vítr nebo někdo otevře dveře.

Datum
Vložil
Titulek

lcd

Dik funguje skvele

Datum
Vložil
Titulek

lcd

Já jsem si k Arduinu pro zobrazení hodnotpřipojil LCD displej 16x2 napojený na I2C modul

Prosim te moh by jsi sem dat program pro lcd displej a BMP085 prosmejdil jsem cele net a nenasel nic dik

Datum
Vložil
Titulek

Re: lcd

// BAROMETER s modulom BMP085 16.1.2014
// by Filipe Vieira - knižnica
// Simple test of BMP085 output using default settings using dynamic update.
// In order to take full advantage of dynamic measurement, automatic temperature updates must be disabled.
// To disable automatic updates set AUTO_UPDATE_TEMPERATURE to false in bmp085.h.
// IMPORTANT!! To get correct values you MUST CHANGE init() parameters, in
// this example I've set 668m based on GPS data for my location.

// recreated by Pavel Putna

#include <Wire.h>
#include <BMP085.h>
#include <LiquidCrystal.h> //importuje knihovnu LiquidCrystal

//inicializuje objekt jménem dps pro získání dat ze senzoru
BMP085 dps = BMP085(); // Digital Pressure Sensor
// připraví promené pro tlak, výšku a teplotu
long Pressure = 0, Altitude = 0, Temperature = 0;

// Inicializujeme LCD objekt
// 12 - RS, 11 - E, 5 - DB4, 4 - DB5, 3 - DB6, 2 - DB7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Definicia znaku 'stupeň'
byte degree[8] = {0b01100,0b10010,0b10010,0b01100,0b00000,0b00000,0b00000,0b00000 };

void setup(void) {

Serial.begin(9600);
Wire.begin();
lcd.begin(16, 2); // nastaví typ displeje na 16 znaků a 2 řádky (upravte dle sebe)
lcd.print("***BAROMETER***");
delay(500);
lcd.setCursor(2, 1);
lcd.print("Poprad 668m.");
delay(2000);
lcd.createChar(0, degree);

// odkomentujte pro rozdílný postup při použití senzoru
//dps.init(); // QFE (Field Elevation above ground level) je nastaveno na 0 metrů.
// jako kdyby jste měřili tlak u hladiny moře
// to samé jako init(MODE_STANDARD, 0, true);

//dps.init(MODE_STANDARD, 101850, false); // 101850Pa = 1018.50hPa, false = nastavené jednotky v Pa
// tuto metodu použijte, když znáte tlakve vašem místě např. z meteorologické stanice
// nebo z internetu z počasí

dps.init(MODE_STANDARD, 66800, true); // 668 metrů, true = nastavené jednotky v metrech
// tuto metodu použijte, když znáte Vaši nadmořskou výšku,
// tlak bude přepočítán automaticky na hladinu moře
// nastavenie MODE - funkcia určuje s akou presnoeťou bude počítať senzor dáta
// MODE_ULTRA_LOW_POWER --> přesnost 0,06hPa
// MODE_STANDARD --> přesnost 0,05hPa
// MODE_HIGHRES --> přesnost 0,04hPa
// MODE_ULTRA_HIGHRES --> přesnost 0,03hPa
}


void loop(void) {
// uloží do proměné "Pressure" hodnotu tlaku
dps.getPressure(&Pressure);
// uloží do proměné "Altitude" hodnotu výšky
dps.getAltitude(&Altitude);
// uloží do proměné "Altitude" hodnotu výšky
dps.getTemperature(&Temperature);

// Výstup na Seriový port
// - nazapomenme, že teplota se pro správný výsledek musí
// vydělit číslem 10, protože je v rozlišení 0,1C a je udávaná
// v celých číslech
Serial.print(" Vyska(m):");
Serial.print(Altitude*0.01); //*0.01- v metroch
Serial.print(" Tlak(Pa):");
Serial.print(Pressure);
Serial.print(" Teplota(C):");
Serial.println((float)Temperature/10);

//výstup na LCD 16x2, iba teplota a tlak
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Tlak ");
lcd.print(Pressure*0.01);
//lcd.write(' ');
lcd.print(" hPa");
lcd.setCursor(0,1);
lcd.print("Teplota ");
lcd.print(Temperature*0.1);
lcd.write(' ');
lcd.write(byte(0)); //zobrazí znak stupeň
lcd.write('C');

// počkáme 5 sekund, ať se z toho seriový port nezblázní :-)
delay(5000);
}

Vyhledávání

arduino8.cz © 2015 Všechna práva vyhrazena.