気の向くままに辿るIT/ICT/IoT
webzoit.net
IoT・電子工作

Arduinoで『自動ON/OFFタイマー付きLEDライト』を作る

ウェブ造ホーム前へ次へ
サイト内検索
カスタム検索
Arduinoって?

Arduinoで『自動ON/OFFタイマー付きLEDライト』を作る

Arduinoで『自動ON/OFFタイマー付きLEDライト』を作る

Arduino/LEDストリップライト/RTCモジュールを使ったライト自動ON/OFFタイマー回路
2018/02/04

 Arduinoを使って『ON/OFFタイマー付きLEDライト』を自作してみるページ。

 例えば、17:00に点灯、午前0:00に消灯するライト。

 まる1日や数日間、留守にする際などの防犯対策の一環として、規則正しい生活をしている場合、要介護など、電気のON/OFFがままならない状況にある場合、また、夜、明かりが灯っている自宅への帰宅だけでなく、眠る前に電気を消すのすら面倒な!?一人暮らしや家族にとって嬉しいかもしれないオートタイマーライト。

 ただ、ここでは、室内照明にLEDテープ(ストリップ)ライトを、タイマーにRTCモジュールを使い、これをON/OFFさせるものとする。

 Arduinoボードには、Arduino Nano 5V 16MHz互換機 350円、LEDには、12V 5m SMD3238 600球 単色LEDストリップライト411円、仮に1m使うとして約82円、タイマーにRTC DS1302 115円、バックアップ電池にCR2032 54円、昇圧モジュールにMT3608(5個449円)、整流ダイオードに1N4004(50個147円)、ハイパワーMOSFETにIRFZ34N(5個208円)、ブレッドボード、ジャンパワイヤ、1/4Wカーボン抵抗220Ωなど多めに見積もっても約300円をAmazonマーケットプレイスで、LED放熱兼固定用アルミアングル 0.8mmx1.2mmx1.2mmx2000m 343円、1mとして約172円を近所のホームセンターで買うとして、締めて約1203円程度。

 写真では、ケーブル付きDCプラグと端子付きDCジャックも使っているが、他から一時的に持ってきた関係で、そのまま使っているだけ、使用したLEDストリップライト(単色)もケーブル出しなので昇圧モジュールに直結することで省略可能。

 また、パワーMOSFET、整流ダイオード、抵抗の回路を、見づらいながら、写真下の黒い170穴ミニブレッドボードに載せているが、これも他から一時的に持ってきたこと、回路の確認、複製が容易だからというだけでNanoが載った400穴ブレッドボードにまとめて組み込むことも可能。

EasyWordMall Arduino UNO R3互換ボード(USBケーブル付属)

EasyWordMall Arduino Pro Mini互換ボード Atmega328 5V 16MHz

Rasbeeオリジナル FT232RL互換 3.3V/5V FTDI/USB/TTL変換アダプタ

KKHMF Arduino Nano Ver 3.0互換ボード ATmega328P CH340G 5V 16MHz

SODIAL(R) 5M 600 3528 SMD LEDストリップ 白 屋内屋外の装飾

EasyWordMall DS1302 RTC リアルタイムクロックモジュール

EasyWordMall DS1307 RTC 7クロックモジュール I2C

HiLetgo RTC時計モジュール DS3231 AT24C32 IIC

KKHMF 5PCS MT3608 DC-DC 2A Boost ステップアップ 転換モジュール 2V-24V to 5V-28V 9V 12V 24V

SODIAL(R) 50×1N4004 400V 1A DO-41アキシャルリード整流ダイオード

SODIAL(R) 5個 IRFZ34N 30A 55V高速スイッチング電源 MOSFETトランジスタ

SODIAL(R) IRF530 100V 14ANチャネルパワーMOSFET TO-200AB 5個

Rasbee 400穴 ブレッドボード 8.5*5.5cm 1個

HiLetgo 400穴 ブレッドボード 8.5*5.5cm 5個セット

HiLetgo 400穴 ブレッドボード 8.5*5.5cm 10個セット

Rasbee SY-170 ミニブレッドボード カラフルブレッドボード 5個

HiLetgo 金属皮膜抵抗 1/4W 41種類x20=820個

HiLetgo ジャンパーワイヤー(オス-オス) 20cmx40本 5セット

Rasbee ジャンパーワイヤー(オス-オス) 各種長さx65本

 回路は、LEDテープによる誘導イルミでも使わせて頂いたMOSFET Motor Example画像の回路でモータ部をLEDストリップライト+昇圧モジュールに替えただけ。

 これでも機能することは確認済みなのだが、とりあえずにも140型DCモータでの検証でもいけたのだから、たぶん大丈夫だろうという程度でAmazonで買える極々限られた候補の中から選び、データシートにも目を通していないハイパワーMOSFETと手持ちのものを使った整流ダイオードの選定は、かなり適当。

#include <MyRealTimeClock.h>
 
MyRealTimeClock myRTC(6, 7, 8);
const int led = 13;
 
void setup() {
// Serial.begin(9600);
 pinMode(led, OUTPUT);
// myRTC.setDS1302Time(00, 24, 11, 12 , 04, 02, 2018);
}
 
void loop() {
 myRTC.updateTime();
 
 if(myRTC.hours == 17 && myRTC.minutes == 00 && myRTC.seconds == 00) {
  digitalWrite(led, HIGH);
 }
 if(myRTC.hours == 23 && myRTC.minutes == 59 && myRTC.seconds == 59) {
  digitalWrite(led, LOW);
 }
/*
 Serial.print("Current Date / Time: ");
 Serial.print(myRTC.dayofmonth);
 Serial.print("/");
 Serial.print(myRTC.month);
 Serial.print("/");
 Serial.print(myRTC.year);
 Serial.print(" ");
 Serial.print(myRTC.hours);
 Serial.print(":");
 Serial.print(myRTC.minutes);
 Serial.print(":");
 Serial.println(myRTC.seconds);
*/ 
}

 sleep(スケッチは『鳥よけ装置』参照)を入れていないし、より正確を期すためのNTPによる時刻補正(Arduino IDEサンプルスケッチNTPClient参照)も取り込んではいないが、ラフスケッチとしては、動作確認でも使わせて頂いたThe DS1302 Real Time Clock on Arduinoのinclude行のみ修正したものを流用、あとはLEDを点灯・消灯させるだけ。

 RTCモジュール(DS1302/DS1307はそのまま、DS3231は要加工)にボタン電池CR2032を入れ、myRTC.setDS1302Time()関数で一度、RTCモジュール上の日付時刻を設定すべくArduinoボードにアップロード、その後、当該行をコメントアウトし、再度、スケッチをArduinoボードにアップロードすれば、設定した時間を保持してくれる。

(実用品への実装、運用時は、当該作業は1度だけだが、当然、検証時などif文の条件となる時間を変更したい場合は、スケッチを編集後、再度アップロードする必要がある。)

 検証時には、if文の時間を変更すれば、数秒や数十秒といった短時間で動作確認できるし、setup()/loop()関数内でそれぞれコメントアウトしてあるシリアル操作部を有効にすれば、シリアルモニタ上でRTCモジュール+バックアップ電池が保持している時間の確認も可能。

 今回は、スケッチ上で決め打ちで時間指定しているが、作りようによっては、物理スイッチやタッチパネル、スマホなどで時間を指定できるようにすることもできるだろう。

[2018/02/13]

 と思ったが、さて、スリープを...と考えた時、DS1302によるこの方法だとディープスリープモードからの割り込みがかけられない、かと言ってアラーム機能はない模様、DS1307にはタイマーらしきものがあるようだが、時間指定、特にON、OFFの2段階はできそうもない...ことに気づいた。

 やっぱり、DS3231を使わないとダメか...。

#include <DS3232RTC.h>    // http://github.com/JChristensen/DS3232RTC
#include <Streaming.h>    // http://arduiniana.org/libraries/streaming/
#include <avr/sleep.h>
#include <avr/power.h>
 
const int trigerPin = 2;
const int ledPin = 13;
const uint8_t alarmInput(trigerPin);
bool alarm_state = false;
 
const int on_hour = 19;
const int on_minutes = 28;
const int on_seconds = 40;
const int off_hour = 19;
const int off_minutes = 30;
const int off_seconds = 0; // 今回のようにAlarm2とした場合は使えないので固定
 
void wakeUpNow(){
 Serial.println("Wake up!");
 
 alarm_state = true;
 
 // デバグ用
 int val = digitalRead(ledPin);
 Serial.print("val = ");
 Serial.println(val);
 Serial.print("hour = ");
 Serial.println(hour());
 Serial.print("minute = ");
 Serial.println(minute());
 Serial.print("second = ");
 Serial.println(second());
 // デバグ用
 
// if (hour() == off_hour) {
// if (minute() == off_minutes && second() == off_seconds) {
 if (minute() == off_minutes || digitalRead(ledPin)) {
  digitalWrite(ledPin, LOW);
// } else {
// } else if(hour() == on_hour) {
// } else if(minute() == on_minutes && second() == on_seconds) {
 } else if(minute() == on_minutes || !digitalRead(ledPin)) {
  digitalWrite(ledPin, HIGH);
 }
 
/*
 // LEDのON/OFFで評価するとスケッチアップや電源ONのタイミングによっては挙動が逆に...
 if (digitalRead(ledPin)) {
  digitalWrite(ledPin, LOW);
 } else {
  digitalWrite(ledPin, HIGH);
 }
*/
}
 
void sleepNow(){
 Serial.println("Sleep...");
 delay(10);
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 sleep_enable(); //スリープの有効化
 
 // アラームの割り込み時の信号はLOWなので第3引数は、FALLING
 attachInterrupt(digitalPinToInterrupt(alarmInput), wakeUpNow, FALLING);
 sleep_mode(); //指定したモードでスリープを開始
 sleep_disable(); //割り込み時、スリープから復帰
 detachInterrupt(0); //割り込み処理解除
}
 
void setup() {
 Serial.begin(9600);
 
 pinMode(trigerPin, INPUT_PULLUP);
 
 // アラームフラグ、アラーム割り込みフラグの初期化
 RTC.alarm(ALARM_1);
 RTC.alarm(ALARM_2);
 RTC.alarmInterrupt(ALARM_1, false);
 RTC.alarmInterrupt(ALARM_2, false);
 // 割り込み用のINT/SQWピン使用時は、方形(矩形)波出力を無効にする必要がある
 RTC.squareWave(SQWAVE_NONE);
 
 // RTCモジュールで時刻を同期
 setSyncProvider(RTC.get);
 if (timeStatus() != timeSet)
  Serial.println("Unable to sync with the RTC");  // RTCで同期不能
 else
  Serial.println("RTC has set the system time");  // RTCでシステム時刻を設定中
 Serial.flush();
 
/*
 // 初回のスケッチアップロード時の日付時刻を設定、初回のみコメント外し有効にする
 // RTC時間設定 例) 2018/02/13 19:28:20
 tmElements_t tm;
 tm.Hour = 19;
 tm.Minute = 28;
 tm.Second = 20;
 tm.Day = 13;
 tm.Month = 2;
 tm.Year = 2018 - 1970; // tmElements_t.Yearの初期値は1970から始まるものとして算出される
 RTC.write(tm);   // tm構造体からRTCを設定
*/
 
 // 例) アラーム1を19:28:40に設定
 //RTC.setAlarm(ALM1_MATCH_HOURS, 40, 28, 19, 0);
 RTC.setAlarm(ALM1_MATCH_DATE, on_seconds, on_minutes, on_hour, 0);
 // アラーム1の有効化
 RTC.alarmInterrupt(ALARM_1, true);
 
 // 例) アラーム2を19:29に設定
 //RTC.setAlarm(ALM2_MATCH_HOURS, 00, 29, 19, 0);
 RTC.setAlarm(ALM2_MATCH_DATE, off_seconds, off_minutes, off_hour, 0);
 // アラーム2の有効化
 RTC.alarmInterrupt(ALARM_2, true);
 
 // シリアルモニタに日付時刻を表示
 digitalClockDisplay();
}
 
void loop() {
 // 経過日付時刻表示と必要に応じて割り込みフラグを初期化
 if (alarm_state) {
  alarm_state = false;
  digitalClockDisplay();
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
 }
 sleepNow(); // スリープ
}
 
void digitalClockDisplay(void)
{
 setSyncProvider(RTC.get);
 Serial.print(year());
 Serial.print('/');
 Serial.print(month());
 Serial.print('/');
 Serial.print(day());
 Serial.print(' ');
 printDigits(hour());
 Serial.print(':');
 printDigits(minute());
 Serial.print(':');
 printDigits(second());
 Serial.println();
 Serial.flush();
}
 
void printDigits(int digits)
{
 // 日付時刻1桁時、1桁めに0を設定
 if (digits < 10)
  Serial.print('0');
 Serial.print(digits);
}

 というわけで改めて買うとして今、唯一、手持ちのDS3231を積んだRTCモジュールZS-042は、以前作った温湿度計付き時計に使ったものなので、そこから持ってくることにした。

 回路は、前述のものとほとんど同じでRTCモジュールをDS1302からDS3231に差し替え、DS3231搭載モジュールのVCC/GND/SDA/SCL/SQWをArduino Nano互換機の5V/GND/A4/A5/D2に接続するだけ(Uno系で割り込みに使えるピンはD2/D3、内D2を使った)。

 JChristensen/DS3232RTCライブラリをダウンロード、本ライブラリのサンプルスケッチalarm_ex7.inoとMega用だが、このライブラリを使っているというArduinoでDS3231 RTCモジュールを使った定期処理のスケッチを拝借、一部変更したものと、前述(前リンク)の鳥よけ回路で参照させて頂いたスリープ機能を盛り合わせたラフスケッチがこれ。

 ただ、分単位などの短時間設定による検証時には、そんなことにはならないだろうが、スリープから復帰した際のif文をLEDテープライトのON/OFF状態で評価しており、アラーム1とアラーム2の区別がつかず、スケッチアップロードのタイミングによっては挙動が逆になる電源投入時間を考慮(ON/OFFの場合、ON前かつOFF後に)する必要が出てくるため、時間で評価する方がベターだろう。

 と...放置するのも何なので若干、ごちゃごちゃするが、スケッチを追加編集して、時間で評価してみたところ、期待通りの結果を得ることができた。

 注意点として、この例のように分単位で評価する場合、デバグ用時刻表示がRTC設定時間に、attachInterrupt()、もしくは、alarmInput()との兼ね合いからなのか、秒指定可能なアラーム1も分単位(0秒)の直前でスリープから復帰するようでスリープ復帰時における時間評価の際には、アラーム設定よりマイナス1分しておかないと、うまくいかなかった。(これからやってみるが1時間単位でも同じかも?)...現時点ではLEDのON/OFF評価にして挙動が正しくなるタイミングでスケッチをアップするのが無難かも。

 んー...なぜか、スリープ復帰初回の時刻が、RTC設定日付になってしまうため、評価できない...全く解決策にはなっていないものの、後に改善策を見出す、きっかけとするためにも経過を残し、時間とLED消灯を条件とした合作にしておくことにする。(挙動の逆転電源投入タイミングを考慮する必要を回避するため、1回めをON、2回めをOFFとした場合、1回めのアラーム時刻より前かつ2回めのアラーム時刻の後にスケッチのアップロード電源投入を行なうものとする。)

 ライトには、LEDテープライトを使うわけだが、先日作ったばかりのデスク下にある棚用の照明と同様にLEDテープライト+アルミアングル+カプトンテープで補強したものを使う予定。

 と思ったが、デスク下用のライトは作り直すことにし、差し替えたので、そのアルミアングル約34cm、LEDテープライト36球 約30cmを、ここで使うことにした。

 検証時に少しハマったのは、モジュール仕様なので当然なのだが、RTC.setAlarm()関数は、DS3232RTC.h上では、引数に[秒]を入れても入れなくてもよいようになっているが、アラーム2については、秒指定しても割り込みが入らず、分指定をすると割り込みできたこと。

 あ、日付・時刻などでアラーム設定している場合、運用するなら、他のRTCライブラリ同様、RTCモジュールにバックアップ電池(CR2032を使う場合、DS1302/DS1307は、そのまま、DS3231はパターンカットなど要加工)をセット、RTC時刻を設定してスケッチをアップロード、スケッチのRTC時刻設定箇所をコメントアウト後、再度、スケッチをアップロードしておかないとダメだ。

 1度も電源を落とさないなら不要だが、運用場所への移動時など、1度でも電源を落とすことがあるなら、コメントアウトしておかないと再度電源を投入した際、以前アップロードした時点でスケッチ上に設定してあったRTC時刻に再設定されてしまい、日付・時刻などでアラーム設定している場合は、その分、誤差が出て、たいていの場合、アラーム設定の意味がなくなってしまうため。

 というわけでスリープ初回復帰時にRTC設定時間になってしまう問題は解決...。

[2018/02/17]

 ん...?期待しない時間に点いたり消えたりする...。

 何か勘違いしてる?もしかしてALM1_MATCH_HOURS/ALM2_MATCH_HOURSだとX時Y分じゃなくてX時間Y分後になっちゃうとか!?それをやるなら、ALM1_MATCH_DATE/ALM2_MATCH_DATE!?違うよね...HOURSでいけるよね?いやいや、やっぱり、DATEか...。

 だとすると、LEDのON/OFF状態での評価はいらなくなって、ちゃんと指定時刻でON/OFFしてくれる...なら全て解決だが、とりあえず、スケッチを修正しつつ、試してみよう...。

[2018/02/18]

 と思いきや...先に機能するアラーム1を時間で評価しようとチェックしてみると電源投入時間になってしまい、電源投入時間が限定されてしまう...これなら、まだ、タイミングの制約はあるとはいえ、電源投入時間に幅があるLED点灯/消灯を評価した方がマシ...。

 ライブラリの説明にあるif(RTC.alarm(ALARM_1)){}を使うとloop{}内のアラームリセットの有効・無効に関わらず、アラームのリセットが先にかかってしまうようで条件文内の処理を1行も実行できない上に[Wake up]の[Wa]でシリアルモニタ上の表示が止まり、後のif(RTC.alarm(ALARM_2)){}のSerial文は表示されないので評価すらされていない模様...。

 LEDの点灯タイミングでdigitalWriteでledPinをHIGHにし、RTC.alarm(ALARM_1);とすると点灯はするが、その後のelse文(digitalWrite(ledPin, LOW);やRTC.alarm(ALARM_2);)が評価されないようでLEDがOFFにならない...。

 尚、時間、分(、秒)の指定は、ALM1_MATCH_HOURS/ALM2_MATCH_HOURSでよさ気だが、少なくともアラーム2の結果を見る限り、アラームが機能した時点の[時間]は、設定通りだが、アラーム時間をジャストX時0分とした場合、アラーム復帰時として評価する時間は、やはり、[分]同様、早めに復帰するようでアラーム設定時間マイナス1時となった。([分]指定時刻によっては[X時]自体は、アラーム設定と同じ時間になるかも...?)

#include <DS3232RTC.h>    // http://github.com/JChristensen/DS3232RTC
#include <Streaming.h>    // http://arduiniana.org/libraries/streaming/
#include <avr/sleep.h>
#include <avr/power.h>
 
const int trigerPin = 2;
const int ledPin = 13;
const uint8_t alarmInput(trigerPin);
bool alarm_state = false;
 
const int on_hour = 17;
const int on_minutes = 0;
const int on_seconds = 0;
const int off_hour = 23;
const int off_minutes = 59;
const int off_seconds = 0; // 今回のようにAlarm2とした場合は使えないので固定
 
void wakeUpNow(){
 Serial.println("Wake up!");
 
 alarm_state = true;
 
 // デバグ用
 int val = digitalRead(ledPin);
 Serial.print("val = ");
 Serial.println(val);
 Serial.print("hour = ");
 Serial.println(hour());
 Serial.print("minute = ");
 Serial.println(minute());
 Serial.print("second = ");
 Serial.println(second());
 // デバグ用
 
 if (digitalRead(ledPin)) {
  digitalWrite(ledPin, LOW);
 } else {
  digitalWrite(ledPin, HIGH);
 }
}
 
void sleepNow(){
 Serial.println("Sleep...");
 delay(12);
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 sleep_enable(); //スリープの有効化
 
 // アラームの割り込み時の信号はLOWなので第3引数は、FALLING
 attachInterrupt(digitalPinToInterrupt(alarmInput), wakeUpNow, FALLING);
 sleep_mode(); //指定したモードでスリープを開始
 sleep_disable(); //割り込み時、スリープから復帰
 detachInterrupt(0); //割り込み処理解除
}
 
void setup() {
 Serial.begin(9600);
 
 pinMode(trigerPin, INPUT_PULLUP);
 
 // アラームフラグ、アラーム割り込みフラグの初期化
 RTC.alarm(ALARM_1);
 RTC.alarm(ALARM_2);
 RTC.alarmInterrupt(ALARM_1, false);
 RTC.alarmInterrupt(ALARM_2, false);
 // 割り込み用のINT/SQWピン使用時は、方形(矩形)波出力を無効にする必要がある
 RTC.squareWave(SQWAVE_NONE);
 
 // RTCモジュールで時刻を同期
 setSyncProvider(RTC.get);
 if (timeStatus() != timeSet)
  Serial.println("Unable to sync with the RTC");  // RTCで同期不能
 else
  Serial.println("RTC has set the system time");  // RTCでシステム時刻を設定中
 Serial.flush();
 
/*
 // 初回のスケッチアップロード時の日付時刻を設定、初回のみコメント外し有効にする
 // RTC時間設定 例) 2018/02/13 19:28:20
 tmElements_t tm;
 tm.Hour = 19;
 tm.Minute = 28;
 tm.Second = 20;
 tm.Day = 13;
 tm.Month = 2;
 tm.Year = 2018 - 1970; // tmElements_t.Yearの初期値は1970から始まるものとして算出される
 RTC.write(tm);   // tm構造体からRTCを設定
*/
 
 RTC.setAlarm(ALM1_MATCH_HOURS, on_seconds, on_minutes, on_hour, 0);
 // アラーム1の有効化
 RTC.alarmInterrupt(ALARM_1, true);
 
 RTC.setAlarm(ALM2_MATCH_HOURS, off_seconds, off_minutes, off_hour, 0);
 // アラーム2の有効化
 RTC.alarmInterrupt(ALARM_2, true);
 
 // シリアルモニタに日付時刻を表示
 digitalClockDisplay();
}
 
void loop() {
 // 経過日付時刻表示と必要に応じて割り込みフラグを初期化
 if (alarm_state) {
  alarm_state = false;
  digitalClockDisplay();
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
 }
 sleepNow(); // スリープ
}
 
void digitalClockDisplay(void)
{
 setSyncProvider(RTC.get);
 Serial.print(year());
 Serial.print('/');
 Serial.print(month());
 Serial.print('/');
 Serial.print(day());
 Serial.print(' ');
 printDigits(hour());
 Serial.print(':');
 printDigits(minute());
 Serial.print(':');
 printDigits(second());
 Serial.println();
 Serial.flush();
}
 
void printDigits(int digits)
{
 // 日付時刻1桁時、1桁めに0を設定
 if (digits < 10)
  Serial.print('0');
 Serial.print(digits);
}

 他のDS3231/DS3232ライブラリでも同様なのかは、未確認だが、もう疲れたので、タイミングを見計らって電源を投入することにし、LEDの点灯/消灯状態を条件として評価しておくことにする...。

[2018/03/16]

 ん...?アラーム(割り込み)が効かない(失敗する)ことがある...?

 たいていは、うまくいくのだが、たまに点灯していないことがあり、原因がわからず困っていた。

 調べてみるとDS3231の入力電圧は、推奨3.3Vとのこと...何も考えず、5Vかけていた...。

 3.3Vに変更してテスト中...。

#include <DS3232RTC.h>    // http://github.com/JChristensen/DS3232RTC
#include <Streaming.h>    // http://arduiniana.org/libraries/streaming/
#include <avr/sleep.h>
#include <avr/power.h>
 
const int trigerPin = 2;
const int ledPin = 13;
const uint8_t alarmInput(trigerPin);
bool alarm_state = false;
bool led_state = false;
 
const int on_hour = 17;
const int on_minutes = 0;
const int on_seconds = 0;
const int off_hour = 23;
const int off_minutes = 59;
const int off_seconds = 0; // 今回のようにAlarm2とした場合は使えないので固定
 
void wakeUpNow(){
 Serial.println("Wake up!");
 
 alarm_state = true;
 
 // デバグ用
 int val = digitalRead(ledPin);
 Serial.print("val = ");
 Serial.println(val);
 Serial.print("hour = ");
 Serial.println(hour());
 Serial.print("minute = ");
 Serial.println(minute());
 Serial.print("second = ");
 Serial.println(second());
 // デバグ用
 
 if (digitalRead(ledPin) || led_state) {
  digitalWrite(ledPin, LOW);
 } else if (!digitalRead(ledPin) || !led_state) {
  digitalWrite(ledPin, HIGH);
 }
}
 
void sleepNow(){
 Serial.println("Sleep...");
 delay(12);
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 sleep_enable(); //スリープの有効化
 
 // アラームの割り込み時の信号はLOWなので第3引数は、FALLING
 attachInterrupt(digitalPinToInterrupt(alarmInput), wakeUpNow, FALLING);
 sleep_mode(); //指定したモードでスリープを開始
 sleep_disable(); //割り込み時、スリープから復帰
 detachInterrupt(0); //割り込み処理解除
}
 
void setup() {
 Serial.begin(9600);
 
 pinMode(trigerPin, INPUT_PULLUP);
 
 // アラームフラグ、アラーム割り込みフラグの初期化
 RTC.alarm(ALARM_1);
 RTC.alarm(ALARM_2);
 RTC.alarmInterrupt(ALARM_1, false);
 RTC.alarmInterrupt(ALARM_2, false);
 // 割り込み用のINT/SQWピン使用時は、方形(矩形)波出力を無効にする必要がある
 RTC.squareWave(SQWAVE_NONE);
 
 // RTCモジュールで時刻を同期
 setSyncProvider(RTC.get);
 if (timeStatus() != timeSet)
  Serial.println("Unable to sync with the RTC");  // RTCで同期不能
 else
  Serial.println("RTC has set the system time");  // RTCでシステム時刻を設定中
 Serial.flush();
 
/*
 // 初回のスケッチアップロード時の日付時刻を設定、初回のみコメント外し有効にする
 // RTC時間設定 例) 2018/02/13 19:28:20
 tmElements_t tm;
 tm.Hour = 19;
 tm.Minute = 28;
 tm.Second = 20;
 tm.Day = 13;
 tm.Month = 2;
 tm.Year = 2018 - 1970; // tmElements_t.Yearの初期値は1970から始まるものとして算出される
 RTC.write(tm);   // tm構造体からRTCを設定
*/
 
 RTC.setAlarm(ALM1_MATCH_HOURS, on_seconds, on_minutes, on_hour, 0);
 // アラーム1の有効化
 RTC.alarmInterrupt(ALARM_1, true);
 
 RTC.setAlarm(ALM2_MATCH_HOURS, off_seconds, off_minutes, off_hour, 0);
 // アラーム2の有効化
 RTC.alarmInterrupt(ALARM_2, true);
 
 // シリアルモニタに日付時刻を表示
 digitalClockDisplay();
}
 
void loop() {
 // 経過日付時刻表示と必要に応じて割り込みフラグを初期化
 if (alarm_state) {
  alarm_state = false;
  digitalClockDisplay();
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
 }
 sleepNow(); // スリープ
}
 
void digitalClockDisplay(void)
{
 setSyncProvider(RTC.get);
 Serial.print(year());
 Serial.print('/');
 Serial.print(month());
 Serial.print('/');
 Serial.print(day());
 Serial.print(' ');
 printDigits(hour());
 Serial.print(':');
 printDigits(minute());
 Serial.print(':');
 printDigits(second());
 Serial.println();
 Serial.flush();
}
 
void printDigits(int digits)
{
 // 日付時刻1桁時、1桁めに0を設定
 if (digits < 10)
  Serial.print('0');
 Serial.print(digits);
}
[2018/03/18]

 これはこれとしてHIGH/LOWの判断が微妙なケースがあるのか、状況は変わらないっぽい。

 仕方ないのでLEDの状態を示すboolean型フラグに変更...でもよいが、敢えてor条件として追加し、検証中。

[2018/03/21]

 HIGH/LOWが微妙とかいう話ではなく、コンセントかな...?

[2018/03/24]

 う、違った...大丈夫だと思っていた位置のコンセントでも点灯しないことがあった...一体、なぜ...。

...
 
void loop() {
 // 経過日付時刻表示と必要に応じて割り込みフラグを初期化
 if (alarm_state) {
  alarm_state = false;
  digitalClockDisplay();
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
  setSyncProvider(RTC.get);
  if (hour() == off_hour && flg_led) {
   digitalWrite(ledPin, LOW);
   flg_led = false;
  } else if(hour() == on_hour && !flg_led){
   digitalWrite(ledPin, HIGH);
   flg_led = true;
  }
 }
 sleepNow(); // スリープ
}
 
...
[2018/03/29]

 え...、ON時間にオフになり、OFF時間にONになることがあった...。

 if(RTC.alarm(ALARM_1)){}とかが使えれば、こんなことにはならないと思うが...なぜか、使えないし...。

 仕方ないから、loop()内で苦肉の策を講じてみた...。

[2018/04/02]

 なんでだ...、何か勘違いしているのかな...謎すぎる...。

ウェブ造ホーム前へ次へ