Last active
August 29, 2015 14:19
-
-
Save tasasaki-github/6962af54c3aef6183a56 to your computer and use it in GitHub Desktop.
Arduino yunでpocket geigerの測定データをxivelyとM2Xに上げるスケッチ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////// | |
// Radiation-Watch.org | |
// URL http://www.radiation-watch.org/ | |
////////////////////////////////////////////////// | |
// put a shell script which is attached at the end of this sketch | |
// on yun's /root/ directory as m2x_up.sh. | |
/// デジタルIOのピンの設定 /// | |
int signPin = 4; //信号(黄) | |
int noisePin = 5; //ノイズ(白) | |
//VCC(赤) | |
//GND(青) | |
//////////////////////////////// | |
/// 改変メモ /////////////////////////////////////////////////// | |
// ヒストリサイズを定義するHISTSIZEを導入。 | |
// 改変前の200だとメモリ不足でXivelyへのアップロードに失敗。150ならOK。 | |
// データ出力を少数以下5位まで拡張。改変前は3。 | |
// xivelyへのアップロード機能を追加 | |
// yunの/root/ディレクトリにM2Xアップロード用のシェルスクリプトm2x_up.shが必要 | |
///////////////////////////////////////////////////////////////// | |
// include all Libraries needed: | |
#include <Process.h> //Process lib use to call Linux Commands in Yun Shield | |
#include <Console.h> //Console lib, used to show debug info in Arduino IDE | |
#define APIKEY "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" | |
#define FEEDID "000000000" | |
#define HISTSIZE 150 | |
// set up net client info: | |
const unsigned long postingInterval = 60000; //delay between updates to xively.com | |
unsigned long lastRequest = 0; // when you last made a request | |
//String dataString = ""; | |
const double alpha=53.032; // cpm = uSv × alpha | |
int index=0; //ループを回った回数 | |
char msg[256]=""; //シリアルで出力する文字列用 | |
int signCount=0; //信号のカウント回数 | |
int noiseCount=0; //ノイズのカウント回数 | |
int sON=0;//信号検出時のロックフラグ | |
int nON=0;//ノイズ検出時のロックフラグ | |
double cpm = 0; //現在のカウント数 | |
double cpmHistory[HISTSIZE]; //カウント回数の履歴 | |
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); | |
Bridge.begin(); | |
Console.begin(); | |
//while (!Console); // wait for Network Serial to open | |
Console.println("Xively client"); | |
lastRequest = millis(); | |
//信号検出ピンの設定 | |
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<HISTSIZE;i++ ) | |
{ | |
cpmHistory[i]=0; | |
} | |
//ループ開始時間を取得 | |
prevTime = millis(); | |
} | |
void loop() | |
{ | |
long now = millis(); | |
// 信号のローデータ 通常: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 >= HISTSIZE) | |
{ | |
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, 5, cpmBuff); | |
dtostrf(cpm / min / alpha, -1, 5, uSvBuff); | |
dtostrf(sqrt(cpm) / min / alpha, -1, 5, uSvdBuff); | |
}else{ | |
//0割り算のときは、0にする | |
dtostrf(0, -1, 5, cpmBuff); | |
dtostrf(0, -1, 5, uSvBuff); | |
dtostrf(0, -1, 5, uSvdBuff); | |
} | |
//シリアルで送信する文字列の生成 | |
sprintf(msg, "%d,%d.%03d,%d,%s,%s,%s", | |
totalHour, | |
totalSec, | |
cpmTimeMSec, | |
signCount, | |
cpmBuff, | |
uSvBuff, | |
uSvdBuff); | |
//シリアルで送信 | |
//Serial.println(msg); | |
} | |
//次の10000回のループのための変数の初期化 | |
prevTime = currTime; | |
signCount=0; | |
noiseCount=0; | |
index=0; | |
} | |
index++; | |
if (now - lastRequest >= postingInterval) { | |
sendData(); | |
lastRequest = now; | |
} | |
} | |
// this method makes a HTTP connection to the server: | |
void sendData() { | |
// form the string for the API header parameter: | |
String apiString = "X-ApiKey: "; | |
apiString += APIKEY; | |
// form the string for the URL paramete: | |
String url = "https://api.xively.com/v2/feeds/"; | |
url += FEEDID; | |
url += ".csv"; | |
String dataString = ""; | |
dataString = "Radiation,"; | |
dataString += uSvBuff; | |
dataString += "\nRadiation_cpm,"; | |
dataString += cpmBuff; | |
dataString += "\nRadiation_error,"; | |
dataString += uSvdBuff; | |
// Send the HTTP PUT request, form the linux command and use Process Class to send this command to Yun Shield | |
// Is better to declare the Process here, so when the | |
// sendData function finishes the resources are immediately | |
// released. Declaring it global works too, BTW. | |
Console.println("\nSending data to Xively... "); | |
Console.println(dataString); | |
Process p; | |
p.begin("curl"); | |
p.addParameter("-k"); | |
p.addParameter("--request"); | |
p.addParameter("PUT"); | |
p.addParameter("--data"); | |
p.addParameter(dataString); | |
p.addParameter("--header"); | |
p.addParameter(apiString); | |
p.addParameter(url); | |
p.run(); | |
Console.println("done!"); | |
// I gave up uploading to M2X using the same way as xively because of memory limitation of yun. | |
// The uploading functions are moved to m2x_up.sh script. | |
p.begin("/root/m2x_up.sh"); | |
p.addParameter("-r"); | |
p.addParameter(uSvBuff); | |
p.addParameter("-e"); | |
p.addParameter(uSvdBuff); | |
p.run(); | |
} | |
/* m2x_up.sh script | |
// locate this script on yun's /root/ directory. | |
// I assume you have already created two streams in M2X: | |
// 1. radiation | |
// 2. radiation_error | |
// I know "data" variable is too dirty with a lot of back slashes but so what? | |
// | |
#!/bin/sh | |
THISNAME=`basename $0` | |
M2X_DEV_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' | |
M2X_API_KEY='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' | |
M2X_RADIATION='radiation' # radiation stream | |
M2X_RAD_ERROR='radiation_error' # radiation error stream | |
while getopts r:e: OPT | |
do | |
case $OPT in | |
"r" ) FLG_R="TRUE"; RAD_VAL="$OPTARG";; | |
"e" ) FLG_E="TRUE"; RAD_ERR="$OPTARG";; | |
* ) echo "Usage: $THISNAME -r radiation -e radiation_error" | |
exit 1;; | |
esac | |
done | |
now=`date -u -Iseconds | sed -e s/UTC/.000Z/` | |
url="http://api-m2x.att.com/v2/devices/${M2X_DEV_KEY}/updates" | |
key="X-M2X-KEY:${M2X_API_KEY}" | |
type="Content-Type:application/json" | |
data="{\"values\":\ | |
{\"${M2X_RADIATION}\":\ | |
[{\"timestamp\":\"${now}\",\"value\":\"${RAD_VAL}\"}],\ | |
\"${M2X_RAD_ERROR}\":\ | |
[{\"timestamp\":\"${now}\",\"value\":\"${RAD_ERR}\"}]}}" | |
curl -i -X POST -H $key -H $type -d $data $url | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Fixed index variable re-initialization.