Skip to content

Instantly share code, notes, and snippets.

@izumogeiger
Created August 12, 2016 14:31
Show Gist options
  • Save izumogeiger/8c120c177ea1a56030c99c0c38d3fc0a to your computer and use it in GitHub Desktop.
Save izumogeiger/8c120c177ea1a56030c99c0c38d3fc0a to your computer and use it in GitHub Desktop.
#include <TM1638.h>
// data,clk,stb
TM1638 tm1638(7, 8, 9);
/// デジタルIOのピンの設定 ///
int signPin = 2; //信号(黄)
int noisePin = 5; //ノイズ(白)
const double alpha=53.032; // cpm = uSv × alpha
unsigned int icount = 0;
int index=0; //ループを回った回数
char msg[256]=""; //シリアルで出力する文字列用
int signCount=0; //信号のカウント回数
int noiseCount=0; //ノイズのカウント回数
int sON=0;//信号検出時のロックフラグ
int nON=0;//ノイズ検出時のロックフラグ
double cpm = 0; //現在のカウント数
double cpmHistory[200]; //カウント回数の履歴
int cpmIndex=0;//カウント回数の現在配列の格納位置
int cpmIndexPrev=0;//二重カウントの防止用
//ループの時間間隔の計測用
int prevTime=0;
int currTime=0;
int totalSec=0; //計測開始からのトータルの時間(秒)
int totalHour=0; //計測開始からのトータルの時間(時間)
//cpm計算用の時間
int cpmTimeMSec=0;
int cpmTimeSec=0;
int cpmTimeMin=0;
//シリアルで出力するときの浮動少数を文字列に変換用
char cpmBuff[20];
char uSvBuff[20];
char uSvdBuff[20];
void setup()
{
Serial.begin(9600);
tm1638.setupDisplay(true, 7);
//信号検出ピンの設定
pinMode(signPin,INPUT);
digitalWrite(signPin,HIGH);
//ノイズ検出ピンの設定
pinMode(noisePin,INPUT);
digitalWrite(noisePin,HIGH);
//CSV形式でシリアルで出力するときの列の名前を列挙(_を,に読み替える)
//Serial.println("hour[h]_sec[s]_count_cpm_uSv/h_uSv/hError");
//cpmの履歴を保存する配列の初期化
for(int i=0; i<200;i++ )
{
cpmHistory[i]=0;
}
//ループ開始時間を取得
prevTime = millis();
}
void loop()
{
unsigned long cpm2;
unsigned long cpm3;
// 信号のローデータ 通常:High 検出時:Low
int sign = digitalRead(signPin);
// ノイズのローデータ 通常:Low 検出時:High
int noise = digitalRead(noisePin);
//信号の検出(100us程度 Lowになる)
if(sign==0 && sON==0)
{//信号の検出開始、しばらく続くのでその間はカウントしないようにする
sON = 1;
signCount++;
}
else if(sign==1 && sON==1){
//信号が終了したのでフラグを解除
sON = 0;
}
//ノイズの検出(100us程度 Lowになる)
if(noise==1 && nON==0)
{//ノイズの検出開始、しばらく続くのでその間はカウントしないようにする
nON = 1;
noiseCount++;
}
else if(noise==0 && nON==1){
//ノイズが終了したのでフラグを解除
nON = 0;
}
//10000回ループを回ったら、計測値を計算して、シリアルで出力する
if(index==10000) //Arduino Nano(ATmega328)で160-170ms程度
{
//現在の時刻を取得
currTime = millis();
//ノイズが10000回のループの中でまったく検出されないとき
//ノイズが検出されたときは、処理をしない
if(noiseCount == 0)
{
//6秒ごとにカウント回数の履歴を格納する配列をずらす
if( totalSec % 6 == 0 && cpmIndexPrev != totalSec)
{
cpmIndexPrev = totalSec;
cpmIndex++;
//最後まできたら元に戻す
if(cpmIndex >= 200)
{
cpmIndex = 0;
}
//一周してきたときに次に格納する配列に値が詰まっていれば、
//現在の合計しているカウント(変数cpm)から引いて、無かったことにする
if(cpmHistory[cpmIndex] > 0)
{
cpm -= cpmHistory[cpmIndex];
}
cpmHistory[cpmIndex]=0;
}
//カウント回数の履歴を保存
cpmHistory[cpmIndex] += signCount;
//カウント回数の蓄積
cpm += signCount;
//10000回、データを取得するのにかかった時間を取得
cpmTimeMSec += abs(currTime - prevTime);
//ms→secに変換する(オーバーフロー対策)
if(cpmTimeMSec >= 1000)
{
cpmTimeMSec -= 1000;
//cpmを求めるときに使用する計測時間(最大20分)を加算
if( cpmTimeSec >= 20*60 )
{
cpmTimeSec = 20*60;
}
else{
cpmTimeSec++;
}
//トータルでの計測時間
totalSec++;
//sec→hourに変換する(オーバーフロー対策)
if(totalSec >= 3600)
{
totalSec -= 3600;
totalHour++;
}
}
//現在の計測時間(最大20分)
double min = cpmTimeSec / 60.0;
if(min!=0)
{
//cpm、uSv/h、uSv/hの誤差をそれぞれ計算する
//sprintfに%lfがないので文字列変換
dtostrf(cpm / min, -1, 3, cpmBuff);
dtostrf(cpm / min / alpha, -1, 3, uSvBuff);
dtostrf(sqrt(cpm) / min / alpha, -1, 3, uSvdBuff);
cpm2 = (unsigned long)(cpm/min * 100);
cpm3 = ((unsigned long)(cpm/min)) % 256;
}
else{
//0割り算のときは、0にする
dtostrf(0, -1, 3, cpmBuff);
dtostrf(0, -1, 3, uSvBuff);
dtostrf(0, -1, 3, uSvdBuff);
cpm2 = 0;
cpm3 = 0;
}
//シリアルで送信する文字列の生成
sprintf(msg, "%d,%d.%03d,%d,%s,%s,%s",
totalHour,totalSec,
cpmTimeMSec,
signCount,
cpmBuff,
uSvBuff,
uSvdBuff
);
//シリアルで送信
Serial.println(msg);
if (icount % 10 == 9) {
tm1638.setDisplayToDecNumber(cpm2,1<<2);
tm1638.setLEDs(cpm3);
}
}
//次の10000回のループのための変数の初期化
prevTime = currTime;
signCount=0;
noiseCount=0;
index=0;
icount++;
}
index++;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment