//散水用プログラム #include #include  //LCD #include //リアルタイム・クロック #include //赤外線温度センサー #include //割り込みタイマー #include //SDカード #include //気圧温度センサー #include //照度センサー DS3232RTC RTC; LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display Adafruit_MLX90614 mlx = Adafruit_MLX90614(); BH1750 lightMeter; BMP280 bmp280(0x76); BMP280 bmp280a(0x77); volatile bool sdw = 1; // SD書き込み volatile int plcd = 10; // LCD表示 volatile bool waterable = 1; // 散水許可 volatile bool long_lcd = 0; // lcd長押し判定 volatile bool long_sdw = 0; // SD長押し判定 volatile bool long_watering = 0; // 散水長押し判定 volatile bool watering = 0; // 散水中 volatile int waint = 2; // 散水間隔 分 volatile int watime = 50; // 散水時間 秒 volatile int wacount = waint; // 散水カウント volatile int starttime = 8; // スタート時間 volatile int endtime = 16; // 終了時間 const int chipSelect = 10; // SDモジュールのチップセレクトのピン番号 const float illmax[] = {20,520,1370,4720,7020,7810,8860,8070,7800,7070,4610,2340,1010,200,10}; // 照度最大値の目安 volatile float ill_av = 0; // 照度平均 volatile int ill_c = 0; // 照度カウント void setup() { Serial.begin(9600); //RTC.begin(); Wire.begin(); bmp280.begin(); bmp280a.begin(); lightMeter.begin(); pinMode(2,OUTPUT); pinMode(5,INPUT_PULLUP); pinMode(6,INPUT_PULLUP); pinMode(7,INPUT_PULLUP); lcd.init(); // initialize the lcd lcd.backlight(); // SD カード初期化 lcd.print("Initializing SD card..."); while (!SD.begin(chipSelect)) { lcd.print("Card failed, or not present"); delay(3000); } lcd.print("card initialized."); delay(2000); ///// 時刻の設定 (必要時にコメントアウトを消す)///// //setTime(16, 50, 0, 30, 8, 2023); // 時,分,秒,日,月,年の順となっています //RTC.set(now()); // 時刻情報を書き込む setSyncProvider(RTC.get); // RTCから時刻を取得する関数 MsTimer2::set(60000, m_timer); // 1分毎に”m_timer”関数を割り込みで呼び出す MsTimer2::start(); // 割り込みを有効にする float li = lightMeter.readLightLevel(); //照度の平均を出す ill_c = ill_c+1; ill_av = (ill_av * (ill_c-1) + li)/ill_c; printLCD(); } //************************************************** void loop() { //シリアルからコマンド入力 if ( Serial.available() > 0 ) { String keystr = Serial.readStringUntil('\r'); Serial.println(keystr); //SDカードの内容をシリアルモニタに表示 if ( keystr.indexOf("print")==0 ) { print_sd(); } //SDカードのファイルを削除 if ( keystr.indexOf("remove")==0) { remove_sd(); } //時刻設定 if ( keystr.indexOf("set")==0) { String setmo_s = keystr.substring(3,5); String setda_s = keystr.substring(5,7); String seth_s = keystr.substring(7,9); String setm_s = keystr.substring(9,11); int setmo_i = setmo_s.toInt(); int setda_i = setda_s.toInt(); int seth_i = seth_s.toInt(); int setm_i = setm_s.toInt(); setTime(seth_i, setm_i, 0, setda_i, setmo_i, year()); // 時,分,秒,日,月,年の順となっています RTC.set(now()); // 時刻情報を書き込む Serial.print("set time "); Serial.print(setmo_s); Serial.print("/"); Serial.print(setda_s); Serial.print(" "); Serial.print(seth_s); Serial.print(":"); Serial.println(setm_s); printLCD(); } //数字のみは入力秒数強制散水 int wacom = keystr.toInt(); if ( wacom > 0 ) { MsTimer2::stop(); Serial.println("watering!"); watering_t(wacom); Serial.println("stop."); MsTimer2::start(); } } //5番ピン LCD表示切り替え 長押し:SDカードのファイルを削除 if(digitalRead(5)==LOW){ if(long_lcd==1){ remove_sd(); } if(plcd>0){ plcd=0; }else{ plcd=10; } printLCD(); delay(2000); long_lcd = 1; }else{ long_lcd = 0; } //6番ピン 散水許可切り替え 長押し:30秒強制散水 if(digitalRead(6)==LOW){ if(long_watering==1){ watering_t( 30 ); } if(waterable==0){ waterable=1; }else{ waterable=0; } printLCD(); long_watering = 1; delay(2000); }else{ long_watering = 0; } //7番ピン SDカード保存切り替え 長押し:ファイル内容をシリアルモニタに表示 if(digitalRead(7)==LOW){ if(sdw==0){ sdw=1; }else{ sdw=0; } if(long_sdw==1){ print_sd(); sdw=1; } printLCD(); delay(2000); long_sdw = 1; }else{ long_sdw = 0; } float li = lightMeter.readLightLevel(); //照度の平均を出す ill_c = ill_c+1; ill_av = (ill_av * (ill_c-1) + li)/ill_c; //散水 if (watering == 1){ watering_t( watime ); } delay(500); } //************************************************** void m_timer() //1分毎に呼び出し { interrupts(); // 割り込み許可 //散水カウント float li = lightMeter.readLightLevel(); ill_c = ill_c+1; ill_av = (ill_av * (ill_c-1) + li)/ill_c; if (waterable and hour()>=starttime and hour()illmax[hour()]*0.3){ //illmaxの30%以下はカウントしない wacount = wacount-1; } if (wacount <= 0){ float et = bmp280a.getTemperature(); waint =12; if (et>28 and ill_av>2500){ waint =10; } if (et>30 and ill_av>4800){ waint =7; } if (ill_av<1500){ waint =22; } wacount = waint; watering = 1; } } //LCD,SDカード書き込み printLCD(); if(sdw){ writeSD(); } ill_c = 0; ill_av = 0; } //************************************************** void printLCD() //LCDに書き出し { if (plcd>0){ lcd.backlight(); lcd.display(); lcd.clear(); // 時刻表示 lcd.setCursor(0,0); lcd.print(month()); lcd.print("/"); lcd.print(day()); lcd.print(" "); lcd.print(hour()); lcd.print(":"); lcd.print(minute()); //lcd.print(":"); //lcd.print(second()); if (waterable){ lcd.print(" "); lcd.print(starttime); lcd.print("-"); lcd.print(endtime); } if(sdw){ lcd.print(" S"); // SD書き込み } if (watering) { lcd.print("W"); // 散水中 } // 温度気圧表示 lcd.setCursor(0,1); lcd.print("In:"); lcd.print(mlx.readAmbientTempC()); //室内気温 lcd.setCursor(9,1); lcd.print("Ce:"); lcd.print(mlx.readObjectTempC()); //天井温度 lcd.setCursor(0,2); lcd.print("Ex:"); float et = bmp280a.getTemperature(); lcd.print(et); //外気温 lcd.setCursor(9,2); lcd.print("Pr:"); float pr = bmp280.getPressure(); double pr1 = pr/100*pow((1+0.0065*80/(et+273.15)),5.257); lcd.print(pr1); //気圧 // 照度・その他表示 lcd.setCursor(0,3); lcd.print("Il:"); lcd.print(ill_av); //照度 if (waterable) { lcd.setCursor(12,3); lcd.print(wacount); //散水カウント lcd.print("/"); lcd.print(waint); // 散水間隔 分 lcd.print("-"); lcd.print(watime); // 散水時間 秒 lcd.print(" "); } plcd = plcd-1; //LCD消灯カウント } else { //LCD消灯 lcd.noBacklight(); lcd.noDisplay(); } } //************************************************** void writeSD() //SD CARDに書き出し { //データ作成 String dataString = ""; //dataString += String(year()); //dataString += ","; dataString += String(month()); dataString += ","; dataString += String(day()); dataString += ","; dataString += String(hour()); dataString += ","; dataString += String(minute()); dataString += ","; dataString += String(mlx.readAmbientTempC()); //室内気温 dataString += ","; dataString += String(mlx.readObjectTempC()); //天井温度 dataString += ","; float et = bmp280a.getTemperature(); dataString += String(et); //外気温 dataString += ","; float pr = bmp280.getPressure(); double pr1 = pr/100*pow((1+0.0065*80/(et+273.15)),5.257); dataString += String(pr1); //気圧 dataString += ","; dataString += String(ill_av); //照度 dataString += ","; if (watering){ dataString += String(watime); //散水時間 } else { dataString += String(0); //散水時間 } Serial.println(dataString); //シリアルポートに書き出し int i; i = 0; while (i<3){ //書き込みを3回トライする File dataFile = SD.open("LOGGING.CSV", FILE_WRITE); // ファイルを開く // 正常に開かれたか確認して、データ書き込みを行ってフィアルを閉じる if (dataFile) { dataFile.println(dataString); // データ書き込み dataFile.close(); // ファイルを閉じる break; }else{ Serial.println("SDcard writing error"); delay(3000); } i=i+1; } } //************************************************** void print_sd(){ //SDカードの内容をシリアルモニタに書き出す MsTimer2::stop(); Serial.println("***********"); File dataFile = SD.open("LOGGING.CSV"); if (dataFile) { // 64byte単位で読み出す byte buffer[64]; while (dataFile.available()) { int length = dataFile.available(); if(length > 64){ length = 64; } dataFile.read(buffer, length); Serial.write(buffer, length); } dataFile.close(); Serial.println("***********"); }else{ Serial.println("Data None"); } MsTimer2::start(); } void remove_sd(){ //SDカードのファイルを削除 MsTimer2::stop(); if (SD.exists("LOGGING.CSV")) { SD.remove("LOGGING.CSV"); Serial.println("Remove Data"); } MsTimer2::start(); } void watering_t(int wt){ //散水実行 //MsTimer2::stop(); watering = 1; printLCD(); watering = 0; digitalWrite(2,HIGH); for (int i = 0; i < wt; i++) { delay(1000); } digitalWrite(2,LOW); printLCD(); //MsTimer2::start(); }