ESP8266 割り込みパルスカウント (ガイガーカウンターの心臓部)
先日は、割り込みを使ってLチカ やってみました。
そのときに軽く触れましたが、Lチカしてる部分でカウンターを仕込めば、そのまんまガイガーカウンターになります。
連載3回目でいきなりですが、ガイガーカウンター(モニタリングポスト)の心臓部に仕立てちゃいます。
#include "Ticker.h" Ticker ticker; Ticker led; const unsigned char pinSignal = 0; const unsigned char pinLED = 15; const unsigned short l_sma = 60 * 60; // moving average(1hour) const unsigned short m_sma = 60 * 20; // moving average(20minutes) const unsigned short s_sma = 60 * 5; // moving average(5minute) volatile unsigned char cps[l_sma]; // max 255cps volatile unsigned short idx_cps = 0; volatile unsigned long countup = 0; volatile unsigned long total_count = 0; void setup() { // put your setup code here, to run once: // for debug Serial.begin(115200); Serial.print("uptime"); Serial.print(","); Serial.print("total_count"); Serial.print(","); Serial.print("s_cpm"); Serial.print(","); Serial.print("m_cpm"); Serial.print(","); Serial.println("l_cpm"); for(int i=0; i<l_sma; i++) cps[i] = 0; pinMode(pinSignal, INPUT); pinMode(pinLED, OUTPUT); attachInterrupt(pinSignal, signal, FALLING); ticker.attach(1, tick); // every 1 second } void loop() { // put your main code here, to run repeatedly: } void signal() { cps[idx_cps] ++; total_count ++; digitalWrite(pinLED, HIGH); led.attach(0.0001f, ledoff); } void ledoff() { led.detach(); digitalWrite(pinLED, LOW); } void tick() { float l_cpm = 0.0f; float m_cpm = 0.0f; float s_cpm = 0.0f; idx_cps ++; if(idx_cps == l_sma) { idx_cps = 0; countup ++; } if(countup) l_cpm = cps[idx_cps]; cps[idx_cps] = 0; // calc cpm int cnt = 0; int idx = idx_cps; while(cnt < (!countup ? idx_cps : (l_sma - 1))) { idx --; if(idx < 0) idx = l_sma - 1; l_cpm += cps[idx]; if(cnt < m_sma) m_cpm += cps[idx]; if(cnt < s_sma) s_cpm += cps[idx]; cnt ++; } l_cpm *= (60.0f / (!countup ? idx_cps : l_sma)); m_cpm *= (60.0f / (!countup && idx_cps < m_sma ? idx_cps : m_sma)); s_cpm *= (60.0f / (!countup && idx_cps < s_sma ? idx_cps : s_sma)); // for debug Serial.print(countup * l_sma + idx_cps); Serial.print(","); Serial.print(total_count); Serial.print(","); Serial.print(s_cpm); Serial.print(","); Serial.print(m_cpm); Serial.print(","); Serial.println(l_cpm); }
サンプルと言ったって半端なものではなく、3種類の移動平均処理を同時に計算しています。
あとは使用する管の特性に応じた cpm→μSV/h の変換式を追加してやれば、ただちにガイガーカウンターになります。
(慣れてくると cpm のままでも不自由しなくなりますが)
詳しくはソースを読んでもらうとして、Tick() の中の //calc cpm 以降がキモですな。
3600秒分の配列化された cps[] から平均化時間ごとに抜き出しているだけですけど。
上はタクトスイッチのボタンを数えていますが、汎用ガイガー検波ユニット みたいなのを繋いでカウントしたらいいですね。
あとは、I2C液晶を繋いで測定値を表示させるもよし、TCPやUDPで測定値をサーバーに送信させるもよし、と。
なにも考えず 3600秒分(3.6KB) な配列を定義して使っちゃってますが、ESP8266 は RAM が 96KB くらいあるそうで、ぶっちゃけ、mbed より多いんですわ、これ。
Arduino 使うと、その関係で幾分メモリー食うと思いますが、Arduino じゃなくて Native GCC でプログラム書けば、理論的には mbed より複雑なことが出来そうです。
(追記)2016/01/31
ハードウェア部を含めて ESP8266 ガイガーカウンターの製作 という記事を続きに書きました。
複数管にも対応しています。(その関係でソフトも若干かわってます)