Seeeduino XIAOによるCO2モニター(3) Arduinoスケッチ検討編

2020年5月9日土曜日

CO2モニター Seeeduino XIAO

t f B! P L

プログラムの基本機能

フロントエンド側を別途用意するので、Seeeduino XIAO側のArduinoプログラムは非常にシンプルな構成になります。
  • 1秒毎にCO2濃度、温度、湿度データをシリアル経由でテキストデータとして送信。
  • CO2濃度の計算は、EXSEN社のライブラリをそのまま使用する。
  • CO2センサーの個体別のキャリブレーション係数 (float値 x 2) は、シリアル経由の受信コマンドを設けてSeeeduino XIAOのFlash領域に保存

シリアル出力形式

上記を踏まえシリアル出力フォーマット(テキスト形式)を以下のように定めました。
# C:452 T:27.80 H:52.40

  • C: CO2濃度 (ppm) (432 ~ 6000)
  • T: 温度 (℃) (マイナス値もあり得る)
  • H: 湿度 (%) (0.0 ~ 100.0)

ただし、無効データが得られたときは"xxxx"で送信することにします。
これは、CO2濃度は起動後数分間のセンサーのウォームアップ(ヒーティング動作)中は、センサーから有効なデータが得られないのと、以前ESP32でDHT22のライブラリを使用した際、ごくごく稀にFloat値のNaN (Not a Number)を出力することがあったため、そのための対応策です。
CO2濃度計算のライブラリでは、ppm値以外にもppm値に対して事前に設定した4つの境界値を基準とした5 Stepの判定値も得られるのですが、今回のプログラムではStep判定値は送信しません。(ppm値があれば後でも判定できるため)

CO2センサーの個体別キャリブレーション

CO2センサーRX-9の基板裏には、QRコード値がプリントされたシールが貼付されています。これをQRコードリーダで読み取ると例えば以下のような文字列が出てきます。
15742214167K0544CAB07A

ちなみにQRコードが若干不鮮明な個体もあり、QRコード読み取りアプリによっては読み取りができない場合がありました。アララ株式会社のクルクルというアプリでは安定して読み取れるようです。デンソーウェーブのアルゴリズムを使用しているようでQRコード生みの親の面目躍如といったところでしょうか。

クルクルでの読み取り例

で、最初の4桁を10進整数解釈して0.1倍した値をcal_A (上記読み取り例では384.8)、次の4桁を10進整数解釈して0.01倍した値をcal_B (同様に59.64)として使用します。次の3桁は仕様書にはTemperature compensation factorと記載されていますが、サンプルコードには適用箇所がなく167 (1.67)で固定のようです。残りのKから始まる値はシリアルナンバーです。仕様書では全体で22文字のはずですが、手持ちの個体では21文字になっており、シリアルナンバーが1文字少ない場合もあるようです。

cal_A, cal_Bの値はArduinoスケッチに直書きしてプログラムにロードさせても良いのですが、複数台の運用を考えているので少々煩雑になります。
そこで今回は、このQRコード文字列をPC側からシリアル経由で
calib 15742214167K0544CAB07A
のようにそのままテキスト送信すれば、Seeeduino XIAO側で2つのfloat値係数を抜き出してFlashに保存するようにします。このようにすることでスケッチの書き換えなしに、PC側でQRコード読み取り値をそのままコピペしてシリアル端末で送信すればキャリブレーションできますし、さらに今後のネタとしてカメラ画像取り込みを含めてQRコードスキャン→キャリブレーションのツールをpythonで作成することも考えています。
なお、キャリブレーションをしていな状態ではデフォルトの係数値が適用されますが、この状態でもCO2濃度値が大きく異常な値となるということはなさそうで、それなりに使えそうではあります。実際、RX-9には個別キャリブレーションQRコードが添付されていない見た目は同じで若干安価なSimpleバージョンが存在するのですが、おそらくモノとしては全く同じもので、キャリブレーション値あり/なしで管理を分けているのではないかと思われます。

Flash領域へのキャリブレーション値保存

SAMD21G18のFlashは以下のような仕様となっています。


Flash容量256 KBytes
アドレス0x00000000 ~ 0x0003FFFF(先頭から256 KBytes)
Regionサイズ16 KBytes(Region単位でLockをかけられる)
Pageサイズ64 Bytes(Page単位でErase)
Page数4096(64 Bytes x 4096 = 256 KBytes)

今回、末尾のPageの64Byteをキャリブレーション値の保存領域として使用することにします。

アドレス用途type
0x0003FFC0ブート回数uint32_t
0x0003FFC4キャリブレーション回数uint32_t
0x0003FFC8cal_A値float
0x0003FFCCcal_B値float
0x0003FFD0 ~ 0x0003FFFF(reserved)

自己紹介

自分の写真
電子工作&プログラミング、オーディオ・音楽

注目の投稿

Raspberry Pi Pico Wで電波時計を合わせる (JJY標準電波エミュレータ)

Raspberry Pi Pico Wのアプリケーションとして 最少の周辺部品で電波時計むけJJYエミュレータ(時刻合わせ用)を製作しました。 ※2023年6月6日: ソースコード修正の内容を反映させました。 時刻合わせ風景 概要 電波時計は電波が届くところで使...

QooQ