RaspberryPi + MH-Z19C + BMP280 + GASで研究室の環境を可視化した話(前編)
こんにちは、M1のYukimuraです。暑くなってきました(執筆時点では日中の最高気温35度とか言ってます)がいかがお過ごしでしょうか?
さてしかし、こんなに暑いと、研究室はエアコンと除湿機で快適であることを期待しながら苦労して大学までの上り坂を登るわけですが、「来てみたら、研究室が暑かった」なんていう事態になれば、もう期待と現実の落差で涙が出てしまいそうです。
とまあ、暑いなあと思いながらそんなことを考えていたのですが、よく考えてみたら弊研には、上原先生に買っていただいたラズパイとMH-Z19Cという二酸化炭素濃度センサー、そしてBMP280という温度湿度気圧センサーがあったことを思い出しました。
これは元々、トンガの噴火のときに気圧が大きく変わって話題になったのを弊研でも(また機会があれば)観測してみよう!ということで購入していただいたのですが、すっかり忘れて研究室の肥やしになってました。反省反省。
そんなわけで今回は、表題の通りラズパイとセンサーとGASを組み合わせて研究室の環境を可視化します。これで今研究室に行くべきか否かがわかるって算段です。
デバイス作り
今回使うハードウェアは以下の3点です。
- reTerminal(Raspberry Pi model 4)
- MH-Z19C
- BMP280
このreTerminalなるデバイスはかんたんに言うとディスプレイがついたラズパイで、タッチパネルで遊べるので便利です。
閑話休題、早速ラズパイにMH-Z19CとBMP280をつないで作っていきます。
配線図は以下
つなぐだけなので難しいことは無いです(が私は間違えました)。
続いて計測してみましょう。
MH-Z19Cは、親切な方が書いてくださったライブラリがあるので、それを引っ張ってきて使います。
$ sudo pip3 install mh-z19
コードは以下
import mh_z19
def read():
out = mh_z19.read()
return str(out)[8:-1]
if __name__=='__main__':
co2=read()
print(co2)
これだけで、二酸化炭素濃度が取得できます。
次にBMP280から気温湿度気圧を計測します。
こちらも親切な会社が公開してくださったライブラリがあるので、それを引っ張ってきて使います。
$ sudo pip3 install cgsensor
コードは以下
import cgsensor
def read():
bme280=cgsensor.BME280(i2c_addr=0x76)
bme280.forced()
return bme280.temperature,bme280.humidity,bme280.pressure
if __name__=='__main__':
print(read())
これで気温湿度気圧が取得できました。
GUIソフト作り
以上までで二酸化炭素濃度・気温・湿度・気圧が取得できるようになりましたが、このままではターミナルにちまちまと数字が出るだけなので、GUIソフトを作っていきます。
今回は、もはや定番であるtkinterを使って作っていきます。
コードは以下。
import tkinter as tk
import co2ppm
import thp
import time
import csv
import datetime
import os
import requests
def update():
co2=0
temp=0
humi=0
pres=0
try:
co2=co2ppm.read()
temp,humi,pres=thp.read()
except Exception as e:
print("error",e)
label1.configure(text=str(co2)+"ppm")
label2.configure(text=str(temp)+"℃")
label3.configure(text=str(humi)+"%")
label4.configure(text=str(pres)+"hPa")
nowtime=datetime.datetime.now()
dname='./data/'+nowtime.strftime('%Y%m/')
fname=dname+nowtime.strftime('%d')+'.csv'
os.makedirs(dname,exist_ok=True)
with open(fname,'a+') as f:
writer = csv.writer(f)
writer.writerow([co2,temp,humi,pres,nowtime.strftime('%H%M%S')])
label4.after(10000,update)
def close():
root.destroy()
root=tk.Tk()
root.title("Sensors")
root.geometry("1280x720")
root.attributes('-fullscreen',True)
tl1=tk.Label(root,text="CO2",font=("Digital-7",40))
tl1.place(x=10,y=40)
tl2=tk.Label(root,text="Temperature",font=("Digital-7",40))
tl2.place(x=10,y=400)
tl3=tk.Label(root,text="Humidity",font=("Digital-7",40))
tl3.place(x=650,y=40)
tl4=tk.Label(root,text="Pressure",font=("Digital-7",40))
tl4.place(x=650,y=400)
label1=tk.Label(root,text=str(co2ppm.read())+"ppm",font=("Digital-7",80))
label1.place(x=30,y=100)
label2=tk.Label(root,text=str(thp.read()[0])+"℃",font=("Digital-7",80))
label2.place(x=30,y=460)
label3=tk.Label(root,text=str(thp.read()[1])+"%",font=("Digital-7",80))
label3.place(x=670,y=100)
label4=tk.Label(root,text=str(thp.read()[2])+"hPa",font=("Digital-7",80))
label4.place(x=670,y=460)
button=tk.Button(root,text="CQ",command=close)
button.pack(side=tk.BOTTOM)
label4.after(10000,update)
root.mainloop()
10秒おきにupdate()を実行することで、情報を更新しています。csvにデータを蓄積してもいます。(ちなみにソケットを開きすぎということで、ファイルディスクリプタ上限に引っかかるので3時間に一度再起動しています)
気になる完成品はこちら!!
なんかお風呂の操作盤感を感じますが、とにかくこれで完成です。
めでたしめでたし...
...とは行きません。これでは研究室に来れば二酸化炭素濃度・気温・湿度・気圧がわかりますが、逆を言えば研究室に来ないとわからない、それでは不便すぎます。
不便すぎるので家からでも見れるようにしたい...のですが、長くなりそう&だいぶ雰囲気が変わるので後編に続く...
(IoTカテゴリを付けておいて今の所インターネット要素が無いという...これではただのThings...後編乞うご期待)
(文責:2022年度M1 木村悠生)