この記事ではスマートリモコンを作ってみたで紹介したスマートリモコンのプログラムを記載していきます。回路はスマートリモコン(回路)に記載してあります。
今回作成するプログラムは以下の4つです。
- (LED点灯確認用プログラム)
- 赤外線信号学習プログラム
- スマートリモコンプログラム
- (温度測定プログラム)
1. LED点灯確認用プログラムは、作成した回路が正常に動作するかの確認や、赤外線を使わずWi-Fi経由で家電を操作する場合(PS4を操作するなど)に、正しく動作しているか確認するために作成します。
2. 赤外線信号学習プログラムでは、家電のリモコンの赤外線信号を学習したり、その学習した赤外線信号を発信するための回路を作成します。
3. スマートリモコンプログラムでは、MQTTという通信プロトコルを使って、beebotteに送ったデータを受信し、その受信したデータに応じた処理(エアコンオンなど)を実行するためのプログラムを作成します。
4. 温度測定プログラムでは、温度によってエアコンの設定を変えたりするために、温度センサーが取得したデータを計算し、温度や湿度を出力するプログラムを作成します。
目次
ラズベリーパイのセットアップ
初期設定
まず、プログラムを作成する上で必要になってくるpythonモジュールや、その他ソフトウェアなどをインストールします。まずはpythonのパッケージをインストールする際に apt-get ではなく apt を使用していくのでaptのバージョンを最新にします。
pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt upgrade
温度測定プログラムのダウンロード
次に、プログラムを保存するディレクトリを作成します。今回はcodeという名前で作成します。 今回作成していくプログラムはこのcodeというディレクトリの中に作成してください。
pi@raspberrypi:~ $ mkdir code
今回使用する温度センサーであるDHT11のサンプルプログラムがgitにあがっているので、これを以下のコマンドでcodeディレクトリの中にダウンロードします。
pi@raspberrypi:~ $ cd code
pi@raspberrypi:~/code $ sudo apt-get install git
pi@raspberrypi:~/code $ git clone https://github.com/szazo/DHT11_Python.git
赤外線信号学習プログラムのダウンロード
まず、GPIOピンを制御するためにpigpioというパッケージをインストールします。 GPIOピンを制御するためのpythonパッケージとして、Raspbianに標準でインストールされているRPi.GPIOというパッケージや、WiringPiというパッケージがあるのですが、pigpioの方が精度や機能的な面で他の2つよりも優れているということなのでこちらを使っていきます。
pi@raspberrypi:~ $ sudo apt install pigpio python3-pigpio
このpigpioというパッケージを使用するにはpigpiodというデーモン(バックグラウンドで動作する常駐プログラム)を起動する必要があります。この操作はRaspberryPiを起動するたびに行う必要があるので、このデーモンをRaspberryPiを起動するときに自動的に起動するようにします。
pi@raspberrypi:~ $ sudo systemctl enable pigpiod.service
pi@raspberrypi:~ $ sudo systemctl start pigpiod
正しく設定できたかどうかを以下のコマンドで確認します。
pi@raspberrypi:~ $ systemctl status pigpiod.service
上記のようになっていれば、pigpioは使えるようになっています。
続いて、赤外線学習用のプログラムを以下のコマンドでダウンロードします。
pi@raspberrypi:~ $ cd code
pi@raspberrypi:~/code $ curl http://abyz.me.uk/rpi/pigpio/code/irrp_py.zip | zcat > irrp.py
スマートリモコンプログラムに必要なパッケージ等のダウンロード
まず、スマートリモコンプログラムで必要となる、BeeBotteにデータが送られてきたかどうかを監視するpaho-mqttというパッケージをインストールします。
pi@raspberrypi:~ $ sudo pip3 install paho-mqtt
続いて、beebotteのサーバにアクセスするために必要となる証明書をダウンロードします。
pi@raspberrypi:~ $ cd code
pi@raspberrypi:~/code $ curl -O https://beebotte.com/certs/mqtt.beebotte.com.pem
以上で必要なパッケージ等のインストールは完了です。
LED点灯確認用プログラム
今回作成した回路は、FETによって電流が増幅されているので、よくある数秒間隔で点滅させるというようなLチカプログラムを実行した場合、接続するLEDによっては流れる電流に耐えきれず、壊れてしまう可能性があります。なので点滅間隔を短めに設定したLチカプログラムを作成します。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#L_tika.py
import time
import pigpio
pi = pigpio.pi()
set_pin = 17
pi.set_mode(set_pin, pigpio.OUTPUT)
for i in range(10):
pi.write(set_pin, 1)
time.sleep(0.001)
pi.write(set_pin, 0)
time.sleep(0.3)
赤外線学習プログラム
外線学習には先ほどダウンロードしたirrp.pyというプログラムを使うのですが、このプログラムを使用する際、このプログラムの中身を変更してGPIOの設定をするわけではないので、初めに使用するGPIOピンの設定をする必要があります。
(今回はスマートリモコンの回路設計編で作成した回路に基づいて記載していくので、ピン配置を変えた方はご自身の回路に合わせてピン番号を読みかえて行ってください。)
事前準備
以下のコマンドで、17ピンを出力に、18ピンを入力に設定します。
pi@raspberrypi:~ $ echo 'm 17 w w 17 0 m 18 r pud 18 u' > /dev/pigpio
赤外線の学習
赤外線の学習をするには以下のようにコマンドを入力します。
pi@raspberrypi:~ $ python3 irrp.py -r -g18 -f codes air_con:on --post 130
この例では18ピンを赤外線信号を受信するピンに設定し、codesというファイルにair_con:onという名前で学習したデータを保存するというコマンドを実行しています。以下で作成するスマートリモコンプログラムに対応させるために名前は 機器名:操作名 と記述してください。
このコマンドを実行すると上図のように表示されるので、表示されたら赤外線を赤外線受信モジュールに向けて発信します。すると、確認用にもう一度送信するように促されるので、もう一度赤外線を発信します。okayと表示されプログラムが終了したら成功です。
※つまづきやすいポイント! エアコンのリモコンなど、リモコンの種類によっては”温度”、”風量”、”風向”など、複数の信号を一度に送信したり、ONとOFFで信号が違ったりする場合があるため注意してください。
(例えば、私のエアコンのリモコンでは、赤外線送信時に温度情報ものせて送信しているので、リモコンの表示が26度のときに温度を上げるのと、リモコンの表示が27度のときに温度を上げるのとでは信号が違うため、1回目と2回目で信号が一致せずエラーとなります。)
赤外線の送信
学習した赤外線を送信するには以下のようにコマンドを入力します。
pi@raspberrypi:~ $ python3 irrp.py -p -g17 -f codes air_con:on
この例では17ピンを赤外線信号を送信するピンに設定し、codesというファイルに記述されているair_con:onという名前のデータを送信するというコマンドを実行しています。
スマートリモコンプログラム
後に、メインとなるプログラムを作成します。ここでは、外部サービスで設定する情報が必要になるので、先に外部サービスとの連携を済ませておいたほうがいいかもしれません。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#smartremocon.py
import paho.mqtt.client as mqtt
import subprocess
import json
from time import sleep
HOST = 'mqtt.beebotte.com'
PORT = 8883
CA_CERTS = 'mqtt.beebotte.com.pem'
TOKEN = 'token_xxxxxxxxxxxxxxxxxx' #Beebotteで作成したチャンネルのトークンを入力
TOPIC = 'RaspberryPi/SmartRemocon' #Beebotteで作成したトピック名を入力
def on_connect(client, userdata, flags, respons_code):
print('status {0}'.format(respons_code))
def on_disconnect(client, userdata, flags, respons_code):
print("Unexpected disconnection.")
client.loop_stop()
def on_message(client, userdata, msg):
print(msg.topic + ' ' + str(msg.payload))
data = json.loads(msg.payload.decode("utf-8"))["data"][0]
print(msg.payload.decode("utf-8"))
print(data)
def default_command(data):
subprocess.call(["python3", "irrp.py", "-p", "-g17", "-f", "codes", data["device"]+":"+data["action"]])
print("excuted command: " + data["device"]+":"+data["action"])
# control
# control
# control air_con
list_summer=[5,6,7,8,9,10]
list_winter=[11,12,1,2,3,4]
if (data["device"] == 'air_con'):
if (data["action"] == 'on'):
date = datetime.datetime.now()
if date.month in list_summer:
print(date.month,"月 ","冷房をつけます")
subprocess.call(["python3", "irrp.py", "-p", "-g17", "-f", "codes", data["device"]+":"+"on"])
elif date.month in list_winter:
print(date.month,"月 ","暖房をつけます")
subprocess.call(["python3", "irrp.py", "-p", "-g17", "-f", "codes", data["device"]+":"+"on-winter"])
else:
default_command(data)
# control TV
elif (data["device"] == 'TV'):
if (data["action"] == 'input_switch1'):
input_switch(data)
sleep(0.1)
input_switch(data)
elif (data["action"] == 'input_switch2'):
input_switch(data)
sleep(0.1)
input_switch(data)
input_switch(data)
elif (data["action"] == 'input_switch3'):
input_switch(data)
sleep(0.1)
input_switch(data)
input_switch(data)
input_switch(data)
else:
default_command(data)
# control ps4
elif (data["device"] == 'ps4'):
if (data["action"] == 'on'):
subprocess.call(["sudo", "ps4-waker"])
if (data["action"] == 'standby'):
subprocess.call(["sudo", "ps4-waker", "standby"])
if (data["action"] == 'enter'):
subprocess.call(["sudo", "ps4-waker", "remote", "enter"])
if (data["action"] == 'back'):
subprocess.call(["sudo", "ps4-waker", "remote", "back"])
if (data["action"] == 'torne'):
subprocess.call(["sudo", "ps4-waker", "start", "CUSA00442"])
if (data["action"] == 'primevideo'):
subprocess.call(["sudo", "ps4-waker", "start", "CUSA03099"])
if (data["action"] == 'youtube'):
subprocess.call(["sudo", "ps4-waker", "start", "CUSA01065"])
# control temperature
elif (data["device"] == 'temp'):
subprocess.call(["cd", "DHT11_Python"])
subprocess.call(["python3", "dht11_example.py"])
subprocess.call(["cd", "DHT11_Python"])
# control other
else:
default_command(data)
if __name__ == '__main__':
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.username_pw_set('token:%s' % TOKEN)
client.tls_set(CA_CERTS)
client.connect(HOST, PORT)
client.subscribe(TOPIC)
client.loop_forever()
このプログラムは現在私が使用しているプログラムです。
TOKENとTOPICのところに次の記事で紹介する自分のTOKENとTOPICを入力してください。
また、if (data[“device”] == ‘xxxxx’):と書いてあるところのxxxxxに赤外線学習させたときに自分でつけた機器名を、
if (data[“action”] == ‘xxxxx’):と書いてあるところのxxxxxに操作名を記載して、オリジナルの処理を行うプログラムを作成してみてください。
(※特に特別な処理をする必要がない場合は、プログラムを変更しなくてもdefault_commandとして実行されるので大丈夫です。)
オリジナルの処理というのは、例えば自分のプログラムのように5~10月にエアコンをつけた場合冷房を実行し、11~4月につけた場合は暖房を実行するなどです。
ちなみに、ps4-wakerというpythonパッケージを使うと上記のプログラムのようにPS4をRaspberryPiで操作できるようになります。やってみたい方はこちらを見てみてください!
温度測定プログラム
先ほどgitからダウンロードしたプログラムはDHT11_Pythonというフォルダの中に入っています。dht11.pyというプログラムが温度や湿度を計算してくれるプログラムで、dht11_example.pyというプログラムが温度や湿度を表示するプログラムで、1秒おきにデータを取得して良好なデータが取得された場合のみ表示されます。
スマートリモコンと連動させたい場合は、一回温度が取得できれば十分なので、1回温度を取得したら終了する、または何かのプログラムを実行する、というほうが扱いやすいです。なので今回は1回温度を取得したら、温度に応じてエアコンをつけるプログラムを作成します。以下のプログラムをDHT11_Pythonというフォルダの中に作成してください。
import RPi.GPIO as GPIO
import dht11
import time
import datetime
import sys
import subprocess
# 実行するコマンドを以下に書き込んでください(pythonプログラムを実行する場合はパスに注意!)
command = ("python3 ../irrp.py -p -g17 -f codes air_con:on")
# コマンドを実行する基準となる温度を以下に書き込んでください
set_temp = 26
# initialize GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()
# read data using pin 14
instance = dht11.DHT11(pin=14)
while True:
result = instance.read()
if result.is_valid():
print("Last valid input: " + str(datetime.datetime.now()))
print("Temperature: %d C" % result.temperature)
print("Humidity: %d %%" % result.humidity)
if set_temp < result.temperature:
subprocess.call(command.split())
else:
print("設定した温度より室温が低かったため,コマンドは実行されませんでした")
#プログラム終了
sys.exit()
else:
#print("couldn't get good data")
time.sleep(1)
上記のプログラムは、実行するコマンドを “エアコンをつける赤外線を発信するコマンド” 、基準となる温度を “26℃” に設定し、1度温度を取得したら、その室温と基準温度を比較し、基準温度よりも室温が高かったら “エアコンをつける赤外線を発信するコマンド” を実行するというプログラムです。
(注意:ここでは、DHT11_Pythonというフォルダが以下の 4. で説明するirrp.pyというプログラムと同じ階層にあることを想定しています。他の階層にある場合や他のプログラムを実行する場合にはパスに注意してください。)
このプログラムのsubprocess.callのところを以下のように編集すると温度や湿度をjsonデータとして送ることができ、外出先から室温を確認できたりします。
subprocess.call(["curl", "-X", "POST", "-H", "\"Content-Type: application/json\"", "-d", "'{\"value1\":\"%s\",\"value2\":\"%d\",\"value3\":\"%d\"}'" % (datetime.datetime.now(),result.temperature,result.humidity), "https://xxx/xxxxx/xxxx/xxxxx"])
Alexa, Google HomeをRasberryPiと連携するへ進む