前回はFader Unitの入出力を確認しました。
ちょうどIR Unitがあったのでシーリングライトの調光をしてみたいと思います。
リモコン操作
我が家のPC部屋で使用している照明はNECの調光付きLED照明で、こんなリモコンで操作します。
照明のモードは
- 消灯
- 明るさ1
- 明るさ2
- 明るさ3
- 明るさ4
- 明るさ5 (全灯)
で(モード名は私が適当につけました)、下記の遷移をします。
消灯が絡む遷移だけ特別な遷移となっていてややこしいので、フェーダーの位置に合わせて明るさ5〜明るさ1を調光することとします。
リモコンコード
赤外線リモコンの送受信には IRremoteESP8266
というライブラリを利用します。名前がESP8266ですがESP32にも対応しています。
IR Unitは発光受光どちらもできるのでExamplesのIRrecvDumpV2
を参考にしてリモコンから実際のコードを解析すればOKです。
ちなみに、「明」ボタンは Codeが0x41B65DA2、「暗」ボタンは Codeが 0x41B6DD22で、どちらもProtocolがNECですね。
色々実験したところ、コード送出してから照明の処理が完了するまでに70msec程度のウエイトが必要でした。
70msecのウエイトを挟んでコードを連続して送出してみましたが、問題なさそうですね。
M5StickCPlus: IR Unit sample · GitHub
ボタン押すとシーリングライトが5回点滅する迷惑なリモコンできたよ #m5stickc pic.twitter.com/KLSEH5KjLq
— イナバ (@hollyhockberry) 2021年10月22日
フェーダー値読み取りとリモコン送信
リモコンコード送出から処理完了まで約70msecの時間がかかりますが、人間によるフェーダー操作はそんなことはお構いなしに行われます。
例えば、明るさ1の状態でフェーダーの値が最大だった場合「明」のコードを4回送る必要がありますが、ウエイトだけで280msecもかかります。
その間フェーダーの値は読むことができないし他の処理もできません。
操作感をよくするために、フェーダーの値に照明を追従する処理を別タスクで処理してみます。
リモコンコード送信タスクのやるべきことは、フェーダー読み取りのタスク(ArduinoのloopTask)から指示された照明の明るさと現在の明るさが異なる場合、必要な回数「明」ボタンか「暗」ボタンのリモコンコードを送出することです。他にやることはないので、この処理をループします。
なお、タスク毎にメモリ空間が切り替わるわけではないので、グローバルな変数へのアクセスが可能です。
照明の明るさ指示はグローバルな変数で共有することにします。(同一のファイルに実装したのでstaticな変数で実装しました)
読み取りと書き込みがどちらかのタスクでしか発生しないのでそれほどシビアに考えなくても良さそうですが、念のためセマフォで排他制御を行います。
文章で書くとなんのこっちゃ?ですがコードだとスッキリ理解できるんじゃないかと思います。
Fader UnitとIR Unitでシーリングライト祭り開催したよ!たーのしー!
— イナバ (@hollyhockberry) 2021年10月20日
リモコン応答が100msぐらい必要だったのでフェーダーの動きに追従するためマルチタスクで動作させるハメに‥ #m5stack pic.twitter.com/AtT6HCHqzs
補足
わざわざ別タスクで実装しましたが、実験した例では表示も無くフェーダー値を読んで値を更新しているだけなのでそれほど意味のない感じになってしまいました。
この程度であれば、
常に最新のフェーダー値を読んで、現在の明るさと異なっていればコード送出.
を繰り返してあげるだけでよさそうですね。
シンプルな実装で実現する場合のコードも載せておきます。シングルタスクですが、先程の例と全く同じ動きになります。