リモートワークしてるからリモコンつくろうかなと思った.数年前に Arduino で赤外線リモコン作って塩漬けにしてたので,そのときのコードを使ってなにかできそうだ,という感じのモチベーションだ.
できあがったもの
表現しづらいので動画を撮ることにした:
コードはこちら:
概要
Arduino 側で赤外線通信し,PC 側で それとシリアル通信する API サーバーをたてることにより,適当な REST API リクエストを送って赤外線操作できるようになった.クライアントサイドはただリクエストをなげればいい.
用意
用意するのは
- Arduino (なんでもいい)
- 赤外線受光センサー (なんでもいい)
- 赤外線 LED (なんでもいい)
- ブレッドボード (なんでもいい)
ホントになんでもいい.共立電子とか秋月電子とかでパーツを買ってくればいい.どこの電気街にもパーツ屋は存在するし,ステイホームということで通販をつかって待ち遠しいのも楽しい.
Arduino もなんでもよくて,なんなら Arduino でなくてもいい.GPIO があればいい.使ったのは Arduino Duemilanove というやつで,2009 年 大学 1 年のときに買ったもの.ちなみに Duemilanove とは 2009 という意味.
ブレッドボードもなんでもいい.なんでもいいって言ったけど,昔安いのを買ったら配線が微妙につながってなくて原因不明のデバッグに長時間要したことがあったので,それなりのものを選ぶのがよいのかも.やる気があればユニバーサル基板ではんだ付けしてもいいが,今回その価値はなさそうだ.
電子回路の知識はないので信憑性に自信はなく,語れることはない.
赤外線センサーを接続する
赤外線センサーは適当にぶっさす.大抵同じだと思うので自分の例で解説.
データシートを見てピンの用途を確認する.左のピンから (1) Vout の検出した信号,真ん中のピンが (2) GND,右のピンが (3) Vcc となっていた.昔授業で素子の Vcc と GND を間違えた結果,触ったらやけどするほど熱くなって煙を出したことがあるので注意が必要.ハードウェアは厳しい.
なので Arduino の +5V を (3) に,GND を (2) に接続する.(1) は適当にデジタル 4 とかに接続する.
赤外線 LED を接続する
赤外線 LED も適当にぶっさす.これも普通の LED と同じで長い足がアノードで,短い足がカソード.これも Arduino のデジタル 3 とかをアノードに,カソードを GND に接続する.
昔何個か買って数個ぶっ壊したのでこのデータシートが本当にこの LED のものかは不明だけど,グッズのなかに残ってたのでこれだと思うことにする.
完全余談で,潰さないためと確認用にデバッグ中は適当な LED をつけておくとよい.赤外線 LED は不可視なのでカメラを使わないと本当に発してるのかわからない.適当な LED 詰め合わせを買ってたけどこんなには要らない.
抵抗は? となるのだけれど,入れたらなんか光量が足りなすぎたので直接接続することにした.素子にダメージを与えるのでよくないかもしれない.計算して必要に応じて適切な抵抗をいれるのが本当はよいでしょう.
Arduino でコーディングする
Arduino 側の作業になる.やることは C 言語でコーディングするだけだ (Arduino は C++ でもいいが STL もないしパワーもないので結局 Better C になる).
- 入力/出力ピンやシリアルポートの設定
- 赤外線の入力をバッファに入れる
- 赤外線 LED にバッファの内容を出力
- シリアル通信で入力や出力を操作できるようにする
なぜシリアル通信するのかというと, PC で操作したいという理由がまずある.そしてArduino 側でいろいろするのはスペック的にも言語的にも厳しい.ので,Arduino はただの赤外線入力/出力に徹してもらって,PC 側でいい感じの言語で計算をやってシリアル通信でやりとりしよう,というモチベーションになる.
赤外線リモコンの仕様については微妙にややこしいが,以下のページがズバリ参考になる:
赤外線センサーの入力は各値が変化するまでの時間をバッファに記録する.値は 0, 1, 0, 1 と交互に来て,その長さが異なるだけなので長さだけを記録しておけばいいからだ.
赤外線 LED の出力時のポイントは,リモコンの赤外線は 38 kHz で変調されているということ.漫然と 1 で光らせて,0 で引かせない,では反応しない.なので 38 kHz の周期で 0 / 1 をパタパタさせればいい.出したい値が 1 (HIGH) のときは変調した信号を送り続け,0 (LOW) のときは何も出さない,という実装になる.
さて,HIGH と LOW の継続させる長さがデータの 0 / 1 を表すのだが,学習リモコンであれば何も考えずにセンサーの入力をそのままフォワードすればいい.つまりバッファに記録しておいた各値の長さで信号を流し続ける感じになる.(センサーからの出力は復調後のものになっている).
ちなみに Arduino の digitalWrite
関数は結構遅いので,レジスタを直接いじらないとマイクロ秒オーダーではタイミングが合わない現象に見舞われた.
my-super-remote/arduino.ino at master · mangano-ito/my-super-remote · GitHub
久しぶりに温かみのある感じのコテコテの C っぽいコードを書いた. ところで Arduino には赤外線のデコードやエンコードをするライブラリがあるようで,自分で実装する必要はない.
API サーバー
シリアル通信ができればなんでもいい,ので大抵の言語で可能だ (ホントかな). 今回は Python で FastAPI + pySerial というのを使った.理由は昔 pySerial を使ったことがあるから.
my-super-remote/api.py at master · mangano-ito/my-super-remote · GitHub
作ってからおもったのは,普通に node.js で NestJS と node-serialport
とかを使って実現するとよいと思った.
TypeScript で isomorphic にサーバーサイドとクライアントサイドが構築できてオシャレかも.
クライアントサイド
やることは REST のリクエストを送るだけなのでなんでもいい.とりあえず Web ベースの簡易的なダッシュボードを作った. View 側は Hooks を使ってみたかったので React を使ってみることにした.
my-super-remote/app.tsx at master · mangano-ito/my-super-remote · GitHub
ボタンを押すと該当の信号のリクエストが飛んでピッってなるしくみ. ボタンのアニメーションは SoundCloud を意識しているが失敗だろう.
その他
応用として cron
で定時に電灯やエアコンをつけたり消したりできる.
けど,最近の電灯は普通にタイマーがあったりするのであまり意味はない.
光センサーと組み合わせて,暗くなったら電灯をつける,とかはできそうだ.
外出先から遠隔操作できるようにするには,普通にサーバーを公開するか, Firebase Realtime Database みたいなのをリクエストのキューにして, listen していたローカルのサービスがイベントが来たら操作することもできそう.
最近名探偵コナンをよく観ているのでトリックに使えるとかくだらないことを考えていた.
最後に
自分の家は東京の狭い 1K 8畳だし,リモコンは手を伸ばせば届くし, リモコンを使う機器も電灯とエアコンしかないし,リモートワークで更に外に出なくなったしで, 活用できる予定はいまのところない.
夏休みの自由研究や工作のネタにはできそうだ.