スマートサンライズアラーム:優しい光で目覚める
部品と用品
| Arduino Nano R3 | 1 |
| Maxim Integrated DS3231MPMB1 ペリフェラルモジュール(RTC) | 1 |
このプロジェクトについて
冬が近づき、夜が昼より長くなると、朝6時に真っ暗で寒い部屋で目覚めるのは悪夢です。部屋を暖かく快適に感じさせる「人工的な日の出」を作れないかと考えました。
これは簡単な課題です。現在のシーリングライトに取り付けられるスマート電球を作り、徐々に部屋を明るくすることで日の出をシミュレートします。うまくいけばスマホと連携させて本格的な目覚まし時計にします。
電球の準備
スマート電球を作るには、まず「普通の」電球が必要です。ソケットがランプにねじ込まれ、電源を供給するためです。ハンマーで叩き割りました。この楽しい作業でガラスがアルミソケットから外れ、ソケットにリード線を半田付けし、底部のピンにも配線すれば、スマート電球のベースが完成です。
次に、すべての電子部品を載せる基板が必要です。ユニバーサル基板をカットし、Arduino Nano、5V電源、すべての電子部品が収まるようにしました。

高電圧回路
安全警告: 50Vを超える電圧を扱います。高電圧に触れると重傷または死亡の恐れがあります。
通常の電球は商用交流電源で動作するため、マイコンで直接電力を制御できません。そこでTRIACを使用します。このデバイスは高速にオン/オフできるリレーのような役割を果たします。マイコンがTRIACをオン/オフして交流正弦波を制御し、調光・調光を行います。
しかし、交流電圧の制御は直流とは異なります。正弦波を精密にカットする必要があり、TRIACを精密なタイミングでオン/オフしなければなりません(下図参照)。つまり、マイコンは商用電源の正弦波がゼロクロスする瞬間を検知し、各半波を同じ大きさにカットする必要があります。そうしないとチラツキが発生します。

商用電源のゼロクロス検出には、トランジスタ出力の4N35(U1)フォトカプラを使用します。正弦波がゼロクロスするとトランジスタがオンになり、マイコンは入力ピンでハイ信号を検知します。このフォトカプラにはもう一つ重要な役割があり、低電圧回路と商用電源回路を絶縁します。
2つ目のフォトカプラ、MOC3063(U2)はTRIAC出力を持ち、マイコンを高電圧TRIAC(Q2)から絶縁します。ゼロクロス機能付きフォトカプラは使用しないでください。それらは正弦波がゼロクロスしたときにしかオンしないためです。

低電圧回路
マイコンにはArduino Nanoを使用します。主な役割はTRIAC制御と、設定時刻での点灯開始です。正確なリアルタイムクロックにはDS3231高精度RTCモジュールを使用し、停電時も時刻を保持します。
チップ用の5V電源には、電球ソケットからの商用電源に接続した安価な5V 700mA降圧電源モジュールを使用します。手軽で便利なソリューションです!

コード
プログラムはシンプルです。スイッチで電源が入ると、まず部屋を明るくしてから徐々に暗くし、電子部品が動作していることを確認します。夜間はDS3231モジュールに保存されたリアルタイムクロックを監視し、午前6時に徐々に明るくして「昼光」レベルまで上げ、夕方にスイッチで電源を切るまで点灯し続けます。
添付のコードを見てください。自己説明的だと思います。そうでなければ私はダメな開発者です!
今後の展開
数日〜数週間試して、朝ちゃんと起きられるか確認します。うまくいけば、このプロジェクトをよりスマートで洗練されたものに進化させます!

おやすみなさい!
コード
/* スマート電球 - 起床時間になると徐々に点灯
* 動作:
* 1) 電源投入時、動作確認のため点灯
* 2) 徐々に暗くなり完全消灯
* 3) 午前6時に徐々に点灯し、夕方にスイッチで消灯
* 4) 部屋が明るいときは点灯しない(フォトセル)
* 使い方:
* - 就寝時にスイッチオン、朝に点灯、退室時にスイッチオフ
* - DS3231モジュールで時刻を保持
* @author Jiri Praus (https://twitter.com/jipraus)
* AC調光参考: https://arduinotehniq.blogspot.com/2014/10/ac-light-dimmer-with-arduino.html
*/
#include <TimerOne.h> // https://www.arduino.cc/playground/Code/
#include "RTClib.h"
#define TRIAC_PIN 2
#define ZERO_CROSS_PIN 3
#define LIGHT_SENSOR_PIN A6
#define FREQUENCY_STEP 75 // 50Hz用の輝度ステップあたり遅延(μs)(60Hzなら65に変更)
#define CHANGE_DIM_LEVEL_EVERY 1 // 調光レベル変更間隔(秒)
#define MAX_DIM_LEVEL 128 // 消灯
#define MIN_DIM_LEVEL 0 // 点灯
#define DARK_THRESHOLD 300 // 暗いと判定するフォトセル抵抗値
// TRIAC制御変数
volatile byte triacCounter = 0;
volatile boolean zeroCrossed = false;
// 調光制御
byte dimLevel = MIN_DIM_LEVEL;
boolean lightOn = false;
// アラームクロック
RTC_DS3231 rtc;
void setup() {
Serial.begin(115200);
digitalWrite(TRIAC_PIN, LOW);
pinMode(TRIAC_PIN, OUTPUT);
pinMode(ZERO_CROSS_PIN, INPUT);
pinMode(LIGHT_SENSOR_PIN, INPUT);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while(1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
noInterrupts();
attachInterrupt(digitalPinToInterrupt(ZERO_CROSS_PIN), zeroCrossDetected, RISING);
interrupts();
Timer1.initialize(FREQUENCY_STEP);
Timer1.attachInterrupt(triacTimerInterrupt, FREQUENCY_STEP);
}
void loop() {
delay(CHANGE_DIM_LEVEL_EVERY * 1000);
checkAlarmClock();
adjustDimLevel();
debugPrint();
}
void zeroCrossDetected() {
zeroCrossed = true;
triacCounter = 0;
digitalWrite(TRIAC_PIN, LOW);
}
void triacTimerInterrupt() {
if (dimLevel >= MAX_DIM_LEVEL) {
digitalWrite(TRIAC_PIN, LOW);
} else if (dimLevel <= MIN_DIM_LEVEL) {
digitalWrite(TRIAC_PIN, HIGH);
} else if (zeroCrossed) {
if (triacCounter >= dimLevel) {
digitalWrite(TRIAC_PIN, HIGH);
zeroCrossed = false;
} else {
triacCounter++;
}
}
}
void adjustDimLevel() {
if (lightOn && dimLevel > MIN_DIM_LEVEL) dimLevel--;
else if (!lightOn && dimLevel < MAX_DIM_LEVEL) dimLevel++;
}
void checkAlarmClock() {
if (!lightOn && isRoomDark()) {
DateTime now = rtc.now();
if (now.hour() == 6 && now.minute() == 0) {
lightOn = true;
}
}
}
boolean isRoomDark() {
return analogRead(LIGHT_SENSOR_PIN) < DARK_THRESHOLD;
}
void debugPrint() {
Serial.print("lightOn="); Serial.println(lightOn);
Serial.print("dimLevel="); Serial.println(dimLevel);
DateTime now = rtc.now();
Serial.print("datetime=");
Serial.print(now.year(), DEC); Serial.print('/');
Serial.print(now.month(), DEC); Serial.print('/');
Serial.print(now.day(), DEC); Serial.print(' ');
Serial.print(now.hour(), DEC); Serial.print(':');
Serial.print(now.minute(), DEC); Serial.print(':');
Serial.println(now.second(), DEC);
Serial.print("lightLevel="); Serial.println(analogRead(LIGHT_SENSOR_PIN));
}
回路図
製造プロセス
- 直列電池接続による電圧加算の実験
- 分圧回路ラボ:設計・測定・キルヒホフの電圧法則検証
- 熱電効果の理解:サーモカップルとゼーベック効果
- ポテンショメトリック電圧計:最小限の負荷で精密な電圧測定
- ジャガイモ電池の作り方:DIY電気化学電源のステップバイステップガイド
- 低電圧AC電源:位相シフト回路のコンポーネントとベストプラクティス
- 12Vツェナーダイオードによる電圧レギュレータ実験
- 電圧フォロワー増幅器:設計、構築、測定ガイド
- 負帰還付き高利得マルチステージ共通エミッタ増幅器の設計
- NPNトランジスタによる高利得差動増幅器の設計
- 特殊ダイオード:ショットキー、トンネル、LED、レーザー、フォトダイオード、ソーラーセルの革新