IRリモコン
Windows PCを赤外線リモコンを使って操作したいため,USBで接続出来るIRリモコンレシーバーを作成してみた。
以前LinuxのMythTVやRaspberry Piで学習リモコンを作るときにLIRCを使ったので,WindowsのLIRCであるWinLIRCを使いたいが,元々WinLIRCというかLIRCは,古いシリアルポートのDCDに赤外線受信センサーを接続したハードウェアのためのツール。
このためシリアルポートが搭載されていない最近のPCでは使うのが難しい。シリアルポートが無いPCでシリアルポートを利用したい場合,普通はFTDI等のチップを搭載したUSB-Serialコンバーターを使うのだが,このようなコンバーターのDCDに赤外線センサーをつけてもWinLIRCのプログラムはうまく動作してくれない。
これはWinLIRCではリモコン信号の解析などにクリティカルなタイミングでの操作が必要なのだが,USB-Serialコンバーターを使うとどうしてもダイレクトに操作が出来ないため。
実際にFTDIのFT232RLなんかを使っていろいろやってみたが,受信データが正常に得られないためうまく動作しなかった。おそらくBig-Bangモードを使えばうまく行くと思うのだが,Bit-Bangモードがよくわからない。
ただWinLIRCの0.9.0以降のバージョンでは,プラグインによってシリアルポート以外のハードウェアに対して多少対応するようになった。
PCのMic入力に赤外線センサーの出力を接続してAudioCapture.dllプラグインを使う方法もあるので試してみたが,なかなか安定してリモコンデータが取得できなかった。うまく動けばハードウェアとしては一番簡単だし,どんなPCでも使えるのでメリットがあるのだが。
COMポート接続のIRMan IR ReceiverやUSB接続のUSB IR Toyも使えるようだ。これらのCOMポート接続タイプ・USB接続タイプでは機器側でリモコンデータを解析するようになっていて,WinLIRCではそのリモコンデータをプラグイン経由でそのまま使用するようにして対応している。
そこで作成したIRリモコン・レシーバーは,WinLIRCのIRManプラグインで使えるようにしてみた。
これでWinLIRCと各種のコンパニオンツールが使えるようになると思われ,Windows PCでリモコン操作することが実現出来そう。
残念ながらIRManプラグインではIR信号の送信はサポートされてないので,今回は受信専用となる。
ハードウェア
FTDIのUSBコンバーターが実装されている自作のATMEL AVRボード(ATmega168P)に,手持ちのIR受信センサーを接続した。市販のボードを使う場合は,Arduino Nano互換ボードなんかが良さそう。
回路図:IR受信センサーのVCC,GND,OUTピンをボードのAVRのポートに接続する。
IR受信センサー ATMEL AVR Board
SHARP GP1UD281XK ATmega168P
+---------+ +--------------+
| OUT 1 |---------------|PD2 受信 |
| VCC 2 |---------------|+5V |
| GND 3 |---------------|GND |
+---------+ | |
+5V +5V | |
+--- R +--- R | MOSI|-----+
|15ohm |15ohm | | |
IR A IR A | | SW
LED K LED K | | |
| | | | GND
+---------+ | |
| | |
+------ D | |
G -- R --|PD3 送信 |
+------ S 10ohm | |
| 2SK1748 | |
| | USB |<============> PC
| | | USB
+------------------|GND |
| |
+--------------+
IR受信センサーは38KHzの物なら何でも良い。
作成してみた基板。
動作チェックプログラム
以下のプログラムrcvsend.inoでハードウェアの動作チェックをした。
使用するArduino IDEとIRremoteライブラリ(version 3.x以降)は,自作のAVRボード(ATmega168P)を扱えるように若干改造している。
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
-
!
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
-
-
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
-
-
|
|
!
!
|
!
-
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
!
|
!
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
| #define MARK_EXCESS_MICROS 20
#define RAW_BUFFER_LENGTH 200
#include <IRremote.hpp>
#include <avr/eeprom.h>
#define SW MOSI #define LED LED_BUILTIN #define PUSH 1000
#define EEPROM_V1 0x0000 #define EEPROM_V2 0x0004 #define EEPROM_V3 0x0005
int IR_RECEIVE_PIN = 2; int IR_SEND_PIN = 3;
long recdata; byte recbits; byte rectype; byte recflags; uint16_t recaddr,reccom,recextra;
int swcount;
void setup() {
digitalWrite(LED, LOW); Serial.begin(9600); pinMode(SW, INPUT_PULLUP); pinMode(LED, OUTPUT); IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK); IrSender.begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK, LED);
swcount = 0;
eeprom_busy_wait();
recdata = eeprom_read_dword((uint32_t *)EEPROM_V1); eeprom_busy_wait();
recbits = eeprom_read_byte((uint8_t *)EEPROM_V2); eeprom_busy_wait();
rectype = eeprom_read_byte((uint8_t *)EEPROM_V3);
Serial.print("rcv and send IR remokon signal.\n"); SPRI(); }
void loop() {
if (IrReceiver.decode()) { recbits = IrReceiver.decodedIRData.numberOfBits; recflags = IrReceiver.decodedIRData.flags; recdata = IrReceiver.decodedIRData.decodedRawData; rectype = IrReceiver.decodedIRData.protocol; recaddr = IrReceiver.decodedIRData.address; reccom = IrReceiver.decodedIRData.command; recextra = IrReceiver.decodedIRData.extra;
if (rectype != 0){
eeprom_busy_wait();
eeprom_update_dword((uint32_t *)EEPROM_V1, recdata); eeprom_busy_wait();
eeprom_update_byte((uint8_t *)EEPROM_V2, recbits); eeprom_busy_wait();
eeprom_update_byte((uint8_t *)EEPROM_V3, rectype);
Serial.print("Memorized! "); SPRI();
for (byte i = 0 ; i < 5 ; i++) {
digitalWrite(LED, i % 2);
delay(100);
}
}
IrReceiver.resume(); }
while (digitalRead(SW) == 0) { digitalWrite(LED, HIGH); swcount++;
if (swcount > PUSH) { eeprom_busy_wait();
recdata = eeprom_read_dword((uint32_t *)EEPROM_V1); eeprom_busy_wait();
recbits = eeprom_read_byte((uint8_t *)EEPROM_V2); eeprom_busy_wait();
rectype = eeprom_read_byte((uint8_t *)EEPROM_V3);
IrSender.sendNECRaw(recdata, 3); Serial.print("SEND! "); SPRI(); digitalWrite(LED, LOW); delay(1000); IrReceiver.resume(); swcount = 0; }
}
swcount = 0; }
void SPRI() {
Serial.print("> Protocol:");
Serial.print(getProtocolString(rectype)); Serial.print(" BITS:");
Serial.print(recbits); Serial.print(" FLAG:");
Serial.print(recflags); Serial.print(" ADDR:0x");
Serial.print(recaddr, HEX); Serial.print(" CMD:0x");
Serial.print(reccom, HEX); Serial.print(" EXTD:0x");
Serial.print(recextra, HEX); Serial.print(" DATA:0x");
Serial.print(recdata, HEX); Serial.println();
}
|
リモコン送信機のボタンを押すとリモコン信号を学習する。MOSIピンをLowにして送信モードにするとそのデータを送信する。機器が反応すれば動作していることになる。
シリアルコンソールで,リモコンの押されたボタンのコードが確認できる。
IRMan IR Recieverプロトコル
IRMan IR Reciever(もう販売はされていない)は,シリアルポートでPCと接続する。
リモコン信号はIRMan IR Recieverで解析して,そのデータをPCに送るようになっている。
- PCとのSerial通信パラメータ
Baudrate:9600
Data:8bit
Stop bit:1 stop
Parity: non parity
- HostからRTSとDTRをHiにする
これによりIRMan IR Recieverに電源が供給されて起動される。
- Hostからスタートコマンドを送信
HostからIRと送信する。(IとRの間は最小500usの時間が必要。)
- IRManデバイスからOKの返答
HostからのIRへの返答。OKを返す。
- IRManデバイスで受信したリモコンのリモコン・コードをHostに送信する
リモコンから受信したデータを,
0x1E, 0xXX, 0x00,0x00,0x00,0x00
という6byteのパケットデータでPCに非同期で送信するようだが,1Byte目は0x1E固定で,2byte目がリモコンコマンドを表していてその後はオプションのようだ(と思う)。
- HOSTからIRManデバイスへIRリモコン・コードを送信
WinLIRCのIRManデバイスでは,リモコン・コードの送信は残念ながら実装されていない。
ソフトウェア
作成したIRリモコン・レシーバーをWinLIRCで使用するために,IRMan IR Reciver準拠の(実際のIRManは見たこと無いので知らないけど・・・)プログラムavrlirc.inoを作成して書き込んだ。
今回は2-5byteにリモコンデータをそのままマッピングした。WinLIRCのプラグインIRMan.dllでは,受け取ったパケットデータを全てデータとして利用しているのでこれでも問題ない。
おそらく,0x1Eのヘッダーもなくても良いんだと思う。
-
|
|
|
!
-
|
|
|
|
-
!
|
-
-
|
|
|
|
|
-
|
!
|
-
|
!
-
|
!
!
!
|
-
-
|
-
|
|
!
!
!
|
-
-
-
|
|
!
!
| #define MARK_EXCESS_MICROS 20
#define RAW_BUFFER_LENGTH 200
#include <IRremote.hpp>
int RECV_PIN = 2; int SEND_PIN = 3; unsigned char lastdata[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
long recdata; byte recbits; byte rectype; byte recflags;
void setup() {
pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); Serial.begin(9600); IrReceiver.begin(RECV_PIN, DISABLE_LED_FEEDBACK); }
void loop() {
if (IrReceiver.decode()) { recbits = IrReceiver.decodedIRData.numberOfBits; recflags = IrReceiver.decodedIRData.flags; recdata = IrReceiver.decodedIRData.decodedRawData; rectype = IrReceiver.decodedIRData.protocol;
if (recflags != 1) { memcpy(lastdata, &recdata, 4); }
Serial.write(0x1E); for (int i = 0; i <= 4; i++) { Serial.write(lastdata[i]); }
IrReceiver.resume(); }
}
void serialEvent() {
while (Serial.available() > 0) { char rcvdat = (char)Serial.read(); if (rcvdat == 'R') { Serial.write("OK"); onoffLED(4); }
}
}
void onoffLED(int times) {
for (byte i = 0 ; i < times ; i++) {
digitalWrite(LED_BUILTIN, i % 2);
delay(100);
}
digitalWrite(LED_BUILTIN, LOW); }
|
PC側のソフトウェア
Windows PCには,WinLIRCとWinLIRCに対応しているコンパニオンツールを使用する。
WinLIRCは作成したIRリモコンとPCをUSBで接続して,以下のことを行う。
- リモコンからのデータを受信する。
- リモコンからのデータを解析・学習してリモコンを識別・管理する。
- コンパニオンツールやアプリケーションへリモコンデータ情報を提供する。
NetworkのTCP通信でリモコンの情報をツールやアプリケーションに送る。
直接WinLIRCに接続出来るアプリケーションは,そんなに多くはない。
- リモコン信号をリモコンに代わって機器に送信する。
IRManプラグインでは対応していない。
iRExやEventGhostはWinLIRCに対応しているコンパニオンツールで,WinLIRCが受信したリモコンデータからWindows PCでのキー入力やMouse操作をエミュレーションしたり,任意のアプリを起動したりすることが出来るようになる。
これらでPCをリモコンで操作出来るようになる。
WinLIRC
LIRCのWindows版であるWinLIRCをダウンロードする。ダウンロードするバージョンは0.9.0i。
インストールはダウンロードしたzipファイルを任意の場所に解凍すればOK。
ダウンロードしたWinLIRCとプラグインIRMan.dllを使ってみたところ,作成したIRレシーバーとうまく接続出来ないで,IRRecordでの学習モードに移行しないですぐに終了してしまう。
DTR信号が出力されると自作のIRレシーバーのCPUがResetされちゃう*1のと,ヘッダー送信前にゴミデータが受信されているのが原因と思われる。
しょうがないので,WinLIRC 0.9.0iのIRMan.dllのソースコードを少し修正してDTR信号が出力された後のwaitタイミングを長めに変更した。
この
修正したIRMan.dllファイルを,WinLIRCをインストールした場所にあるpluginsディレクトリのIRMan.dllと入れ替える。
これでうまく動作するようになった。
WinLIRCでリモコンを学習する
WinLIRCを起動して,最初に使用するプラグインをInput PluginでIRMan.dllに設定する。
そして使用するCOMポートをPlugin Setupボタンで設定する。
その後作成するconfigファイルを指定した上で,Create Configボタンをクリックするとリモコンの学習を行うIRRecordプログラムが起動する。
コマンドプロンプトを開いて,
> IRRecord -d IRMan.dll ..\px-w3u4.conf
とかしても同じ。
リモコン信号の学習は以下の手順。
- 「Enterを押せ」と表示される
説明を読んでEnterを押す。
- 「任意のリモコンボタンを押し続けろ」と指示される
リモコンのどれかのボタンを押しっぱなしにする。
.....というようにドットが表示されていく。これでリモコン信号の解析を行っている。
かなり入力されると,このフェーズが終了する
- 「学習対象のラベルを入力して,リモコンのボタンを押せ」と指示が出る
リモコン送信機の学習したいボタンに相当する名前を入力する。
- 学習させたいリモコンのボタンを押す
リモコン送信機のボタン信号を一つ一つ学習していく。ボタンは学習するまで押しっぱなしにする。
学習したいボタンを繰り返し同じように行う。
- 全て終わったらラベル入力時にEnterのみを押す。
- さらに「Enterを押せ」と表示される
Enterを押す。
- リモコンのいくつかのボタンを1回づつ押していく
ボタンは押しっぱなしにはしないで1回だけ押す。学習データを最適化するために行うようだ。
設定ファイルが作成されたら,nameのところを任意のわかりやすいものに変更しておく。
コンパニオンツールのiRExでのリモコン指定は,このnameを参照する。
WinLIRCを再起動する
その後WinLIRCを再起動すると,リモコン信号の受信待ち状態になりシステムトレイに丸のアイコンが表示される。
リモコンのボタンを押した時にこのアイコンが緑に変化すれば,学習したリモコン信号に反応していることになる。
PX-W3U4の付属リモコンを学習させて作成したファイル:px-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 Wed Dec 14 14:59:07 2022
#
# contributed by
#
# brand: PLEX
# model no. of remote control: PX-W3U4
# devices being controlled by this remote: USB TV-Tunner PX-W3U4
#
begin remote
name PXW3U4
bits 16
eps 30
aeps 100
one 0 0
zero 0 0
pre_data_bits 40
pre_data 0xFFFF1E2010
post_data_bits 8
post_data 0x0
gap 110000
toggle_bit_mask 0x0
begin codes
Power 0x20DF
Mute 0x2AD5
Recbtn 0x04FB
Epg 0x25DA
Tv 0x06F9
Dvd 0x07F8
Hidari 0x08F7
Cc 0x09F6
PlayerOn 0x02FD
PlayerOff 0x03FC
SndChange 0x0CF3
Full 0x0EF1
Up 0x0DF2
Down 0x13EC
Left 0x0FF0
Right 0x11EE
Ok 0x30CF
Info 0x0BF4
Rec 0x18E7
Pause 0x16E9
Play 0x35CA
Stop 0x17E8
Back 0x19E6
Fwd 0x3AC5
LeftSkip 0x1BE4
RightSkip 0x1CE3
1 0x1DE2
2 0x1EE1
3 0x1FE0
4 0x21DE
5 0x42BD
6 0x43BC
7 0x45BA
8 0x26D9
9 0x47B8
0 0x4AB5
* 0x49B6
# 0x4BB4
ChUp 0x40BF
ChDown 0x44BB
VolUp 0x48B7
VolDown 0x4CB3
Tunner 0x4DB2
Clr 0x4EB1
Input 0x2FD0
Data 0x4FB0
Blue 0x50AF
Red 0x51AE
Green 0x52AD
Yellow 0x22DD
end codes
end remote
複数のリモコンを使いたい場合は,各リモコンの設定ファイルを一つのファイルにマージすればいいみたいだ。
LinuxのLIRCではそれぞれの設定ファイルを読み込めたのだが,WinLIRCではそのようには出来なかった。
WinLIRCの動作確認
WinLIRCの動作確認をしてみる。
telnetでWinLIRCに接続する。
リモコンのボタンを押すとトレイアイコンが緑に点灯し,以下のようにメッセージが返答があればOK。
> telnet 127.0.0.1 8765
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
ffff1ef30c080420 00 Ok PXW3U4
ffff1e7788080420 00 Right PXW3U4
ffff1e47b8080420 00 1 PXW3U4
ffff1e8778080420 00 2 PXW3U4
ffff1e07f8080420 00 3 PXW3U4
ffff1e7b84080420 00 4 PXW3U4
telnet> \q
Connection closed.
iREx
WinLIRCに対応したツールとしては,iRExやEventGhost等多くある。
ここではiRExを使ってみた。
iRExのインストールは上記のリンクのDownloadからirex.zipをダウンロードして任意の場所に解凍すればOK。
下記のような設定ファイルを用意してirex.exeをダブルクリックで起動すればOK。
iRExの設定ファイル
設定ファイル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(テンキー)
- マルチメディアキー
- 一部のPCに搭載のキー
- 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
設定ファイルを編集するテキストエディターを設定する。
設定ファイルの例
作成したPX-W3U4のリモコン用のirex.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
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 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が起動され,チャンネルや音量なんかが操作ができるようになった 
任意のアプリを起動することも出来るので便利!
使ってみて
作成したIRリモコン・レシーバーとWinLIRC/iRExを組み合わせると,Windows PCをリモコンで操作できるようになった。
PCでテレビを見る時に,リモコンでいろいろ操作出来るようになって便利。けっこう高速に反応するのでストレスなどは感じない。
IRMan.dllにはPCからリモコン信号を送信するコードが実装されていない。そのうち送信できるようにしたい。
新しくコメントをつける