微生物達のシンフォニー。 芳しい味噌の香り。 醸すぞ、醸すぞ。 現在、ぼかし肥料が発酵中。 発酵温度はこちら。 Microorganisms play the symphony. I smelt the smell of the miso. It has fermented, fermented! The shadeing off fertilizer is fermenting, now! You can observe the fermentation temperature here. Fermentation temperature of composts on Pachube |
||
|
2011年5月24日火曜日
Fermentation temperature of composts on Pachube: ぼかし肥料、発酵中。
2011年5月11日水曜日
ぼかし肥料作り-2: Pachubeで発酵熱オンラインモニタリング
|
||
『Pachube (パッチベイ)』はインターネットを介してセンサーなどからの環境データをリアルタイムに共有できるサイトだ。 ユーザ登録すれば誰でも計測した環境データをアップロードできるし、APIを利用することによって 公開アップされている全てのデータに様々なアプリケーションからアクセスが可能である。 トップページのタグクラウドではユーザが公開している様々なデータがどのような種類のものなのかが伺える。 radiation(放射線) elevation(標高) gas connections(ガス接続)? watts(ワット数) humidity(湿度) longitude(経度) Co2(二酸化炭素) … 各タグの遷移先では、そのタグをつけているセンシングデータの配置を表示した地図が観れる。 試しに「radiation」をクリックしてみると… |
||
|
||
恐ろしい結果が返ってくる。 現在進行中の東京電力第一原子力発電所人災によって飛散した放射線のリアルタイム計測である。 各マーカーをクリックするとセンシングのフィードの画面に遷移し、データグラフが表示される。 フィードには複数のデータストリームが表示され、その場所でどんなデータがリアルタイムに計測されているかがわかる。 ちなみに以下のフィードは、僕がリアルタイムに公開しているぼかし肥料の発酵熱と気温・湿度・露点温度である。 |
||
|
||
今回はArduinoとEthernet Shieldを使い、自作したぼかし肥料の発酵熱をリアルタイムでモニタリングしてみる。 使用する部品は以下。
参考サイト (こちらのサイトでは、Sparkfun Pachube製のガイガーカウンターモジュールSEN-09848を使用してPachubeにアップロードするための詳細な情報あり。 大変参考にさせていただきました。Sketchの一部分使わせていただいております。) 参考リンク先にはArduinoとPachubeを接続するためのたいていの事が書いてあるので、ここでは割愛する。 Pachubeにユーザ登録してフィードとデータストリームを設置した後、回路図とArduino、Ethernet Sheild、Ethernetケーブルをルータにつなげて 以下のスケッチをアップ。 CompostsFermentationTemp2Pachube ▼ /* * sketch name : CompostsFermentationTemp2Pachube * summary : ぼかし肥の発酵温度を4種類のフィードでオンラインモニタリングする */ // init setting ////////////////////////////////// #include <SPI.h> #include <Ethernet.h> #include <EthernetDHCP.h> #include <Sensirion.h> // 設定ファイル読み込み #include "PrivateSettings.h" // Arduino 基準電圧 #define ARDUINO_VCC 5 // Pachube データストリームID unsigned int datastream_ids[] = {0, 1, 2, 3, 4, 5, 6}; // 温度センサ type / 0:LM35DZ 1:LM60BIZ 2:LM61CIZ unsigned int temperature_pins[] = {0, 1, 2, 3}; // アナログピン0,1,2,3 unsigned int temperature_sensor_type[] = {0, 0, 0, 0}; // 使用センサタイプ(temperature_pins の値に対応) float temperature_gain[] = {5, 5, 5, 5}; // Op-amp ゲイン(temperature_pins の値に対応) #define CNT_TEMPERATURE_PINS sizeof(temperature_pins) / sizeof(temperature_pins[0]) float temp_data[CNT_TEMPERATURE_PINS]; // 温度データ格納 // 気温・湿度・露点 type / SHT71 #define SHT_CLOCK_PIN 7 // CLOCK(デジタルピン) #define SHT_DATA_PIN 8 // DATA(デジタルピン) #define CNT_SHT 3 float sht_data[CNT_SHT]; // SHTデータ格納 // センシングデータ総数 #define SENSOR_CNT CNT_TEMPERATURE_PINS + CNT_SHT // api.pachube.com IPアドレス byte server_ip_address[] = { 173, 203, 98, 29 }; // TCP client Client client(server_ip_address, 80); // TCP client Client log_client(log_server_ip_address, 80); // 更新インターバル(minutes) const unsigned int update_interval = 5; // 次にフィードを更新する時刻 unsigned long next_execute_millis = 0; // 更新データ String csv_data = ""; // Pachube float log_data[SENSOR_CNT]; // ログサーバ // SHT-71 Sensirion obj_sht = Sensirion(SHT_DATA_PIN, SHT_CLOCK_PIN); // function ////////////////////////////////// /* * func name : calcTemperature * processing : 温度センサの種類別計算処理 * param : arduino_vcc Arduino基準電圧 * sensor_type 0:LM35DZ / 1:LM60BIZ / 2:LM61CIZ * analog_val Analog値(0-1023) * gain Op-amp ゲイン * return : 計測温度(℃) */ float calcTemperature(float arduino_vcc, int sensor_type, int analog_val, float gain) { float dc_offset; // DCオフセット電圧(V) float factor; // 温度係数(V/1℃) switch (sensor_type) { case 0: // LM35DZ dc_offset = 0; // DC offset;0V factor = 0.01; // +10mV/℃ break; case 1: // LM60BIZ dc_offset = 0.424; // DC offset 424mV factor = 0.00625; // +6.25mV/℃ break; case 2: // LM61CIZ dc_offset = 0.6; // DC offset 600mV factor = 0.01; // +10mV/℃ break; default: return 0; break; } return (((arduino_vcc * analog_val) / 1023) - (dc_offset * gain)) / (factor * gain); } /* * func name : appendFloatValueAsString * processing : Float型の値をString型に整形 * param : outString 文字列格納 * value 値格納 * return : 整形後の文字列 */ void appendFloatValueAsString(String& outString, float value) { int integerPortion = (int)value; int fractionalPortion = (value - integerPortion + 0.0005) * 1000; outString += integerPortion; outString += "."; if (fractionalPortion < 10) { // e.g. 9 > "00" + "9" = "009" outString += "00"; } else if (fractionalPortion < 100) { // e.g. 99 > "0" + "99" = "099" outString += "0"; } outString += fractionalPortion; } /* * func name : updateDataStream2Pachube * processing : Pachubeに値をアップデート * param : environment_id 環境ID * api_key APIキー * value 更新値文字列(CSV形式) * return : なし */ void updateDataStream2Pachube(int environment_id, char *api_key, String value) { Serial.println(environment_id); Serial.println(api_key); Serial.println(value); Serial.println(value.length()); // Try to connect to the server Serial.println(); Serial.print("Connecting to Pachube..."); if (client.connect()) { Serial.println("connected"); } else { Serial.println("failed"); return; } // サーバにアクセスして指定したデータストリームを更新 client.print("PUT /v2/feeds/"); client.print(environment_id); client.println(" HTTP/1.1"); client.println("User-Agent: Arduino"); client.println("Host: api.pachube.com"); client.print("X-PachubeApiKey: "); client.println(api_key); client.print("Content-Length: "); client.println(value.length()); client.println("Content-Type: text/csv"); client.println(); client.println(value); } /* * func name : updateDataLog * processing : ログサーバにデータをアップロード * param : value 更新値配列 * cnt 更新値総数 * return : なし */ void updateDataLog(float *value, unsigned int cnt) { // Try to connect to the server Serial.println(); Serial.print("Connecting to Log Server..."); if (log_client.connect()) { Serial.println("connected"); } else { Serial.println("failed"); return; } // 指定のwebサーバのPHPスクリプトにGET送信 log_client.write("GET "); log_client.write(LOG_DIR); for (int i = 0; i < cnt; i++) { Serial.print("val"); Serial.print(i); Serial.print(":"); Serial.println(value[i]); if (i==0) { log_client.write("?"); } else { log_client.write("&"); } log_client.write("val"); log_client.print(i, DEC); log_client.write("="); log_client.print(value[i], DEC); } log_client.write(" HTTP/1.1"); // log_client.write("HOST: "); // log_client.write(LOG_DOMAIN); // log_client.write("\n\n"); } // setup ////////////////////////////////// void setup() { Serial.begin(9600); // DHCPセッション開始 EthernetDHCP.begin(mac_address); } // loop ////////////////////////////////// void loop() { // DHCPによるIPアドレスのリースを維持 EthernetDHCP.maintain(); // 発酵温度(CSV形式で送信値を整形) csv_data = ""; for (int i = 0; i < CNT_TEMPERATURE_PINS; i++) { // Pachube temp_data[i] = calcTemperature(ARDUINO_VCC, temperature_sensor_type[i], analogRead(temperature_pins[i]), temperature_gain[i]); csv_data += datastream_ids[i]; csv_data += ","; appendFloatValueAsString(csv_data, temp_data[i]); csv_data += "\n"; // ログサーバ log_data[i] = temp_data[i]; } // 気温 & 湿度 & 露点 obj_sht.measure(&sht_data[0], &sht_data[1], &sht_data[2]); int j = 0; for (int k = CNT_TEMPERATURE_PINS; k < SENSOR_CNT; k++) { // Pachube csv_data += datastream_ids[k]; csv_data += ","; appendFloatValueAsString(csv_data, sht_data[j]); csv_data += "\n"; // ログサーバ log_data[k] = sht_data[j]; j++; } /* Pachube */ // ホストからの応答を表示 if (client.available()) { char c = client.read(); Serial.print(c); } if (client.connected()) { Serial.println("Disconnecting."); client.stop(); } Serial.println(); Serial.println("Updating..."); // Pachubeにアップ updateDataStream2Pachube(environment_id, API_KEY, csv_data); /* ログサーバ */ // ホストからの応答を表示 if (log_client.available()) { char c = client.read(); Serial.print(c); } if (log_client.connected()) { Serial.println("Log Client Disconnecting."); log_client.stop(); } Serial.println(); Serial.println("Log Updating..."); // 別サーバにログを記録 updateDataLog(log_data, SENSOR_CNT); delay((update_interval * 60) * 1000UL); } /* * sketch name : CompostsFermentationTemp2Pachube(PrivateSetting.h) * summary : ぼかし肥の発酵温度を4種類のフィードでオンラインモニタリングする */ /* Pachube */ const int environment_id = 24902; // APIキー #define API_KEY "○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○" // MACアドレス byte mac_address[] = { ○○○○, ○○○○, ○○○○, ○○○○, ○○○○, ○○○○ }; /* ログサーバ */ // IPアドレス byte log_server_ip_address[] = { ○○○, ○○○, ○○○, ○○○ }; // ホスト名 #define LOG_DOMAIN "○○○○○○○○○○○○" // 保存処理ファイルパス #define LOG_DIR "○○○○○○○○○○○○○○○○" |
||
|
||
リアルタイムのデータはこちらから。 Pachubeのサーバとは別のサーバにログを溜める予定だったけど、なぜかこれはうまくいっていない。 サーバにあるログ処理スクリプトを直接叩くと思ったとおりにログファイルが生成されるので、SketchからPHPが叩けてないっぽい。 原因調査中。 |
2011年5月10日火曜日
ぼかし肥料作り-1: Pachubeで発酵熱オンラインモニタリング
- Fermentation temperature of 'Slow working fertilizer' on Pachube -
ぼかし肥料とは、有機肥料を微生物によって発酵させて作る堆肥である。 発酵していない肥料を土に混ぜ込んだ時、量の加減にもよるが葉が萎れてしまったり黄色くなってしまう場合がある。 あれは肥料焼けといって、急激に過多な栄養分を与えることによって起こる。 多くの市販の肥料は発酵という過程を特別に踏んでいるわけではないので、肥料の効きは早いけれど効果は長続きしない(その都度買わなくてはならない)。 短い期間の中で急激な栄養分を与えるわけだから見た目の効果はあるが、与える量に気をつけないと逆効果になる場合がある。 人間で言うと塩分を摂り過ぎて口内炎ができるようなもの?だと思う。 ぼかし肥料は一定期間発酵させることによって上質な有効菌の塊となり、肥効が長続きする。 穏やかに効き目があることから「ぼかし」肥料というらしい。 The 'Slow working fertilizer' is compost that ferments an organic fertilizer by the microorganism and makes it. When you mix the fertilizer that has not fermented with the soil, though it depends on the mixed amount, the leaf might wilt and it become yellow. This phenomenon is said the fertilizer scorch, and happens because they give the plant a rapidly excessive nutrient. It doesn't last long the effect though working of the fertilizer of them is early, because a fertilizer a lot on the market doesn't spend long time in fermentation. I should buy it many times by just that much. Because a rapid nutrient is given in the short span of time, externals are effective. But, if we do not take care them about the amount in which the fertilizer is given, we occasionally keep not good. It thinks like being able to do the stomatitis by taking salinity too much when comparing it with man it. We can change it into the mass of a high quality bacterium by fermenting the fertilizer at long time. It is 'Slow working fertilizer'. The 'Slow working fertilizer' continues slowly the effect, and continues for a long time. The Japanese name is 'BOKASHI-HI' ('BOKASHI' means 'slowly' in Japanes). |
||
|
||
使っていないプランターが二つあったので、この中にぼかし肥料を仕込むことにした。 材料と配合比(容量比)は以下。 I decided to train the fertilizer to two planters who had not been using it. Material and compounding ratio rate is...
EM菌とは Effective Micro-organisms の略、つまり有用微生物の群体である。 材料にはもともと付着している微生物がいるが、EM菌を混ぜることによってさらに発酵の質が上がるという。 なお、僕の畑の管理者でぼかし肥料を作っておられる方に聞いたところ、EM菌はどうも嫌気性であるとのこと。 つまり、なるべく密閉させた容器の中で発酵させた方がよいのだという。 The EM Bacterium is abbreviation of Effective Micro-organisms. Though the microorganism originally adheres to the material, it is said that the quality of fermentation will go up further by mixing the effective microorganism. According to the heard story, the effective microorganism seems to be anaerobic. Therefore, you should ferment it in the container in which it sealed up as much as possible. |
||
|
||
プランターを100円ショップの黒いゴミ袋で覆う。 その中に米ぬか、油かす、魚かす、くん炭を少しづつ混ぜていく。 均一に混ざり合うようにしなければならない。 かつおぶしの香りが立ち込めるが、これは魚かすの匂いだ。 材料を混ぜ終えたら、シロップを溶かしておいたお湯と水道水をまぜ、少しずつ材料に混ぜていく (本当は糖蜜がよいのだけど、手持ちがなかった)。 The planter is covered with the garbage bag with black 100yen store. I mix rice bran and oil meal and fish meal, and charcoal, EM bacterium with the material little by little. It should mix evenly. I smell the smell of the dried bonito. When you finish mixing the material, I mix the hot water and tap water that melts molasses, and I mixes it with it as the material. |
||
|
||
|
||
|
||
発酵の過程で生じる熱によって悪玉菌が減り、その後から有効菌が増え始める。 水分の具合が悪いと腐敗してくされぼかし肥料となり使い物にならなくなるので、温度はなるべく有効菌が繁殖しやすい60℃、水分は60%に保つ。 ぼかし肥料の作り時は真冬がよいのだという。 温かい時期だと水分調整が難しく、虫が沸きやすいからだ。 気温が高いと発酵が進むので、冬よりは完熟までの期間が短くなる。 とりあえず仕込みはこれでOK。 The number of bad bacteria decreases by the heat caused in the process of fermentation, and the number of good bacteria begins to increase afterwards Because the fertilizer rots when the condition of moisture is bad, the temperature is 60℃ to which good bacteria breed easily as much as possible, and moisture is kept 60%. It is said that the midwinter is good at the time of making the fertilizer. It is because the insect boils easily when it is warm time the moisture adjustment is difficult. The period until ripening into full maturity shortens more than winter because fermentation advances when the temperature is high. The training of the fertilizer is OK. 森林地帯を歩いている時、すこし甘酸っぱい匂いがする。 そして、良い土からは、森林地帯を歩いている時のような匂いがする。 それは有効菌の匂いであり、土そのものであるのだ。 ぼかし肥料もうまくいくとそのような匂いがするみたいだ。 When walking in the weald, we smell a sweet smell a little. And, we smell the smell when walking from a good soil in the weald. It is fragrant of an effective bacterium, and it is a soil. When the fertilizer making goes well, we can smell the smell. |
||
|
||
さて、せっかくなので、Arduinoで発酵熱を計測することにした。 どうせならリアルタイムに計測値がみれるように、次回は環境データ共有サイト『 Pachube (パッチベイ)』にデータをアップロードしてみることにする。 I decided to measure the fermentation heat by using Arduino. I want to have the measurement value can seen in real time. I will up-load data to the environmental data common site 'Pachube'. |
2011年3月26日土曜日
定点観測データロガー -9 : 観測用シールド RTC Ver.
RTC8564モジュールを組み込んだ定点観測シールド。 | ||
| ||
| ||
| ||
温度センサLM35DZの値をSHTセンサの温度計測値と同じになるように調整する。 以下のテスト用スケッチを使用。 Sketch: Honeypot2_sensor_test(センサーテスト用) ▼ /*
* sketch name : Honeypot2_sensor_test
* summary : フィールド設置型 省電力定点計測データロガーセンサーテスト
* Sensors : 計測時刻タイムスタンプ & 温度 & 照度 & 気温 & 湿度 & 露点
* releases : 2011/3/27
*/
#include <Wire.h>
#include <Rtc8564AttachInterrupt.h>
#include <Sensirion.h>
#include <DateTime.h>
#include <Sleep.h>
////////////////////////////////////////////////////
// init default vals ///////////////////////////////
////////////////////////////////////////////////////
/* Arduino 基準電圧 */
#define ARDUINO_VCC 3.3
/* RTC定周期タイマ割り込み設定 */
// RTCタイマ開始日付時刻
#define RTC_SEC 0x00 // 秒
#define RTC_MIN 0x05 // 分
#define RTC_HOUR 0x12 // 時
#define RTC_DAY 0x27 // 日
#define RTC_WEEK 0x00 // 曜日(00:日 〜 06:土)
#define RTC_MON 0x03 // 月
#define RTC_YEAR 0x11 // 西暦
#define RTC_INTERRUPT_MODE 0 // 定周期タイマ間隔設定単位 0:秒/1:分
#define RTC_INTERRUPT_TERM 5 // 計測間隔(定周期タイマ間隔)
#define RTC_INTERRUPT_PIN 2 // 外部割り込みピン(Digital 2 pin)
byte date_time[7] = {
RTC_SEC,
RTC_MIN,
RTC_HOUR,
RTC_DAY,
RTC_WEEK,
RTC_MON,
RTC_YEAR,
};
boolean init_flg = false; // 電源リセット確認フラグ
time_t make_time;
unsigned long log_timestamp; // 計測日付時刻
#define TIMESTAMP_JST_DEF_SEC 32400 // 日本標準時(JST)への修正秒数(9時間固定)
/* 計測設定 */
#define SMOOTHING_DELAY_SEC 50 // スムージング計測間隔
#define SMOOTHING_BUFFER_LENGTH 5 // スムージング計測回数
// 温度センサ type / 0:LM35DZ 1:LM60BIZ 2:LM61CIZ
unsigned int temperature_pins[] = {0, 1, 2}; // アナログピン0,1,2
unsigned int temperature_sensor_type[] = {0, 0, 0}; // 使用センサタイプ(temperature_pins の値に対応)
float temperature_gain[] = {3.3, 3.3, 3.3}; // Op-amp ゲイン(temperature_pins の値に対応)
// 照度センサ type / 0:S9648-100
unsigned int illumination_pins[] = {3}; // アナログピン3
// 気温・湿度・露点 type / SHT71
#define SHT_CLOCK_PIN 7 // CLOCK(デジタルピン)
#define SHT_DATA_PIN 8 // DATA(デジタルピン)
// センサ別計数
#define CNT_TEMPERATURE_PINS sizeof(temperature_pins) / sizeof(temperature_pins[0]) // 温度センサ
#define CNT_ILLUMINATION_PINS sizeof(illumination_pins) / sizeof(illumination_pins[0]) // 照度センサ
#define CNT_SHT 3 // SHTセンサ
// 計測値格納用
float temperature_data[CNT_TEMPERATURE_PINS]; // 温度データ格納
unsigned int illumination_data[CNT_ILLUMINATION_PINS]; // 照度データ格納
float sht_data[CNT_SHT]; // SHTデータ格納
/* ライブラリのインスタンス化 */
Sensirion obj_sht = Sensirion(SHT_DATA_PIN, SHT_CLOCK_PIN);
////////////////////////////////////////////////////
// function ////////////////////////////////////////
////////////////////////////////////////////////////
/*
* func name : calcTemperature
* processing : 温度センサの種類別計算処理
* param : arduino_vcc Arduino基準電圧
* sensor_type 0:LM35DZ / 1:LM60BIZ / 2:LM61CIZ
* analog_val Analog値(0-1023)
* gain Op-amp ゲイン
* return : 計測温度(℃)
*/
float calcTemperature(float arduino_vcc, int sensor_type, int analog_val, float gain)
{
float dc_offset; // DCオフセット電圧(V)
float factor; // 温度係数(V/1℃)
switch (sensor_type) {
case 0: // LM35DZ
dc_offset = 0; // DC offset;0V
factor = 0.01; // +10mV/℃
break;
case 1: // LM60BIZ
dc_offset = 0.424; // DC offset 424mV
factor = 0.00625; // +6.25mV/℃
break;
case 2: // LM61CIZ
dc_offset = 0.6; // DC offset 600mV
factor = 0.01; // +10mV/℃
break;
default:
return 0;
break;
}
return (((arduino_vcc * analog_val) / 1023) - (dc_offset * gain)) / (factor * gain);
}
/*
* func name : calcIllumination
* processing : 照度センサS9648-100計算処理
* param : arduino_vcc Arduino基準電圧
* analog_val Analog値(0-1023)
* return : 照度(lx)
*/
unsigned int calcIllumination(float arduino_vcc, unsigned int analog_val)
{
unsigned int illumination_max_lx = arduino_vcc * 1000; // S9648-100使用時の最大計測照度(lx)
return (analog_val * (illumination_max_lx / 1024));
}
/*
* func name : measuerTemperature
* processing : 温度センサ計測
* param : arduino_vcc Arduino基準電圧
* temperature_pins 使用アナログピン
* temperature_sensor_type 使用センサタイプ
* temperature_gain Op-amp ゲイン
* temperature_data 温度データ格納
* cnt_temperature_pins センサのカウント数
* smoothing_delay_sec スムージング計測間隔
* smoothing_buffer_length スムージング計測回数
*/
void measuerTemperature(
float arduino_vcc,
unsigned int *temperature_pins,
unsigned int *temperature_sensor_type,
float *temperature_gain,
float *temperature_data,
unsigned int cnt_temperature_pins,
unsigned int smoothing_delay_sec,
unsigned int smoothing_buffer_length
){
float sum = 0;
for (int i = 0; i < cnt_temperature_pins; i++) {
// Meanフィルタによるスムージング処理:複数回計測の平均値を算出
for (int j = 0; j < smoothing_buffer_length; j++) {
sum += calcTemperature(
arduino_vcc,
temperature_sensor_type[i],
analogRead(temperature_pins[i]),
temperature_gain[i]
);
delay(smoothing_delay_sec);
}
temperature_data[i] = sum / smoothing_buffer_length;
sum = 0;
}
}
/*
* func name : measuerIllumination
* processing : 照度センサ計測
* param : arduino_vcc Arduino基準電圧
* illumination_pins 使用アナログピン
* illumination_data 温度データ格納
* cnt_illumination_pins センサのカウント数
* smoothing_delay_sec スムージング計測間隔
* smoothing_buffer_length スムージング計測回数
* return :
*/
void measuerIllumination(
float arduino_vcc,
unsigned int *illumination_pins,
unsigned int *illumination_data,
unsigned int cnt_illumination_pins,
unsigned int smoothing_delay_sec,
unsigned int smoothing_buffer_length
){
unsigned long sum = 0;
for (int i = 0; i < cnt_illumination_pins; i++) {
// Meanフィルタによるスムージング処理:複数回計測の平均値を算出
for (int j = 0; j < smoothing_buffer_length; j++) {
sum += calcIllumination(arduino_vcc, analogRead(illumination_pins[i]));
delay(smoothing_delay_sec);
}
illumination_data[i] = sum / smoothing_buffer_length;
sum = 0;
}
}
/*
* func name : measuer
* processing : 計測
*/
void measuer(void)
{
// タイムスタンプ作成
Rtc.available();
make_time = DateTime.makeTime(
(int)Rtc.seconds(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.minutes(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.hours(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.days(Rtc8564AttachInterrupt::Decimal),
(((int)Rtc.months(Rtc8564AttachInterrupt::Decimal)) - 1),
(int)(2000 + Rtc.years(Rtc8564AttachInterrupt::Decimal))
);
DateTime.sync(make_time);
log_timestamp = DateTime.now() - TIMESTAMP_JST_DEF_SEC;
// 温度計測
measuerTemperature(
ARDUINO_VCC,
temperature_pins,
temperature_sensor_type,
temperature_gain,
temperature_data,
CNT_TEMPERATURE_PINS,
SMOOTHING_DELAY_SEC,
SMOOTHING_BUFFER_LENGTH
);
// 照度計測
measuerIllumination(
ARDUINO_VCC,
illumination_pins,
illumination_data,
CNT_ILLUMINATION_PINS,
SMOOTHING_DELAY_SEC,
SMOOTHING_BUFFER_LENGTH
);
// 気温 & 湿度 & 露点計測
obj_sht.measure(&sht_data[0], &sht_data[1], &sht_data[2]);
// データ表示
Serial.println();
Serial.println("********************************************");
Serial.print("log_timestamp : ");
Serial.println(log_timestamp);
Serial.print("temperature_data 1 : ");
Serial.println(temperature_data[0]);
Serial.print("temperature_data 2 : ");
Serial.println(temperature_data[1]);
Serial.print("temperature_data 3 : ");
Serial.println(temperature_data[2]);
Serial.print("illumination_data 1 : ");
Serial.println(illumination_data[0]);
Serial.print("sht_data 1 : ");
Serial.println(sht_data[0]);
Serial.print("sht_data 2 : ");
Serial.println(sht_data[1]);
Serial.print("sht_data 3 : ");
Serial.println(sht_data[2]);
Serial.println("********************************************");
Serial.println();
}
////////////////////////////////////////////////////
// setup ///////////////////////////////////////////
////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
// RTC日付時刻初期化
Rtc.initDatetime(date_time);
// RTC設定初期化(日付時刻の継続確認を含む)
Rtc.begin();
// RTC定周期割り込みタイマ継続確認
if (!Rtc.isInterrupt()) {
// 割り込み周期設定
Rtc.syncInterrupt(RTC_INTERRUPT_MODE, RTC_INTERRUPT_TERM);
}
// RTC割り込み設定
pinMode(RTC_INTERRUPT_PIN, INPUT);
digitalWrite(RTC_INTERRUPT_PIN, HIGH);
}
////////////////////////////////////////////////////
// loop ////////////////////////////////////////////
////////////////////////////////////////////////////
void loop() {
// 初期化(電源OFF=>ON)すぐ後は計測しない
if (init_flg) measuer();
// スリープ (パワーダウン+外部割り込みによる復帰)
SleepClass::powerDownAndWakeupExternalEvent(0);
init_flg = true;
}
| ||
| ||
校正後に、以下のスケッチを順番にアップする。 フィールドセット用スケッチを書き込む前に、RTC8564モジュールが前のアップスケッチでの設定を引き継がないように 強制的に日付時刻とタイマー設定をセットするスケッチ。 Sketch: RTC8564DatetimeInit(日付時刻設定用) ▼ /*
* sketch name : RTC8564DatetimeInit
* summary : RTC初期化
* releases : 2011/3/27
*/
#include <Wire.h>
#include <Rtc8564AttachInterrupt.h>
/* RTCタイマ開始日付時刻 */
#define RTC_SEC 0x00 // 秒
#define RTC_MIN 0x05 // 分
#define RTC_HOUR 0x12 // 時
#define RTC_DAY 0x27 // 日
#define RTC_WEEK 0x00 // 曜日(00:日 〜 06:土)
#define RTC_MON 0x03 // 月
#define RTC_YEAR 0x11 // 西暦
byte date_time[7] = {
RTC_SEC
,RTC_MIN
,RTC_HOUR
,RTC_DAY
,RTC_WEEK
,RTC_MON
,RTC_YEAR
};
/* 定周期タイマ間隔設定単位 0:秒/1:分 */
#define RTC_INTERRUPT_MODE 1
/* 計測間隔(RTC割り込み間隔) */
#define RTC_INTERRUPT_TERM 5
/* 外部割り込みピン */
#define RTC_INTERRUPT_PIN 2
/* 計測許可フラグ */
volatile int flg = LOW;
void setup() {
Serial.begin(9600);
// 日付時刻初期値プロパティにセット
Rtc.initDatetime(date_time);
// RTC日付時刻継続確認なしの日付時刻初期化
Rtc.beginWithoutIsValid();
// RTC定周期割り込み設定
Rtc.syncInterrupt(RTC_INTERRUPT_MODE, RTC_INTERRUPT_TERM);
// 割り込み設定
pinMode(RTC_INTERRUPT_PIN, INPUT);
digitalWrite(RTC_INTERRUPT_PIN, HIGH);
attachInterrupt(0, printDatetime, FALLING);
}
void loop() {
if (flg) {
ReadRTC();
flg = LOW;
}
}
void printDatetime(void)
{
flg = HIGH;
}
void ReadRTC()
{
Rtc.available();
Serial.print(Rtc.years(), HEX);
Serial.print("/");
Serial.print(Rtc.months(), HEX);
Serial.print("/");
Serial.print(Rtc.days(), HEX);
Serial.print(" ");
Serial.print(Rtc.hours(), HEX);
Serial.print(":");
Serial.print(Rtc.minutes(), HEX);
Serial.print(":");
Serial.print(Rtc.seconds(), HEX);
Serial.print(" ");
Serial.println((int)Rtc.weekdays());
}
フィールド設置用スケッチ。 Sketch: Honeypot2_timestamp_sleep(セット用) ▼ /*
* sketch name : Honeypot2_timestamp_sleep
* summary : フィールド設置型 省電力定点計測データロガー
* Sensors : 計測時刻タイムスタンプ & 温度 & 照度 & 気温 & 湿度 & 露点
* releases : 2011/3/27
*/
#include <Wire.h>
#include <Rtc8564AttachInterrupt.h>
#include <Fat16.h>
#include <Fat16util.h>
#include <Sensirion.h>
#include <DateTime.h>
#include <Sleep.h>
////////////////////////////////////////////////////
// init default vals ///////////////////////////////
////////////////////////////////////////////////////
/* Arduino 基準電圧 */
#define ARDUINO_VCC 3.3
/* RTC定周期タイマ割り込み設定 */
// RTCタイマ開始日付時刻
#define RTC_SEC 0x00 // 秒
#define RTC_MIN 0x05 // 分
#define RTC_HOUR 0x12 // 時
#define RTC_DAY 0x27 // 日
#define RTC_WEEK 0x00 // 曜日(00:日 〜 06:土)
#define RTC_MON 0x03 // 月
#define RTC_YEAR 0x11 // 西暦
#define RTC_INTERRUPT_MODE 1 // 定周期タイマ間隔設定単位 0:秒/1:分
#define RTC_INTERRUPT_TERM 5 // 計測間隔(定周期タイマ間隔)
#define RTC_INTERRUPT_PIN 2 // 外部割り込みピン(Digital 2 pin)
byte date_time[7] = {
RTC_SEC,
RTC_MIN,
RTC_HOUR,
RTC_DAY,
RTC_WEEK,
RTC_MON,
RTC_YEAR,
};
boolean init_flg = false; // 電源リセット確認フラグ
time_t make_time;
unsigned long log_timestamp; // 計測日付時刻
#define TIMESTAMP_JST_DEF_SEC 32400 // 日本標準時(JST)への修正秒数(9時間固定)
/* 計測設定 */
#define SMOOTHING_DELAY_SEC 50 // スムージング計測間隔
#define SMOOTHING_BUFFER_LENGTH 5 // スムージング計測回数
// 温度センサ type / 0:LM35DZ 1:LM60BIZ 2:LM61CIZ
unsigned int temperature_pins[] = {0, 1, 2}; // アナログピン0,1,2
unsigned int temperature_sensor_type[] = {0, 0, 0}; // 使用センサタイプ(temperature_pins の値に対応)
float temperature_gain[] = {3.3, 3.3, 3.3}; // Op-amp ゲイン(temperature_pins の値に対応)
// 照度センサ type / 0:S9648-100
unsigned int illumination_pins[] = {3}; // アナログピン3
// 気温・湿度・露点 type / SHT71
#define SHT_CLOCK_PIN 7 // CLOCK(デジタルピン)
#define SHT_DATA_PIN 8 // DATA(デジタルピン)
// センサ別計数
#define CNT_TEMPERATURE_PINS sizeof(temperature_pins) / sizeof(temperature_pins[0]) // 温度センサ
#define CNT_ILLUMINATION_PINS sizeof(illumination_pins) / sizeof(illumination_pins[0]) // 照度センサ
#define CNT_SHT 3 // SHTセンサ
// 計測値格納用
float temperature_data[CNT_TEMPERATURE_PINS]; // 温度データ格納
unsigned int illumination_data[CNT_ILLUMINATION_PINS]; // 照度データ格納
float sht_data[CNT_SHT]; // SHTデータ格納
// SDカード関連
#define SD_ERROR_OK 0
#define SD_ERROR_CARD_INIT 2
#define SD_ERROR_FAT16_INIT 3
#define SD_ERROR_OPEN 4
#define SD_ERROR_WRITE 5
#define SD_ERROR_CLOSE 6
#define SD_LOG_DELIMITER ',' // 記録時のデータ区切り文字 ','(カンマ)
#define LOG_FILE_NAME "log_data.csv" // 記録ファイル名
unsigned int sd_error_no; // SDエラー番号格納
// エラー文字列
char *sd_error[] = {
"no error.",
" ",
"error about sd card init.",
"error about sd fat16 init.",
"error about sd open.",
"error about sd write.",
"error about sd close.",
};
/* 計測時の確認用点滅LED */
#define CONF_LED_PIN 9
/* ライブラリのインスタンス化 */
SdCard obj_card;
Fat16 obj_file;
Sensirion obj_sht = Sensirion(SHT_DATA_PIN, SHT_CLOCK_PIN);
////////////////////////////////////////////////////
// function ////////////////////////////////////////
////////////////////////////////////////////////////
/*
* func name : calcTemperature
* processing : 温度センサの種類別計算処理
* param : arduino_vcc Arduino基準電圧
* sensor_type 0:LM35DZ / 1:LM60BIZ / 2:LM61CIZ
* analog_val Analog値(0-1023)
* gain Op-amp ゲイン
* return : 計測温度(℃)
*/
float calcTemperature(float arduino_vcc, int sensor_type, int analog_val, float gain)
{
float dc_offset; // DCオフセット電圧(V)
float factor; // 温度係数(V/1℃)
switch (sensor_type) {
case 0: // LM35DZ
dc_offset = 0; // DC offset;0V
factor = 0.01; // +10mV/℃
break;
case 1: // LM60BIZ
dc_offset = 0.424; // DC offset 424mV
factor = 0.00625; // +6.25mV/℃
break;
case 2: // LM61CIZ
dc_offset = 0.6; // DC offset 600mV
factor = 0.01; // +10mV/℃
break;
default:
return 0;
break;
}
return (((arduino_vcc * analog_val) / 1023) - (dc_offset * gain)) / (factor * gain);
}
/*
* func name : calcIllumination
* processing : 照度センサS9648-100計算処理
* param : arduino_vcc Arduino基準電圧
* analog_val Analog値(0-1023)
* return : 照度(lx)
*/
unsigned int calcIllumination(float arduino_vcc, unsigned int analog_val)
{
unsigned int illumination_max_lx = arduino_vcc * 1000; // S9648-100使用時の最大計測照度(lx)
return (analog_val * (illumination_max_lx / 1024));
}
/*
* func name : measuerTemperature
* processing : 温度センサ計測
* param : arduino_vcc Arduino基準電圧
* temperature_pins 使用アナログピン
* temperature_sensor_type 使用センサタイプ
* temperature_gain Op-amp ゲイン
* temperature_data 温度データ格納
* cnt_temperature_pins センサのカウント数
* smoothing_delay_sec スムージング計測間隔
* smoothing_buffer_length スムージング計測回数
*/
void measuerTemperature(
float arduino_vcc,
unsigned int *temperature_pins,
unsigned int *temperature_sensor_type,
float *temperature_gain,
float *temperature_data,
unsigned int cnt_temperature_pins,
unsigned int smoothing_delay_sec,
unsigned int smoothing_buffer_length
){
float sum = 0;
for (int i = 0; i < cnt_temperature_pins; i++) {
// Meanフィルタによるスムージング処理:複数回計測の平均値を算出
for (int j = 0; j < smoothing_buffer_length; j++) {
sum += calcTemperature(
arduino_vcc,
temperature_sensor_type[i],
analogRead(temperature_pins[i]),
temperature_gain[i]
);
delay(smoothing_delay_sec);
}
temperature_data[i] = sum / smoothing_buffer_length;
sum = 0;
}
}
/*
* func name : measuerIllumination
* processing : 照度センサ計測
* param : arduino_vcc Arduino基準電圧
* illumination_pins 使用アナログピン
* illumination_data 温度データ格納
* cnt_illumination_pins センサのカウント数
* smoothing_delay_sec スムージング計測間隔
* smoothing_buffer_length スムージング計測回数
* return :
*/
void measuerIllumination(
float arduino_vcc,
unsigned int *illumination_pins,
unsigned int *illumination_data,
unsigned int cnt_illumination_pins,
unsigned int smoothing_delay_sec,
unsigned int smoothing_buffer_length
){
unsigned long sum = 0;
for (int i = 0; i < cnt_illumination_pins; i++) {
// Meanフィルタによるスムージング処理:複数回計測の平均値を算出
for (int j = 0; j < smoothing_buffer_length; j++) {
sum += calcIllumination(arduino_vcc, analogRead(illumination_pins[i]));
delay(smoothing_delay_sec);
}
illumination_data[i] = sum / smoothing_buffer_length;
sum = 0;
}
}
/*
* func name : dataToSdFileWrite
* processing : SDカード記録
* param : log_timestamp / 日付時刻タイムスタンプ
* temperature_data / 温度データ格納配列
* illumination_data / 照度データ格納配列
* sht_data / SHTデータ格納配列
* cnt_temperature_pins / 温度データ数
* cnt_illumination_pins / 照度データ数
* cnt_sht / SHTデータ数
* return : エラー番号
*/
int dataToSdFileWrite (
unsigned long log_timestamp,
float *temperature_data,
unsigned int *illumination_data,
float *sht_data,
int cnt_temperature_pins,
int cnt_illumination_pins,
int cnt_sht
){
if (!obj_card.init()) return SD_ERROR_CARD_INIT;
if (!Fat16::init(&obj_card)) return SD_ERROR_FAT16_INIT;
// O_CREAT : ファイルが存在しなかったら作成する
// O_APPEND : 書き込み前に、ファイル内のデータの最後尾を探す(追記)
// O_WRITE : 書き込みのためにファイルを開く
if (!obj_file.open(LOG_FILE_NAME, O_CREAT | O_APPEND | O_WRITE)) return SD_ERROR_OPEN;
obj_file.writeError = false;
// 日付時刻タイムスタンプ記録
obj_file.print(log_timestamp);
obj_file.print(SD_LOG_DELIMITER);
// 温度記録
for (int i = 0; i < cnt_temperature_pins; i++) {
obj_file.print(temperature_data[i]);
obj_file.print(SD_LOG_DELIMITER); // 区切り文字
if (obj_file.writeError) return SD_ERROR_WRITE;
}
// 照度記録
for (int j = 0; j < cnt_illumination_pins; j++) {
obj_file.print(illumination_data[j]);
obj_file.print(SD_LOG_DELIMITER); // 区切り文字
if (obj_file.writeError) return SD_ERROR_WRITE;
}
// SHTデータ記録
for (int k = 0; k < cnt_sht; k++) {
obj_file.print(sht_data[k]);
// 最後のデータだったら改行
if (k == (cnt_sht - 1)) {
obj_file.println();
// それ以外は区切り文字
} else {
obj_file.print(SD_LOG_DELIMITER);
}
if (obj_file.writeError) return SD_ERROR_WRITE;
}
if (!obj_file.close()) return SD_ERROR_CLOSE;
return SD_ERROR_OK;
}
/*
* func name : measuer
* processing : 計測
*/
void measuer(void)
{
// 処理確認用LED ON
digitalWrite(CONF_LED_PIN, HIGH);
delay(100);
digitalWrite(CONF_LED_PIN, LOW);
// タイムスタンプ作成
Rtc.available();
make_time = DateTime.makeTime(
(int)Rtc.seconds(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.minutes(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.hours(Rtc8564AttachInterrupt::Decimal),
(int)Rtc.days(Rtc8564AttachInterrupt::Decimal),
(((int)Rtc.months(Rtc8564AttachInterrupt::Decimal)) - 1),
(int)(2000 + Rtc.years(Rtc8564AttachInterrupt::Decimal))
);
DateTime.sync(make_time);
log_timestamp = DateTime.now() - TIMESTAMP_JST_DEF_SEC;
// 温度計測
measuerTemperature(
ARDUINO_VCC,
temperature_pins,
temperature_sensor_type,
temperature_gain,
temperature_data,
CNT_TEMPERATURE_PINS,
SMOOTHING_DELAY_SEC,
SMOOTHING_BUFFER_LENGTH
);
// 照度計測
measuerIllumination(
ARDUINO_VCC,
illumination_pins,
illumination_data,
CNT_ILLUMINATION_PINS,
SMOOTHING_DELAY_SEC,
SMOOTHING_BUFFER_LENGTH
);
// 気温 & 湿度 & 露点計測
obj_sht.measure(&sht_data[0], &sht_data[1], &sht_data[2]);
// SDメディアに記録
sd_error_no = dataToSdFileWrite (
log_timestamp,
temperature_data,
illumination_data,
sht_data,
CNT_TEMPERATURE_PINS,
CNT_ILLUMINATION_PINS,
CNT_SHT
);
// エラー時はエラーNo.分だけ点滅
if (sd_error_no != SD_ERROR_OK) {
for (int i = 1; i <= sd_error_no; i++) {
digitalWrite(CONF_LED_PIN, HIGH);
delay(100);
digitalWrite(CONF_LED_PIN, LOW);
}
}
// 処理確認用LED OFF
digitalWrite(CONF_LED_PIN, HIGH);
delay(100);
digitalWrite(CONF_LED_PIN, LOW);
}
////////////////////////////////////////////////////
// setup ///////////////////////////////////////////
////////////////////////////////////////////////////
void setup() {
// 処理確認LED
pinMode(CONF_LED_PIN, OUTPUT);
// RTC日付時刻初期化
Rtc.initDatetime(date_time);
// RTC設定初期化(日付時刻の継続確認を含む)
Rtc.begin();
// RTC定周期割り込みタイマ継続確認
if (!Rtc.isInterrupt()) {
// 割り込み周期設定
Rtc.syncInterrupt(RTC_INTERRUPT_MODE, RTC_INTERRUPT_TERM);
}
// RTC割り込み設定
pinMode(RTC_INTERRUPT_PIN, INPUT);
digitalWrite(RTC_INTERRUPT_PIN, HIGH);
}
////////////////////////////////////////////////////
// loop ////////////////////////////////////////////
////////////////////////////////////////////////////
void loop() {
// 初期化(電源OFF=>ON)すぐ後は計測しない
if (init_flg) measuer();
// スリープ (パワーダウン+外部割り込みによる復帰)
SleepClass::powerDownAndWakeupExternalEvent(0);
init_flg = true;
}
|
登録:
投稿 (Atom)