室内灯自動点灯システム

システムなんて言うほど大した物ではないが、先日室内灯の蛍光灯が切れたのを機会に、LEDシーリングライトに交換した(日立LEC-AH08U)。お安い割に明るさ調整や色も白から電球色まで変えられるです。

付属のリモコンでON/OFF出来るのだが、リモコンが小さく、さらにボタンも小さくて押しにくい感じ、暗い部屋に来ていざ点けようとするとマゴマゴ感が否めない。そこでせっかくのリモコン受信付きの室内灯ということで人感センサーで自動で点灯する仕組みを作ることにした。

計画内容

  • 基本的にリモコンは使用せず、光量や色合い設定の為だけとする。
  • Arduinoなどのワンボードマイコンを使用して学習リモコンの要領でIR LEDを発光させる
  • 人感センサーでONさせるがOFFはしない(トイレの人感センサーライトで散々経験しているが、人がじっとしていると消灯してしまうので)。OFFの仕組みは別に用意する(フォトレジスタに手をかざしてOFFにする仕様)。
  • センサとLEDを仕込んだ適当なケースを3Dプリンタで製作

学習リモコン仕様

  • Arduino Nano(安い互換品)を使用
  • 人感センサー:‎ARCELI00595
  • IR LED:uxcell IRLED
  • IR受光素子:HX1838(リモコンコード取得用)
  • フォトレジスタ uxcell GL5528

右が配線図。受光素子はブレッドボード環境で実験的にリモコンコードを読み込むために使用することとし、実際の装置には組み込まない(装置としての学習機能は無し)

学習リモコン配線図

リモコン信号の学習

Arduinoのライブラリとして、ライブラリマネージャから赤外線リモコンのためのIRremoteをインストールすると、サンプルで付いてくる「ReceiveDump」を使用すると、使用したいリモコン信号を取得することが出来る。Arduino開発環境からシリアルモニタを起動しておくと下記のようにリモコン受信データの詳細がレポートされる。下記の例は今回ターゲットとしているシーリングライトのリモコン信号(ON)の詳細。

Protocol=PULSE_DISTANCE Address=0x0 Command=0x0 Raw-Data=0x3DC2FB 88 bits LSB first

Raw result in internal ticks (50 us) - with leading gap
rawData[180]: 
・・・・・
Raw result in microseconds - with leading gap
rawData[180]: 
・・・・・
Result as internal ticks (50 us) array - compensated with MARK_EXCESS_MICROS=20
uint8_t rawTicks[179] = {65,33, 10,24, 9,7, 9,8, 8,9, 8,9, 8,8, 8,9, 8,9, 8,9, 8,8, 8,9, 8,9, 8,25, 8,9, 8,8, 8,9, 8,9, 8,9, 8,8, 9,8, 9,24, 9,24, 9,8, 9,8, 9,8, 8,8, 9,8, 9,8, 8,25, 9,8, 8,25, 8,9, 8,25, 9,24, 9,24, 9,25, 8,8, 9,24, 9,8, 9,25, 8,8, 9,8, 9,8, 8,9, 8,8, 9,8, 8,9, 8,9, 8,25, 8,25, 8,25, 9,24, 9,24, 9,25, 8,25, 8,25, 9,8, 9,8, 8,25, 8,9, 8,8, 9,8, 9,8, 8,9, 8,25, 8,25, 9,8, 8,25, 9,25, 8,25, 8,25, 8,25, 9,8, 8,25, 9,8, 8,9, 8,9, 8,8, 8,25, 9,25, 8,25, 8,9, 8,25, 8,25, 8,25, 8,25, 9,8, 8,9, 8};  // Protocol=PULSE_DISTANCE Address=0x0 Command=0x0 Raw-Data=0x3DC2FB 88 bits LSB first

Result as microseconds array - compensated with MARK_EXCESS_MICROS=20
uint16_t rawData[179] = {3230,1670, 480,1220, 430,370, 430,420, 380,470, 380,470, 380,420, 380,470, 380,470, 380,470, 380,420, 380,470, 380,470, 380,1270, 380,470, 380,420, 380,470, 380,470, 380,470, 380,420, 430,420, 430,1220, 430,1220, 430,420, 430,420, 430,420, 380,420, 430,420, 430,420, 380,1270, 430,420, 380,1270, 380,470, 380,1270, 430,1220, 430,1220, 430,1270, 380,420, 430,1220, 430,420, 430,1270, 380,420, 430,420, 430,420, 380,470, 380,420, 430,420, 380,470, 380,470, 380,1270, 380,1270, 380,1270, 430,1220, 430,1220, 430,1270, 380,1270, 380,1270, 430,420, 430,420, 380,1270, 380,470, 380,420, 430,420, 430,420, 380,470, 380,1270, 380,1270, 430,420, 380,1270, 430,1270, 380,1270, 380,1270, 380,1270, 430,420, 380,1270, 430,420, 380,470, 380,470, 380,420, 380,1270, 430,1270, 380,1270, 380,470, 380,1270, 380,1270, 380,1270, 380,1270, 430,420, 380,470, 380};  // Protocol=PULSE_DISTANCE Address=0x0 Command=0x0 Raw-Data=0x3DC2FB 88 bits LSB first

uint16_t address = 0x0;
uint16_t command = 0x0;
uint32_t data = 0x3DC2FB;
・・・・・

この例ではプロトコルがPULSE_DISTANCEとなっており、サポートしているメーカーフォーマットでは無いっぽいため、rawDataとして直接送信する必要がある。ターミナルに出力された詳細データのrawDataはそのままCのソースに貼り付けられる形式となっている。

// 初期化
IrSender.begin(IR_SEND_PIN);
// 送信部
uint16_t rawData[179] = {
  3230,1720, 380,1270, 380,470, 380,420, 480,370, 430,420, 430,420,
  430,420, 380,420, 430,420, 430,420, 430,420, 380,470, 380,1270,
  380,470, 380,420, 430,420, 430,420, 430,420, 380,470, 380,420,
  430,1270, 380,1270, 430,420, 380,470, 380,420, 430,420, 430,420,
  430,420, 380,1270, 430,420, 380,1270, 430,420, 430,1220, 430,1270,
  380,1270, 380,1270, 430,420, 380,1270, 430,420, 430,1220, 430,420,
  430,420, 430,420, 380,470, 380,420, 430,420, 430,420, 380,470, 380,1270,
  430,1220, 430,1270, 380,1270, 380,1320, 380,1270, 380,1270, 380,1270,
  430,420, 430,420, 380,1320, 380,420, 380,470, 380,420, 430,420, 430,420じ,
  430,1270, 380,1270, 380,470, 380,1270, 380,1270, 430,1270, 380,1270,
  380,1320, 380,420, 430,1270, 380,420, 430,420, 380,470, 380,470, 380,1270,
  380,1270, 430,1270, 380,470, 380,1270, 380,1270, 380,1270, 430,1270,
  380,420, 430,420, 380
};
IrSender.sendRaw(rawData, sizeof(rawData) / sizeof(rawData[0]), 38);

Arduinoのプログラムでは人感センサーの出力に連動してON信号を送信、フォトレジスタのアナログ入力レベルが一定以下になったとき(手をかざすなど)にOFF信号を送信する仕組みとした。

フローチャート(draw.io)
START
START
初期化
初期化
Yes
Yes
No
No
readmode?
readmode?
受信モード初期化
受信モード初期化
送信モード初期化
送信モード初期化
Loop
Loop
Yes
Yes
No
No
readmode?
readmode?
Yes
Yes
受信データあり
受信データあり
受信データ
ターミナル出力
受信データ ターミナル出力
光センサ
光センサ
On
On
Off
Off
LIGHT Mode
LIGHT Mode
LIGHT OFF CMD
LIGHT Mode Off
LIGHT OFF CMD…
Off
Off
Off
Off
LIGHT Mode
LIGHT Mode
5000ms
5000ms
Yes
Yes
No
No
人感センサ
人感センサ
LED インジケータON
LED インジケータON
1500ms
1500ms
Yes
Yes
人感センサ
人感センサ
LIGHT ON CMD
LIGHT ON CMD
1000ms
1000ms
500ms
500ms
LED インジケータOFF
LED インジケータOFF
100ms
100ms
LIGHT Mode On
LIGHT Mode On
Text is not SVG – cannot display

←ソースコードと簡単な資料はこちら

完成した装置全貌

3Dプリンタでザックリ作ったボックスと内部配線。

ボックスの上部にリモコン発信用赤外線LEDとOFF感知用フォトレジストを埋め込んでます。

リモコンが小さすぎて操作しにくいなら、従来通り壁スイッチで良いじゃん!というのはごもっともなお話ですが、それに気づいたのが一通り完成して運用し始めてからでしたw
あと、最近の半導体不足でArduinoが純正品しか手に入らず比較的高価なため、安価なRaspberryPi Picoに移植するべく開発環境など準備中・・・てか次の投稿ネタに保存中。。

テスト印刷など

3Dプリンタ購入後、各種設定や印刷環境の整理を行い、テスト印刷などをボチボチ始めている。

ガチガチにサポート材が追加されてます

まずは定番として、FF11からの吸い出しモデルのタルタルを印刷。Metasequoiaに読み込んでSTL出力。それをプリント出力用のFlashPrintにてプリンタ出力。FlashPrintでは土台やサポート材も自動で追加してくれるので、複雑な形状もあまり気にせずに印刷出来そう。但し、あまりゴチャゴチャしたサポート材だとプリントアウト終了後にサポート材を取りはずす時にモデルを破壊してしまう可能性もあり、どこかで工夫が必要なような気がする。

とりあえず完成品

完成後の物が右の写真。サポート材を除去したときに色々折れてしまった所もあり、接着剤で補修してます。フィラメントは同時購入の物ではなく、フィギュアとか仕上がりのキレイなシルク仕上げのPLAを使用しました。

製作した防湿ケース

表面がキラキラしていてとても良い感じ。通常のPLA素材とは違った質感が良いです。

また、フィラメントもボチボチ増えてきてしまい、保管方法も考えなければと、色々調査し、

https://www.youtube.com/channel/UCn23JisBcbb-Nw-3IhofaNA

↑のサイト様を参考に、保管兼引き出し用の防湿ケースの設計と製作を行った。

ケースは参考のサイト様どおりにダイソーで買ってきた300円タッパにフィラメントリール用軸とケースを立てて使うための脚、湿度計取り付けホルダをFreeCADで設計して製作しました。

その他、フィラメント引き出し用のナイロンチューブの蓋とかも製作。またナイロンチューブのケース通し穴に関しては参考サイト様ではTPU素材で製作されていたけど、こちらではホームセンターで適当なサイズのゴムグロメットを買ってきて密閉用として代用してます。

いろいろ試しながら印刷条件を見つけている段階です。タルタルフィギュアもフィギュアサイズやサポート材の数、元のモデルの微調整やら印刷時温度設定など変えながら何度かやり直してます。
だいたいノリが分かってきた所で、再び実用品も作って行こうかと思います。

3Dプリンタ購入

以前から検討していた3Dプリンタを購入しました。動機の大半が興味本位でオモチャが欲しかった程度なんですが、生活用便利治具や自在なケース類、慣れてきたらプラモデルの補助パーツの作成を考えての事なので、方式としてはFDM、またあまり大きいと自部屋での作業に向かないのである程度小さい物(金属製ラックで運用出来る程度)。

ということで、FLASHFOGEのAdventure3に決定し。日本法人の公式ページでポチりました。最低一週間で納品とのことなのでとりあえず発注だけしてボチボチ準備をしようとしていたら、何と次の日に発送通知メールが届き、その次の日の午前に佐川さんが届けに来てくれました。「ちょ、Amazonより早くね?」ということで慌てて開封。

お早い到着で
ラックにもスッキリ収まるサイズ

ルミナスのシステムラック(25mm)でスッキリ収まったけど、天板の水平がイマイチ取れていなそうなのが心配。

マニュアルを見ながら初期設定(キャリブレーション)など行い、付属のフィラメントを導入して、内蔵メモリにある単純な直方体と、使い方の良く分からないNozzle_Remover(ノズルを取り外すための治具らしい)を印刷。

20mm四方の直方体は10分程度、治具は1時間半くらいかかりました。

次に当初の目的である生活治具で、天板固定治具の印刷を行った。これは部屋で使用しているコンパクトな作業台としてキャンプ用のキッチンテーブルを使用しているが、天板がアルミのロールテーブルになっているためコレをホームセンターで買ってきたパイン材に変更している。とりあえずはロールアルミテーブルの上に乗せて使っていたが、3Dプリンタで治具を作製してアルミパイプにしっかり取り付けるという目的。

↑3mmの木ネジ4個で天板に取り付け、アルミパイプを軽くホールド出来る治具を4個作製

アルミパイプに取り付けたところ、お試し試作でPLAなので割れないように少し緩めに製作。コレでも十分に実用的だが、あまりよく外れるようなら内側にテープを貼るか、きつめのABSで製作する必要があるかも知れない。

←は使用しているキッチンテーブル、古いヤツなので、これの収納ラックとか風除け板の付いていないヤツ。メインの天板を16mmのパイン材に交換しました(水性ニスをベタベタに塗ってツヤを出してます)。

いきなり目的のブツを作ってしまったという。。。それくらいお手軽に使えるのは想定外でした。次は何を作ろうかと、フリー素材でハロウィンのカボチャお化けのデータを取ってきて作ってみたら、目と口の穴のところで材料が飛んでしまい失敗(お試しでモデルを小さくしすぎてサポート材が入れられなかったのか)。
複雑な物を作るときはまだまだ勉強が必要ッぽい(データ作成用ソフトFlashPrintの使い方を含めて)。