IRリモコン anchor.png

PCを赤外線リモコンを使って操作したいと思い,PCとUSBで接続出来るIRリモコン送受信機(AVRマイコン搭載ボード)を作成してみた。

以前LinuxのMythTVやRaspberry Piで学習リモコンを作るときにLIRCを使ったので,WindowsのLIRCであるWinLIRCを使いたいと思ったのだが,元々WinLIRCというかLIRCは,古いシリアルポートのDCDに赤外線受信センサーを接続したハードウェアのためのツール。

schematics.png

なのでシリアルポートが搭載されていない最近のPCでは使うのが難しい。シリアルポートが無いPCでシリアルポートを使いたい場合,普通はFTDI等のチップを搭載したUSB-Serialコンバーターを使うのだが,このようなコンバーターのDCDに赤外線センサーの出力を接続してもWinLIRCのプログラムはうまく動作してくれなかった。

これはWinLIRCではリモコン信号を解析する時にクリティカルなタイミングが必要となるのだが,USB-Serialコンバーターを使うとどうしてもダイレクトにポートにアクセス出来ないので,うまくリモコン信号の解析が出来ないみたいだ。
実際にFTDIのFT232RLなんかを使っていろいろやってみたが,受信データが正常に得られなかった。おそらくBig-Bangモードを使えばうまく行くと思うのだが,Bit-Bangモードの使い方がよくわからない。

ただWinLIRC(LIRC)ではプラグインによってシリアルポート以外のハードウェアのいくつかに対応するようになっている。

その中でもPCのマイク入力に赤外線センサーの出力を接続したハードウェアとAudioCapture.dllプラグインを使う方法がユニークなので試してみたが,なかなか安定してリモコンデータが取得できなかった。
うまく動けばハードウェアとしては安価に比較的簡単に作成できるし,どんなPCでも使えるメリットがある。

また,市販されているCOMポート接続のIRMan IR ReceiverやUSB接続のUSB Infrared Toyも,プラグイン経由でWinLIRCで使えるようだ。
これらのCOMポート接続タイプやUSB接続タイプでは,アダプター機器でリモコンデータを解析するようになっていて,その解析したリモコンデータをWinLIRCがプラグイン経由で受け取って使用出来るようにしているようだ。

そこで自作したIRリモコンでは,WinLIRCのIRManプラグインで動作するようにしてみた。

うまく動作すればWinLIRCと各種のコンパニオンツールが使えるようになり,PCをリモコンで操作することが実現出来そう。

残念ながらIRManプラグインではIR信号の送信はサポートされてないので今回は受信専用となる。
送信も出来るようにIRManプラグインに機能を追加してみた。これで,PCから家電なんかを制御したりも出来るようになった。

Page Top

ハードウェア anchor.png

FTDIのUSBコンバーターが実装されている自作のATMEL AVRボード(ATmega168P)に,手持ちのIR受信センサーと赤外線LEDを接続した。
市販のボードを使う場合は,Arduino Nano互換ボードが小さくて良さそう。

作成したIRリモコン回路図

IRremokon回路図.png

IR受信センサーは38KHzの物なら何でも良い。
avrir.png 作成した基板。

Page Top

動作チェックプログラム anchor.png

赤外線リモコン信号の解析はIRremoteライブラリを使ってみた。Arduinoボード(Arduino IDE)用に作られていて,多くのメーカーのリモコンに対応しているのもうれしい。

IRremoteライブラリは使い始めた時はバージョン2.xだったが3.x,4.xと更新されて,使い方もその都度変更されていたりする。
また,自作のAVRボード(ATmega168PやATmega328)で動くように少し修正して使用している。

作ったIRリモコンを,以下のプログラムで動作チェックをした。

filercvsend.ino
Everything is expanded.Everything is shortened.
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
 
 
 
 
 
 
 
 
 
 
 
-
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
 
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
-
|
|
!
|
|
!
-
|
|
|
-
|
|
|
|
|
|
|
-
|
|
|
|
-
|
!
|
|
|
|
|
|
!
!
|
!
 
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
// rcvsend
// by Yuji Ueno
// AVRIRでのIRリモコンの受信・送信のテストプログラム
// ・待機中にリモコン信号を受信するとデータをEEPROMに保存する(学習)
// ・MOSI(MISO)端子をLowにすると保存したデータを送信する(1s毎に再送信)
// ・シリアルコンソールに情報を表示する
// ・IRRemoteライブラリを使用
// 
// ハードウェア
//  IR Sensor                 ATMEL AVR Board
//  SHARP GP1UD281XK          (ATmega168P etc...)
//  +---------+               +--------------+
//  |   OUT 1 |---------------|PD2 Rx        |
//  |   VCC 2 |---------------|+5V           |
//  |   GND 3 |---------------|GND           |
//  +---------+               |              |
//                            |              |
//  +5V -- R  +5V -- R        |          MISO|-----+
//         |15ohm    |15ohm   |              |     |
//         A IR      A IR     |              |    Tact SW
//         K LED     K LED    |              |     |
//         |         |        |              |    GND
//         +---------+        |              |
//         |                  |              |
//         +------ D          |              |
//                   G -------|PD3 Tx        |
//         +------ S          |              |
//         |       2SK1748    |              |
//         |                  |          USB |<==========> PC
//         |                  |              |     USB     (WinLIRC)
//         +------------------|GND           |
//                            |              |
//                            +--------------+
//
#define MARK_EXCESS_MICROS 20
 
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__)
#define RAW_BUFFER_LENGTH 250
#else
#define RAW_BUFFER_LENGTH 500
#endif
 
#include <IRremote.hpp>
#include <avr/eeprom.h>
 
#define SW MISO                                                 // 送信SW PB4 MISO
//#define SW MOSI                                                   // 送信SW PB4 MOSI(piramp)
#define LED LED_BUILTIN                                         // onボード LED
#define PUSH 1000                                               // 送信SW確認用
 
#define EEPROM_V1 0x0000                                        // dataを保存するEEPROMのアドレス
#define EEPROM_V2 0x0004                                        // bitsを保存するEEPROMのアドレス
#define EEPROM_V3 0x0005                                        // bitsを保存するEEPROMのアドレス
 
int IR_RECEIVE_PIN = 2;                                         // IRセンサーを接続するポートPD2
int IR_SEND_PIN = 3;                                            // IR LEDを接続するポートPD3
 
long recdata;                                                   // data temp.
byte recbits;                                                   // bits temp.
byte rectype;                                                   // protocol temp.
byte recflags;                                                  // flags temp.
uint16_t recaddr,reccom,recextra;                               // address, command, extra temp.
 
int swcount;                                                    // 送信SW counter
 
void setup() {
    digitalWrite(LED, LOW);                                     // LED off
    Serial.begin(9600);                                         // init comポート(9600)
    pinMode(SW, INPUT_PULLUP);                                  // SWポートをプルアップ
    pinMode(LED, OUTPUT);                                       // LEDポートを出力モードに設定
    IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK);     // IR受信を開始
    IrSender.begin(IR_SEND_PIN);                                // IR送信を開始
 
    swcount = 0;                                                // init SW counter
    
    eeprom_busy_wait();
    recdata = eeprom_read_dword((uint32_t *)EEPROM_V1);         // EEPROMからdataを読み出す
    eeprom_busy_wait();
    recbits = eeprom_read_byte((uint8_t *)EEPROM_V2);           // EEPROMからbitsを読み出す
    eeprom_busy_wait();
    rectype = eeprom_read_byte((uint8_t *)EEPROM_V3);           // EEPROMからtypeを読み出す
    
    Serial.print("rcv and send IR remokon signal.\n");          // startup表示
    SPRI();                                                     // データ表示
}
 
void loop() {
    if (IrReceiver.decode()) {                                  // IRリモコン受信?
        recbits = IrReceiver.decodedIRData.numberOfBits;        // IRビット長をRAMに保存
        recflags = IrReceiver.decodedIRData.flags;              // IRビット長をRAMに保存
        recdata = IrReceiver.decodedIRData.decodedRawData;      // IRデータをRAMに保存
        rectype = IrReceiver.decodedIRData.protocol;            // IR受信プロトコルをRAMに保存
        recaddr = IrReceiver.decodedIRData.address;             // IR受信アドレスを保存
        reccom = IrReceiver.decodedIRData.command;              // IR受信コマンドを保存
        recextra = IrReceiver.decodedIRData.extra;              // IR受信extraデータを保存
        
        eeprom_busy_wait();
        eeprom_update_dword((uint32_t *)EEPROM_V1, recdata);    // EEPROMにdataを保存
        eeprom_busy_wait();
        eeprom_update_byte((uint8_t *)EEPROM_V2, recbits);      // EEPROMにbitsを保存
        eeprom_busy_wait();
        eeprom_update_byte((uint8_t *)EEPROM_V3, rectype);      // EEPROMにtypeを保存
        
        Serial.print("Memorized! ");                            // メモリー表示
        SPRI();                                                 // データ表示
        
        // リモコンを学習したらLEDを点滅
        for (byte i = 0 ; i < 5 ; i++) {
            digitalWrite(LED, i % 2);
            delay(100);
        }
 
        IrReceiver.resume();                                    // 次の受信の準備       
    }
    while (digitalRead(SW) == 0) {                              // sw on?
        digitalWrite(LED, HIGH);                                // LED on
        swcount++;                                              // sw onされている場合Counter +1する
        
        if (swcount > PUSH) {                                   // counterがPUSH以上だったら?
            eeprom_busy_wait();
            recdata = eeprom_read_dword((uint32_t *)EEPROM_V1); // EEPROMからdataを読み出す
            eeprom_busy_wait();
            recbits = eeprom_read_byte((uint8_t *)EEPROM_V2);   // EEPROMからbitsを読み出す
            eeprom_busy_wait();
            rectype = eeprom_read_byte((uint8_t *)EEPROM_V3);   // EEPROMからtypeを読み出す
 
            if (rectype == UNKNOWN) {                           // UNKNOWNタイプ?
                unsigned int rawData[100];                      // 送信buffer
                int sendsize = (int)(recbits/4);                // dataサイズ
                memcpy(&rawData[0],&recdata, sendsize);         // 送信bufferにコピー
                IrSender.sendRaw(rawData, sendsize, 38);        // 38kHzでdataを送信
            } else {
                IrSender.sendNECRaw(recdata, 3);                // 送信する
            }
            Serial.print("SEND! ");                             // 送信表示
            SPRI();                                             // データ表示
            digitalWrite(LED, LOW);                             // LEDをオフ
            delay(1000);                                        // wait 1s
            IrReceiver.resume();                                // 次の受信の準備(irsendすると受信が停止するため)
            swcount = 0;                                        // counterをクリヤー
        }
    }
    swcount = 0;                                                // counterをクリヤー
}
 
// 情報の表示
void SPRI() {
    Serial.print("> Protocol:");
    Serial.print(getProtocolString(rectype));                   // protocol表示
    Serial.print(" BITS:");
    Serial.print(recbits);                                      // bit表示
    Serial.print(" FLAG:");
    Serial.print(recflags);                                     // flags表示
    Serial.print(" ADDR:0x");
    Serial.print(recaddr, HEX);                                 // address表示
    Serial.print(" CMD:0x");
    Serial.print(reccom, HEX);                                  // command表示
    Serial.print(" EXTD:0x");
    Serial.print(recextra, HEX);                                // extra data表示   
    Serial.print(" DATA:0x");
    Serial.print(recdata, HEX);                                 // data表示
    Serial.println();
}
  • テレビなんかのリモコンのボタンを押すとそのリモコン信号を学習する。
    受信したリモコン信号をEEPROMに保存する。
  • MOSI(またはMISO)ピンをLowにすると,その保存したEEPROMのリモコン信号を送信する。
  • リモコンはNECタイプを使う。

シリアルコンソールを使うと,リモコンの押されたボタンのコードやリモコン信号のタイプが確認できる。

学習したリモコン信号を送信してみて機器が反応すれば,ハードウェアはうまく動作していることになる。

Page Top

IRMan IR Recieverプロトコル anchor.png

irman.png

IRMan IR RecieverはPCとシリアルポートで接続して,赤外線リモコンの信号を受信できる機器だったようだ。(もう販売はされていない)

IRMan IR Recieverでは赤外線リモコンから受信した信号を解析して,そのリモコンボタンの情報データをPCに送っている。

  • PCとIRMan IR RecieverとのSerial通信パラメータ
    Baudrate:9600
    Data:8bit
    Stop bit:1 stop
    Parity: non parity
  • PCのシリアルポートのRTSとDTRをHiにする
    これによりIRMan IR Recieverに電源が供給されて起動される。
    起動するとリモコンデコードモードになり,赤外線リモコン信号を受信したら解析しPCに返答する。
  • PCからスタートコマンドを送信
    HostからIRと送信する。(IRの間は最小500usの時間が必要。)
  • IRMan IR RecieverからOKの返答
    HostからのIRへの返答としてOKを返す。
    PCでOKを受信した場合,IRMan IR Recieverが正常に接続されていることがわかる。
  • IRMan IR Recieverでリモコン信号を受信したら,そのリモコン・コードをPCに送信する
    リモコンから受信したデータを,
    0x1E, 0xXX, 0x00,0x00,0x00,0x00
    という6byteのパケットデータでPCに非同期で送信するようだが,1Byte目は0x1E固定で,2byte目がリモコンのボタンに割り当てられているコマンドで,その後のデータはオプションのようだ。
    6byteでのデータ転送なので,エアコンなどのサイズが大きいリモコンデータのやり取りは出来ない
  • PCからIRMan IR RecieverへIRリモコン・コード送信機能はない
    WinLIRCのIRManプラグインとこのIRMan IR Recieverでは,リモコン・コードの送信は残念ながら実装されていない。

これ以外にもいくつか機能があるようだが,詳細はわからない。

Page Top

WinLIRC用IRリモコンのソフトウェア anchor.png

作成したIRリモコンをWinLIRCで使用出来るように,IRMan IR Reciver準拠の(実際のIRMan IR Reciverを見たこと無いので知らないけど・・・)プログラムavrlirc.inoを作成してArduino IDEから書き込んだ。

今回は以下の6byteをWinLIRCとやり取りするようにしてみた。

byteデータ内容
0HeaderIRMan Pluginでのヘッダー(0x1E)
1-2Addressリモコンのアドレス(LSB first)
3-4Commandリモコンのコマンド(LSB first)
5Protocolリモコンのメーカー(タイプ)

最初は32bitのRawDataを使っていたが,IRリモコンから赤外線リモコン信号を送信する時,RawDataでは送信できないリモコン・タイプがあったり,リモコン・タイプを特定する必要もあってこのように変更した。*1

WinLIRCのプラグインIRMan.dllでは,受け取ったパケットデータを全てデータとして利用しているのでこれでも問題ないようだ。おそらく,0x1Eのヘッダーもなくても良いんだと思う。

IRMan IR Recieverにはないリモコン信号の出力もできるようにした

fileavrlirc.ino
Everything is expanded.Everything is shortened.
-
|
|
|
|
|
|
|
|
!
 
 
 
 
 
 
 
-
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
|
|
|
!
 
-
-
|
|
|
|
|
|
|
|
|
|
|
!
-
|
|
|
|
|
|
-
|
|
|
!
|
-
|
!
|
-
|
!
!
!
 
-
-
|
-
|
|
|
|
|
|
|
-
|
|
!
|
|
-
-
|
!
!
-
-
|
!
|
!
|
|
!
!
!
 
-
-
-
|
|
!
|
!
// avrlirc
// IRリモコン for AVR
// with WinLIRC IRMan Plugin改
// by Yuji Ueno
//  1.0.0    init version
//  1.0.1    send IR Protocol at last data
//           support output IR signal
//  1.0.2    use IRremote Lib. v4.x
//
#define MARK_EXCESS_MICROS 20
 
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__)
#define RAW_BUFFER_LENGTH 250
#else
#define RAW_BUFFER_LENGTH 500
#endif
 
// use IRremote Lib. v4.x (https://github.com/Arduino-IRremote/Arduino-IRremote)
#include <IRremote.hpp>
 
int RECV_PIN = 2;                                                   // IRセンサーを接続するポートPD2
int SEND_PIN = 3;                                                   // IRLEDを接続するポートPD3
unsigned char lastdata[5] = {0x00, 0x00, 0x00, 0x00, 0x00};         // リモコン信号IR code受信用buffer
unsigned char sdata[6] = {0x00,0x00, 0x00, 0x00, 0x00, 0x00};       // リモコン信号IR code送信用buffer
 
int cmd;                                                            // cmd受信seq. flag
int cmdok;                                                          // IR data 受信済み flag
 
char rcvdat;
 
long recdata;                                                       // data temp.
byte recbits;                                                       // bits temp.
byte rectype;                                                       // protocol temp.
byte recflags;                                                      // flags temp.
uint16_t recaddress;                                                // address temp
uint16_t reccommand;                                                // command temp
 
IRData IRSendData;                                                  // init send IR data buffer
 
void setup() {
    pinMode(LED_BUILTIN, OUTPUT);                                   // onboardLEDの設定
    digitalWrite(LED_BUILTIN, LOW);                                 // onboardLED off
    Serial.begin(9600);                                             // Serial Port baudrate=9600
    IrReceiver.begin(RECV_PIN, DISABLE_LED_FEEDBACK);               // IR Recieverの開始
    IrSender.begin(SEND_PIN);                                       // IR Senderの開始
    cmd = 0;                                                        // init cmd seq. flag
    cmdok = 0;                                                      // init cmdok flag
}
 
void loop() {
    if (cmdok == 1) {
        IRSendData.flags = IRDATA_FLAGS_EMPTY;                      // set IR flags
        IRSendData.address = (uint16_t)sdata[2] << 8;               // set IR address MSB
        IRSendData.address += (uint16_t)sdata[1];                   //                LSB
        IRSendData.command = (uint16_t)sdata[4] << 8;               // set IR command MSB
        IRSendData.command += (uint16_t)sdata[3];                   //                LSB
        IRSendData.protocol = sdata[5];                             // set IR protocol
        IrSender.write(&IRSendData, 3);                             // IR signal(3回)を出力 Protocol対応 max.32bit(address+command)
        delay(1000);                                                // wait 1s
        IrReceiver.resume();                                        // 次の受信の準備(irsendすると受信が停止するため)
        cmdok = 0;                                                  // init cmdok flag
        cmd = 0;                                                    // init cmd seq. flag
    }
    if (IrReceiver.decode()) {                                      // IRリモコン受信?
        recbits = IrReceiver.decodedIRData.numberOfBits;            // IRビット長をコピー
        recflags = IrReceiver.decodedIRData.flags;                  // IRフラグをコピー
        recdata = IrReceiver.decodedIRData.decodedRawData;          // IRデータをコピー
        rectype = IrReceiver.decodedIRData.protocol;                // IR受信プロトコルをコピー
        recaddress = IrReceiver.decodedIRData.address;              // IR受信アドレスをコピー
        reccommand = IrReceiver.decodedIRData.command;              // IR受信コマンドをコピー
        if (recflags != 1) {                                        // リピートではない?
            memcpy(&lastdata[0], &recaddress, 2);                   // リピート用にaddressを保存
            memcpy(&lastdata[2], &reccommand, 2);                   // リピート用にcommandを保存
            memcpy(&lastdata[4], &rectype,1);                       // リピート用にprotocoを保存
        }
        Serial.write(0x1E);                                         // ヘッダーを送信
        for (int i = 0; i <= 3; i++) {                              // 4byteリモコンコードを送信
            Serial.write(lastdata[i]);                              // データを送信
        }
        Serial.write(lastdata[4]);                                  // IR protocolを送信        
        //delay(250);                                               // wait(250ms)
        //onoffLED(6);                                              // LEDを点滅(6回)
        IrReceiver.resume();                                        // 次の受信の準備
    }
}
 
void serialEvent() {
    while (Serial.available() > 0) {                                // Serial Portに受信?
        rcvdat = (char)Serial.read();                               // get data
        switch(rcvdat) {
            case 'R':                                               // 'R'だったら(本来はIR手抜き)
                Serial.write("OK");                                 //   OKを送信 (WinLIRCへのACK)
                onoffLED(4);                                        //   LEDを点滅
                cmdok = 0;                                          //   init cmdok flasg
                cmd = 0;                                            //   init cmd seq. flag
                break;
            case 0x1E:                                              // IR dataヘッダー(0x1E)
                if (cmd == 0 && cmdok ==0) {                        // ヘッダーだったら?
                    sdata[0] = rcvdat;                              //   buffer[0] <- data
                    cmd++;                                          //   cmd++
                }
                break;
            default:
                if (cmd >= 1 || cmd <= 4) {                         // dataを受信?
                    if (cmdok == 0) {                               //   受信中だったら?
                        sdata[cmd] = rcvdat;                        //   buffer[1..4] <- data
                    }
                }
                if (cmd == 5 ) {                                    // dataを受信6byte目?
                    if (cmdok == 0) {                               //   受信中だったら?
                        sdata[5] = rcvdat;                          //   sbuffer[5] <- data
                    }
                    cmdok = 1;                                      //   IR送信データ受信した
                }
                cmd++;                                              // cmd++
                break;
        }
    }
}
 
// onboard LEDを点滅(100ms)
void onoffLED(int times) {
    for (byte i = 0 ; i < times ; i++) {                            // 点滅回数
        digitalWrite(LED_BUILTIN, i % 2);                           //   点滅
        delay(100);                                                 //   wait 100ms
    }
    digitalWrite(LED_BUILTIN, LOW);                                 // LED off
}
Page Top

PC側のソフトウェア anchor.png

Windows PCにはWinLIRCとWinLIRCに対応しているコンパニオンツールを使用する。

WinLIRCは作成したIRリモコンとPCをUSBで接続して,以下のことを行う。

  • リモコンからのデータを受信する。
  • リモコンからのデータを解析・学習してリモコンを識別・管理する。
    学習したデータをファイルに保存して,識別や学習リモコンとして送信するときにファイルを利用する。
  • コンパニオンツールやアプリケーションへリモコンデータ情報を提供する。
    NetworkのTCP通信で,リモコンの情報をツールやアプリケーションに送る。
    直接WinLIRCに接続出来るアプリケーションもいくつかある。
  • リモコン信号をリモコンに代わって機器に送信する。
    オリジナルのIRManプラグインでは送信には対応していなかったので,独自にIRMan.dllに機能を追加した。

iRExEventGhostはWinLIRCに対応しているコンパニオンツールで,WinLIRCが受信したリモコンデータからPCでのキー入力やMouse操作をエミュレーションしたり,任意のアプリを起動したりすることが出来るようになる。

これらのソフトウェアを使うことで,PCをリモコンで操作出来るようになる。

Page Top

WinLIRC anchor.png

LIRCのWindows版であるWinLIRCをダウンロードする。ダウンロードするバージョンは0.9.0i
インストールはダウンロードしたzipファイルを任意の場所に解凍すればOK。

ダウンロードしたWinLIRCとプラグインIRMan.dllを使ってみたところ,自作したIRリモコンとうまく接続出来なくて,IRRecordでの学習モードに移行しないですぐにエラーで終了してしまう。

DTR信号が出力されると自作のIRリモコンのCPUがResetされちゃう*2のと,IRManデバイスからOKの返答を待つ時間が250msと短いのと,ヘッダー送信前にゴミデータが受信されているのが原因と思われる。

しょうがないので,WinLIRC 0.9.0iのIRMan.dllのソースコードを少し修正して,DTR信号が出力された後の返答待ちの最大時間を5sと長めに変更した。また,赤外線信号を出力する機能も追加した。

このfile修正したIRMan.dllファイルを,WinLIRCをインストールした場所にあるpluginsディレクトリのIRMan.dllと入れ替える。

これでうまく動作するようになった。

Page Top

WinLIRCでリモコンを学習する anchor.png

自作のIRリモコンをPCにUSBで接続する。

WinLIRCを起動して,最初に使用するプラグインをInput PluginでIRMan.dllに設定する。

setting.png

そして使用するCOMポートをPlugin Setupボタンで設定する。
その後作成するconfigファイルを保存場所を指定してCreate Configボタンをクリックすると,リモコンの学習を行うIRRecordプログラムがコマンドプロンプトで起動する。

コマンドプロンプトを開いて,

> IRRecord -d IRMan.dll ..\px-w3u4.conf

とかしても同じ。

リモコン信号の学習は以下の手順で行う。

  • 「Enterを押せ」と表示される
    説明を読んでEnterを押す。
  • 「任意のリモコンボタンを押し続けろ」と指示される
    リモコンのどれかのボタンを押しっぱなしにする。
    .....というようにドットが表示されていく。これでリモコン信号の解析を行っているのかな。
    かなり入力すると,このフェーズが終了する。
  • 「学習させたいリモコンのボタンの名前を入力して,リモコンのボタンを押せ」と指示が出る
    リモコン送信機の学習したいボタンに相当する名前を入力する。
  • 学習させたいリモコンのボタンを押す
    リモコン送信機のボタン信号を一つ一つ学習していく。ボタンは学習するまで2回押す。
  • リモコンにある学習したいボタンを繰り返し同じように行う。
  • 全てのリモコンのボタン学習が終わったらラベル入力時にEnterのみを押す。
  • さらに「Enterを押せ」と表示される
    Enterを押す。
  • リモコンのいくつかのボタンを1回づつ押していく
    ボタンは押しっぱなしにはしないで1回だけ押す。学習データを最適化するために行うようだ。

設定ファイルが作成されたら,nameのところを任意のわかりやすいものに変更しておく。
コンパニオンツールのiRExでのリモコン指定は,このnameを参照する。

Page Top

WinLIRCを再起動する anchor.png

うまく学習してデータファイルが作成できたらWinLIRCを再起動する。リモコン信号の受信待ち状態になりシステムトレイに黄色の丸のアイコンが表示され,しばらくすると色が消えた丸アイコンになる。
これで自作にIRリモコンと接続が出来たことになる。
tray.pngリモコンのボタンを押した時にこのアイコンが緑に変化すれば,学習したリモコン信号に反応していることになる。

Page Top

リモコンの学習データ anchor.png

いくつかリモコンを学習してみた。
最終byteが0x08の場合は,リモコンがNECタイプを意味する。

Plex PX-W3U4の付属リモコン:

filepx-w3u4.conf
# Please make this file available to others
# by sending it to <winlirc.configs@gmail.com>
#
# this config file was automatically generated
# using lirc-0.9.0(irman) on Thu May 03 13:43:54 2021
#
# contributed by 
#
# brand: Plex
# model no. of remote control: PX-W3U4
# devices being controlled by this remote: Plex TV Tuner PX-W3U4
#
 
begin remote
 
  name  PXW3U4
  bits           32
  eps            30
  aeps          100
 
  one             0     0
  zero            0     0
  pre_data_bits   24
  pre_data       0xFFFF1E
  post_data_bits  8
  post_data      0x08
  gap          116000
  toggle_bit_mask 0x0
 
      begin codes
          Power                    0x20102000
          Mute                     0x20102A00
          Recbtn                   0x20100400
          Epg                      0x20102500
          Tv                       0x20100600
          Dvd                      0x20100700
          Hidari                   0x20100800
          Cc                       0x20100900
          PlayerOn                 0x20100200
          PlayerOff                0x20100300
          SndChange                0x20100C00
          Full                     0x20100E00
          Up                       0x20100D00
          Down                     0x20101300
          Left                     0x20100F00
          Right                    0x20101100
          Ok                       0x20103000
          Info                     0x20100B00
          Rec                      0x20101800
          Pause                    0x20101600
          Play                     0x20103500
          Stop                     0x20101700
          Back                     0x20101900
          Fwd                      0x20103A00
          LeftSkip                 0x20101B00
          RightSkip                0x20101C00
          1                        0x20101D00
          2                        0x20101E00
          3                        0x20101F00
          4                        0x20102100
          5                        0x20104200
          6                        0x20104300
          7                        0x20104500
          8                        0x20102600
          9                        0x20104700
          0                        0x20104A00
          *                        0x20104900
          #                        0x20104B00
          ChUp                     0x20104000
          ChDown                   0x20104400
          VolUp                    0x20104800
          VolDown                  0x20104C00
          Tunner                   0x20104D00
          Clr                      0x20104E00
          Input                    0x20102F00
          Data                     0x20104F00
          Blue                     0x20105000
          Red                      0x20105100
          Green                    0x20105200
          Yellow                   0x20102200
      end codes
 
end remote

Toshiba Regza 37Z3500: file37z3500.conf
TVS Regza 50Z670L: file50z670l.conf
Denon AVR-X1600H: fileAVR-X1600H.conf
Toshiba V65/86L PQ6586LRT: filequosmio.conf
オーム電機 シーリングライト: fileohmlight.conf
Sony DSR-A700: fileRMT-DSLR1.conf
Pioneer CLD-500: fileCLD-500.conf

複数のリモコンを使いたい場合は,各リモコンの設定ファイルを一つのファイルにマージすればいいみたいだ。
LinuxのLIRCではそれぞれの設定ファイルを読み込めたのだが,WinLIRCではそのようには出来なかった。

Page Top

WinLIRCの動作確認 anchor.png

WinLIRCを使って作成したIRリモコンの動作確認をしてみた。

  • リモコン信号の受信の確認
    コマンドプロンプトを起動し,telnetコマンドを使用してみた。
    リモコンのボタンを押すとトレイアイコンが緑に点灯し,以下のようにどのボタンが押された/離されたかのメッセージの返答があった。
    > telnet 127.0.0.1 8765
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    ffff1e2010300008 00 Ok PXW3U4
    ffff1e2010300008 01 Ok PXW3U4
    ffff1e2010110008 00 Right PXW3U4
    ffff1e2010110008 01 Right PXW3U4
    ffff1e20101d0008 00 1 PXW3U4
    ffff1e20101d0008 01 1 PXW3U4
    ffff1e20101e0008 00 2 PXW3U4
    ffff1e20101e0008 01 2 PXW3U4
    ffff1e20101f0008 00 3 PXW3U4
    ffff1e20101f0008 01 3 PXW3U4
    ffff1e2010210008 00 4 PXW3U4
    ffff1e2010210008 01 4 PXW3U4
    telnet> \q
    Connection closed.
    これでリモコン信号の受信の動作が確認できた。
  • リモコン信号の送信の確認
    リモコン信号の送信が出来るか確認してみた。
    コマンドプロンプトを開き,WinLIRCのtransmitコマンドを使用してみた。
    > transmit PXW3U4 Power
    としたら,リモコン信号が送信され機器が動作した。
    うまく送信できたようだ。
Page Top

iREx anchor.png

WinLIRCに対応したツールとしては,iRExEventGhost等いくつかある。
今回はシンプルなiRExを使ってみた。

iRExはWinLIRCが受信したリモコン信号から,Windowsのキーイベント等を発生させる事ができるツール。

iRExのインストールは上記のリンクのDownloadからirex.zipをダウンロードして任意の場所に解凍すればOK。

下記のような設定ファイルを用意してirex.exeをダブルクリックで起動する。

Page Top

iRExの設定ファイル anchor.png

設定ファイルirexe.cfgをテキストエディタで作成する。
設定できる内容は,readme.txtに書かれている。

リモコン名<space>ボタン名<space>タイプ<space>動作内容

の設定を1行に1動作を定義する。

エミュレーションできる機能のタイプと動作内容には以下がある。

  • exe
    アプリケーションを実行する。アプリケーションはフルパスで設定する。
  • key
    キーボードの入力をエミュレーションする。通常のキーボードはその文字を設定すれば良い。
    • 特殊なキー
      文字では表せないキーは,以下のようにする。
      enter, space,back, +, -, pgup, pgdn, home, end, insert
      delete, help, pause, tab, print, shift, ctrl, alt, win
      shift-alt, shift-ctrl, alt-ctrl, esc
      up(カーソルキー), down(カーソルキー), left(カーソルキー), right(カーソルキー)
      apps, F1, ... F19(ファンクションキー), num0-num9(テンキー)
    • マルチメディアキー
      next, prev, play, stop
    • 一部のPCに搭載のキー
      mail, select, app1, app2
    • WEBブラウザを制御するキー
      b-back,b-forward,b-refresh,b-stop,b-search,b-favorites,b-home
  • vol
    音量を調整する。
    v-up(音量を上げる), v-down(音量を下げる),v-mute(音をミュート)
  • mouse
    Mouseの動きをエミュレーションする。移動量は数字で指定する。
    up ###, down ###, right ###, left ###
    lmb(左ボタン), rmb(右ボタン), mmb(中ボタン)

    ###は移動量。

一つのリモコンボタンに複数イベントを発生するには,同じリモコンボタンに2行で設定するとエミュレートされる。

その他の設定。

  • server
    ip   WinLIRCが動作しているIP Address
    port WinLIRCが動作しているport(8765)
  • editor
    設定ファイルを編集するテキストエディターを設定する。
Page Top

設定ファイルの例 anchor.png

作成したPX-W3U4のリモコン用のirexe.cfgファイル。

fileirexe.cfg
; remote    key   type  command
server  ip 127.0.0.1
server  port 8765
 
trayicon    on
 
mixer		line  main
 
editor		C:\WinApl\Sakura\sakura.exe
 
keypause	half
 
PXW3U4 1 key 1
PXW3U4 2 key 2
PXW3U4 3 key 3
PXW3U4 4 key 4
PXW3U4 5 key 5
PXW3U4 6 key 6
PXW3U4 7 key 7
PXW3U4 8 key 8
PXW3U4 9 key 9
PXW3U4 0 key 0
PXW3U4 * key shift :
PXW3U4 # key Shift 3
PXW3U4 VolUp key up
PXW3U4 VolUp key v-up
PXW3U4 VolDown key down
PXW3U4 VolDown key v-down
PXW3U4 Power key Q
PXW3U4 Tunner key Z
PXW3U4 Cc key C
PXW3U4 Data key D
PXW3U4 Full key F
PXW3U4 SndChange key S
PXW3U4 Mute key M
PXW3U4 Mute key v-mute
PXW3U4 Epg key E
PXW3U4 Up key up
PXW3U4 Down key down
PXW3U4 Left key left
PXW3U4 Right key right
PXW3U4 Ok key enter
PXW3U4 Play key play
PXW3U4 Stop key stop
PXW3U4 Pause key space
PXW3U4 ChUp key left
PXW3U4 ChDown key right
PXW3U4 RightSkip key >
PXW3U4 LeftSkip key <
PXW3U4 Fwd key right
PXW3U4 Back key left
PXW3U4 Tv exe C:\WinApl\TV\TVTest64\TVTest.exe /d BonDriver_Mirakurun.dll
PXW3U4 DvD exe "C:\Program Files\SMPlayer\smplayer.exe"

この設定ファイルで,リモコンのTVボタンを押すとテレビ視聴アプリのTVTestが起動され,チャンネルや音量なんかが操作ができるようになった :)

任意のアプリを起動することも出来るので便利!

Page Top

使ってみて anchor.png

作成したIRリモコンとWinLIRC/iRExを組み合わせると,PCやアプリケーションをリモコンで操作できるようになった。またいくつかのアプリケーションではWinLIRCに対応している。

PCでテレビを見る時,リモコンで操作出来るようになってこれが便利。わりあい早く反応するのでストレスなどは感じない。

オリジナルのIRMan.dllにはPCからリモコン信号を送信する機能はなかったが,機能を追加して送信もできるようにしたので,PCから家電なんかを制御したりすることも出来るようになった。 :)

IRremoteのおかげで多くのメーカーの赤外線リモコンに対応出来ている。ありがたいです。

ただPanasonic製の扇風機のリモコンを学習してみると,リモコンタイプがUNKNOWNになってしまうので,RawDataで扱わないと送受信できない。
また,エアコンのように32bit以上のサイズのリモコンデータを使用するリモコンには対応できていない。
対応するには,自作のIRリモコンとWinLIRCでのリモコンデータのやり取りをRAW_CODESタイプで行うようにする必要がある。

UNKNOWNタイプやエアコンのリモコンにも対応出来るようにするのが今後の課題。


*1 エアコンのリモコンのように,リモコン信号が32bit以上になるような場合には対応できない。
*2 Arduinoのボードはプログラムを内蔵ファームウェアを使って書き込むために,DTR信号でResetしファームウェアを起動させるようになっている。自作のボードでも同じようにしてあるため。

新しくコメントをつける

題名
ゲスト名
投稿本文
より詳細なコメント入力フォームへ

トップ   凍結 差分 バックアップ 複製 名前変更 リロード   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom
Counter: 1730, today: 1, yesterday: 0
最終更新: 2022-05-20 (金) 16:41:37 (JST) (1140d) by yuji