RaspberryPi
NDIR方式によるCO2センサー

 様々なガスは、それぞれ特有の赤外線吸収波長を持っています。その特性を利用したガス計測の方法にNDIR方式(Non Dispersive InfraRed)があります。赤外光源より照射された赤外線は広域の波長を含んでいますが、ガスによる吸収で、そのガス特有の波長の赤外線は、ガス濃度に応じた割合で減衰します。このガスの吸収波長と吸収の影響を受けない参照波長でのセンサーからの信号を比較することにより、ppmレベルでの高精度な分析・検知ができるといいます。
 NDIR方式のCO2センサーは様々なものが市販されていますが、安価な中国製のMH-Z19をトライしてみましたが、値の信頼性がいまいちでした。あらたに農業分野でよく使われている、スウェーデン製のK30 CO2 Sensorを入手しリニューアルしました。


 計測してみると、一日の変化が大きく、日中に低下し、夜間に増加するのがみられます。木々の炭酸同化作用によるものと思われます。
 (2019/08/01公開) 


以前のMH-Z19版はこちら


K30 CO2 センサー
 K30 CO2 センサーは、スウェーデンのSenseair ABという会社の製品で、国内代理店があり、amazon.co.jpやmonotaro.comのサイトから、1万5000円くらいで入手できます。

型番 :CO2 Engine K30
販売サイト:amazon.co.jp  monotaro.com
メーカ: Senseair AB  
ホームページ(日本語)
製品仕様書(日本語)
Modbus on CO2 Engine Document TDE2336

項目 CO2 Engine K30
CO2測定 非分散型赤外線吸収法(NDIR方式)
測定範囲 0〜5000ppm
応答時間(T1/e) 20秒、拡散時間
測定サイクル 2秒ごと
ウォームアップ時間 <1分
出力インターフェース    2アナログ出力、2デジタル出力、UART(Modbusプロトコル)、I2C
精度 ±30 ppm(5000ppm以下の場合)
動作範囲 0〜+50℃ 湿度 0〜95%、結露なきこと
センサーの平均寿命 15年以上
メンテナンス間隔 センスエアABCアルゴリズム(Automatic Baseline Calibration)を使用することでメンテナンスフリー
自己診断 起動時の完全機能チェック
寸法 51×57×14 mm(長さ×幅×おおよその高さ)
電源入力 5.5〜14 VDC(逆接に対して非保護)
消費電流 平均40mA  IRランプ点灯時150mA  初期IRランプ点灯時300mA


K30 CO2 センサー
接続図

赤丸のUARTを使う



RaspberryPiとの接続
K30 CO2 センサーは、アナログ、デジタル出力のほか、UART、I2Cインターフェースをもっています。拡張性のためにI2Cをトライしてみましたが、うまくいかず、MH-Z19の場合と同じく、UARTでRaspberryPiのGPIOにつなぎます。
また、電源は、RaspberryPiの5VをK30 CO2 センサーにつなぐ例が多いですが、規格表にあるとおり、かなりの間欠的な大きな電流がながれ、動作が不安定になりましたので、独立の12Vから供給することとしました。手元に古い小型パソコンから取り出した電源があり、5Vと12Vが出力でしたので、それを用いることとしました。(9Vを推奨しています。)下の図のように結線します。


 
秋月電子のRaspberryPi用ユニバーサル基板にK30 CO2 センサーをのせ、ピンヘッダで接続
このほかに固定はネジ1か所
黒いピンは電源とFANの端子
これをRaspberryPiのGPIOコネクタに差し込む

上の写真の裏側の結線
ケースはタカチのTW13-5-13を加工
空気が左の穴から
入り、蓋につけたFANで排気する
花粉症用のマスクを適当にカットしフィルターとしている。
  上側が、K30 CO2 センサーをしょったRaspberryPi(旧型のモデルB)
時々CO2 センサーの内部でLEDが発光するのが見える

下側の基板が古いパソコン再利用の電源回路

蓋に12V 50mm角DCファン(5Vで駆動)をつけ、冷却をかね空気の流れをつくる
屋外の雨が直接かからないところに設置
ケーブルは、LANとAC100V


UARTの準備
RaspberryPiでシリアル通信UARTを使う準備をします。


OSは最新の Raspbian Busterの場合

ステップ1  /boot/cmdline.txtを次のように編集
$ sudo nano /boot/cmdline.txt

dwc_otg.lpm_enable=0 console=tty1 root=PARTUUID=399cd9a8-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

のように編集。すなわちconsole=serial0,115200という部分を外します。

ステップ2  config.txtを次のように編集
$ sudo nano /boot/config.txt
config.txtの最後に
enable_uart=1
を追加

ステップ3 リブートして/devディレクトリのなかに、ttyAMA0 があるのを確認します。このデバイス名は、後ほどプログラムに必要です。

ステップ4 つぎにPythonからUARTを使えるようにするために、シリアルポート操作ライブラリpython-serialをインストール
$ sudo apt-get install python-serial



Raspberry PiのCO2センサソフトの作成

 

Raspberry Piで動かす、CO2センサーのよみとりプログラムをPythonで作ります。

K30 CO2 センサーは電源が入っているといつでも計測しており、レジスタに入っている最新の計測値を外部から読みに行きます。

K30 CO2 センサーには、センスエアABCアルゴリズムという自己校正機能があります。これは予め設定された時間インターバル(デフォルトは180時間)中のCO2センサの最小測定値を常に内部記録し、長期ドリフトを緩やかに補正する機能です。屋内アプリケーションを想定しており、デフォルトではこの機能はオンになっています。当方のように長期間同じ条件で計測したい場合は、オフとすべきと考えます。
サンプルプログラムががこちらにありますが、センスエアABCアルゴリズムを無効にすることを含め、 Modbusプロトコル仕様 Document TDE2336 にしたがって、あらたに作りました。


CO2sensor.py をコメント番号にしたがって説明します。


(1)  UARTを読めるようにserialをinclude

(2)  /dev/ttyAMA0 にUARTの設定
Baud rate = 9600
timeout=0.5

(3)  ABCアルゴリズムを無効にする

Document TDE2336 によると、ABCアルゴリズムの周期をゼロにすることにより無効にできます。そのためセンサーに次の8バイトを送ります。

<>はhexadecimal

<FE> <06> <00> <1F> <00> <00> <AC> <03>

ここで<FE> :Any address <06> :Write Single Register <00> <1F> :レジスタ・アドレス<00> <1F>にゼロ<00> <00>を書き込む <AC> <03>:CRCコード


(4) データの読み取りコマンド

データの読み取りの前にセンサーに次のコマンドを送ります。

<FE> <04> <00> <03> <00> <01> <D5> <C5>

ここで<FE> :Any address  <04>: Read input registers  <00> <03>:レジスタ・アドレス  <00> <01>:Quantity of registers <D5> <C5>:CRCコード

(5) 8バイトのreturn valueを読んでresultに代入
3バイト目と4バイト目にCO2濃度(ppm)が入る。CRCコードはドントケア


(6) 出力データは時刻、濃度

(7) ファイル出力
CO2data.txtというCSV形式のファイルができる。たとえば
2019/07/23 14:51:19,437

(8) 1分に一度よみとる

 CO2センサーのよみとりプログラム  CO2sensor.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-


# 2019/08/04 (C)Dr.H.Ishikawa

import serial  #(1)
import time
import datetime
   
s = None
def setup():
	global s
	s = serial.Serial('/dev/ttyAMA0',baudrate=9600,timeout=0.5) #(2)
	s.flushInput()	
	try:
		s.write("\xFE\x06\x00\x1F\x00\x00\xAC\x03") # (3) Disabele ABC function 
		time.sleep(0.5)
		result = s.read(8)
		ABC_PERIOD = ord(result[4])*256 + ord(result[5])
		print ("ABC_PERIOD = " + str(ABC_PERIOD) )
	except Exception as e:
		 print(e)
def readdata():
	try:
		s.flushInput()
		now = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
		s.write("\xFE\x04\x00\x03\x00\x01\xD5\xC5") #(4) Document TDE2336 
		time.sleep(0.5)
		result = s.read(8) #(5)
		data = now + "," + str(ord(result[3])*256 + ord(result[4])) + "\n" #(6)
		filename = 'CO2data/' + datetime.datetime.now().strftime("%Y%m") + 'CO2data.txt'
		file_data = open(filename , "a" )
		file_data.write(data) #(7)
		print (data)
		file_data.close()	
	except Exception as e:
		 print(e)
   
if __name__ == '__main__':
	setup()
	while True:
		readdata()
		time.sleep(59.5) #(8)

 

起動は
$ sudo python ./CO2sensor.py とします。
ファイル 201908CO2data.txtを、親機のパソコンからよんで、適宜グラフ化します。

10分ごとに移動平均した結果をこちらに示します。
長期間のドリフト性能については、これから評価します。

top