赤外線リモコンでGPIOを操作する


Raspberryに赤外線受光素子と赤外線発光素子をつけて、学習リモコンとして利用する例はたくさん紹介されていますが、
Raspberryそのものをリモコンで制御したり、GPIOをリモコンで制御する例はあまり(と言うかほとんど)見かけません。

私が探した範囲では、以下のページで、テレビのリモコンを使ってRaspberryをコントロールする例が紹介されています。
『テ レビのリモコンでRaspberry Piをコントロールしよう』

そこで、今回は赤外線リモコンを使ってGPIOを制御する方法を紹介します。
なお、アメリカなどではガレージの電動シャッターの開閉に、433Mhzの無線リモコンがよく使われますが、
この電波帯は日本ではアマチュア無線に割り当てられているので、使うことができません。

赤外線リモコン入手

使用する赤外線リモコンは「RW-PCM37BK」です。
AMAZONや楽天などで容易に入手可能です。
「DN-PCREMOCON」と言う型番もWEBで見る限り同じ製品です。

リモコン本体

lircのインストール

Raspbian-Jessiの場合は、こ ちらを参考にlircをインストールします。
ざっくり書くと以下の様になります。
Jessieでインストールされるlircは以下のバージョンです。
$ dpkg -l | grep lirc
ii  liblircclient0                    0.9.0~pre1-1.2                   armhf        infra-red remote control support - client library
ii  lirc                              0.9.0~pre1-1.2                   armhf        infra-red remote control support


Raspbian-Stretchの場合も、色々なところでlircのインストール方法が紹介されていますが、
インストールの手順がカーネルバージョンに依存するみたいです。
色々試しましたが、こ ちらに紹介されている手順で動くようになりました。
ざっくり書くと以下の様になります。
Stretchでは、赤外線オーバレイドライバーがgpio_ir(受信用ドライバー)、gpio_ir_tx(送信用ドライバー)に変わってい ます。
この関係で、Stretchでリモコンの学習を行うときはlircをソースからインストールする必要が有ります。
これ、はっきり言って面倒です。
Jessieで作った定義ファイル(xxx.conf)は、そのままStretchでも使えるので、リモコンの学習はJessieで学習して、
動作を確認した後で、Stretchにアップデートした方がいいです。

赤外線送受信のための回路図がこ ちらに公開されています。
赤外線LEDの消費電流は大きいので、GPIOから直接電源を供給せず、トランジスタを使って5Vピンから電源を供給します。
この回路図を使用する場合、オーバーレイドライバーを以下の様に登録します。
dtoverlay=gpio-ir,gpio_pin=24
dtoverlay=gpio-ir-tx,gpio_pin=25

/etc/lirc/lirc_options.conf の変更は以下の2か所です。
driver          = default
device          = /dev/lirc0

mode2を使って赤外線が正しく受信できることを確認することができます。
$ mode2 -d /dev/lirc0

この状態で赤外線受信モジュールに向けてリモコンを発射すると、受信した信号をずらずらと表示します。
信号が表示されればOKです。
$ mode2 -d /dev/lirc0
Using driver default on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
pulse 9060
space 4528
pulse 531
space 589
pulse 541
space 588
pulse 542
space 587
pulse 553
space 579
pulse 540
space 591
pulse 537
space 590
pulse 541
space 587
pulse 543
space 599
pulse 539
space 1703
pulse 537
space 1636
pulse 626
space 1663
pulse 539
space 1687
pulse 552
space 1708
pulse 531
space 1690
pulse 547
space 1692
pulse 546
space 1692
pulse 547
space 1697
pulse 543
space 586
pulse 548
space 1692
pulse 545
space 584
pulse 550
space 1694
pulse 545
space 588
pulse 546
space 589
pulse 551
space 589
pulse 542
space 585
pulse 549
space 1703
pulse 540
space 583
pulse 535
space 1703
pulse 538
space 587
pulse 546
space 1692
pulse 537
space 1685
pulse 548
space 1690
pulse 546
space 39953
pulse 9007
space 2224
pulse 584
timeout 142493

リモコンの学習

irrecordの使い方が少し難しいですが、こ ちらにirrecordの使い方を詳しく紹介しています。
リモコンの学習を行い、学習結果ファイル(/etc/lirc/lircd.conf.d/hoge.lircd.conf)を作成します。
lircdデーモンを再起動した後で、以下のコマンドでリモコンが認識されることを確認して下さい。
$ sudo systemctl restart lircd
$ irsend LIST "" ""

devinput-32
kodak -------------> 追加した学習結果ファイル
devinput-64

$ irw -------------> ここでリモコンを発射
0000000000ffe21d 00 wifi kodak
0000000000ffe21d 01 wifi kodak
0000000000ffe21d 02 wifi kodak


回路図

回路図は以下のとおりです。
使用した赤外線受光モジュールは3.3V駆動が可能なTL1838で す。
PL-IRM2121/PL- IRM0101など、動作電圧が4.5V以上のモジュールはRaspberryでは使えません。
こちらで 紹介されているRCフィルター回路(RCローパスフィルタ)を付けていますが、無くてもそれほど赤外線の精度は落ちません。



必要なライブラリのインストール

以下のライブラリをインストールしてください。
$ sudo apt-get install liblircclient-dev

定義ファイルとソースコード

ソースコード(lirc_sample2.c)は以下のとおりです。
なお、ソースコードは、こちらの ページを参考にさせていただきました。
このページで初めて「pinMode(Port, OUTPUT)」として設定したポートでも「digitalRead(Port)」 が できることを知りました。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <wiringPi.h>
#include <lirc/lirc_client.h>

void flipLED (int led);

#define LED1 4 // Rasp pin 16
#define LED2 5 // Rasp pin 18
#define LED3 6 // Rasp pin 22
#define ON 1
#define OFF 0
#define DEBUG 0

int main(int argc, char *argv[]){
    struct lirc_config *config;
    char *code;
    char *string;
    int ret;
    int quitFlag=0;

    if(wiringPiSetup() == -1) {
        printf("Setup Fail\n");
        exit(-1);
    }
    pinMode (LED1, OUTPUT);
    pinMode (LED2, OUTPUT);
    pinMode (LED3, OUTPUT);

    digitalWrite(LED1, OFF);
    digitalWrite(LED2, OFF);
    digitalWrite(LED3, OFF);

    if(lirc_init("irexec",1) == -1) {
        printf("lirc_init Fail\n");
        exit(-1);
    }

    if(lirc_readconfig(argc==2 ? argv[1]:NULL,&config,NULL)==0) {

        while(lirc_nextcode(&code)==0) {
if(DEBUG) printf("lirc_nextcode(): code=[%s]\n",code);
            if(code==NULL) continue;
            while((ret=lirc_code2char(config,code,&string))==0 && string!=NULL) {
if(DEBUG) printf("lirc_code2char(): ret=%d,string=[%s]\n",ret,string);
                if(strcmp (string,"LED1") == 0){
                    flipLED(LED1);
                } else if(strcmp (string,"LED2") == 0){
                    flipLED(LED2);
                } else if(strcmp (string,"LED3") == 0){
                    flipLED(LED3);
                } else if(strcmp (string,"QUIT") == 0){
                    quitFlag=1;
                }
            }
            free(code);
            if(quitFlag == 1) break;
        }
        lirc_freeconfig(config);
    }
    lirc_deinit();
    digitalWrite(LED1, OFF);
    digitalWrite(LED2, OFF);
    digitalWrite(LED3, OFF);
    exit(0);
}

void flipLED (int led){
    if(digitalRead(led)==ON) digitalWrite(led, OFF);
    else                     digitalWrite(led, ON);
}

また、以下の定義ファイルをmylircとしてソースファイルと同じディレクトリにおいてください。
button=XXXXの部分は「/etc/lirc/lircd.conf」に定義したボタン名称、config=XXXXの部分はそのボタン が押されたときに、アプリケーションに渡る文字です。
begin
 button = ButtonA
 prog   = irexec
 config = LED1
end

begin
 button = ButtonB
 prog   = irexec
 config = LED2
end

begin
 button = ButtonC
 prog   = irexec
 config = LED3
end

begin
 button = ButtonD
 prog   = irexec
 config = QUIT
end

リンク方法と起動方法は以下のとおりです。
$ cc -o lirc_sample2 lirc_sample2.c -llirc_client -lwiringPi
$ sudo ./lirc_sample2 ./mylirc

動作確認

リモコンのA、B、Cボタンを押すと、対応するLEDが点灯します。
Dボタンでプログラムを終了します。

全体
ブレッドボード

次回はリモコンで好きなコマンドを実行する方法を紹介します。

続く
...