Raspberry Pi用赤外線学習リモコン基板「ADRSIR」を動かしてみる

Google Homeでホームオートメーションごっごがしたいので、Raspberry Pi用学習リモコン基板「ADRSIR」を購入しました。
まずは単体で動作確認をしたいのですが・・・
・・・? どうやって動かしたら良いのでしょう?添付の資料が簡素過ぎです。
Linux文化圏で生活していないWindowsユーザー向けに書いてみたいと思います。


Google Homeを購入していました。
関連記事:半額に釣られてGoogle Homeを買いました
高価なお料理タイマーです。

ネットで制御できる赤外線リモコンとつなぐとホームオートメーションごっこができるようです。でも赤外線リモコンが1万円以上するようです。
ちょっと高価すぎです。Google Homeと合わせて2万円越えの出費をするような方はコンピュータに興味があるでしょうから、Raspberry Piあたりを赤外線リモコンにした方が費用対効果が良いでしょう。

昨年末にRaspberry Piを赤外線リモコンにする方法を調べていました。赤外線LEDを直接Raspberry Piにつないで動かそうとも思ったのです赤外線LEDの入手が難しかったです。

アマゾンでトランジスタなど他の部品も買えるなら良かったのですが、もろもろ揃えると送料がとんでもないことに・・・
秋葉原へ行こうかと思ったのですが我が家からは少し遠く、時間と電車賃を考えると他に買うものが無いと行く気になりません。あぁ、秋葉原へ行く理由が本当に無くなったなぁ・・・

学習リモコン ADRSIR

そんな事を考えていたらタイミングよく(株)ビット・トレード・ワンよりADRSIRというRaspberry Piで使う学習リモコン基板が発売されました。
そのとき、注文するか悩んでいたらあっという間に売り切れ。次回入荷は1月19日という事でアマゾンでポチっときました。

赤外線LEDがたくさん付いています。半球状に赤外線光を発する事ができます。赤外線リモコンを置く位置に悩まなくて良さそうです。
物理的なボタンが10個あるようです。ネットでコマンドを打つのが面倒な時に使えそうです。
沢山のリモコンコードがホームページで公開されています。

ADRSIRが来た

発売日を忘れていたら宅配の不在票が置いてありました。再配達を頼んで着荷。
開梱します。
ADRSIR

Raspberry Piに付けます。
ピンがズレて刺さっていないか確認しましょう。
1列ずれてる
 こんなのはダメです。
1列ずれてる
1列ずれてますが気づかなかったりします。

ADRSIRを動かしてみる

早速ADRSIRを動かしてみたいと思います。
何から始めれば良いのでしょうか。添付されていた説明書を見ても何もわかりません。
ホームページからプログラムをダウンロードしなくては何もできないようです。

ツールを入手する

ビット・トレード・ワン(http://bit-trade-one.co.jp/)
のホームページを開きます。
サポート→ダウンロードと選びます。
”ADRSIR”でページ内検索をしてリンクを探します。
この記事の公開時では3つの資料がありました。
・リモコンコードリスト(CSV) [Download]
・ソフトウェア3種[配布ページ] [直接Download]
・I2C仕様 [PDFDownload]
リモコンコードリストとソフトウエア3種をダウンロードします。
ZIPで圧縮されているので展開してRapberry Piへ送ります。
Raspberry Piで展開するとリモコンコードリストのファイル名が文字化けするようです。適当な名前に直しましょう。

展開したファイルはRaspberry Piの適当なフォルダへ置きますが、説明のためここでは
/home/Pi/Downloads/ADRSIR
に展開したとして話を進めます。
ADRSIRのツールを展開
Windowsのフォルダではありません。すべてRaspberry Piで使うものです。説明などのファイルはWindowsで開いた方が見やすいでしょう。

赤外線データ20171212.csv

このファイルにはいろいろなメーカーの赤外線データが書かれています。エクセルがあればエクセルで開いてオートフィルタをかけて、ご自分のテレビメーカやエアコンメーカだけを表示させると良いでしょう。

リモコンのボタンに対応したデータが書かれています。後で説明するツールで4列目のコードを使います。

I2C仕様-TOOL20171213.xlsx

このファイルを開くとコマンドの使い方のような説明が見つかります。
3つのツールがあると書かれています。

  1. コマンドベース ツール
  2. コマンドライン ツール
  3. ディレクトリ単位処理 ツール

何を言っているかさっぱりわかりません。Linux文化圏の片鱗を垣間見せてくれます。事前知識のすり合わせをすっ飛ばされます。

Python用ツール

コマンドベースツールとコマンドラインツールはPythonのプログラムです。PythonとはWindowsのVisual Basicみたいな物だと思いましょう。豊富なライブラリがあるため簡単にいろいろなプログラムを組むことができます。高級言語なので理解も容易です。
私はPythonという言語がある事を知っている程度の知識しかありません。

コマンドベースツール IR-remocon01-commandbase.py

コマンドベースというのが何を言っているのかわかりませんが、このプログラムはPythonの開発環境(IDE)上で実行するもののようです。

コマンドラインツール IR-remocon02-commandline.py

こちらはコマンドプロンプトのコマンドの様に使えるようです。

ディレクトリ単位処理ツール IR-remocon03-dirbase.py

ディレクトリ単位というのが何を言っているのかわかりません。たぶん、基板上の10個のボタンをまとめて設定するものだと思います。ディレクトリ毎に10個のリモコンデータを切り替えるのでしょうか?

nod-red-program20171213.json

Node-REDのサンプルだそうです。Node-REDって何?
データの流れに着目しグラフィカルに編集する事ができる言語のようです。Webサーバーを動かしてリクエストが来たら何をするかとか簡単に書けそうです。
Raspberry PiのOS Raspbianには最初から入っているでしょう。
Node.jsの上に構築されているそうです。Node.jsをより簡単に使う事ができるようです。ところでNode.jsって何?
Webサーバーで動くJavaScriptをいろいろ作りやすくなっています。インターネットでのやりたい通信などのモジュールが多くあり楽に実現できるようです。

今回は使いませんが、Google Homeと連携させたい時に使うかもしれません。

ツールを使ってみる

それではツールを動かしてみましょう。ですが、その前にRaspberry Piの環境の確認です。
今回の記事ではRaspberry Pi 3 Model BにADRSIRを挿しています。

OSは
RASPBIAN STRETCH WITH DESKTOP Version:November 2017
です。Debian 9 strechベースです。
バージョンは次の通りです。
$ uname -a
Linux raspberrypi 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l GNU/Linux

I2Cを有効にします。
sudo raspi-config

Pythonは3.5.3となっています。
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170124] on linux

IR-remocon01-commandbase.pyを動くようにする

Raspberry Pi上のファイルマネージャでファイルIR-remocon01-commandbase.pyをダブルクリックします。
するとThonnyというPythonの開発環境でファイルが開かれるでしょう。
IR-remocon01-commandbase.py
ここでF5キーを押すとスクリプトが実行されます。緑のアイコンボタンを押してもいいです。
早速実行すると・・・
>>> %Run IR-remocon01-commandbase.py
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 179
    if dir_name <>'':
                 ^
SyntaxError: invalid syntax
はい、エラーです・・・わたしPython知らないんですけど・・・

まぁ高級言語なのでちょろっと調べれば直せるでしょう。
エラー行へはメッセージをクリックすると飛べます。
不等号がおかしいようです。179行の"<>"を"!="に直します。多分古いバージョンの表記なのでしょう。
直したら保存して再実行します。

またエラーがでます。
Traceback (most recent call last):
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 42, in 
    import commands
ImportError: No module named 'commands'
"import commands"とあります。commandsというモジュールはPython 3では無いようです。commandsモジュールの代わりはsubprocessモジュールのようです。次の行にありますね。
42行目の先頭に"#"を入れてコメントアウトしてしまいましょう。
"#import commands"とします。

保存して再実行します。

当たり前のようにエラーがでます。
Traceback (most recent call last):
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 169, in 
    os.chdir(dir_name)
FileNotFoundError: [Errno 2] No such file or directory: '/home/pi/I2C0x52-IR/'
/home/pi/I2C0x52-IR/なんていうディレクトリは無いと怒られました。どうやらこのディレクトリにファイルを展開して使う事を想定しているようです。今回は/home/pi/Downloads/ADRSIRディレクトリに展開してしまいました。168行目にディレクトリの指定があるので変更してしまいましょう。
dir_name = '/home/pi/Downloads/ADRSIR/'

保存して再実行します。

はい、エラー!
Traceback (most recent call last):
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 193, in 
    command = raw_input("command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= ")
NameError: name 'raw_input' is not defined
"raw_input"なんて関数は無いそうです。Pythonのバージョン違いの影響です。"raw_input"は"input"になったそうです。
複数行に"raw_input"があるのでCtrl+Fを押して置き換えをします。
置き換え

保存して再実行します。

やっと動いたー!
>>> %Run IR-remocon01-commandbase.py
command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= 

それでは本題、動かしてみましょう。

IR-remocon01-commandbase.pyを動かしてみる

赤外線リモコンのコマンドが5種類あるようです。
rdとwdコマンドは10個のボタンのデータをまとめてファイルに読み書きするようです。
読みだしたデータは"chx.data"というファイルに保存されます。xはボタンの番号で0~9になります。

rとwはボタンの番号を指定してデータをファイルに読み書きするようです。ファイル名も任意に指定できます。

それではやってみましょう。

リモコンコードをADRSIRへ書き込んでみましょう。
先ほどダウンロードした"赤外線データ20171212.csv"ファイルを開きます。お使いのテレビの電源ボタンのコードを探してみます。もちろん他のコードでも良いです。
/home/pi/Downloads/ADRSIRディレクトリに新規でテキストファイルを作りコードを貼り付けてください。コードはこんなやつですね。
”5701AD00160017001・・・”
ファイル名は”test.dat”としてみます。
コマンドは"w"です。
>>> %Run IR-remocon01-commandbase.py
command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= w
w
Enter memo_no: 0-9 0
memo_no write= [0]
filename =test.dat
filename= test.dat
5701A90018001500180014001800150017001500170016001700160016003F001900140018003F0018003E00
できたと思ったらエラーで終わります。
Traceback (most recent call last):
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 256, in 
    write_command(filename,memo_no)
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 109, in write_command
    for i in range(len(block2)/2):
TypeError: 'float' object cannot be interpreted as an integer
今度は何のエラーでしょうか?
floatとかintegerとか書いてありますので変数の型が合わないようです。Python 3で型の種類が変わったせいでしょう。
割り算をして小数点があるとfloatになってしまうようです。write_command関数の引数はintegerでなくてはいけないようです。型変換ってどうやるの?
変に高級言語っぽいのにこういう問題が起きると面倒です。勝手にキャストしてくれと思います。

割り算などで小数点があるとfloatになってしまうので小数点が出たら切り捨てれば良いようです。という事で109行目の"/"を"//"に変更します。
    for i in range(len(block2)//2):
保存して再実行します。

ですがまた同じようなエラーが出ます。
Traceback (most recent call last):
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 256, in <module>
    write_command(filename,memo_no)
  File "/home/pi/Downloads/ADRSIR/IR-remocon01-commandbase.py", line 121, in write_command
    bus.write_i2c_block_data(SLAVE_ADDRESS, W2_data_num_write ,  data_numHL)   #=
TypeError: Third argument must be a list of at least one, but not more than 32 integers
エラーの生じた行に問題はありませんが、引数の計算をする行の割り算を"//"に直せば良さそうです。
117行目を直します。
    data_num = len(int_tmp)//4  #for test
119行目を直します。
data_numHL[0] = data_num//256 
保存して再実行します。

今度は動くでしょう。
これでボタン1にリモコンコードが記憶されました。ADRSIR上のボタン1を押してみましょう。テレビ電源のオンオフができれば成功です。

次はリモコンコードの読出しをしてみます。

注意
※ADRSIRを使い始めたばかりでボタンに何も学習データが無い状態で読み出しをするとフリーズするようです。データ数が65535となっているようでとても長い通信時間がかかるのでしょうか?Pythonの変数はやたらメモリーを使うので巨大配列でメモリーが無くなるのかもしれません。壊れていると勘違いしますね。こうなったらThonnyをkillします。
事前にリモコンコードを書き込むか現物リモコンで学習させておくと良いでしょう。学習の仕方は製品の袋に入っていたペラ紙に書いてあります。

>>> %Run IR-remocon01-commandbase.py
command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= r
r
Enter memo_no: 0-9 0
memo_no write= [0]
filename =test.dat
filename= test.dat
memo_no write= [0]
data_num = 34
[87, 1, 173, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 24, 0, 21, 0, 66, 0, 22, 0, 24, 0, 20, 0, 67, 0, 22, 0, 66, 0, 22, 0, 66, 0, 22, 0, 66, 0, 22, 0, 66, 0, 21, 0, 66, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 66, 0, 21, 0, 24, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 23, 0, 22, 0, 23, 0, 22, 0, 66, 0, 22, 0, 66, 0, 22, 0, 66, 0, 22, 0, 66, 5]
test.dat
command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= 
コマンド"r"を打ちます。するとボタン番号を聞いてきます。ここでは"0"を指定しました。次にデータを保存するファイル名を聞いてきます。今回は"test.dat”としてみました。
データが読みだされファイルに保存されます。

ボタンの番号を指定するのが気になりますね。ボタンは10個しかありません10個しか使えないのでしょうか?
ファイルを指定すると同時に赤外線が光るのが"t"コマンドです。
先ほど作ったtest.datファイルのコードを送信してみましょう。
command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= t
t
filename =test.dat
5701A90018001500180014001800150017001500170016001700160016003F001900140018003F0018003E00
"t"とコマンドを打ち"test.dat"のファイルを指定します。

エラーが出るでしょう。先ほどの"w"コマンドと同じエラーです。
143行目を直します。
for i in range(len(block2)//2):
149行目を直します。
data_num = len(int_tmp)//4  #for test
151行目を直します。
data_numHL[0] = data_num//256
保存して再実行します。

今度はファイルを指定すると同時に赤外線が発光しテレビの電源のオンオフができるでしょう。

まとめ

今回はIR-remocon01-commandbase.pyを動かすところで終わります。エラーばかり出るとは思っていませんでしたので記事が長くなってしまいました。
次回はIR-remocon02-commandline.pyを動かしてみます。
IR-remocon02-commandline.pyも同じようにエラーがでますが、次回の記事では修正は簡単に紹介する程度にします。
ADRSIRのコマンドラインツール IR-remocon02-commandline.pyを使ってみる
Google HomeとRaspberry PiのNode-REDで赤外線リモコンのコントロールをする

ADRSIRのホームページで公開されているツールはRaspbianの古いバージョンで開発されているのでしょう。この記事公開時の最新のRaspbianではそのまま動きませんでした。
なかなかの初心者キラーっぷりです。
ですがLinux文化圏では良くあることです。前提環境が揃えば楽ちんなのですが、前提環境がなんだかわからなかったり・・・誰も環境を教えてくれない、あるいは誰も知らないなんてことも・・・あぁ恐ろしい。
しかし、このエラーのおかげでPythonツールが何をしているか知ることができました。

ほとんどの家電のリモコンコードが公開されているのは便利です。リモコンを無くしてしまい動かせなくなった機能を使うのにもいいですね。

最初は戸惑いますがリモコンの学習も簡単にでき赤外線リモコンで遊ぶにはとても良い商品です。

ツールの差分を下に置いておきます。



IR-remocon01-commandbase.pyの差分

diff --git a/org_IR-remocon01-commandbase.py b/IR-remocon01-commandbase.py
index 323161b..080d428 100644
--- a/org_IR-remocon01-commandbase.py
+++ b/IR-remocon01-commandbase.py
@@ -39,7 +39,7 @@
 import smbus
 import time
 from time import sleep
-import commands
+#import commands
 import subprocess
 import os
 import sys
@@ -106,7 +106,7 @@ def write_command(filename ,memo_no):
     print(len(block2))
     str_tmp = ""
     int_tmp = []
-    for i in range(len(block2)/2):
+    for i in range(len(block2)//2):
         str_tmp = block2[i*2] + block2[i*2+1]
         int_tmp.append( int(str_tmp, 16))
     print(int_tmp)  
@@ -114,9 +114,9 @@ def write_command(filename ,memo_no):
 # cmd W1_memo_no_write 0x19 bus-write(ADR,cmd,1)
     bus.write_i2c_block_data(SLAVE_ADDRESS, W1_memo_no_write ,memo_no )   #= 
 # cmd W2_data_num_write 0x29 bus-write(ADR,cmd,3)
-    data_num = len(int_tmp)/4  #for test
+    data_num = len(int_tmp)//4  #for test
     data_numHL = [0x31,0x32] #for test
-    data_numHL[0] = data_num/256
+    data_numHL[0] = data_num//256
     data_numHL[1] = data_num%256
     bus.write_i2c_block_data(SLAVE_ADDRESS, W2_data_num_write ,  data_numHL)   #= 
 # cmd W3_data_write           0x39 bus-read(ADR,cmd,n)
@@ -140,15 +140,15 @@ def trans_command(filename ):
     print(len(block2))
     str_tmp = ""
     int_tmp = []
-    for i in range(len(block2)/2):
+    for i in range(len(block2)//2):
         str_tmp = block2[i*2] + block2[i*2+1]
         int_tmp.append( int(str_tmp, 16))
     print(int_tmp)  
     print(len(int_tmp))
 # cmd W2_data_num_write 0x29 bus-write(ADR,cmd,3)
-    data_num = len(int_tmp)/4  #for test
+    data_num = len(int_tmp)//4  #for test
     data_numHL = [0x31,0x32] #for test
-    data_numHL[0] = data_num/256
+    data_numHL[0] = data_num//256
     data_numHL[1] = data_num%256
     bus.write_i2c_block_data(SLAVE_ADDRESS, W2_data_num_write ,  data_numHL)   #= 
 # cmd W3_data_write           0x39 bus-read(ADR,cmd,n)
@@ -165,7 +165,7 @@ def trans_command(filename ):
     bus.write_i2c_block_data(SLAVE_ADDRESS, T1_trans_start,memo_no )   #= 
 
 ###########################   main
-dir_name = '/home/pi/I2C0x52-IR/'
+dir_name = '/home/pi/Downloads/ADRSIR/'
 os.chdir(dir_name)
     
 while True:
@@ -176,7 +176,7 @@ while True:
        command = sys.argv[1]
        print('command=',command)
        dir_name = sys.argv[2]
-       if dir_name <>'':
+       if dir_name !='':
           cmd = 'mkdir  -p ' + dir_name    #-pオプション(--parentsオプション)を指定
           d = subprocess.check_output(cmd.split())
           os.chdir(dir_name)
@@ -190,18 +190,18 @@ while True:
 
        print('dir_name=',dir_name)
 
-    command = raw_input("command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= ")
+    command = input("command: rd/wd/r/w/t/e  ls/mkdir/cd/touch/pwd= ")
     print(command)
     if command == 'ls' :
         cmd = 'ls -l'
         d = subprocess.check_output(cmd.split())
         print(d)
     if command == 'mkdir' :
-        dir_name = raw_input("dirname = ")
+        dir_name = input("dirname = ")
         cmd = 'mkdir ' + dir_name
         d = subprocess.check_output(cmd.split())
     if command == 'cd' :
-        dir_name = raw_input("dirname = ")
+        dir_name = input("dirname = ")
         print(dir_name)
         os.chdir(dir_name)
         cmd = 'ls -l'
@@ -212,7 +212,7 @@ while True:
         d = subprocess.check_output(cmd.split())
         print(d) 
     if command == 'touch' :
-        file_name = raw_input("touch filename = ")
+        file_name = input("touch filename = ")
         cmd = 'touch ' + file_name
         d = subprocess.check_output(cmd.split())
         cmd = 'ls -l'
@@ -239,23 +239,23 @@ while True:
           print("wd_mode_end")
           sleep(1.0)           #0.55>NG 0.6:ok  sleep(1.0)  
     if command == 'r' :
-        command = raw_input("Enter memo_no: 0-9 ")
+        command = input("Enter memo_no: 0-9 ")
         memo_no= [0x02 ] #for test
         memo_no[0] = int(command) 
         print("memo_no write=",memo_no)
-        filename = raw_input('filename =')
+        filename = input('filename =')
         print('filename=',filename)
         read_command(filename,memo_no)
     if command == 'w' :
-        command = raw_input("Enter memo_no: 0-9 ")
+        command = input("Enter memo_no: 0-9 ")
         memo_no= [0x02 ] #for test
         memo_no[0] = int(command) 
         print("memo_no write=",memo_no)
-        filename = raw_input('filename =')
+        filename = input('filename =')
         print('filename=',filename)        
         write_command(filename,memo_no)
     if command == 't' :
-        filename = raw_input('filename =')
+        filename = input('filename =')
         trans_command(filename)
     if command == 'e' :
         break

コメント

最近のコメント

Threaded Recent Comments will be here.