[code lang=”c”]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
//Digital I/O
#define DIO_RELAY_OUTPUT 3
#define DIO_TACTSW_INPUT 4
#define DIO_STATUSLED_INPUT 13
//Analog input
#define ANG_WATER_SENSOR 0
//Relay mode
#define RELAY_ACT_MODE_ON 0
#define RELAY_ACT_MODE_OFF 1
//tactSW status
#define TACT_SW_STATUS_ON 1
#define TACT_SW_STATUS_OFF 0
#define EXEC_MODE_NORMAL 0
#define EXEC_MODE_WATERPLANTS 1
#define EXEC_MODE_SILENT 2
#define ONE_MINUTE 60000
#define ON 1
#define OFF 0
#define MAX_UL 4294967295
#define INTERVAL_MAIN_LOOP 100
//LCD I2C
//int I2CADR = 0x3F;
int I2CADR = 0x3E;
//int I2CADR = 0x27;
LiquidCrystal_I2C lcd(I2CADR, 16, 2);
String strBuf = "";
int msec;
char s[32];
int i;
int stat;
int relay_act_mode;
int tact_sw_status;
int last_tact_sw_status=-1;
int exec_mode = EXEC_MODE_NORMAL; //0:通常モード、1:水やりモード、2:サイレントモード
int last_exec_mode = -1; //動作モードの前回値
int setting_mode = 0; //0:OFF(非設定モード)、1:ON(設定モード)
int soilanalog = 0; //土壌水分センサー生データ(0~1023)
int soilhumid = 0; //土壌水分センサー相対値(0~100%)
unsigned long count_watermode_reminder1 = 0; //暫定10回
unsigned long startedtime_allmode_sensing = 0;
unsigned long startedtime_normalmode_lcd_display=0;
unsigned long startedtime_watermode_reminder1=0;
unsigned long startedtime_watermode_reminder2=0;
//unsigned long startedtime_watermode_pump=0; //モータ駆動はDELAYを使用する(安全のため)
unsigned long startedtime_watermode=0;
unsigned long startedtime_silentmode=0;
unsigned long startedtime_silentmode_lcd_flash_on=0;
unsigned long startedtime_silentmode_lcd_flash_off=0;
unsigned long maxcount_watermode_reminder1 = 10; //暫定10回
unsigned long maxcount_watermode_reminder2 = MAX_UL; //暫定制限なし
unsigned long intervaltime_allmode_sensing = 1000; //暫定1秒
unsigned long intervaltime_normalmode_lcd_display = 3000; //暫定3秒
unsigned long intervaltime_watermode_reminder1 = 10000; //暫定10sec
unsigned long intervaltime_watermode_reminder2 = 600000; //暫定10min
unsigned long intervaltime_watermode_pump=2000; //暫定2秒
unsigned long intervaltime_watermode = 1800000; //暫定30min
unsigned long intervaltime_silentmode = 7200000; //暫定2h
unsigned long intervaltime_silentmode_lcd_flash_on = 60000; //暫定1min
unsigned long intervaltime_silentmode_lcd_flash_off = 2000; //暫定2秒
int thr_soil_himid_level_A = 70;
int thr_soil_himid_level_B = 50;
int thr_soil_himid_level_C = 30;
/****************************************************
* タイトル:n分経過判定 *
* 概要:startedtimeからn分経過判定処理をする *
* 内容:startedtimeからn分が経過したかどうか *
* 判定する。経過時はstartedtimeを初期化する *
* *
***************************************************/
int check_overtime(unsigned long n, unsigned long &startedtime) {
if(startedtime != MAX_UL && (millis() - startedtime) > n){
startedtime= millis();
return ON;
}else{
return OFF;
}
}
/****************************************************
* タイトル:LEDフラッシング *
* 概要:LEDを指定の間隔でフラッシングする *
* 内容: *
* *
* *
***************************************************/
void flashLed(int pin, int times, int wait) {
for (int i = 0; i < times; i++) {
digitalWrite(pin, HIGH);
delay(wait);
digitalWrite(pin, LOW);
if (i + 1 < times) { delay(wait); } } } /**************************************************** * タイトル:LCDに土壌水分データを表示 * * 概要:LCDに土壌水分データを表示する * * 内容: * * * * * ***************************************************/ void lcd_display(){ lcd.setBacklight(1); //LCD表示用メッセージを作成する lcd.setCursor(0, 0); if(exec_mode == EXEC_MODE_NORMAL) { lcd.print("Raw Ratio (^^)"); }else if(exec_mode == EXEC_MODE_WATERPLANTS) { lcd.print("Raw Ratio T_T"); }else if(exec_mode == EXEC_MODE_SILENT) { lcd.print("Raw Ratio .zzZ"); }else{ lcd.print("Raw Ratio ????"); } //LCDに土壌水分量情報を出力する lcd.setCursor(0, 1); sprintf(s, "%5d %5d",soilanalog, soilhumid); lcd.print(s); } /**************************************************** * タイトル:セットアップ関数 * * 概要:ARDUINO起動直後の初期処理実行関数 * * 内容: * * * * * ***************************************************/ void setup() { pinMode(DIO_TACTSW_INPUT, INPUT); //タクトSW pinMode(DIO_STATUSLED_INPUT, OUTPUT); //ARDUINO LED pinMode(DIO_RELAY_OUTPUT, OUTPUT); //リレー出力 digitalWrite(DIO_RELAY_OUTPUT, RELAY_ACT_MODE_OFF); //リレー出力(OFF) relay_act_mode=RELAY_ACT_MODE_OFF; //実際のリレー出力の状態と一致させる //LCD初期化 lcd.setBacklight(0); lcd.init(); //LCD初期表示 lcd.setCursor(0, 0); lcd.print(" A HINT OF"); lcd.setCursor(0, 1); lcd.print(" SMART AGRI!!"); lcd.setBacklight(1); delay(2000); //wait 1ms for mp3 module to set volume lcd.setBacklight(0); //SERIAL I/F初期化 //Serial1.begin (9600); //Serial1 for DFPlayer-mini mp3 module Serial.begin (9600); //Serial for standard serial I/F //while (!Serial); //MP3初期化 mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module mp3_set_volume (20); delay(100); //wait 1ms for mp3 module to set volume mp3_play (9); //Startup sound delay (12000); mp3_stop (); //Stop after played for XXsec. } /**************************************************** * タイトル:メイン処理関数 * * 概要:メイン処理関数 * * 内容: * * * * * ***************************************************/ void loop() { //1s間隔でセンサーデータを取得 if(check_overtime(intervaltime_allmode_sensing, startedtime_allmode_sensing)) { //土壌水分センサー取得値を変数に保存する soilanalog = analogRead(ANG_WATER_SENSOR); //土壌水分センサー取得値を0~100%の相対値に変換して変数に保存する soilhumid = (int)((soilanalog-523.0)/500.0*100); } tact_sw_status = digitalRead(DIO_TACTSW_INPUT); /* digitalWrite(DIO_RELAY_OUTPUT, HIGH); digitalWrite(DIO_STATUSLED_INPUT, LOW); delay(2000); digitalWrite(DIO_RELAY_OUTPUT, LOW); digitalWrite(DIO_STATUSLED_INPUT, HIGH); delay(2000); */ /* if(millis() % 3600000L == 0) { lcd.setBacklight(1); lcd.setCursor(0, 0); lcd.print(" A HINT OF"); lcd.setCursor(0, 1); lcd.print(" SMART AGRI!!"); digitalWrite(DIO_RELAY_OUTPUT, 0); } else if(millis() % 3600000L == 5000) { lcd.setBacklight(0); lcd.clear(); digitalWrite(DIO_RELAY_OUTPUT, 1); } */ //通常モード時の処理 if(exec_mode == EXEC_MODE_NORMAL) { //起動直後または通常モードに移行してはじめての場合 if(last_exec_mode != exec_mode) { last_exec_mode = exec_mode; startedtime_normalmode_lcd_display = millis(); } //土壌のかわきがLEVELAを超過すれば水やりモードに移行する if(soilhumid > thr_soil_himid_level_A) {
//水やりモード移行する
last_exec_mode = exec_mode;
exec_mode = EXEC_MODE_WATERPLANTS;
}
//タクトスイッチの立ち上がり検出時
if(last_tact_sw_status != tact_sw_status && tact_sw_status==TACT_SW_STATUS_ON) {
//LCDに土壌水分量を表示する
lcd_display();
//LCD表示直後の時間を保存する
startedtime_normalmode_lcd_display = millis();
}
//タクトスイッチの立ち下がり検出時
else if(check_overtime(intervaltime_normalmode_lcd_display, startedtime_normalmode_lcd_display) && tact_sw_status==TACT_SW_STATUS_OFF) {
//LCDを消灯する
lcd.setBacklight(0);
lcd.clear();
}else{
}
}
//水やりモード時の処理
else if(exec_mode == EXEC_MODE_WATERPLANTS) {
//LCDに土壌水分量を表示する(常時表示)
lcd_display();
//起動直後または水やりモードに移行してはじめての場合
if(last_exec_mode != exec_mode) {
last_exec_mode = exec_mode;
//水をくださいの音声メッセージ
mp3_play (1);
//水やりモード移行直後の時間を保存する
startedtime_watermode = millis();
startedtime_watermode_reminder1 = millis();
startedtime_watermode_reminder2 = MAX_UL;
count_watermode_reminder1 = 0;
//SWがOFFになるまで待機
while((tact_sw_status = digitalRead(DIO_TACTSW_INPUT)) == ON);
delay(100);
}
//前回水をください出力後、一定時間経過した場合
if(check_overtime(intervaltime_watermode_reminder1, startedtime_watermode_reminder1)) {
count_watermode_reminder1++;
if(count_watermode_reminder1 > maxcount_watermode_reminder1){
startedtime_watermode_reminder1 = MAX_UL;
startedtime_watermode_reminder2 = millis();
}
//土壌のかわきがLEVELAを超過すれば水やりモードに移行する
if(soilhumid > thr_soil_himid_level_A) {
//水をくださいの音声メッセージ
mp3_play (1);
}
else if(soilhumid > thr_soil_himid_level_B) {
//たりないの音声メッセージ
mp3_play (2);
}
else if(soilhumid > thr_soil_himid_level_C) {
//あとすこしの音声メッセージ
mp3_play (3);
}
}
//前回水をください出力後、一定時間経過した場合
if(check_overtime(intervaltime_watermode_reminder2, startedtime_watermode_reminder2)) {
//土壌のかわきがLEVELAを超過すれば水やりモードに移行する
if(soilhumid > thr_soil_himid_level_A) {
//水をくださいの音声メッセージ
mp3_play (1);
}
else if(soilhumid > thr_soil_himid_level_B) {
//たりないの音声メッセージ
mp3_play (2);
}
else if(soilhumid > thr_soil_himid_level_C) {
//あとすこしの音声メッセージ
mp3_play (3);
}
}
//水やりモードで一定時間経過した場合
if(check_overtime(intervaltime_watermode, startedtime_watermode)) {
//サイレントモードへ移行する
last_exec_mode = exec_mode;
exec_mode = EXEC_MODE_SILENT;
//LCDを消灯する
lcd.setBacklight(0);
lcd.clear();
}
//リレー停止中かつタクトSW ON検出時は、リレー停止⇒リレー駆動⇒リレー停止
if(relay_act_mode==RELAY_ACT_MODE_OFF && tact_sw_status==TACT_SW_STATUS_ON) {
//リレー停止⇒リレー駆動
relay_act_mode=RELAY_ACT_MODE_ON;
//リレー動作モードを出力する(DIO出力の誤動作を防止するため常時出力する)
digitalWrite(DIO_RELAY_OUTPUT, relay_act_mode);
delay (intervaltime_watermode_pump); //駆動時間2秒
//リレー駆動⇒リレー停止
relay_act_mode=RELAY_ACT_MODE_OFF;
//リレー動作モードを出力する(DIO出力の誤動作を防止するため常時出力する)
digitalWrite(DIO_RELAY_OUTPUT, relay_act_mode);
//ありがとうの音声メッセージ
mp3_play (5);
startedtime_watermode_reminder1 = millis();
startedtime_watermode_reminder2 = MAX_UL;
startedtime_watermode = millis();
}
//安全措置:ポンプ駆動開始から一定時間経過時は、リレー駆動⇒リレー停止
else if(relay_act_mode==RELAY_ACT_MODE_ON) {
//リレー駆動⇒リレー停止
relay_act_mode=RELAY_ACT_MODE_OFF;
//リレー動作モードを出力する(DIO出力の誤動作を防止するため常時出力する)
digitalWrite(DIO_RELAY_OUTPUT, relay_act_mode);
}
if(soilhumid <= thr_soil_himid_level_C) {
//通常モードへ移行する
last_exec_mode = exec_mode;
exec_mode = EXEC_MODE_NORMAL;
//LCDを消灯する
lcd.setBacklight(0);
lcd.clear();
//ARIGATOの音声メッセージ
mp3_play(4);
}
}
//サイレントモード時の処理
else if(exec_mode == EXEC_MODE_SILENT) {
//起動直後またはsilentモードに移行してはじめての場合
if(last_exec_mode != exec_mode) {
last_exec_mode = exec_mode;
//LCDに土壌水分量を表示する(常時表示)
lcd_display();
//水をくださいの音声メッセージ
mp3_stop ();
startedtime_silentmode = millis();
}
//一定時間経過した場合
if(check_overtime(intervaltime_silentmode_lcd_flash_on, startedtime_silentmode_lcd_flash_on)) {
//LCDに土壌水分量を表示する(インターバル表示)
lcd_display();
startedtime_silentmode_lcd_flash_off = millis();
}
//一定時間経過した場合
if(check_overtime(intervaltime_silentmode_lcd_flash_off, startedtime_silentmode_lcd_flash_off)) {
//LCDを消灯する
lcd.setBacklight(0);
lcd.clear();
startedtime_silentmode_lcd_flash_off = MAX_UL;
startedtime_silentmode_lcd_flash_on = millis();
}
//SW立ち上がり検出
if((last_tact_sw_status != TACT_SW_STATUS_ON && tact_sw_status == TACT_SW_STATUS_ON)
|| check_overtime(intervaltime_silentmode, startedtime_silentmode)) {
//サイレントモードへ移行する
last_exec_mode = exec_mode;
exec_mode = EXEC_MODE_WATERPLANTS;
//LCDを消灯する
lcd.setBacklight(0);
lcd.clear();
}
}else{
}
last_tact_sw_status = tact_sw_status;
/*
//if(digitalRead(DIO_TACTSW_INPUT)){
lcd.setBacklight(1);
mp3_set_volume (20);
delay (100);
// mp3_random_play ();
mp3_single_play (5);
for(i=0;i<5;i++){
digitalWrite(DIO_RELAY_OUTPUT, RELAY_ACT_MODE_ON);
delay(1000); //10sec
digitalWrite(DIO_RELAY_OUTPUT, RELAY_ACT_MODE_OFF);
delay(1000); //10sec
}
delay (8000);
//mp3_get_state ();
//delay (10);
//stat = mp3_wait_state();
// sprintf(s, "stat:%5d.", stat);
// lcd.setCursor(0, 0);
//lcd.print(s);
mp3_stop ();
delay (2000);
lcd.setBacklight(0);
}else{
digitalWrite(DIO_RELAY_OUTPUT, RELAY_ACT_MODE_ON);
}
delay(500);
*/
}
[/code]