前回、前々回では温湿度計の使い方、SDカードへのデータ保存方法を覚えました。
今回はこれらを組み合わせて温度湿度の記録機、温湿度ロガーを作ってみます。
使用ピンは全く同じなので過去記事参考ということで割愛します。
ちなみに、Amazonで現在販売されている温湿度の記録計はスマホとも連携できて液晶も付いていて電池駆動というスタイリッシュさで2000円弱という素晴らしいマシーンです。
対して、自作のロガーは↓
・・・・・。
はい!
では早速プログラムを作ります。
<概要>
・動作
電源を入れた直後から15分置きにデータを取ってSDカードに蓄積させる。
・考察
きっちり15分ごとに計測なら開始時間だけメモしておくと、カード回収してからPCでデータを読みだしたら記録した時間が解るから時刻設定は特にいらない。
15分ごとなので1時間で4回計測、センサーの電源を入れっぱなしだと湿度計の寿命が短いとAmazonレビューにあるのでArduinoのD3ピンから計測時のみ電源を確保する。
delay関数を使って15分待ち時間を作ると、長期記録の場合は計測&記録の時間が徐々に蓄積されて記録時間のズレが大きくなるから、出来るだけ正確になるよう内蔵タイマー割り込みを使って記録させる。
SDカード書き込み中に電源切らないようにインジケータランプを書き込み2秒ぐらい前に点灯させておく。
<参考>
Arduinoでtimerを使った割込み処理の方法 – imo Lab.
Arduinoでタイマー割り込みを初めて使いましたが、割り込みから直接センサーの値を取得することができなかったため、割り込みが発生したらグローバル領域にフラグを立て、loop関数からフラグを見て計測するようにしました。
スコープの違いだと思うのですがArduino初心者なのでわかりません。
プログラム
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <SPI.h>
#include <SD.h>
#include <EEPROM.h>#define DHTPIN 2 // 2番ピンをDHTセンサーとする
#define DHTTYPE DHT11 // センサーはDHT11
DHT_Unified dht( DHTPIN, DHTTYPE );
File myFile;const int dht_pw = 3; //HDTセンサーの電源
const int led_busy = 4; //SDカード記録中インジケータ
int cnt = 0; //電源投入から何回目の記録かカウント用
int tmr_cnt = 0; //タイマー割り込み発生のカウント//今回3秒ごとにタイマー割り込み発生なので、15分=300回割り込みが発生したら計測開始する。
int act_tm = 300; // 15min = 900s 900s / 3s = 300cnt
bool flag = true; //記録開始するためのフラグvoid setup() {
//タイマー1をクリア
TCCR1A = 0;
TCCR1B = 0;
//DHT センサの電源とインジケータ初期化
pinMode( dht_pw , OUTPUT);
pinMode( led_busy , OUTPUT);
digitalWrite( dht_pw , HIGH);//Serial 初期化
Serial.begin( 9600 );//SDカードモジュール初期化
if ( !SD.begin( 10 ) ) {
Serial.println( "SD initialization failed!" );
while ( 1 );
}
//DHT センサー初期化
dht.begin();//SDカードに保存するファイル名、EEPROMに記録させて電源投入ごとにファイル名を分ける。
byte ecnt = EEPROM.read( 0 );
ecnt++;
if( 100 <= ecnt){
ecnt = 0;
}
EEPROM.write( 0,ecnt );
Serial.println("Filename:"); Serial.println( ecnt );
//Timer1の割り込み設定3秒ごとに割り込み発生開始
TCCR1B |= (1 << WGM12) | (1 << CS12) | (1 << CS10); //CTCmode //prescaler to 256
OCR1A = 46875-1; //0~65535 46875=3s
TIMSK1 |= (1 << OCIE1A);
Serial.println("Initialization - Done.");
}//温度の取得
float getTemp(){
sensors_event_t event;
dht.temperature().getEvent(&event);
return event.temperature;
}//湿度の取得
float getHumi(){
sensors_event_t event;
dht.humidity().getEvent(&event);
return event.relative_humidity;
}//DHTセンサーの電源を入れ、安定するまで待って、温度湿度を取得してSDカードに書き込んでセンサーとインジケータの電源を切る
void saveVal(){
digitalWrite( dht_pw , HIGH );
delay( 2000 );float temp = getTemp();
float humi = getHumi();//ファイル名は0埋めが面倒なので100埋め
myFile = SD.open( String( String( byte( 100 + EEPROM.read(0) ) ) + ".txt" ), FILE_WRITE); //100~199.txt
if( myFile ){
cnt++;//記録はcsvでも読み出せるよう[,]区切り
myFile.print( cnt );myFile.print( "," ); myFile.print( temp ); myFile.print( "," ); myFile.print( humi ); myFile.println();
myFile.close();//見るのは自分で見やすいよう区切る
Serial.print( cnt );Serial.print( ":" ); Serial.print( temp ); Serial.print( "/" ); Serial.print( humi ); Serial.println();
Serial.println( "Saved." );
} else {
Serial.println( "Err : saveFile" );
}
digitalWrite( dht_pw , LOW);
digitalWrite( led_busy , LOW );
}//3秒毎に読み出される割り込み関数
ISR ( TIMER1_COMPA_vect ) {
tmr_cnt++;
//Serial.print( "Timer!" ); Serial.println( tmr_cnt );
if( act_tm <= tmr_cnt ){
tmr_cnt = 0;
//saveVal(); //何故かここで読み出すとセンサー値が取得できない
flag = true; //フラグを立てるだけ
digitalWrite( led_busy , HIGH ); //インジケータ点灯
}
}void loop() {
delay( 1000 ); //インターバル。ずっと分岐より省電力?(わからんけど気持ちだけ)//フラグが立ったら計測させる
if( flag ){
flag = false;
saveVal();}
}
記録されたものがこちら↓
きちんと記録はされているようです。
一応動いたので数日間このままで放置してみることにします。
インジケータランプは未搭載(実験で使うのは自分だけなので時間わかればいいや)。
念の為、端子はマスキングしておきます。
やっぱり市販のものはよく出来ていますね^^(今更)
追記
回収してデータをNumbers(Mac版のExcelのようなソフト)でグラフ化しました。
約2日分のデータが綺麗にとれています。
温度と湿度が同軸になっていますが、雨上がりからのデータですのので湿度が少しずつ落ちて日中と夜間で温度変化も見て取れます。面白いですね。
プログラムは.txtではなく.csvで保存するように修正しました。