2016年2月9日火曜日

ダストカウンターPPD42について

先日、ESP-WROOM-02とダストカウンターPPD42 / DSM501を接続しました。

ESP-WROOM-02カスタム基板:ダストカウンター&OLED

受注前に作例を探してみたのですが、Arduinoに接続しているほとんどの作例がP1かP2のどちらか一方の信号しか使っていません。それらのソースを読んでみると、だいたいこんな処理でした:
  • 時計をリセット
  • pulseInでlowの時間を計測し、集計する
  • 時計が30秒経過したら集計結果を計測値とする

pulseInはlowまたはhighの継続時間を簡単に測ることができて便利なのですが、2つ以上の独立事象には対応できません。今回のダストカウンターのように2つのパルスがバラバラに来るものを同時に測定することはできません。まぁ15秒ごとにP1とP2交互に切り替える等で対応は可能ですが、同時でないとなんとなく気持ちわるいですねぇ。

なので私はArduinoと違いESPにはインターバル割り込みがあることを利用して次のような処理を行いました:
  • 100μ秒ごとに割り込みを発生する
  • 割り込みごとにLowだったら回数をカウントする
  • 1秒ごとに結果をテーブルに格納する

これであれば、1秒間に10000回それぞれのポートを見に行って状態を調べることができるので、かりに計測対象がもう少し多いとしても理論上一万分の一の精度が得られます。まぁ原理的に言ってもセンサー自体そこまで高い精度はないのですがw

なお、上で「1秒ごとに結果をテーブルに格納する」と書いてますが、テーブルは60個の要素を用意してます。「秒」を配列の添字にすることによって、ごく単純に「過去60秒間のデータによる移動平均」を求めています。昔からあるリングバッファという技術を単純化したものですが、ダストカウンターのみならず温度や湿度などセンサーへのノイズなどでバラつくデータを扱うときには簡単で良いです。

応用として10秒間の移動平均を取りたい時には table[second()] の替わりに table[second() % 10] と書けばOKです。「%」は割り算の余りを求める演算子なので、秒が0-59に変化しても[ ]の間は0-9までしか変化しないので、結果として過去10秒分をぐるぐるとエンドレスサマーするわけです。nice boat。

また、2秒分集計して1分間なら table[second() / 2] と書きます。正式(?)なリングバッファはいろいろと面倒くさいのですが、時間が相手なら便利に使える方法です。ちなみに、second()のかわりにmillis()やmicros()を使えばミリ秒, マイクロ秒単位での集計も可能です。Arduinoでマイクロ秒はさすがにキツいと思いますが。

以上、最近ハードばっかりいじっているので、ソフトの記事も書いてみました。

しかしソフトの記事だと適当な写真がないな。でもソフトの話だからってgetti imageあたりから外国人幼女がソフトクリームを舐めているフリー写真(鼻の頭にクリームをつけているのはお約束)を貼ったりするのもアレなので、DustCounter基板の写真を貼るw


最初の頃と比べるとリフロー上達したなー、と、誰も言ってくれないので自分で言うw

0 件のコメント:

コメントを投稿