Skip to content

Instantly share code, notes, and snippets.

@tasasaki-github
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tasasaki-github/6962af54c3aef6183a56 to your computer and use it in GitHub Desktop.
Save tasasaki-github/6962af54c3aef6183a56 to your computer and use it in GitHub Desktop.
Arduino yunでpocket geigerの測定データをxivelyとM2Xに上げるスケッチ
//////////////////////////////////////////////////
// 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
*/
@tasasaki-github
Copy link
Author

Fixed index variable re-initialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment