起きれない
朝、ちゃんと起きてますか?私は起きてません。アラームが鳴っても無意識で止めて二度寝をしてしまいます。気づいたときにはもう手遅れ。そんなとき、アラームと同時に部屋の明かりを点けてくれると自然と目が覚めるのではないかと思いつきました。
時計 + 学習リモコン
構成はシンプルです。時計と学習リモコンを合体させるだけです。CPUには、arduinoのブートローダーを搭載したATmega328を使用するので、arduinoのライブラリがそのまま使用できます。時計・リモコンともに、検索すればすぐに作り方やサンプルコードを見つけることができます。
具体的には、リモコン部分は「IRremote Arduino Library」を使用しました。時計は「RX8900 DIP化モジュール(秋月電子 K-13009)」を接続して取得するようにしました。ライブラリはこちらのページを参考に、初期化部分を少し変更したものを使用しました。
表示部には、LCDキャラクタディスプレイを使用しました。「KanaLiquidCrystalライブラリ」を使用し、カタカナを表示できるようにしました。
ハードウェア
今回は、ユニバーサル基板で作成しました。プリント基板が便利で今回も発注しようかと思ったんですけど、ツイッターなどで他の方の作品を見るとユニバーサル基板でしかも配線がきれいな方がいて、私もプリント基板に甘えないでユニバーサル基板できれいな配線をしたいと思いました。
しかし、最後の最後で配線のし忘れが発覚し、しかもすでに配線先は被覆線で埋もれているので裏からの配線は不可能でした。仕方がないので、ICのピンを曲げて表から配線しました。
やっぱり、プリント基板に甘えていこうと思います。
学習リモコン
赤外線LEDでリモコン信号を送信する必要があるのですが、これが難しかったです。可視光のLEDは1kΩの抵抗と直列に繋いで5Vの電圧をかければ光るだろうという認識なのですが、赤外線は違いました。少なくともリモコンとして機能させるには、可視光のLEDと比較して大きい電流を流す必要があります。今回は39Ωの抵抗を使用し、約90mA流れるようにしました。また、このときの抵抗の消費電力は約500mWです。なので、1Wの抵抗を使用しました。実際には赤外線信号はパルスなので、ここまで大きい定格電力の抵抗を使う必要は無いかもしれませんが、手持ちの抵抗がすべて1/4Wで心もとないのでいっその事1Wでいったれと言うことで1Wにしました。
ちなみに、これで悩んでいる時にこの記事を書きました。
抵抗は1/2ワットを買っておけ
赤外線LEDは3つ使いました。これは単に照明のリモコンがLEDを3つ使っていたからです。
ATmega328は、90mAもの電流を直接制御できないので、MOSFETを使ってスイッチングしました。3つのLEDを1つのMOSFETで制御したかったので、500mAに対応したものを使用しました。
赤外線受光部分は簡単です。赤外線リモコン信号を受信するモジュールがあるので、これを使いました。電源のプラスとマイナスと信号の3pinで簡単な構成です。
時計
時計部分のハードは、割りと簡単でした。RTCモジュールをi2cで接続するだけです。主電源がなくなっても時を刻んでほしかったので、電気二重層コンデンサーをバックアップ電源として搭載しました。RTCが優秀なのか、一週間主電源に接続しなくても動作していました。正確な測定はしていませんが。
ボタン
ボタンの配置は、You Tubeの「よみやチャンネル」さんの動画を参考に配置しました。
ArduinoでAudio Timerを作ろう 1 - 時計・タイマー部製作編
接続方法は、ピン数が足りなくなりそうだったので、抵抗分圧を使用したアナログ入力を使用しました。その際、しなぷすさんの「I/Oピン一つで読めるキーパッドの設計サービス」を使い抵抗値の設計をしました。
全体回路図
ソフトウェア
loop関数
時刻を表示したり、リモコン信号を受信したり、アラーム設定をしたり、モードを切り替えできるようにしています。「メッセージ」という現在の状態を表す仕組みを作り、モード切り替えを制御してみました。win32のメッセージループを想像しながら作成しました。ちなみに、メッセージループはなんとなくの仕組みを知っているだけで実際に書いたことはありません。
消費電力を抑えるために、スリープを使用しました。Narcolepticというライブラリを使用して簡単に実装できました。スリープ中はほぼすべての機能が停止するので、ボタンの状態変化を検知できません。定期的にスリープから復帰して、ボタンの状態を見る必要があるので、ウォッチドックタイマで15ms置きに復帰してボタンの状態を見るようにしました。ボタン押下による外部割り込みで復帰できればスリープ間隔を長くできるのですが、外部割り込みの回路を作っていないので出来ませんでした。
loop関数
void loop() {
RX8900.getDateTime(&tim);
// アラーム処理
AlarmProcessing();
// lcdバックライト処理
//millisを使用していたが、スリープを導入したことでmillisが使えなくなったので、
//ループ関数を実行した回数で指定時間が経過したかの判定を行う。
prevButtonMillis++;
if (prevButtonMillis > 5000 / 15) {
SetLCDbacklight(false);
}
lcd.home();
//メッセージの設定
SetModeMessage();
//メッセージ処理
switch (GetModeMessage()) {
case ModeMessage::DateTime:
DispDateTime();
break;
case ModeMessage::Learn:
lcd.print(F("ガクシュウ モード "));
lcd.setCursor(0, 1);
lcd.print(F(" "));
break;
case ModeMessage::LearnDetail:
LearnMode();
message = ModeMessage::DateTime;
break;
case ModeMessage::Alarm:
lcd.print(F("アラーム モード "));
lcd.setCursor(0, 1);
lcd.print(F(" "));
break;
case ModeMessage::AlarmDetail:
AlarmMode();
message = ModeMessage::DateTime;
break;
case ModeMessage::TimeSetting:
lcd.print(F("ジカン セッテイ "));
lcd.setCursor(0, 1);
lcd.print(F(" "));
break;
case ModeMessage::TimeSettingDetail:
TimeSettingMode();
message = ModeMessage::DateTime;
break;
case ModeMessage::DeleteData:
lcd.print(F("データ サクジョ "));
lcd.setCursor(0, 1);
lcd.print(F(" "));
break;
case ModeMessage::DeleteDataDetail:
DeleteDataMode();
message = ModeMessage::DateTime;
break;
case ModeMessage::AlarmTest:
lcd.print(F("IR テスト "));
lcd.setCursor(0, 1);
lcd.print(F(" "));
break;
case ModeMessage::AlarmTestDetail:
IrSendTest();
message = ModeMessage::DateTime;
break;
default:
break;
}
//スリープ ウォッチドックタイマで15msスリープ
Narcoleptic.sleep(WDTO_15MS);
}
曜日判定
使用したRTCには、曜日を計算して設定する機能がありません。自分で計算して正しい曜日を設定する必要があります。この計算には、C言語の標準機能であるtime.hのmktime関数を使用しました。mktime関数は、日付を設定したtm構造体のポインタを渡すと、正しい曜日を計算して設定してくれます。
曜日設定部分抜粋
// time.hの機能を使用し、曜日の算出
tm timeHstruct;
timeHstruct.tm_sec = 0;
timeHstruct.tm_min = 0;
timeHstruct.tm_hour = 1;
timeHstruct.tm_mday = tim.day;
timeHstruct.tm_mon = tim.month - 1;
timeHstruct.tm_year = 2000 + tim.year - 1900;
// mktimeを呼ぶことで、曜日が計算され、引数で渡した構造体が変更される
mktime(&timeHstruct);
tim.week = GetRX8900WeekDayFromTimeHData(timeHstruct.tm_wday);
ソースコード全体
全体のコードはとても大きく、フラッシュメモリを22728バイト(70%)使っています。書き込みにも時間がかかります。すべてのコードは、GitHubにあるので興味のある方は御覧ください。
TimerRemoCon(GitHub)
電池駆動のテスト
以前作成したアナログメーター時計のリベンジです。アナログメーター時計は一晩で電池が無くなってしましました。今回はスリープを使っているので省電力なはずです。
今回、5Vで動くように設計したので、電池ボックスに昇圧モジュールをつけた簡単な回路を作成し、テストしました。電池基盤には、スイッチ・昇圧モジュール・ダイオード・リセッタブルヒューズ・コネクタを搭載しています。RTCのバックアップ用に1Fの大容量コンデンサを使っていて逆流したらいやなのでダイオードをつけました。ショットキーバリアダイオードを使用しています。
結果
エネループ三個で一週間くらい動作続けました。アナログメーター時計より長いですが、めざまし時計として使うには短いです。スリープから復帰する方法を全く考えずに設計し、スリープ間隔を短くしたことが原因かと思います。また、昇圧モジュールを使って5Vを作っているので、昇圧部分でロスが発生しているのも原因の一つかと思います。
省電力化するには、スリープ間隔を長くしてボタン押下でスリープから復帰できるようにする・低い電圧でも動作するようにして昇圧回路を使わなようにする、等が考えられます。
まとめ
今回使用した部品は、PartsCabi.netにまとめました。
目覚まし学習リモコン(PartsCabi.net)
PartsCabi.netのリストには抵抗等を入れていません。複数個入ってパック売りしているものから数個しか使っていないものもあります。総額は2千円ちょいといったところでしょうか。
じつは、同じようなことを実現する既製品は存在します。皆さんご存知、スマートリモコンですね。スマホやスマートスピーカーと連動して家電を操作するやつです。高機能の代わりに値段が高くなっています。どれもスマホと連携して使います。
今回作成したものは、単独で動作して時間になったら赤外線信号を発するシンプルなものです。多分、このようなシンプルな製品はないと思われるので、良いものが作れたと満足しています。
ちなみに、朝は、起きれるときは起きれますし、起きれないときは起きれないです。結局、夜更かししたかどうかで朝起きれるかが決まるようです。まぁ、でも、夜更かしして無くても起きれないときが有ったのが、夜更かししなかったら割りと起きれるようになったので、効果は有ったわけです。
投稿者の人気記事
-
shigobu
さんが
2022/04/30
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する