Raspberry Pi Meteostanice - tlakové čidlo MPL3115A2

Každá meteostanice by měla, kromě teploty, měřit i atmosferický tlak. K tomuto účelu se velmi dobře hodí čidlo MPL3115A2. Sehnal jsem si tedy také jedno toto čidlo a připojil ho k Raspberry Pi.

Čidlo MPL3115A2 měří atmosferický tlak, teplotu a nadmořskou výšku. Jedná se o přesnější variantu čidla MPL115A2. Je možné ho sehnat například na rpishop.cz.
Doporučuji koupit verzi z Adafruit (modrá varianta). Není k ní potřeba nic dalšího. Podle toho, co jsem našel na internetu, tak verze od SparkFun (červená varianta) bude asi potřebovat nějaké přídavné odpory (330Ω), které se budou muset zařadit mezi čidlo a Raspberry na pinech SDA a SCL.
Měřící rozsah tlakového čidla je 500-1100 hPa, což na měření atmosferického tlaku v našich zeměpisných končinách naprosto vyhovuje.

Jak tedy toto čidlo připojit k Raspberry Pi?

K připojení čidla nejsou potřeba žádné přídavné odpory. Prostě se jen připájí pinový nástavec a drátovými propojkami (alza.cz nebo rpishop.cz) se připojí k Raspberry Pi.

Schéma připojení je naznačeno na obrázku.

Zapojeni

Hlavně je důležité připojit piny SDA a SCL ke správným pinům na Raspberry Pi (piny 3 a 5). Tyto dva jsou totiž určeny pro připojování I2C zařízení.

Načtení hodnoty z čidla.

sudo raspi-config
Vyberte možnost 5 Interfacing Options a v následujícím menu P5 I2C. Na otázku, zda chcete povolit ARM I2C interface odpovězte Yes :-).
Po povolení bude potřeba Raspberry restartovat. Pokud restart nespustí přímo raspi-config tak použijte příkaz
sudo reboot
Otestovat si připojení čidla je možné pomocí příkazu
gpio i2cd -y 1
Ve výpisu by se mělo vyskytovat číslo 60. To je totiž jeho adresa 7-bitová I2C adresa.

Vypis


Nikde se mi nepodařilo najít postup, jak jen tak cvičně načíst hodnoty z čidla.
Jediné, co jsem nalezl je python script, který načtení a výpis zařídí.
https://github.com/ControlEverythingCommunity/MPL3115A2/blob/master/Python/MPL3115A2.py

Program v Pythonu

Zkoušel jsem tento script a funguje bez problémů. Jen jedna věc mě zarazila :-). Když se teplota v meteostanici dostala pod 0, tak najednou čidlo vykazovalo teploty kolem 250 stupňů celsia a to asi není dobře :-).
Řešení je ale jednoduché. Čidlo používá pro hodnotu teploty doplňkový kód a s tím autor programu nepočítal. Aby i záporné hodnoty byli správně, je nutné doplnit odečtení 256 v případě, že teplota překročí hodnotu 128°C.

Program po zohlednění doplňkového kódu je import time
import smbus

def read_temp_and_presure():
  bus = smbus.SMBus(1)

  # MPL3115A2 address, 0x60(96)
  # Select control register, 0x26(38)
  # 0xB9(185) Active mode, OSR = 128, Altimeter mode
  time.sleep(1)
  bus.write_byte_data(0x60, 0x26, 0xB9)
  # MPL3115A2 address, 0x60(96)
  # Select data configuration register, 0x13(19)
  # 0x07(07) Data ready event enabled for altitude, pressure, temperature
  bus.write_byte_data(0x60, 0x13, 0x07)
  # MPL3115A2 address, 0x60(96)
  # Select control register, 0x26(38)
  # 0xB9(185) Active mode, OSR = 128, Altimeter mode
  bus.write_byte_data(0x60, 0x26, 0xB9)

  time.sleep(1)

  # MPL3115A2 address, 0x60(96)
  # Read data back from 0x00(00), 6 bytes
  # status, tHeight MSB1, tHeight MSB, tHeight LSB, temp MSB, temp LSB
  data = bus.read_i2c_block_data(0x60, 0x00, 6)

  # Convert the data to 20-bits
  tHeight = ((data[1] * 65536) + (data[2] * 256) + (data[3] & 0xF0)) / 16
  temp = ((data[4] * 256) + (data[5] & 0xF0)) / 16
  altitude = tHeight / 16.0
  cTemp = temp / 16.0

  # Negative numbers are in Ones' complement
  if cTemp > 128:
    cTemp = 256 - cTemp
  
  fTemp = cTemp * 1.8 + 32

  # MPL3115A2 address, 0x60(96)
  # Select control register, 0x26(38)
  # 0x39(57) Active mode, OSR = 128, Barometer mode
  bus.write_byte_data(0x60, 0x26, 0x39)

  time.sleep(1)

  # MPL3115A2 address, 0x60(96)
  # Read data back from 0x00(00), 4 bytes
  # status, pres MSB1, pres MSB, pres LSB
  data = bus.read_i2c_block_data(0x60, 0x00, 4)

  # Convert the data to 20-bits
  pres = ((data[1] * 65536) + (data[2] * 256) + (data[3] & 0xF0)) / 16
  pressure = (pres / 4.0) / 100.0

  return pressure, altitude, cTemp, fTemp


while True:
  print(read_temp_and_presure())
  time.sleep(60)

Další věcí, kterou je potřeba vyřešit je, že čidlo měří atmosferický tlak v dané nadmořské výšce (dle umístění meteostanice) a za dané teploty. Všechny běžné meteostanice ale přepočítavají tlak na hladinu moře a teplotu 0°C. Aby byly údaje porovnatelné. Takže pokud Vás nezajímá tlak přesný, ale přepočtený, je nutné tento přepočet také doplnit. Já ho doplnil až v PHP scriptu, který data zobrazuje, abych si nepoškozoval naměřené hodnoty. Údaje pro tento přepočet ale čidlo poskytuje všechny, které jsou potřeba.

Vzorec pro přepočet atmosferického tlaku na hladinu moře
P0 = P * ((1 – ((0,0065 * Alt) / (Temp + 0,0065 * Alt + 273,15))) ^ -5,257) P0 je tlak přepočtený na hladinu moře.
P je tlak naměřený meteostanicí.
Alt je nadmořská výška ve které je umístěna meteostanice.
Temp je teplota naměřená meteostanicí.

A PHP script pro výpočet
$correction = (1 - ((0.0065 * $altitude) / ($temperature + (0.0065 * $altitude) + 273.15)));
$correction = $correction ** (-5.257);
$sea_level_pressure = $pressure * $correction;


Příklad se zápisem hodnot do databáze

Specifikace čidla:
Napájení 3.0 – 5.5 V
Tlakový rozsah 500 – 1100 hPa

Zdroje:
https://github.com/ControlEverythingCommunity/MPL3115A2/blob/master/Python/MPL3115A2.py
http://www.observatore.cz/calc/Psta2Psea.html
https://www.adafruit.com/product/1893

Raspberry Pi, Meteostanice

- (28. 7. 2017)
Kája z Norska
Kája z Norska

Jsem programátor, horolezec a tak trochu FlexiBee fanatik :-).
Na CharlieBlogu sepisuji své nápady a poznatky už od roku 2006.