t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

Arduinoから赤外線を発信して机裏のLEDテープの色を変更する。

今回はArduinoを赤外線リモコンとして使用することでリモコン式LEDテープの色を変更してみた。

以下が作成した試作機。Arduino Uno入りのブレッドボードに赤外線送信モジュールと受信モジュールを指してジャンパーワイヤで繋いだだけの代物だ。
f:id:t-hom:20210809191429p:plain

作成の動機

私の部屋ではムードライトとして机裏にLEDテープを張り付けているのだが、これにステータス通知用LEDとしての機能を持たせたい。
もともとRaspberry PiからArduino Microを操作して小型の信号機でステータスを通知させる機能があるが、こんな感じでお世辞にも格好良いとは言えない。
f:id:t-hom:20210809193330p:plain

LEDテープを活用すれば卓上がスッキリするし、もともとただのムードライトに機能性を持たせることで機能美を堪能できる。

部品

Arduino

今回試作に使ったのはstemteraというブレッドボードにArduino Uno互換機が内蔵されたタイプ。
ただ日本だと共立電子でしか買えないうえ今みたらほとんど終売間際で7,000円近くもするのでお勧めはしない。
stemtera.com

私が買ったときはセールか何かだったのか、かなり安かった覚えがある。まぁ便利といえば便利かな。。

Arduino Unoは正規品が3,000円なので初めての方にはそちらの方がおススメ。
慣れてる人の2台目以降はお好みの互換機で良いと思う。

赤外線送受信モジュール

元々はずいぶん前に赤外線LEDそのまま買って試したのだが、色々試してうまくいかなかったので配線が悪いのが壊してしまったのかそれともコードが悪いのか分からずに挫折したので今回はモジュールを買うことにした。これなら原因はコードに絞ることができる。

配線

f:id:t-hom:20210809211256p:plain

GNDとVCCはそれぞれGNDと5Vに繋ぐ。
データピンは受信機が2番(黒い受光パーツ)、送信機(透明LED)が3番となる。

なお、今回は赤外線リモコンコードの解析と送信プログラムで配線をし直すのが面倒なので一緒に繋いでいるが、解析中は送信機つけなくても良いし、解析が終わったら逆に受信機は不要になる。

コード

ライブラリの準備

ツール→ライブラリの管理からIRremoteを検索してインストールしておく。
f:id:t-hom:20210809203952p:plain

受信と解析

ファイル→スケッチ例→IRremote→ReceiveDumpを開く。
Arduinoに書き込み、シリアルモニターを開く。
通信速度は115200bpsに設定。
f:id:t-hom:20210809204226p:plain


そのままリモコンを受信機に向けて操作すると以下のように内容が出力される。
(注)エアコンのリモコンはコードが長いためデフォルトでは失敗するらしく、バッファを増やしてやる必要があるとのこと。

Protocol=NEC Address=0xEF00 Command=0x4 Raw-Data=0xFB04EF00 32 bits LSB first

Raw result in internal ticks (50 us) - with leading gap
rawData[68]: 
     -65535
     + 178,-  89     +  11,-  12     +  10,-  12     +  10,-  13
     +  10,-  12     +  10,-  12     +  11,-  11     +  11,-  12
     +  11,-  12     +  10,-  34     +  10,-  34     +  11,-  34
     +  10,-  34     +  10,-  12     +  11,-  34     +  10,-  34
     +  11,-  34     +  10,-  12     +  11,-  11     +  11,-  34
     +  11,-  11     +  11,-  11     +  12,-  11     +  11,-  11
     +  11,-  12     +  11,-  33     +  11,-  34     +  11,-  11
     +  11,-  34     +  10,-  34     +  11,-  33     +  11,-  34
     +  10,-  34     +  11
Raw result in microseconds - with leading gap
rawData[68]: 
     -3276750
     +8900,-4450     + 550,- 600     + 500,- 600     + 500,- 650
     + 500,- 600     + 500,- 600     + 550,- 550     + 550,- 600
     + 550,- 600     + 500,-1700     + 500,-1700     + 550,-1700
     + 500,-1700     + 500,- 600     + 550,-1700     + 500,-1700
     + 550,-1700     + 500,- 600     + 550,- 550     + 550,-1700
     + 550,- 550     + 550,- 550     + 600,- 550     + 550,- 550
     + 550,- 600     + 550,-1650     + 550,-1700     + 550,- 550
     + 550,-1700     + 500,-1700     + 550,-1650     + 550,-1700
     + 500,-1700     + 550

Result as internal ticks (50 us) array - compensated with MARK_EXCESS_MICROS
uint8_t rawTicks[67] = {178,89, 11,12, 10,12, 10,13, 10,12, 10,12, 11,11, 11,12, 11,12, 10,34, 10,34, 11,34, 10,34, 10,12, 11,34, 10,34, 11,34, 10,12, 11,11, 11,34, 11,11, 11,11, 12,11, 11,11, 11,12, 11,33, 11,34, 11,11, 11,34, 10,34, 11,33, 11,34, 10,34, 11};  // Protocol=NEC Address=0xEF00 Command=0x4 Raw-Data=0xFB04EF00 32 bits LSB first

Result as microseconds array - compensated with MARK_EXCESS_MICROS
uint16_t rawData[67] = {8880,4470, 530,620, 480,620, 480,670, 480,620, 480,620, 530,570, 530,620, 530,620, 480,1720, 480,1720, 530,1720, 480,1720, 480,620, 530,1720, 480,1720, 530,1720, 480,620, 530,570, 530,1720, 530,570, 530,570, 580,570, 530,570, 530,620, 530,1670, 530,1720, 530,570, 530,1720, 480,1720, 530,1670, 530,1720, 480,1720, 530};  // Protocol=NEC Address=0xEF00 Command=0x4 Raw-Data=0xFB04EF00 32 bits LSB first

uint16_t address = 0xEF00;
uint16_t command = 0x4;
uint32_t data = 0xFB04EF00;

Pronto Hex as string
char ProntoData[] = "0000 006D 0022 0000 0157 00AA 0016 0016 0014 0016 0014 0018 0014 0016 0014 0016 0016 0014 0016 0016 0016 0016 0014 0041 0014 0041 0016 0041 0014 0041 0014 0016 0016 0041 0014 0041 0016 0041 0014 0016 0016 0014 0016 0041 0016 0014 0016 0014 0018 0014 0016 0014 0016 0016 0016 003F 0016 0041 0016 0014 0016 0041 0014 0041 0016 003F 0016 0041 0014 0041 0016 06C3 "

沢山出力されるが、いろんな方法で表示してくれているだけなので、実は必要なのは以下のみ。

uint16_t rawData[67] = {8880,4470, 530,620, 480,620, 480,670, 480,620, 480,620, 530,570, 530,620, 530,620, 480,1720, 480,1720, 530,1720, 480,1720, 480,620, 530,1720, 480,1720, 530,1720, 480,620, 530,570, 530,1720, 530,570, 530,570, 580,570, 530,570, 530,620, 530,1670, 530,1720, 530,570, 530,1720, 480,1720, 530,1670, 530,1720, 480,1720, 530};  // Protocol=NEC Address=0xEF00 Command=0x4 Raw-Data=0xFB04EF00 32 bits LSB first

これはunit16_t型の配列rawData[67]に赤外線のデータを代入するC言語の初期化コードになっている。

送信

送信コードは次のとおり。
先ほどの配列を任意の名前の変数に格納しておき、sendRawメソッドで赤外線送信される。

#include <IRremote.h>

void setup() {
    IrSender.begin(3, false);
}

void loop() {
    uint16_t led_bluegreen[67] = {8930,4420, 580,570, 530,570, 580,570, 530,570, 580,570, 530,570, 530,620, 530,570, 530,1720, 530,1670, 530,1670, 530,1720, 530,570, 530,1720, 480,1720, 480,1720, 530,1720, 480,620, 480,620, 530,1720, 480,620, 530,620, 480,620, 530,620, 480,620, 480,1720, 530,1720, 480,620, 530,1720, 480,1720, 480,1720, 530,1670, 580};
    uint16_t led_red[67] = {8880,4470, 580,570, 530,570, 530,570, 580,570, 530,570, 580,570, 530,570, 580,570, 530,1670, 530,1670, 580,1670, 530,1670, 530,570, 580,1670, 530,1670, 530,1670, 580,570, 530,570, 580,1670, 530,570, 530,620, 530,570, 530,570, 580,570, 530,1670, 580,1670, 530,570, 530,1720, 530,1670, 530,1670, 530,1720, 530,1670, 530};
    uint16_t turn_off[67] = {8880,4470, 530,570, 580,570, 530,570, 580,520, 580,570, 530,570, 580,570, 530,570, 580,1670, 530,1670, 530,1670, 580,1670, 530,570, 530,1670, 580,1670, 530,1670, 580,520, 580,1670, 530,570, 580,570, 530,570, 580,570, 530,570, 530,570, 580,1670, 530,570, 580,1620, 580,1670, 530,1670, 580,1670, 530,1670, 530,1670, 580};
    uint16_t turn_on[67] = {8880,4470, 530,570, 580,570, 530,570, 580,570, 530,570, 530,570, 580,570, 530,570, 580,1670, 530,1670, 530,1670, 580,1670, 530,570, 580,1620, 580,1670, 530,1670, 580,1620, 580,1670, 530,570, 580,570, 530,570, 580,570, 530,570, 530,570, 580,570, 530,570, 580,1670, 530,1670, 530,1670, 580,1670, 530,1670, 530,1670, 580};  // Protocol=NEC Address=0xEF00 Command=0x3 Raw-Data=0xFC03EF00 32 bits LSB first
    
    IrSender.sendRaw(led_bluegreen, sizeof(led_bluegreen) / sizeof(led_bluegreen[0]), 38);
    delay(3000);
    IrSender.sendRaw(led_red, sizeof(led_red) / sizeof(led_red[0]), 38);
    delay(3000);
    IrSender.sendRaw(turn_off, sizeof(turn_off) / sizeof(turn_off[0]), 38);
    delay(3000);
    IrSender.sendRaw(turn_on, sizeof(turn_on) / sizeof(turn_on[0]), 38);
    delay(3000);
}

このコードをArduinoに書き込むと、LEDテープを、青緑・赤・OFF・ONと3秒ごとに切り替える処理を繰り返す赤外線リモコンになる。
注意点として市販リモコンほど効きがよくないので、私の環境だと30センチくらいの距離で正面から当ててやる必要があったので、うまくいかない場合は近づけてみて切り分けすると良いと思う。

今後の展望

ラズパイからシリアル通信で連携して各種通知に使おうと思う。この先は既に経験がある領域なのでそれほど苦労なく実装できるかと思う。
今回はLEDテープの操作だったけど赤外線リモコン全般操作できると思うので寝る前にサーキュレーターの電源を自動で切ったり、色々と応用が効きそうだ。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。