sea side she side

写真と山、資格が好きなアラフォーエンジニアのブログ

簡易ガイガーカウンター(SBM-20) 移動平均

      2011/06/08

Arduino側のスケッチを少し進めます。

ガイガーカウンターで計測できる値はcpm(counts per minute)、1分間あたりの計数率で表示されます。以前簡易動作確認のため、外国のサイトにあったスケッチを拾って動かしたのですが、10秒間の値を6倍させて表示させる物でした。これではあまりにひどいので移動平均を用います。

移動平均は、時系列データ(より一般的には時系列に限らず系列データ)を平滑化する手法である。金融(特にテクニカル分析)分野をはじめ、気象、水象などの計測分野で使われる。有限インパルス応答に対するローパスフィルタ(デジタルフィルタ)の一種であり、分野によっては移動積分とも呼ばれる。

主要なものは、単純移動平均と加重移動平均と指数移動平均の3種類である。普通、移動平均といえば、単純移動平均のことをいう。
wikipediaより引用

なんのこっちゃって方は「ディジタル信号処理の例(移動平均) - HEG」がとてもわかりやすかったです。

イメージとしては、
 ・cpsの値を60個保存できるように配列を60用意
 ・ガイガーカウンターのパルスを拾いカウントアップ
 ・その値を1秒毎にcpsの配列に入れる
 ・61秒目からは1秒目の値を引いて、今のcpsを足すことを繰り返す
 ・60個を足し合わせればcpm
といった具合。

int geiger_input = 2;   // 割り込みpin

int cps_now = 0;        // cpsリアルタイム値
int cps[60] = {0};      // 各秒ごとのcps値
float cpm = 0;          // Counts per Minute
float sv = 0;           // uSv/hr
int all = 0;            // 総カウント
int time = 0;           // 経過時間
int sec = 0;            // 秒


/*----------------------------------------------
 * 関数: setup
 * 概要: 事前処理
 * 引数:
 * 戻値:
 * ---------------------------------------------*/
void setup(void) {
  // シリアルへ出力
  Serial.begin(9600);
  
  // ガイガーカウンターからの入力
  pinMode(geiger_input, INPUT);
  // ガイガーカウンターからの割り込み
  attachInterrupt(0,countPulse,FALLING);
}


/*----------------------------------------------
 * 関数: loop
 * 概要: メイン処理
 * 引数:
 * 戻値:
 * ---------------------------------------------*/
void loop(void) {
  // 1秒待ち
  delay(1000);
  // cpmの計算
  culcCpm();
  time++;
}


/*----------------------------------------------
 * 関数: countPulse
 * 概要: GM係数管パルスで割り込み
 * 引数:
 * 戻値:
 * ---------------------------------------------*/
void countPulse(void) {
  all++;
  cps_now++;
}


/*----------------------------------------------
 * 関数: culcCpm
 * 概要: total、cpm、uSv/hrの計算
 *       delayでの1秒後に処理しているが
 *       後にRTCで割り込みに変更したい
 * 引数:
 * 戻値:
 * ---------------------------------------------*/
void culcCpm(void) {
  sec++;
  if(sec > 60) {
    sec = 0;
  }
  
  // 60秒前のcpsの値を引いて、現在のcpsを足す
  cpm -= cps[sec];
  cps[sec] = cps_now;
  cpm += cps[sec];
  cps_now = 0;
  
  // cpm->sv/uSv簡易計算
  sv  = cpm * 0.00758;
  
  // シリアルへ出力
  outputSerial();
 }


/*----------------------------------------------
 * 関数: outputSerial
 * 概要: シリアル出力
 *       #define DEBUG / #undef DEBUGで
 *       cps配列の展開とグラフ表示をon/off
 * 引数:
 * 戻値:
 * ---------------------------------------------*/
void outputSerial(void) {
  Serial.print("----- ");
  Serial.print(time);
  Serial.println(" -----");
  Serial.print(all);
  Serial.println("times");
  Serial.print(cpm);
  Serial.println("cpm");
  Serial.println("");
}

それっぽく動いているようです。

 - Make , , ,