スマートホーム構築記

IoTの恩恵を受けたいけど家庭用はなかなか出てこない。なら作ろうというブログ

Raspberry Pi3 でlircを使ってエアコンに信号を送信する

目的

前回信号を生成することができたので、
今回はlircを使ってエアコンに生成した信号を送信することを目的とします。

方針

以下の2つのステップで進めていきます.

  1. raspberry pi3の設定
  2. 赤外線発光回路作成
  3. lircの設定生成と送信テスト
  4. 統合スクリプト作成

raspberry pi3の設定

最初に接続回路を接続するためにraspberry pi3の設定を変更します。
今回はGPIO17を使用して赤外線LEDを制御します。
なので違うGPIOピンを使用する場合は17を自分のピン番号に読みかえて設定してください。
まずGPIOピンの設定を出力/プルNoneに変更します.

$raspi-gpio set 17 op pn

次にlircを使用する上でGPIO17を出力ピンとして設定するため/boot/config.txtを以下のように編集します
前回に一度編集していますのでそちらを変更前がどのように変更されたかは前回記事を参照ください。

dtoverlay=lirc-rpi,gpio_in_pin=4 (変更前)
dtoverlay=lirc-rpi,gpio_in_pin=4,gpio_out_pin=17 (変更後)

変更が終了したら一度再起動します。
以上で赤外線発光回路を接続するための準備が完了しました。

赤外線発光回路作成

Raspberry Pi3で赤外線を発光するための回路を作成します。
使用する赤外線LEDはOSI5LA5113Aを使用します。
指向性が高いので直接対象に向ける必要があります強力で安価な赤外線LED素子ですので使用していきます。

回路は以下の図のようになります。
(以下の回路で駆動しますが素人が付け焼刃で作成したものなので専門家の方は自分で設計していただいた方がよいかと思います)
f:id:kagemomiji:20161015095821:plain:w320

以下が設計で加味した部分です。
1.点灯時には約50mA流れる設計
2.50mAはGPIOからは供給できないので5Vラインから点灯用の電源を供給
3.トランジスタ2SC1815
4.抵抗値はオーバードライブを加味した抵抗値
5.リーク電流対策にベースGND間に抵抗を追加

この回路図に従ってブレッドボードとRaspberry Pi3で以下のように配線します。
f:id:kagemomiji:20161015104714p:plain:w480
実際に配線した線は以下のようになります。
f:id:kagemomiji:20161015144054j:plain:w480

以上で赤外線発光回路の作成は完了です。

lircの信号生成と信号送信テスト

前回作成したlirc信号生成スクリプトファイルではlirc用に信号を生成するには若干の改造がpythonスクリプトjsonに必要なのでスクリプトを改造します。
方針としては

  1. lircのRAW_CODESフォーマットで記述する
  2. /etc/lirc/lircd.confをpythonスクリプトから直接編集する
  3. 設定を反映する

RAW_CODESフォーマットで記述する

lircのRAW_CODESフォーマットは以下のようになります.

begin remote
 name 機器名(英字)
 flags RAW_CODES
 eps 30
 aeps 100
 gap 200000
  begin raw_codes
    name 信号名
    (pulse) (space) (pulse) (space)・・・・(繰り返し)
  end raw_codes
end remote 

begin remote~end remoteで一つの機器を設定する定義部となります。
各設定については以下の公式helpページを参照ください.
LIRC - Linux Infrared Remote Control

その中で
begin raw_codes~end raw_codes
が信号一つ一つの定義部となります。
raw_codes形式ではmode2で取得したpulseとspaceの数値を順番に並べていくことで信号を定義することができます。
また1行で全て定義すると読み込みができなくなるとのことなので、10個毎程度で改行をします。

ではスクリプトjsonを改造していきます。
まず、以下のような3部品に分割して考えます

部品 内容
header begin remote ~ name 信号名
body 信号の数値烈|
footer end raw_codes~end remote

このうちheader と footerは機器毎に固定となるのでjsonに以下のように追記して定義します

"signal":{
                #追記 "header":"begin remote \n name aircon \n flags RAW_CODES \n eps 30 \n aeps 100 \n gap 200000 \n  begin raw_codes \n   name json", 
                #追記 "footer":"  end raw_codes \nend remote",
"T":436,
                "trailer_t":10000,

このように編集したjsonを読みこんで先ほどのRAW_CODESフォーマットのテキストを出力するようにpythonスクリプトを改造します.

まずheaderとfooterを読みこむ部分を追記します.

##################################
#convert setting to binary signal
##################################

#initialize
signal = format["signal"]
rule = signal["rule"]
format_type = format["type"]
header = signal["header"] #追記
footer = signal["footer"] #追記

次に

pulse 436
space 436

のように出力されていた信号生成部を改造します。

###################################
#convert binary signal to ir_signal
###################################

#initialize
T = signal["T"]
ir_signal = ''

#AEHA format setting
if format_type == 'AEHA':
        trailer_t = signal["trailer_t"]

        for i in xrange(len(bin_signal)):
                #append 0 #pulse space 改行を削除
                if bin_signal[i] == '0':
                        ir_signal = ir_signal + str(T) + ' ' + str(T) + ' '
                #append 1  #pulse space 改行を削除
                elif bin_signal[i] == '1':
                        ir_signal = ir_signal  + str(T) + ' ' + str(3*T)+ ' '
                #append Leader #pulse space 改行を削除
                elif bin_signal[i] == 'L':
                        ir_signal = ir_signal +  str(8*T) + ' ' + str(4*T)+ ' '
                #append Trailer  #pulse space 改行を削除 またspaceのパルス長は最終出力には不要なので削除
                elif bin_signal[i] == 'T' :
                        if  i < len(bin_signal)-1:
                                ir_signal = ir_signal + str(T) + ' ' + str(trailer_t) + ' '
                        else:
                                ir_signal = ir_signal + str(T)
                #append \n for lircd.conf #10個毎に改行(2個セットになるので%5)
                if i % 5 == 0:
                        ir_signal = ir_signal + '\n'

最後に

print header
print ir_signal
print footer

とするとRAW_CODESフォーマットの信号が標準出力に出力されます。

/etc/lirc/lircd.confに直接記述する。

RAW_CODESフォーマットで出力された文字列を/etc/lirc/lircd.confに記述します。

##################################
#initialize
##################################
#check argvs
argvs = sys.argv
argc = len(argvs)
if(argc !=2):
        print 'Usage: #python %s filename' % argvs[0]
        quit()

#set local value
SIGNAL_LIB_DIR = "../../settings/format/"
LIRCD_CONF = "/etc/lirc/lircd.conf" #追記

lircd.confへのパスを定義します.

#################################
#open lircd.conf
#################################
try:
        lf = open(LIRCD_CONF,'w')
except IOError:
        print 'usage: sudo python %s filename' % argvs[0]
        quit()

これをload format等の下に追記。
lircd.confはrootでしか編集ができないのでsudoを使って実行するようにします。

##################################
#write /etc/lirc/lircd.conf #追記
##################################
lf.write(header + '\n')
lf.write(ir_signal + '\n')
lf.write(footer)

##################################
# finish
##################################
s.close()
f.close()
lf.close() #追記

header,ir_signal,footerの順にlircd.confに書き込み、終了処理を追記して完了です。

設定を反映

/etc/lirc/lircd.confを編集しても設定は反映されません。
lircdを再起動する必要があります。

$ sudo /etc/init.d/lirc restart

を実行してもうまく設定が反映されません。
なので

$ sudo /etc/init.d/lirc stop
$ sudo /etc/int.d/lirc start

を順番に実行する必要があります。

次に設定が反映されているかを確認します

$irsend LIST "" ""

設定が反映されていれば

irsend: aircon

のように設定されたremoteのnameが表示されます。
以上で設定の反映は終了です。

以下のコマンド入力すると信号が読みこまれて信号が送信されます。

$ irsend SEND_ONCE 機器名 信号名

統合スクリプトの作成

信号生成から信号送信までの一連の操作を一つのコマンドで実行できるスクリプトを作成します。

#!/bin/sh
SCRIPT_DIR='スクリプトのパス’
sudo python $SCRIPT_DIR/json2signal.py $1
sudo service lirc stop
sudo service lirc start
irsend SEND_ONCE aircon json

まとめ

今回赤外線発光回路を作成し、信号生成スクリプトを改造し、lircからエアコンへ信号を送信することができました。
今回作成したスクリプト
github.com
に公開していますのでご自由に編集等して利用してください。