// ソーラータイマー、設定機能のテストプログラム // 日の出動作補正機能(±99分の範囲で補正) // 日の入り動作補正機能(±99分の範囲で補正) // 固定時刻ON機能 // 固定時刻OFF機能 // このプログラムは設定機能のテスト用で、タイマーとしての動作はしない。 // 2017/07/13 ラジオペンチ http://radiopench.blog96.fc2.com/ #include #include // N. MitsunagaさんのI2C液晶ライブラリ http://n.mtng.org/ele/arduino/i2c.html I2CLiquidCrystal lcd(30, true); // コントラスト(0-63),液晶電源(true=5V, false=3.3V) int DecB = 8; // − (Dec) ボタンのピン指定 int IncB = 9; // +(Inc)ボタンのピン指定 int EntB = 10; // Enterボタンのピン指定 int SunSetOffset; int SunRiseOffset; int FixOnTime; // 固定ONタイマー設定値(単位:分) int FixOffTime; // 固定OFFタイマー設定値(単位:分) int FixOnMode, FixOffMode; // タイマー使用フラグ(0:不使用、1:使用) void setup() { pinMode(IncB, INPUT_PULLUP); // + (Increment)ボタン pinMode(EntB, INPUT_PULLUP); // Enterボタン pinMode(DecB, INPUT_PULLUP); // - (Decrement)ボタン Serial.begin(115200); lcd.begin(16, 2); // 16文字2行のI2C液晶を使用 lcd.clear(); readSettings(); // EEPROMから設定値を読み出す } void loop() { int hh, mm; lcd.clear(); // 日の入りON動作時刻のオフセット設定 lcd.setCursor(0, 0); lcd.print("ON time offset "); lcd.setCursor(0, 1); lcd.print("Sunset sNN min."); SunSetOffset = lcdInput(SunSetOffset, 9, 1, -99, 99); EEPROM.write(0, (SunSetOffset >> 8)); EEPROM.write(1, (SunSetOffset & 0x00ff)); // Serial.println(SunSetOffset); lcd.clear(); // 日の出OFF時刻のオフセット設定 lcd.setCursor(0, 0); lcd.print("OFF time offset "); lcd.setCursor(0, 1); lcd.print("Sunrise sNN min."); SunRiseOffset = lcdInput(SunRiseOffset, 10, 1, -99, 99); EEPROM.write(2, (SunRiseOffset >> 8)); EEPROM.write(3, (SunRiseOffset & 0x00ff)); // Serial.println(SunRiseOffset); lcd.clear(); lcd.print("Fix On Timer "); // Fix ON 固定オンタイマーの設定 if (FixOnMode != 0) { // このモードを使うなら(USEなら) lcdDispFixTime(FixOnTime); // 設定時刻を表示 } FixOnMode = selMode(FixOnMode, 0, 1, FixOnTime); // 使用の有無の入力 EEPROM.write(8, FixOnMode & 0x00ff); if (FixOnMode != 0) { // 0以外なら設定(実際には1以外は存在しない) lcdDispFixTime(FixOnTime); hh = FixOnTime / 60; hh = lcdInput(hh, 8, 1, 0, 23); // 時の値の入力、値は0-23でサーキュレート mm = FixOnTime % 60; mm = lcdInput(mm, 11, 1, 0, 59); // 分の値の入力、値は0-59でサーキュレート FixOnTime = hh * 60 + mm; // 固定ON時刻の設定 EEPROM.write(4, (FixOnTime >> 8)); EEPROM.write(5, (FixOnTime & 0x00ff)); } lcd.clear(); lcd.print("Fix Off Timer "); // Fix OFF タイマー設定 if (FixOffMode != 0) { // このモードを使うなら(USEなら) lcdDispFixTime(FixOffTime); // 設定時刻を表示 } FixOffMode = selMode(FixOffMode, 0, 1, FixOffTime); // 使用の有無の入力 EEPROM.write(9, FixOffMode & 0x00ff); if (FixOffMode != 0) { lcdDispFixTime(FixOffTime); hh = FixOffTime / 60; hh = lcdInput(hh, 8, 1, 0, 23); mm = FixOffTime % 60; mm = lcdInput(mm, 11, 1, 0, 59); FixOffTime = hh * 60 + mm; EEPROM.write(6, (FixOffTime >> 8)); EEPROM.write(7, (FixOffTime & 0x00ff)); } lcd.clear(); delay(1000); } int lcdInput(int d, int x, int y, int minV, int maxV) { // 液晶表示と値の入力 // +−ボタンで値を変更、Enterボタンで確定 // d=初期値、x, y=液晶座標、 minV,maxV=下限上限、戻り値=入力決定値 // 下限値(minV)が負なら符号付き表示(sNN) 正なら符号無し表示(NN)を行う // minVが正なら値をサーキュレート、minVが負なら値は上下限でストップ lcdDisp(d, x, y, minV); // 値を表示 while (digitalRead(EntB) == LOW) { // もしEntBが押されていたら離されるまで待つ delay(30); } while (digitalRead(EntB) == HIGH) { // EntBが押されていなければ以下の処理を繰り返す if (digitalRead(IncB) == LOW) { // +ボタンが押されていたら delay(30); d++; // dをインクリメント if (d > maxV ) { // 上限を超えていたら if (minV < 0) { // minVがマイナスの場合は d = maxV; // 上限で抑える } else { // そうでなければ d = minV; // 値を下限に変更(サーキュレート) } } lcdDisp(d, x, y, minV); // 指定フォーマットで表示 while (digitalRead(IncB) == LOW) { // +ボタンが離されるまで待つ } delay(30); } if (digitalRead(DecB) == LOW) { // −ボタンが押されていたら delay(30); d--; // dをデクリメント if (d < minV ) { // 下限を下回っていたら if ( minV < 0) { // minVがマイナスの場合は d = minV; // 下限で抑える } else { // そうでなければ d = maxV; // 値を上限に変更(サーキュレート) } } lcdDisp(d, x, y, minV); // 指定フォーマットで表示 while (digitalRead(DecB) == LOW) { // −ボタンが離されるまで待つ } delay(30); } } delay(30); lcd.noCursor(); // 入力が終わったのでカーソルを消す return d; } void lcdDisp(int d, int x, int y, int minV) { // 指定位置に2桁の値を表示 // minVが正ならNN形式、負ならsNN形式 if (minV < 0) { // 負の値がある場合 lcd.setCursor(x - 2, y); // 2文字左にカーソルを移動して if (d >= 0) { // 値が正なら lcd.print("+"); // +を表示 } else { // それ以外(つまり負)なら lcd.print("-"); // −を表示 d = abs(d); } } lcd.setCursor(x - 1, y); // 1文字左から if (d < 10) { // 値が10以下なら lcd.print("0"); // スペースを入れ } lcd.print(d); // 値を表示 lcd.setCursor(x, y); // 1桁目にカーソル移動 lcd.cursor(); // カーソル表示 } void lcdDispFixTime(int x) { // 固定タイマー設定時刻の表示 int hh, mm; hh = x / 60; mm = x % 60; lcd.setCursor(7, 1); // 書き始め位置はここ if (hh < 10) { lcd.print("0"); } lcd.print(hh); lcd.print(":"); if (mm < 10) { lcd.print("0"); } lcd.print(mm); } int selMode(int m, int x, int y, int t) { // モード,表示位置(x、y),タイマーの値(分単位) lcdDispMode(m, x, y, t); // 最初の状態表示 while (digitalRead(EntB) == LOW) { // もしEntBが押されていたら離されるまで待つ delay(30); } while (digitalRead(EntB) == HIGH) { // EntBが押されていなければ以下の処理を繰り返す if (digitalRead(IncB) == LOW) { // +ボタンが押されていたら m = 1; // フラグセット } if (digitalRead(DecB) == LOW) { // −ボタンが押されていたら m = 0; // フラグリセット } lcdDispMode(m, x, y, t); // 変更後の状態表示 delay(30); } delay(30); return m; // 設定されたモードを返す } void lcdDispMode(int m, int x, int y, int t) { lcd.setCursor(x, y); if (m == 0) { lcd.print("No USE "); } else { lcd.print("USE at "); lcdDispFixTime(t); } lcd.setCursor(x, y); lcd.cursor(); // カーソルを先頭に戻して表示 } void readSettings() { // EEPROMからタイマーの設定値を読み出す。不当な値は修正 SunSetOffset = (EEPROM.read(0) << 8) | EEPROM.read(1); if ((SunSetOffset < -99) | (99 < SunSetOffset)) { // ±99の範囲外なら EEPROM.write(0, 0); EEPROM.write(1, 0); // ゼロにする } SunRiseOffset = (EEPROM.read(2) << 8) | EEPROM.read(3); if ((SunRiseOffset < -99) | (99 < SunRiseOffset)) { // ±99の範囲外なら EEPROM.write(2, 0); EEPROM.write(3, 0); // ゼロにする } FixOnTime = (EEPROM.read(4) << 8) | EEPROM.read(5); if ((FixOnTime < 0) | ( 1439 < FixOnTime)) { // マイナスか1439(23*60+59)以上なら EEPROM.write(4, 0); EEPROM.write(5, 0); // ゼロにする } FixOffTime = (EEPROM.read(6) << 8) | EEPROM.read(7); if ((FixOffTime < 0) | ( 1439 < FixOffTime)) { // マイナスか1439(23*60+59)以上なら EEPROM.write(6, 0); EEPROM.write(7, 0); // ゼロにする } FixOnMode = EEPROM.read(8); FixOffMode = EEPROM.read(9); Serial.print(SunSetOffset); Serial.print(", "); Serial.println(SunRiseOffset); Serial.print(FixOnTime); Serial.print(", "); Serial.println(FixOffTime); Serial.print(FixOnMode); Serial.print(", "); Serial.println(FixOffMode); Serial.println(); }