[RasPi] Enviro+ で部屋の状態を数値化してみた 

[Raspberry Pi Advent Calendar 2020](https://qiita.com/advent-calendar/2020/raspberry-pi) 23日目、かしゆかの誕生日ー!!

ﾜｰｲヽ(ﾟ∀ﾟ)ﾒ(ﾟ∀ﾟ)ﾒ(ﾟ∀ﾟ)ﾉﾜｰｲ

ゆかちゃんもめでたく誕生日を迎えたようなので、`Raspberry Pi` に "[Enviro+](https://www.switch-science.com/catalog/6119/)" を組み合わせて、お部屋の空気品質をチェックしてみましょう(๑•̀ㅂ•́)و✧

# Raspberry Pi と "Enviro+" を融合する

なんてことはない、ラズパイにくっつけるだけです。この`Enviro+` は次のセンサがくっついていたり、LEDで表示させたりとテレワーク民を恍惚とさせる多くの機能を持っています。

- BME280：温度、気圧、湿度センサ
- LTR-559：明るさ、近接センサ
- MICS6814：アナログガスセンサ
- ADS1015：アナログ/デジタルコンバータ（ADC）
- MEMSマイクロフォン
- 0.96インチカラーLCD （160 x 80）

さらにこの[微小粒子状物質 (PM) センサ(PMS5003)](https://shop.pimoroni.com/products/pms5003-particulate-matter-sensor-with-cable)をくっつけると、PM1,PM2.5,PM10といった微粒子まで検出できる代物。もちろん買いました( ^ω^ )ﾆｺﾆｺ

# Raspberry Pi で Python のセットアップを行う

この"Enviro+"は、Python の[ライブラリが公開](https://github.com/pimoroni/enviroplus-python)されていて、Python2.x/Python3.xで利用可能です。今回はPython3.xで利用することにして、おまけのプログラムが動くとこまでがんばってみました。

## Python3 と必要なライブラリを入れておく

このライブラリを使うためにいくつか必要なパッケージがあるので、それらをインストールします。

```bash
$ sudo apt install python3-numpy python3-smbus python3-pil python3-setuptools
$ pip3 install enviroplu
$ pip3 install RPi.GPIO
$ pip3 install spidev
$ pip3 install smbus
$ pip3 install numpy
$ pip3 install ltr559
```

他 `/boot/config.txt` に次の3行が必要ですが、インストーラが自動的にやってくれるようです。

```bash:config.txt
enable_uart=1
dtoverlay=pi3-miniuart-bt
dtoverlay=adau7002-simple
```

で、インストールは

```bash
curl -sSL https://get.pimoroni.com/enviroplus | bash
```
です。これでサンプルと必要なライブラリ群が配置されます。

## 試してみる

`examples` 内にサンプルが詰まっているので、いろいろ試してみると良いです。`combined.py` は全部の項目を表示&LCDにも表示なので、見てて楽しいと思います。

```bash
-rwxr-xr-x 1 root root   469 Aug 13 16:12 gas.py
-rwxr-xr-x 1 root root  1453 Aug 13 16:12 compensated-temperature.py
-rwxr-xr-x 1 root root 11285 Aug 13 16:12 combined.py
-rwxr-xr-x 1 root root  6633 Aug 13 16:12 all-in-one.py
-rwxr-xr-x 1 root root  5418 Aug 13 16:12 all-in-one-no-pm.py
-rwxr-xr-x 1 root root  4726 Aug 13 16:12 all-in-one-enviro-mini.py
-rwxr-xr-x 1 root root   511 Aug 13 16:12 adc.py
-rwxr-xr-x 1 root root   748 Aug 13 16:12 weather.py
-rwxr-xr-x 1 root root 13102 Aug 13 16:12 weather-and-light.py
-rwxr-xr-x 1 root root   603 Aug 13 16:12 particulates.py
-rwxr-xr-x 1 root root   878 Aug 13 16:12 noise-profile.py
-rwxr-xr-x 1 root root  1169 Aug 13 16:12 noise-amps-at-freqs.py
-rwxr-xr-x 1 root root  6654 Aug 13 16:12 mqtt-all.py
-rwxr-xr-x 1 root root  5416 Aug 13 16:12 luftdaten.py
-rwxr-xr-x 1 root root   698 Aug 13 16:12 light.py
-rwxr-xr-x 1 root root  1363 Aug 13 16:12 lcd.py
```

これらのサンプルを見て分かることは、温度に関しては不正確になるというとこでしょうか。温度をそのまま取得するとやたらめったら高く出ます。実際にはラズパイで暖められた温度分をさっ引いたりして計算しているようです(雑に)。

また、湿度もずれてる感じ合ったりもするので、配置場所やケースの有無でもずいぶんと変わってきそうです。

ちょっとプログラムを変更して、全体をよしなに表示してくれるやつも作ってみました。夏場と比較して、冬の方がPM1/2.5/10の数値が異常に高いです。ずーっと空気入れ換えてないからかな。ちゃんと空気清浄機近くにあるのに。

```
lux: 327.7169
proxmity: 570
temp: 26.783929517396487
pressure: 1015.2478925286023
humidity: 17.904801703248104
Oxidising: 2333.33 Ohms
Reducing: 553900.99 Ohms
NH3: 96853.60 Ohms

PM1.0 ug/m3 (ultrafine particles):                             9
PM2.5 ug/m3 (combustion particles, organic compounds, metals): 11
PM10 ug/m3  (dust, pollen, mould spores):                      12
PM1.0 ug/m3 (atmos env):                                       9
PM2.5 ug/m3 (atmos env):                                       11
PM10 ug/m3 (atmos env):                                        12
>0.3um in 0.1L air:                                            1662
>0.5um in 0.1L air:                                            468
>1.0um in 0.1L air:                                            68
>2.5um in 0.1L air:                                            2
>5.0um in 0.1L air:                                            2
>10um in 0.1L air:                                             0
```

一応、プログラム載せときます。

```python
#!/usr/bin/env python3
from subprocess import PIPE, Popen
import time
try:
    # Transitional fix for breaking change in LTR559
    from ltr559 import LTR559
    ltr559 = LTR559()
except ImportError:
    import ltr559

from bme280 import BME280
try:
    from smbus2 import SMBus
except ImportError:
    from smbus import SMBus
bus = SMBus(1)
bme280 = BME280(i2c_dev=bus)

from enviroplus import gas

from pms5003 import PMS5003
pms5003 = PMS5003()

def get_cpu_temperature():
    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
    output, _error = process.communicate()
    return float(output[output.index('=') + 1:output.rindex("'")])

cpu_temps = [get_cpu_temperature()] * 5
factor = 2.25

while True:
    # Everything on one screen
    cpu_temp = get_cpu_temperature()
    # Smooth out with some averaging to decrease jitter
    cpu_temps = cpu_temps[1:] + [cpu_temp]
    avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
    raw_temp = bme280.get_temperature()
    temp = raw_temp - ((avg_cpu_temp - raw_temp) / factor)

    gasses = gas.read_all()
    pms = pms5003.read()
    print('lux:',ltr559.get_lux())
    print('proxmity:', ltr559.get_proximity())
    print('temp:',temp)
    print('pressure:', bme280.get_pressure())
    print('humidity:', bme280.get_humidity())
    print(gasses)
    print(pms)
    time.sleep(5)
```

ゆくゆくは、これらの取得されたデータをどっかに集めておいてグラフ化しようというのが、次のステップです。