【RaspberryPi Zero】とMH-Z19
ラズパイ上で、MH-Z19のパッケージが使用できなかったため、MH-Z19で取得したデータをリアルタイムで可視化するプログラムを自作しました。結果は下図のような感じです。
このページの内容で出来ること
ラズベリーパイとCO2センサー「MH-Z19(筆者が使ったのはMH-Z19Cで、MH-Z19B等、他の品番であっても同じものとして扱えます。)」を使って、CO2濃度をリアルタイムでグラフ化し、更に計測したデータをCSVファイルとして保存することができます。
MH-Z19のラズパイへの配線方法は、他の紹介しているページに譲り、割愛させていただきます。
重要!!前提条件
ラズベリーパイにインストールするOSは、bullseye(full)を想定しています。lite版では、matplotlib等のライブラリがインストールされていないため、グラフが表示されず、エラーメッセージが表示されます。
コード紹介
次のコードを、ラズパイの”Thonny”に張り付けて、ラズパイのデスクトップ上にpyファイルとして保存してください。
実行してしばらくするとグラフが表示されます。初回起動時は、グラフ化するためのソフトの起動に2~3分待機する必要があるかもしれません。
import serial
import serial
import time
import csv
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.dates as mdates
from multiprocessing import Process, Queue
#Set Serial Port
ser = serial.Serial('/dev/ttyS0', 9600, timeout=1)
#MH-Z19 Detection Range=5000
command = [0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB]
#Send Command
ser.write(bytearray(command))
#Read Response
response = ser.read(9)
#CSV File Name
csv_filename = time.strftime('%Y%m%d%H%M%S_') + 'co2_data.csv'
#Prepare Plot
fig, ax = plt.subplots()
x, y =[], []
#Error
last_co2 = None
#data Update Function
def get_data(q):
global last_co2
while True:
#Get CO2
ser.write(bytearray([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]))
response = ser.read(9)
co2 = response[2] * 256 + response[3]
#400-5000
if co2 < 400 or co2 > 5000:
co2 = last_co2
else:
last_co2 = co2
#Get Current Time
now = time.gmtime()
#Write CSV
with open (csv_filename, 'a') as f:
writer = csv.writer(f)
writer.writerow([time.time(), time.strftime('%Y-%m-%d'), now.tm_hour, now.tm_min, now.tm_sec, int(time.time() * 1000) % 1000, co2])
#Log
print(f"Measurement time: {time.strftime('%Y:%m:%d:%H:%M:%S', now)}, CO2:{co2}ppm")
#Que
q.put((time.time(),co2))
#Wait 1s
time.sleep(1)
q = Queue()
p = Process(target=get_data, args=(q,))
p.start()
#Update Plot
def update(i):
#Get Data From Queue
while not q.empty():
data = q.get()
x.append(mdates.epoch2num(data[0]))
y.append(data[1])
#Update Plot
ax.clear()
ax.plot(x, y, '-')
#Set X-Axis Format
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H,%M,%S'))
plt.xticks(rotation=60)
plt.xlabel('Time')
#Set Y-Axis Format
plt.ylabel('CO2(ppm)')
#Plot Title
plt.title('enter')
#Start Animation
ani = animation.FuncAnimation(fig, update, interval = 2000)
#Show Plot
plt.show()
工夫した点
はじめは、「グラフ化」と「1秒ごとのデータ保存」を一連の流れで処理していましたが、グラフ化の際にタイムラグが生じるため、「1秒ごとのデータ保存」がうまく行きませんでした。
そこで、multiprocessing
で「グラフ化」と「1秒ごとのデータ保存」を並列処理させることで解決を図りました。
備忘録として、プログラムの各行には説明を記載しました。MH-Z19のパッケージを使った方法は検索するとすぐにヒットしましたが、パッケージを使わずにグラフ化できる点で、本記事を参考にしていただけますと幸いです。
参考としたセンサーのマニュアル
MH-Z19の製造メーカー「Winsen」のHPに掲載されているユーザーマニュアルを参照しました。
|