リモコンでGPIOを操作する


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

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

また、英語のページですが、以下のページでもリモコンを使ってRaspberryをコントロールする例が紹介されています。
How to Control the GPIO on a Raspberry Pi with an IR Remote

そこで、今回はリモコンを使ってGPIOを制御する方法を紹介します。

【STEP1】リモコン入手

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

リモコン本体

【STEP2】lircのインストールとリモコンの学習

以下のページを参考にlircのインストールとリモコンの学習を行い、irwコマンドでリモコンの確認を行います。
Raspberry Pi で赤外線リモコン

なお、3.18.x以降のfirmwareでは仕様が変わりました。
こ ちらこ ちらも記載されていますが、今まで/etc/modulesに記載していた内容は/boot/config.txtに追加する必要 があります。
(モジュールのロードはlircdの起動時に自動で行われますので/etc/modulesへの追加は不要です)
$ sudo cp /boot/config.txt /boot/config.txt.org
$ sudo vi /boot/config.txt



dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=18

4.x以降のfirmwareではさらに仕様が変わりました。
こ ちらに詳しく紹介されています。
$ sudo cp /boot/config.txt /boot/config.txt.org
$ sudo vi /boot/config.txt



dtoverlay=lirc-rpi,gpio_out_pin=17,gpio_in_pin=18,gpio_in_pull=up,invert=on

今回、赤外線の発光は行わないので、「/etc/modules(/boot/config.txt)」に「gpio_out_pin」の指定は 不要です。
「gpio_out_pin」のデフォルトはGPIO17、「gpio_in_pin」のデフォルトはGPIO18が使われます。
irrecordの使い方が少し難しいですが、分からない方は以下のファイルを「/etc/lirc/lircd.conf」として保存し、
「/etc/lirc/hardware.conf」の編集と、lircdデーモンを起動した後で、irwコマンドでリモコンが認識されることを 確認して下さい。

# Please make this file available to others
# by sending it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(default) on Tue Nov 26 21:54:50 2013
#
# contributed by
#
# brand:                       /home/pi/lircd.conf
# model no. of remote control:
# devices being controlled by this remote:
#

begin remote

  name  PCM37BK
  bits            8
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  one           242  1878
  zero          242   817
  ptrail        242
  pre_data_bits   8
  pre_data       0xE2
  gap          46634
  toggle_bit_mask 0x0

      begin codes
          ButtonA                  0xC4
          ButtonB                  0x44
          ButtonC                  0x84
          ButtonD                  0x04
          POWER                    0xE4
          EMAIL                    0x64
          WWW                      0xA4
          CLOSE                    0x24
          Previus                  0x38
          Next                     0x28
          Backward                 0xB8
          Forward                  0xA8
          Play                     0x98
          Stop                     0x88
          VolUp                    0xA0
          VolDown                  0x50
          UP                       0x00
          DOWN                     0x60
          LEFT                     0x90
          RIGHT                    0x20
      end codes

end remote

lircdデーモンを起動した後で、irwコマンドでリモコンの確認を行うと以下のように表示されます。
$ irw
000000000000e2c4 00 ButtonA PCM37BK
000000000000e2c4 01 ButtonA PCM37BK
000000000000e2c4 02 ButtonA PCM37BK
000000000000e2c4 03 ButtonA PCM37BK
000000000000e2c4 04 ButtonA PCM37BK
000000000000e244 00 ButtonB PCM37BK
000000000000e244 01 ButtonB PCM37BK
000000000000e284 00 ButtonC PCM37BK
000000000000e284 00 ButtonC PCM37BK
000000000000e284 01 ButtonC PCM37BK
000000000000e284 02 ButtonC PCM37BK
000000000000e284 03 ButtonC PCM37BK
000000000000e204 00 ButtonD PCM37BK
000000000000e204 01 ButtonD PCM37BK
000000000000e204 02 ButtonD PCM37BK
000000000000e204 03 ButtonD PCM37BK

【STEP3】回路図

回路図は以下のとおりです。
使用した赤外線受光モジュールはPL-IRM2121とPL- IRM0101です。
どちらでも動作を確認していますが、PL- IRM0101の方が感度はいいようです。

回路図

【STEP4】必要なライブラリのインストールソースコード

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

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

ソースコード(lirc_sample2.c)は以下のとおりです。
なお、ソースコードは以下のページを参考にさせていただきました。
How to Control the GPIO on a Raspberry Pi with an IR Remote
このページで初めて「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

【STEP6】動作確認

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

全体
ブレッドボード

次回はリモコンでインターネットラジオを聴く方法を紹介します。