2016年6月30日木曜日

Raspberry Pi上のLIRCでエアコンを操作する

0. はじめに

注意:2020年4月現在において、本ページに記しているエアコン操作の内容は、 「4.19.115+ 以降の kernel 4.19 や kernel 5.x を搭載したRasberry Pi OS Buster / Bullseye」または「kernel 4.14 を搭載した Rasbian Stretch」で動作します。

注意しなければならないのは、 「4.19.115+ 以前の kernel 4.19 を搭載したRasbian Buster」および「アップグレードを実行して kernel 4.19 となった Rasbian Stretch」 では動作しない、ということです。

以上を踏まえ、本ページは以下の2通りに分けて記述します。
  • Rasberry Pi OS Buster / Bullseye の場合 (kernel 4.19.115+ 以降)
  • NOOBS 3.0.1 (Raspbian 2019-04-08) およびそれ以前のRaspbian StretchをOSアップデートをせずに利用している場合 (kernel 4.14)


1. 予備知識

本書の第5章において、LIRC(Linux Infrared Remote Control) というソフトウェアを用いてRaspberry Piを家電製品のリモコンにする方法を紹介しました。

その際、「エアコンのリモコンが発する信号はLIRCで認識できないため、テレビや照明などLIRCが認識できるリモコンを用いる」という方針をとりました。

しかし、難易度は上がりますが、Raspberry Piをエアコンのリモコンとする方法はありますので、ここでその方法を紹介します。

なお、この方法を試すには、LIRCの挙動をよく理解しておく必要がありますので、本書の第5章の演習を一通り終えている方を対象とします。

●エアコンのリモコンが発する信号は継続時間が長い

さて、書籍では「エアコンのリモコンが発する信号は継続時間が長い」と述べましたが、実際に信号を観測してそれを確かめてみましょう。

「テレビの電源」、「エアコンのON信号」、「エアコンのOFF信号」を押したときのリモコンの赤外線LEDの点灯状態を記したのが下図です。


この図は、本書図5-6の回路において赤外線リモコン受信モジュールが受信した信号をオシロスコープで取得し、上下反転するなどして見やすく加工したものです。

まず、テレビの電源ボタンが押されたときの赤外線LEDの点滅状態は約64ミリ秒続くことがわかります。これは本書図5-4にも示されています。

一方、エアコンの電源を入れる際の赤外線LEDの点滅状態は約127ミリ秒続くことが見て取れます。確かに、テレビの信号より継続時間が長いですね。

●エアコンの電源ボタンはON時とOFF時で信号が異なる

さらに、上の図を見ると、「エアコンの電源ボタンはON時とOFF時とで信号が異なる」ことも見て取れます。

信号の継続時間が長いのはON時のみで、OFF時の信号は継続時間が短いこともわかります。

エアコンのリモコンは、多くの場合下図のように液晶画面がついており、このリモコンでエアコンがON状態かOFF状態かを管理しています。その状態に応じて、出力する信号を変えているわけです。


●エアコンのON信号には様々な情報が乗っている

ここまで、「エアコンのON信号」と書いてきましたが、実はエアコンには様々なON信号があり得ます。

これはエアコンのリモコンの使われ方を思い浮かべると分かりやすいと思います。私たちは、エアコンの電源をONにする前に、手元のリモコンで温度を変更したり、冷房/暖房や風量を切り替えてからエアコンの電源をONにすることがあります。

電源をONにされたエアコンは、リモコンの設定に応じたモードで動作を開始するはずです。

これは、「ON」という信号(上図のオレンジのグラフ)の中に、「設定温度」、「冷房/暖房」、「風量」などという情報が乗せられていることを意味します。逆に言えば、そのために信号の継続時間が長くなっているのだとも言えるでしょう。

ですから、一言で「ON信号」といっても、「25度、冷房、風量弱のON信号」と「25度、暖房、風量弱のON信号」は信号の点滅パターンが異なるということになります。

これは、LIRCを用いる上ではあまり都合が良くありません。なぜなら、LIRCはLEDの信号パターンによって異なる名前をつけて管理するので、ON信号だけで数十通りのバリエーションがあると管理が難しくなるからです。

2. 方針

以上を踏まえて、作業の方針を記します。

上で述べたように、エアコンのリモコンにはON信号だけで様々なバリエーションがありますので、それらを全てRaspberry Piから利用可能にするのは現実的ではありません。

そこで、ここでは
  • (お好みの設定での)電源オン
  • 電源オフ
の2つの信号だけを取り扱います。

信号数を2つより増やすことは難しくありませんので、一度2つの信号を利用できるようになってからチャレンジしてみると良いでしょう。

さて、書籍でテレビのリモコンを取り扱った際、下記の順で説明しました。
  • (1) irrecordコマンドによる、リモコンから出力される信号の学習フェーズ
  • (2) irsendコマンドによる、信号の送信フェーズ
このうち(1)の学習フェーズはエアコンのリモコンではうまくいきませんので、これを
  • (1') mode2コマンドによる、リモコンから出力される信号の記録
と差し替えて解説を進めます。

3. エアコンの制御 (1)
Rasberry Pi OS Buster / Bullseye の場合 (kernel 4.19.115+ 以降)

ここからはまず「Rasberry Pi OS Buster / Bullseye の場合 (kernel 4.19.115+ 以降)」において、 mode2コマンドを用いてエアコンのリモコンが出力する信号を記録する方法を解説します。

kernel 4.19.115+ 以降というのは、2020.5.27にリリースされたRaspberry Pi OS以降が該当します。
ターミナルを起動して kernel のバージョンを確認してみましょう。下記のように 4.19.115-v7l+ や5.4以降であれば問題ありません。
pi@raspberrypi:~ $ uname -r
4.19.115-v7l+
それを確認したら、エアコンの制御に入りましょう。

LIRCのインストールや設定は 「Raspberry Pi OS Buster / Bullseye でlircを利用する」 により済ませておいてください。

まず、本書図5-6の「赤外線リモコン受信モジュールを用いた回路」を作成します。

そして、「(お好みの設定での)電源オン」信号の記録から始めましょう。このとき、/etc/lirc/lirc_options.conf の設定は以下である必要があります。この意味がわからない方は、「Raspberry Pi OS Buster / Bullseye でlircを利用する」の内容を復習しましょう。
driver          = default
device          = /dev/lirc1
そして、ターミナルLXTerminalを起動し、下記のコマンドを実行します。
mode2 > on.txt
ターミナルには以下の表示が現れます。そのまま赤外線リモコン受信モジュールに対してリモコンで「(お好みの設定での)電源オン」ボタンを一度押します。
Using driver default on device /dev/lirc1
Trying device: /dev/lirc1
Using device: /dev/lirc1
押してもターミナルは変化しませんが、気にせずターミナル上でCtrl-c (Ctrlキーを押しながらcキーを押す)を実行します。これにより、mode2コマンドが終了します。

ここまでの作業がうまくいけば、「on.txt」というテキストファイルに「(お好みの設定での)電源オン」信号についての情報が記録されているはずです。ターミナルで「mousepad on.txt」または「leafpad on.txt」コマンドを実行するなどして、テキストエディタでon.txtを開いてみましょう。

エアコンのメーカーなどにより異なりますが、例えば下記のような情報が記録されています。何も記録されていない場合、LIRCの設定が正しくない可能性があります。本書の5章の演習を改めてやり直してみましょう。


これは何を表しているでしょうか。1行目は意味のない情報ですが、2行目以降は下図に示すエアコンのリモコンの点滅状態の拡大図を見ることで理解できます。

on.txtに記録された「3327」、「1694」…などの数値は、下図のように点灯や消灯の継続時間を表しているというわけです(単位はマイクロ秒)。


この数値のパターンを最終的にLIRCに渡すことになります。

その前に、リモコンの「電源オフ」信号についても記録しておきましょう。先ほどと同様にターミナルで下記のコマンドを実行します。
mode2 > off.txt
記録先のファイル名が「off.txt」になっていることがわかるでしょうか。その状態で、リモコンの「電源オフ」ボタンを赤外線リモコン受信モジュールに向かって押します。押し終わったら、ターミナル上でCtrl-cを実行してmode2コマンドを終了します。さらに、off.txtを「mousepad off.txt」または「leafpad off.txt」コマンドによりleafpadで開き、中身が記録されていることも確認しておきましょう。

次に、LIRCでエアコンのリモコンの信号を取り扱えるようになる設定ファイルAC.lircd.confを作成していきます。

書籍で取り扱ったテレビのリモコンの場合は、irrecordコマンドが自動的に生成してくれましたが、今回取り扱っているエアコンのリモコンの場合は手作業で作成する必要があります。

まず、テキストエディタを起動します。ターミナルで「mousepad AC.lircd.conf」または「leafpad AC.lircd.conf」のコマンドを実行しましょう。

そして、下記の雛形をコピーして、起動したテキストエディタに貼り付けます。
begin remote

  name  AC
  flags RAW_CODES
  eps            30
  aeps          100

  gap          200000
  toggle_bit_mask 0x0

      begin raw_codes
      name on
# python getinterval.py on.txtの結果を貼り付け 
      name off
# python getinterval.py off.txtの結果を貼り付け 
      end raw_codes

end remote
「#」のついた行はコメントとして無視されるのですが、そこに、on.txtとoff.txtに関する情報を貼り付けるよう指示されています。

ただし、on.txtやoff.txtの中身をそのまま貼り付けるわけではありません。下図のように、on.txtやoff.txtのうち、必要なのは赤い四角で囲われた数値のみです。


これらの数値を手作業で抽出するのは大変なので、抽出を容易にするプログラムgetinterval.pyを用意しました。ターミナルで下記のコマンドを実行してこのプログラムをダウンロードしてください。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/getinterval.py
ダウンロードが済んだら、ターミナルで下記のコマンドを実行してみましょう。
python getinterval.py on.txt
すると、on.txtのうち必要な部分のみが抽出され、下図のようにターミナル上に表示されます。

これを(下図の場合、冒頭の3327から末尾の448までを)マウスでなぞり、メニューから「編集」→「コピー」でコピーします。そして、テキストエディタ上の該当箇所に貼り付けます(「編集」→「貼り付け」)。


同様に、「python getinterval.py off.txt」の結果も指示のある場所に貼り付けます。「#」がついたコメント部は不要なので削除しました。


なおこの際、mousepadでは「編集」→「設定」→「表示」→「行を折り返す」、leafpadでは「オプション」→「右端で折り返す」にチェックを入れないと、結果が見にくいですので注意して下さい。

以上で、設定ファイルAC.lircd.confの作成は完了です。保存してテキストエディタを終了しましょう。

なお、リモコンの信号は用いているエアコンで異なるため、上の設定ファイル上の数値をそのまま写しても意味はありませんのでご注意ください。お使いのリモコンを用いてこの設定ファイルを作成することが重要です。

最後に、このAC.lircd.confを/etc/lirc/lircd.conf.d/にコピーしましょう。ターミナルを起動して下記のコマンドを実行します。
$ sudo cp AC.lircd.conf /etc/lirc/lircd.conf.d/
以上で、信号の記録は終わりです。次に、irsend で信号を送信しますので、 /etc/lirc/lirc_options.conf の設定を以下のように変更する必要があります。この意味がわからない方は、「kernel 4.19以降を搭載したRaspbian Buster/Stretchでlircを利用する」の内容を復習しましょう。
driver          = default
device          = /dev/lirc0
以上が終わったら、Raspberry Piを再起動します。新しいAC.lircd.confを読みこんだ状態でlircdが自動的に起動し、irsend を利用可能な状態になるのでした。

読み込んだAC.lircd.confに基づいて実際にエアコンに信号を送信する方法は本書5.4節と同じです。まず、図5-12の回路を作成する必要があります。

実行するコマンドですが、作成したAC.lircd.confを注意深く見ると、
  • グループ名:AC (Air Conditionerの略)
  • 信号名:on, off
であることが分かりますので、
  • オン:irsend SEND_ONCE AC on
  • オフ:irsend SEND_ONCE AC off
となります。赤外線LEDをエアコンの受光面に向けて実行してみましょう。

4. エアコンの制御 (2)
NOOBS 3.0.1 (Raspbian 2019-04-08) およびそれ以前のRaspbian StretchをOSアップデートをせずに利用している場合 (kernel 4.14)

ここからは「NOOBS 3.0.1 (Raspbian 2019-04-08) およびそれ以前のRaspbian をOSアップデートをせずに利用している場合 (kernel 4.14)」において、 mode2コマンドを用いてエアコンのリモコンが出力する信号を記録する方法を解説します。

LIRCのインストールや設定は「kernel 4.14までを搭載したRaspiban Stretchでlircを利用する」により済ませておいてください。

まず、本書図5-6の「赤外線リモコン受信モジュールを用いた回路」を作成します。

なお、NOOBS 2.4.3以降に含まれるRaspbianをお使いの場合、LIRCが起動した状態では記録用のコマンドの実行時にエラーが出ますので、下記のコマンドであらかじめLIRCを停止しておきます。
sudo service lircd stop
LIRCを停止させたら、 まず、「(お好みの設定での)電源オン」信号の記録から始めましょう。ターミナルLXTerminalを起動し、下記のコマンドを実行します。
mode2 -d /dev/lirc0 > on.txt
ターミナル上では何も起きませんが、そのまま赤外線リモコン受信モジュールに対してリモコンで「(お好みの設定での)電源オン」ボタンを一度押します。

押してもやはりターミナル上では何も起こっていませんが、気にせずターミナル上でCtrl-c (Ctrlキーを押しながらcキーを押す)を実行します。これにより、mode2コマンドが終了します。

ここまでの作業がうまくいけば、「on.txt」というテキストファイルに「(お好みの設定での)電源オン」信号についての情報が記録されているはずです。ターミナルで「leafpad on.txt」コマンドを実行するなどして、テキストエディタLeafpadでon.txtを開いてみましょう。
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。コマンドは「mousepad on.txt」となります。
エアコンのメーカーなどにより異なりますが、例えば下記のような情報が記録されています。何も記録されていない場合、LIRCの設定が正しくない可能性があります。本書の5章の演習を改めてやり直してみましょう。


これは何を表しているでしょうか。1行目は意味のない情報ですが、2行目以降は下図に示すエアコンのリモコンの点滅状態の拡大図を見ることで理解できます。

on.txtに記録された「3327」、「1694」…などの数値は、下図のように点灯や消灯の継続時間を表しているというわけです(単位はマイクロ秒)。


この数値のパターンを最終的にLIRCに渡すことになります。

その前に、リモコンの「電源オフ」信号についても記録しておきましょう。先ほどと同様にターミナルで下記のコマンドを実行します。
mode2 -d /dev/lirc0 > off.txt
記録先のファイル名が「off.txt」になっていることがわかるでしょうか。その状態で、リモコンの「電源オフ」ボタンを赤外線リモコン受信モジュールに向かって押します。押し終わったら、ターミナル上でCtrl-cを実行してmode2コマンドを終了します。さらに、off.txtを「leafpad off.txt」コマンドによりleafpadで開き、中身が記録されていることも確認しておきましょう。
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。コマンドは「mousepad off.txt」です。

次に、LIRCでエアコンのリモコンの信号を取り扱えるようになる設定ファイルlircd.confを作成していきます。

書籍で取り扱ったテレビのリモコンの場合は、irrecordコマンドが自動的に生成してくれましたが、今回取り扱っているエアコンのリモコンの場合は手作業で作成する必要があります。

まず、テキストエディタleafpadを起動します。ターミナルで下記のコマンドを実行しましょう。
leafpad lircd.conf
なお、NOOBS 3.2.1以降ではテキストエディタとしてleafpadではなくmousepadを用います。
mousepad lircd.conf
そして、下記の雛形をコピーして、起動したleafpadに貼り付けます。
begin remote

  name  AC
  flags RAW_CODES
  eps            30
  aeps          100

  gap          200000
  toggle_bit_mask 0x0

      begin raw_codes
      name on
# python getinterval.py on.txtの結果を貼り付け 
      name off
# python getinterval.py off.txtの結果を貼り付け 
      end raw_codes

end remote
「#」のついた行はコメントとして無視されるのですが、そこに、on.txtとoff.txtに関する情報を貼り付けるよう指示されています。

ただし、on.txtやoff.txtの中身をそのまま貼り付けるわけではありません。下図のように、on.txtやoff.txtのうち、必要なのは赤い四角で囲われた数値のみです。


これらの数値を手作業で抽出するのは大変なので、抽出を容易にするプログラムgetinterval.pyを用意しました。ターミナルで下記のコマンドを実行してこのプログラムをダウンロードしてください。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/getinterval.py
ダウンロードが済んだら、ターミナルで下記のコマンドを実行してみましょう。
python getinterval.py on.txt
すると、on.txtのうち必要な部分のみが抽出され、下図のようにターミナル上に表示されます。

これを(下図の場合、冒頭の3327から末尾の448までを)マウスでなぞり、メニューから「編集」→「コピー」でコピーします。そして、leafpad上の該当箇所に貼り付けます(「編集」→「貼り付け」)。


同様に、「python getinterval.py off.txt」の結果も指示のある場所に貼り付けます。「#」がついたコメント部は不要なので削除しました。


なおこの際、leafpad上で下図のように「オプション」→「右端で折り返す」にチェックを入れないと、結果が見にくいですので注意して下さい。


以上で、設定ファイルlircd.confの作成は完了です。ホーム(/home/pi)に保存してleafpadを終了しましょう。

なお、リモコンの信号は用いているエアコンで異なるため、上の設定ファイル上の数値をそのまま写しても意味はありませんのでご注意ください。お使いのリモコンを用いてこの設定ファイルを作成することが重要です。

最後に、このlircd.confを/etc/lircにコピーしましょう。ターミナルを起動して下記のコマンドを実行します。
sudo cp lircd.conf /etc/lirc
なお、NOOBS 2.4.3以降では設定ファイルの保存場所が変わっていますので、コマンドは以下のようになります。
$ sudo cp lircd.conf /etc/lirc/lircd.conf.d/
コピーが終わったら、Raspberry Piを再起動します。新しいlircd.confを読みこんだ状態でlircdが自動的に起動するのでした。

読み込んだlircd.confに基づいて実際にエアコンに信号を送信する方法は本書5.4節と同じです。まず、図5-12の回路を作成する必要があります。

実行するコマンドですが、作成したlircd.confを注意深く見ると、
  • グループ名:AC (Air Conditionerの略)
  • 信号名:on, off
であることが分かりますので、
  • オン:irsend SEND_ONCE AC on
  • オフ:irsend SEND_ONCE AC off
となります。赤外線LEDをエアコンの受光面に向けて実行してみましょう。

5. タクトスイッチとブラウザによる実行

本ページのメインのコンテンツは以上となります。
あとは「5.4.2 タクトスイッチによるテレビの操作」と「5.4.3 ブラウザによるテレビの操作」をエアコン対応にすることが課題となりますが、これらに関しては方針を記すに留めたいと思います。

まず、タクトスイッチについてはPythonプログラムbb2-05-01-TV.pyを編集する必要があります。プログラムから実行されるコマンドは例えば
args = ['irsend', '-#', '1', 'SEND_ONCE', 'TV', 'power']
のように記されていますが、これを
args = ['irsend', '-#', '1', 'SEND_ONCE', 'AC', 'on']
などと編集して保存すると、タクトスイッチを押したときにエアコンの電源をONする信号が出力されることになります。

ブラウザによる操作の場合、編集する必要があるファイルは、
「/usr/share/webiopi/htdocs/bb2/01/index.html」
となります。
この中で、やや長い下記の部分が、テレビリモコンのボタンを配置している部分になります。
<div align="center">
<table border="0">
(略)
</table>
</div>
これを削除し、下記を追加すれば、エアコンONとエアコンOFFのボタンのみが現れます。
<button id="on" onClick="sendCommand('AC', 'on')">エアコンON</button>
<button id="off" onClick="sendCommand('AC', 'off')">エアコンOFF</button>

以上となります。