[arduino][breeding]壁スイッチにタイマーを付ける
生物を室内で飼育するためには日周期をコントロールするために、ライトのON/OFFを毎日行う必要があります。よくやるのはコンセントにタイマーをかませて、ライトのON/OFFをコントロールするものですが、部屋の壁スイッチや、機器に備え付けのスイッチをON/OFFするには電気工事や本格的な改造が必要になります。しかし、やりたいことは単純なのに大掛かりな工事や高額な改造費を要求されるのは、非常に残念です。
そこで、再びarduinoとサーボモーター(角度調整のできるモーター)を利用して、物理的にスイッチをON/OFFするだけのシンプルなタイマーを作りました。
arduinoは非常に自由度の高いマイコンで様々なことが可能ですが、苦手なことの一つは、意外にも時間を設定した単純なタイマー処理です。というのも、arduinoの内部時計は非常に精度が悪く、日差でも1分以上ずれる場合があります。そこで、今回はarudinoに加えて、時計モジュール(zs-042)を利用しました。時計モジュールは200円程度、今回はarduinoも300円程度買えるaruduino nano(300円程度)にしたので、サーボを除けば中心的な電子基板は500円程度で購入できます。サーボはarudinoの電流でも十分利用可能な、マイクロサーボ(SG90)を利用しました。
バッテリーでの運用も考えて、時計モジュールに設定したアラートで1時間ごとにarduinoを起動させ(その間、arudinoはスリープ状態)、その際にアラートが設定した時刻であればサーボを起動してONあるいはOFFにスイッチを動かすということにしました。
スケッチは次の通り。
#include <Time.h> #include <TimeLib.h> #include <DS3232RTC.h> #include <Wire.h> #include <avr/sleep.h> #include <avr/power.h> #include <avr/interrupt.h> #include <Servo.h> boolean restart = false; volatile boolean alarmIsrWasCalled = false; Servo myservo; // create servo object to control a servo void setup() { // Serial の設定 Serial.begin(9600); // RTC Time の設定 setSyncProvider(RTC.get); setTime(RTC.get()); // Alarm 設定 RTC.alarmInterrupt(1, false); RTC.alarmInterrupt(2, false); RTC.alarm(ALARM_2); //一時間に一回起きる。 RTC.setAlarm(ALM2_MATCH_MINUTES , 00, 00, 0, 0); RTC.alarmInterrupt(ALARM_2, true); attachInterrupt(0, wakeup, FALLING); } void loop() { //一時間ごとに起動して時計合わせをする。時間になっていればサーボを作動させる。 if (restart) { if (RTC.alarm(ALARM_2)) { setTime(RTC.get()); //digitalClockDisplay(); if (hour() == 8) { myservo.attach(9); moveservoDown(); myservo.detach(); } if (hour() == 20) { myservo.attach(9); moveservoUp(); myservo.detach(); } } restart = false; } delay(1000); goToBed(); } void digitalClockDisplay(void) { // digital clock display of the time setSyncProvider(RTC.get); //sync time with RTC Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(' '); Serial.print(day()); Serial.print(' '); Serial.print(month()); Serial.print(' '); Serial.print(year()); Serial.println(); Serial.flush(); } void moveservoUp(void) { myservo.write(107); // tell servo to go to position in variable 'pos' delay(1000); // waits 15ms for the servo to reach the position myservo.write(90); // tell servo to go to position in variable 'pos' delay(1000); // waits 15ms for the servo to reach the position } void moveservoDown(void) { myservo.write(73); // tell servo to go to position in variable 'pos' delay(1000); // waits 15ms for the servo to reach the position myservo.write(90); // tell servo to go to position in variable 'pos' delay(1000); // waits 15ms for the servo to reach the position } void printDigits(int digits) { // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(':'); if (digits < 10) Serial.print('0'); Serial.print(digits); } void goToBed() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); power_all_enable(); } // 起動 void wakeup() { restart = true; }