| ぼかし肥料とは、有機肥料を微生物によって発酵させて作る堆肥である。 発酵していない肥料を土に混ぜ込んだ時、量の加減にもよるが葉が萎れてしまったり黄色くなってしまう場合がある。 あれは肥料焼けといって、急激に過多な栄養分を与えることによって起こる。 多くの市販の肥料は発酵という過程を特別に踏んでいるわけではないので、肥料の効きは早いけれど効果は長続きしない(その都度買わなくてはならない)。 短い期間の中で急激な栄養分を与えるわけだから見た目の効果はあるが、与える量に気をつけないと逆効果になる場合がある。 人間で言うと塩分を摂り過ぎて口内炎ができるようなもの?だと思う。 ぼかし肥料は一定期間発酵させることによって上質な有効菌の塊となり、肥効が長続きする。 穏やかに効き目があることから「ぼかし」肥料というらしい。 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年5月10日火曜日
ぼかし肥料作り-1: Pachubeで発酵熱オンラインモニタリング
- Fermentation temperature of 'Slow working fertilizer' on 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;
}
|
2011年2月6日日曜日
定点観測データロガー -8 : データロガーをフィールドに設置する
|
||
<計測内容>
<回路の修正とケーブルの配置> |
||
|
||
| センサを繋げたケーブルは長さが数mにも及ぶので、当然ノイズ対策が必要になる。 こちらを参考にし、温度センサ回路にパスコン・ダンパーを取り付けた。 |
||
|
||
| センサ周りの回路は接触不良を起こさないようにエキポシ樹脂で固める。 ケーブルはシールド線を使う。 温度センサLM35DZのプラスピン・OUTPUTピンにそれぞれシールド線を一本ずつ、そして GNDピンには上記二本のシールド線のシールドそのものをよじってハンダづけする。 配線はホームセンターで0.1m/15円で売っていた透明のホースに通してArduinoまで繋げる。 ヒーターを買った時に付いていた梱包材をホース口にあわせて切り抜き、 センサの頭だけだしてホースに固定し、エキポシ樹脂で固める。 |
||
|
||
|
||
照度センサとSHTセンサは地表約50cmほどの高さに園芸用のトンネル支柱と麻縄で固定する。 照度センサはなるべく日に当たるほうがよいし、 湿度を計るSHTセンサは構造上水没させてはならない。 100円ショップで売っていたきゅうすの金網茶こしで覆ってから 梱包材を屋根にする形で固定して、やはりエキポシ樹脂で固める。 |
||
|
||
| 水没しないように4重に囲った定点観測データロガーHoneypot。 SDカードスロットが上を向いているのですぐに交換できる。 ON/OFFスイッチ付き電池ボックスもタッパ内に入っている。 蓋を閉めて土をかけてからジョウロで水をかけタッパ内を確認してみたが、水漏れはしていなかった。 |
||
|
||
|
||
| 春に向けて土作り。 土を耕した後に米ぬかと腐植土、牛糞堆肥を入れ、よく混ぜ込んで水分を加える。 土を手でぎゅっと握りしめると固まるが、指で押すとポロリと崩れるくらいが丁度よい。 温度センサを堆肥の山の中に入れ、山にビニールをかぶせる。 後はひと月ほど発酵するのを待つ。 うまくいけば発酵熱は60℃程まで上がり、土の中の病原菌を減らしてくれる。 こちらに書いた通り、その後に有効菌が増えて行くはずだ。 |
||
|
||
|
||
<センシングのテスト> すべてのセッティングが終わった後に、持ってきたラップトップとデータロガーを繋ぎ、 以下のスケッチでセンシングのテスト。 Source code: Honeypot_sensor_test ▼ /* * sketch name : Honeypot_sensor_test * summary : フィールド設置型 省電力定点計測データロガー センシングのみのテスト * Sensors : 温度 & 照度 & 気温 & 湿度 & 露点 * releases : 2010/11/6 */ #include <DateTime.h> #include <Sensirion.h> //////////////////////////////////////////////////// // default values ////////////////////////////////// //////////////////////////////////////////////////// /* Arduino 基準電圧 */ #define ARDUINO_VCC 3.3 /* 時刻関連 */ // 計測タイムスタンプ初期値(初回セッティング時のみ) unsigned int year = 2011; unsigned int month = 2; unsigned int day = 5; unsigned int hour = 16; unsigned int minute = 25; unsigned int second = 0; #define LOGGING_INTERVAL_SEC 2 // 計測間隔(秒) #define TIMESTAMP_JST_DEF_SEC 32400 // 日本標準時(JST)への修正秒数(9時間固定) #define SMOOTHING_DELAY_M_SEC 50 #define SMOOTHING_DELAY_NUM 5 unsigned long log_timestamp; // 計測時刻タイムスタンプ /* 温度センサ type / 0:LM35DZ 1:LM60BIZ 2:LM61CIZ */ unsigned int temp_pins[] = {0, 1, 2}; // アナログピン0,1,2 unsigned int temp_sensor_type[] = {0, 0, 0}; // 使用センサタイプ(temp_pins の値に対応) float temp_gain[] = {3.3, 3.3, 3.3}; // Op-amp ゲイン(temp_pins の値に対応) /* 照度センサ type / 0:S9648-100 */ unsigned int illumi_pins[] = {3}; // アナログピン3 unsigned int illumi_sensor_type[] = {0}; // 使用センサタイプ(illumi_pins の値に対応) #define ILLMI_MAX_LX ARDUINO_VCC * 1000 // S9648-100使用時の最大計測照度(lx) /* 気温・湿度・露点 type / SHT71 */ #define SHT_CLOCK_PIN 7 // CLOCK(デジタルピン) #define SHT_DATA_PIN 8 // DATA(デジタルピン) /* センサのカウント回数 */ #define CNT_TEMP_PINS sizeof(temp_pins) / sizeof(temp_pins[0]) // 温度センサ #define CNT_ILLMI_PINS sizeof(illumi_pins) / sizeof(illumi_pins[0]) // 照度センサ #define CNT_SHT 3 // SHTセンサ(センサ数) /* 計測値格納用 */ float temp_data[CNT_TEMP_PINS]; // 温度データ格納 int illmi_data[CNT_ILLMI_PINS]; // 照度データ格納 float sht_data[CNT_SHT]; // SHTデータ格納 /* ライブラリのインスタンス化 */ Sensirion obj_sht = Sensirion(SHT_DATA_PIN, SHT_CLOCK_PIN); //////////////////////////////////////////////////// // setup /////////////////////////////////////////// //////////////////////////////////////////////////// void setup() { Serial.begin(9600); // タイムスタンプ初期化 DateTime.sync(DateTime.makeTime(second, minute, hour, day, (month - 1), year)); // DateTime初期化 log_timestamp = DateTime.now() - TIMESTAMP_JST_DEF_SEC; // 日本標準時(JST) = グリニッジ標準時(GMT) - 9時間 } //////////////////////////////////////////////////// // loop //////////////////////////////////////////// //////////////////////////////////////////////////// void loop() { log_timestamp += LOGGING_INTERVAL_SEC; // タイムスタンプを外部EEPROMに記録 Serial.println("*******************"); Serial.print("timestamp : "); Serial.print(log_timestamp); Serial.println(); /* 計測処理 */ // 温度 float integrated_temp = 0; for (int i = 0; i < CNT_TEMP_PINS; i++) { // 複数回計測の平均値を算出 for (int j = 0; j < SMOOTHING_DELAY_NUM; j++) { integrated_temp += tempCalc(ARDUINO_VCC, temp_sensor_type[i], analogRead(i), temp_gain[i]); delay(SMOOTHING_DELAY_M_SEC); } temp_data[i] = integrated_temp / SMOOTHING_DELAY_NUM; integrated_temp = 0; Serial.print(" temp"); Serial.print(i); Serial.print(" : "); Serial.println(temp_data[i]); } // 照度 float integrated_illmi = 0; for (int k = 0; k < CNT_ILLMI_PINS; k++) { int l = CNT_TEMP_PINS + k; // 複数回計測の平均値を算出 for (int m = 0; m < SMOOTHING_DELAY_NUM; m++) { integrated_illmi += (analogRead(l) * ILLMI_MAX_LX) / 1024; delay(SMOOTHING_DELAY_M_SEC); } illmi_data[k] = integrated_illmi / SMOOTHING_DELAY_NUM; integrated_illmi = 0; Serial.print(" illmi"); Serial.print(k); Serial.print(" : "); Serial.println(illmi_data[k]); } // 気温 & 湿度 & 露点 obj_sht.measure(&sht_data[0], &sht_data[1], &sht_data[2]); Serial.print(" sht temp: "); Serial.println(sht_data[0]); Serial.print(" sht humidity: "); Serial.println(sht_data[1]); Serial.print(" sht dewpoint: "); Serial.println(sht_data[2]); Serial.println("*******************"); Serial.println(); Serial.println(); delay(LOGGING_INTERVAL_SEC * 1000); // 五分間隔 } //////////////////////////////////////////////////// // function //////////////////////////////////////// //////////////////////////////////////////////////// /* * func name : tempCalc * processing : 温度センサ処理 * param : arduinoVcc / Arduino 基準電圧 * sensor / 0 : LM35DZ * 1 : LM60BIZ * 2 : LM61CIZ * analogVal / Analog値(0-1023) * gain / Op-amp ゲイン * return : temp / 計測温度(℃) */ float tempCalc (float arduinoVcc, int sensor, int analogVal, float gain) { float dc_offset; // DCオフセット電圧(V) float factor; // 温度係数(V/1℃) switch (sensor) { // LM35DZ // DCオフセット 0V // +10mV/℃ case 0: dc_offset = 0; factor = 0.01; break; // LM60BIZ // DCオフセット 424mV // +6.25mV/℃ case 1: dc_offset = 0.424; factor = 0.00625; break; // LM61CIZ // DCオフセット 600mV // +10mV/℃ case 2: dc_offset = 0.6; factor = 0.01; break; define: return 0; break; } return (((arduinoVcc * analogVal) / 1023) - (dc_offset * gain)) / (factor * gain); } 計測は一応出来ている模様。 後は以下のスケッチを順次アップすればよい。 Source code: eeprom_I2C_clear ▼(外部EEPROMのメモリクリア) /* * sketch name : eeprom_I2C_clear * summary : 外部EEPROMのクリア */ #include <Wire.h> #define EEPROM_DEV_ADDRESS 0x50 // I2CEEPROM 24LC64 #define CLEAR_BYTE_LEN 10 // クリアするbyte数 void setup(void) { Wire.begin(EEPROM_DEV_ADDRESS); i2cEepromClear(EEPROM_DEV_ADDRESS, 0, CLEAR_BYTE_LEN); // turn the LED on when we're done digitalWrite(13, HIGH); } void loop() {} /* * func name : i2cEeprom4BWrite * processing : 4byte値をI2C外部EEPROMに書き出す * param : device_address / I2C外部EEPROMのデバイスアドレス * start_memory_address / EEPROM上の書き込み開始アドレス * clear_length / クリアするbyte数 * return : */ void i2cEepromClear(int device_address, unsigned long start_memory_address, long clear_length) { Wire.beginTransmission(device_address); Wire.send((int)(start_memory_address >> 8)); Wire.send((int)(start_memory_address & 0xFF)); for (int i = 0; i < clear_length; i++) { Wire.send(0); } Wire.endTransmission(); } Source code: Honeypot ▼(定点観測データロギング) /* * sketch name : Honeypot * summary : フィールド設置型 省電力定点計測データロガー * Sensors : 温度 & 照度 & 気温 & 湿度 & 露点 * releases : 2010/12/27 */ #include <Wire.h> #include <DateTime.h> #include <Fat16.h> #include <Fat16util.h> #include <Watchdog.h> #include <Sleep.h> #include <Sensirion.h> //////////////////////////////////////////////////// // default values ////////////////////////////////// //////////////////////////////////////////////////// /* Arduino 基準電圧 */ #define ARDUINO_VCC 3.3 /* 時刻関連 */ // 計測タイムスタンプ初期値(初回セッティング時のみ) unsigned int year = 2011; unsigned int month = 2; unsigned int day = 5; unsigned int hour = 16; unsigned int minute = 30; unsigned int second = 0; #define LOGGING_INTERVAL_SEC 300 // 計測間隔(秒) #define RETOUCH_INTERVAL_SEC 3600 // 計測間隔によるタイムスタンプのずれの修正間隔(秒) ※必ず LOGGING_INTERVAL_SEC < RETOUCH_INTERVAL_SEC #define WATCHDOG_TIMER_SLEEP_INTERVAL 1 // スリープ間隔(1秒固定) #define TIMESTAMP_JST_DEF_SEC 32400 // 日本標準時(JST)への修正秒数(9時間固定) #define SMOOTHING_DELAY_M_SEC 50 // スムージング計測間隔 #define SMOOTHING_DELAY_NUM 5 // スムージング計測回数 unsigned long log_timestamp; // 計測時刻タイムスタンプ unsigned long time1; // 計測開始時刻(ms) unsigned long time2; // 計測終了時刻(ms) unsigned long integrated_time; // 計測間隔の集積 unsigned int cnt_interval; // スリープカウント unsigned int cnt_interval_full; // 計測までのスリープカウント数 unsigned long retouch_cnt_interval_full; // タイムスタンプ修正までのカウント(秒) /* 外部EEPROMアドレス */ #define EEPROM_DEV_ADDRESS 0x50 /* 温度センサ type / 0:LM35DZ 1:LM60BIZ 2:LM61CIZ */ unsigned int temp_pins[] = {0, 1, 2}; // アナログピン0,1,2 unsigned int temp_sensor_type[] = {0, 0, 0}; // 使用センサタイプ(temp_pins の値に対応) float temp_gain[] = {3.3, 3.3, 3.3}; // Op-amp ゲイン(temp_pins の値に対応) /* 照度センサ type / 0:S9648-100 */ unsigned int illumi_pins[] = {3}; // アナログピン3 unsigned int illumi_sensor_type[] = {0}; // 使用センサタイプ(illumi_pins の値に対応) #define ILLMI_MAX_LX (ARDUINO_VCC * 1000) // S9648-100使用時の最大計測照度(lx) /* 気温・湿度・露点 type / SHT71 */ #define SHT_CLOCK_PIN 7 // CLOCK(デジタルピン) #define SHT_DATA_PIN 8 // DATA(デジタルピン) /* センサのカウント回数 */ #define CNT_TEMP_PINS sizeof(temp_pins) / sizeof(temp_pins[0]) // 温度センサ #define CNT_ILLMI_PINS sizeof(illumi_pins) / sizeof(illumi_pins[0]) // 照度センサ #define CNT_SHT 3 // SHTセンサ(センサ数) /* 計測値格納用 */ float temp_data[CNT_TEMP_PINS]; // 温度データ格納 int illmi_data[CNT_ILLMI_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 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.", }; #define SD_LOG_DELIMITER ',' // 記録時のデータ区切り文字 ','(カンマ) #define LOG_FILE_NAME "log_data.csv" // 記録ファイル名 /* 計測時の確認用点滅LED */ #define LED_PIN 9 /* ライブラリのインスタンス化 */ Sensirion obj_sht = Sensirion(SHT_DATA_PIN, SHT_CLOCK_PIN); WatchdogClass obj_watchdog = WatchdogClass(); SdCard obj_card; Fat16 obj_file; //////////////////////////////////////////////////// // setup /////////////////////////////////////////// //////////////////////////////////////////////////// void setup() { // デバッグ時のみ //Serial.begin(9600); // 処理確認LED pinMode(LED_PIN, OUTPUT); // 外部EEPROM(I2Cデバイス)に接続 Wire.begin(EEPROM_DEV_ADDRESS); // Watchdogとスリープの設定 obj_watchdog.systemResetEnable(false); // スリープからの自動復帰時にスケッチがリセットされないように設定 obj_watchdog.enable(WatchdogClass::TimeOut1s); // スリープ間隔を1秒間にセット cnt_interval_full = LOGGING_INTERVAL_SEC / WATCHDOG_TIMER_SLEEP_INTERVAL; // 1秒間に設定されたスリープの繰り返し回数 // 変数初期化 time1 = 0; time2 = 0; integrated_time = 0; cnt_interval = 0; retouch_cnt_interval_full = 0; // タイムスタンプ初期化 log_timestamp = i2cEeprom4BRead(EEPROM_DEV_ADDRESS, 0); // 外部EEPROMにタイムスタンプが記録されていたら読み込む if (log_timestamp == 0) { // そうでないならばDatetime設定値(最初のセッティング時のみ) DateTime.sync(DateTime.makeTime(second, minute, hour, day, (month - 1), year)); // DateTime初期化 log_timestamp = DateTime.now() - TIMESTAMP_JST_DEF_SEC; // 日本標準時(JST) = グリニッジ標準時(GMT) - 9時間 } } //////////////////////////////////////////////////// // loop //////////////////////////////////////////// //////////////////////////////////////////////////// void loop() { // スリープ開始から設定間隔で自動復帰 time1 = micros(); // 計測と記録 if ((cnt_interval >= cnt_interval_full)) { /* 処理確認用LED ON */ digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW); /* 時刻関連処理 */ // タイムスタンプ追加 log_timestamp += LOGGING_INTERVAL_SEC; // タイムスタンプを外部EEPROMに記録 i2cEeprom4BWrite(EEPROM_DEV_ADDRESS, 0, log_timestamp); // スリープカウント初期化 cnt_interval = 0; // タイムスタンプ修正までのカウントを加える retouch_cnt_interval_full += LOGGING_INTERVAL_SEC; /* 計測処理 */ // 温度 float integrated_temp = 0; for (int i = 0; i < CNT_TEMP_PINS; i++) { // スムージング処理:複数回計測の平均値を算出 for (int j = 0; j < SMOOTHING_DELAY_NUM; j++) { integrated_temp += tempCalc(ARDUINO_VCC, temp_sensor_type[i], analogRead(i), temp_gain[i]); delay(SMOOTHING_DELAY_M_SEC); } temp_data[i] = integrated_temp / SMOOTHING_DELAY_NUM; integrated_temp = 0; } // 照度 float integrated_illmi = 0; for (int k = 0; k < CNT_ILLMI_PINS; k++) { int l = CNT_TEMP_PINS + k; // スムージング処理:複数回計測の平均値を算出 for (int m = 0; m < SMOOTHING_DELAY_NUM; m++) { integrated_illmi += (analogRead(l) * ILLMI_MAX_LX) / 1024; delay(SMOOTHING_DELAY_M_SEC); } illmi_data[k] = integrated_illmi / SMOOTHING_DELAY_NUM; integrated_illmi = 0; } // 気温 & 湿度 & 露点 obj_sht.measure(&sht_data[0], &sht_data[1], &sht_data[2]); /* SDカードに記録 */ sd_error_no = dataToSdFileWrite (log_timestamp, temp_data, illmi_data, sht_data, CNT_TEMP_PINS, CNT_ILLMI_PINS, CNT_SHT); // エラー時はエラーNo.分だけ点滅 if (sd_error_no != SD_ERROR_OK) { for (int n = 1; n <= sd_error_no; n++) { digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW); } // デバッグ //Serial.print(" error! : "); //Serial.println(sd_error[sd_error_no]); } /* 処理確認用LED OFF */ digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW); // デバッグ /* Serial.println("=========="); Serial.print("timestamp : "); Serial.println(log_timestamp); Serial.print("temp1 : "); Serial.println(temp_data[0]); Serial.print("temp2 : "); Serial.println(temp_data[1]); Serial.print("temp3 : "); Serial.println(temp_data[2]); Serial.print("illmi1 : "); Serial.println(illmi_data[0]); Serial.print("sht temp : "); Serial.println(sht_data[0]); Serial.print("sht humidity : "); Serial.println(sht_data[1]); Serial.print("sht dewpoint: " ); Serial.println(sht_data[2]); Serial.println("=========="); Serial.println(); */ // カウントアップ } else { cnt_interval++; } // 計測間隔による時刻カウントのずれの修正 time2 = micros(); integrated_time += (time2 - time1); if (retouch_cnt_interval_full >= RETOUCH_INTERVAL_SEC) { cnt_interval += (int)(integrated_time / 1000000) / WATCHDOG_TIMER_SLEEP_INTERVAL; retouch_cnt_interval_full = 0; integrated_time = 0; } // デバッグ /* Serial.println("=========="); Serial.print("integrated_time : "); Serial.println(integrated_time); Serial.print("retouch_cnt_interval_full : "); Serial.println(retouch_cnt_interval_full, DEC); Serial.println("=========="); Serial.println(); */ // スリープ開始 WatchdogClass::timerReset(); SleepClass::powerDown(); } //////////////////////////////////////////////////// // function //////////////////////////////////////// //////////////////////////////////////////////////// /* * func name : dataToSdFileWrite * processing : SDカード記録 * param : log_timestamp / タイムスタンプ * temp_data / 温度データ格納配列 * illmi_data / 照度データ格納配列 * sht_data / SHTデータ格納配列 * cnt_temp_pins / 温度データ数 * cnt_illmi_pins / 照度データ数 * cnt_sht / SHTデータ数 * return : エラー番号 */ int dataToSdFileWrite (unsigned long log_timestamp, float *temp_data, int *illmi_data, float *sht_data, int cnt_temp_pins, int cnt_illmi_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_temp_pins; i++) { obj_file.print(temp_data[i]); obj_file.print(SD_LOG_DELIMITER); // 区切り文字 if (obj_file.writeError) return SD_ERROR_WRITE; } // 照度記録 for (int j = 0; j < cnt_illmi_pins; j++) { obj_file.print(illmi_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 : i2cEeprom4BWrite * processing : 4byte値をI2C外部EEPROMに書き出す * param : deviceAddress / I2C外部EEPROMのデバイスアドレス * startMemoryAddress / EEPROM上の書き込み開始アドレス * longParam / 書き込む4byteのデータ * summary : デバイスの0番目の番地 / 32〜25bit * 1番目の番地 / 24〜17bit * 2番目の番地 / 16〜9bit * 3番目の番地 / 8〜1bit * return : */ void i2cEeprom4BWrite(int deviceAddress, unsigned long startMemoryAddress, long longParam) { Wire.beginTransmission(deviceAddress); Wire.send((int)(startMemoryAddress >> 8)); Wire.send((int)(startMemoryAddress & 0xFF)); byte byteArray[sizeof(long)] = { (byte)(longParam >> 24), (byte)(longParam >> 16), (byte)(longParam >> 8), (byte)(longParam >> 0) }; for (int i = 0; i < sizeof(long); i++) { Wire.send(byteArray[i]); } Wire.endTransmission(); delay(5); } /* * func name : i2cEeprom4BRead * processing : 4byte値をI2C外部EEPROMから読み出す * param : deviceAddress / I2C外部EEPROMのデバイスアドレス * startMemoryAddress / EEPROM上の読み込み開始アドレス * return : return_long / 読み込んだ4byteデータ */ long i2cEeprom4BRead(int deviceAddress, unsigned long startMemoryAddress) { Wire.beginTransmission(deviceAddress); Wire.send((int)(startMemoryAddress >> 8)); Wire.send((int)(startMemoryAddress & 0xFF)); Wire.endTransmission(); Wire.requestFrom(deviceAddress, sizeof(long)); delay(5); long received_long; long return_long = 0; int cnt = sizeof(long) - 1; for (int i = 0; i <= cnt; i++) { if (Wire.available()) { received_long = Wire.receive(); return_long |= (received_long << (8 * (cnt - i))); } } return return_long; } /* * func name : tempCalc * processing : 温度センサ処理 * param : arduinoVcc / Arduino 基準電圧 * sensor / 0 : LM35DZ * 1 : LM60BIZ * 2 : LM61CIZ * analogVal / Analog値(0-1023) * gain / Op-amp ゲイン * return : temp / 計測温度(℃) */ float tempCalc (float arduinoVcc, int sensor, int analogVal, float gain) { float dc_offset; // DCオフセット電圧(V) float factor; // 温度係数(V/1℃) switch (sensor) { // LM35DZ // DCオフセット 0V // +10mV/℃ case 0: dc_offset = 0; factor = 0.01; break; // LM60BIZ // DCオフセット 424mV // +6.25mV/℃ case 1: dc_offset = 0.424; factor = 0.00625; break; // LM61CIZ // DCオフセット 600mV // +10mV/℃ case 2: dc_offset = 0.6; factor = 0.01; break; define: return 0; break; } return (((arduinoVcc * analogVal) / 1024) - (dc_offset * gain)) / (factor * gain); } |
||
|
||
| スケッチをアップして、データロガーのジッパーを閉じる。 計測開始日付時刻 2011年2月5日 16時30分。 |
||
登録:
投稿 (Atom)





