携帯からインターネット経由で赤外線命令を発行して既設エアコンを操作(Raspberry Pi活用編)

Last-modified: 2016-11-07 (月) 05:48:20
初出 2014-10-23
最終更新 2016-2-15
Raspberry Piが何でもできるのはわかりきっているので、ここ2年ばかり避けていて、代わりにこんなのを使っていたのですが、それも十分飽きたのでいよいよRaspberry Piを買ってみることにしました。用途が決まっていたのでタイプB+じゃなくてタイプBを買いました。
 
 

項目毎にダウンロードリンクを設けていますが数が多いのでここにもまとめておきます。
ダウンロード ir-transmitter.c  赤外線トランミッターのファームウェアソース  PIC18F2550用
ダウンロード ctrl-hitachiAC.sh  赤外線トランスミッターを操作するスクリプト
ダウンロード onoff.php  php画面のソース
ダウンロード rpi-check_and_warning_sendmail.pl  室温が高い場合に冷房を自動的に付けるPerlスクリプト
ダウンロード setup-ttyama0.sh  /dev/ttyMA0設定スクリプト

ダウンロード I2C_temp_sensor.c  PIC18F14K50,18F13K22等用 I2C温度センサのファームウェア(自作はお薦めしません)
ダウンロード get_temp.c  温度取得コマンドのソース(市販センサを使うなら付属のものを使って下さい)  

 

システム全景

internet-ir-aircon-raspberry-pi_1_s.jpg
クリックすると大きな画像で表示されます
このページのシステムをRaspberry Piでリニューアルしたものです。多少不満も上がっていたので今度はON・OFFセンサを取り付けました。

 

Raspberry Piとその周辺デバイス

internet-ir-aircon-raspberry-pi_2_s.jpg
クリックすると大きな画像で表示されます
日頃触れている電子工作とは桁違いの消費電力なので、ファンレスだとこれくらいは通気口を確保するべきだと思いました。ステンレス網は100円ショップのストレーナーから採ったものです。枠は3x10mmの桧棒を8本合わせたものでフィルム貼り&マジック仕上げです。
上に乗っているやや小さめのケースはシリアル接続の赤外線リモコン・トランスミッターです。

 

下にぶら下がっているのはI2C接続温度センサです。Raspberry PiのPin 1,3,5,9と接続しています。自作する人は殆どいないと思います。皆さんは素直に市販品を使って下さい。
一応自作する人の為に情報を書いておきます。8ピンながらMSSPモジュールを持つPIC12F1822を持っていなかったのでPIC18F14K50を使用しました。ファームウェアはAN734に雛形があるのでそれを使えば簡単です。温度センサはMCP9700です。FVRを使い、校正をきちんとおこない、さらに平均化処理を加えれば十分実用になります。一応xc8用のファームウェアソースを載せておきます。I2C_temp_sensor.c  (2014-12-18更新)PIC18F14K50とPIC18F13K22共用で双方で動作確認しています。
あとRaspberry Pi側のソースも載せておきます。一時フルにエラー処理してたんですが全部削除しました。これで十分だと思います。get_temp.c  (2014-12-18更新)

 

Raspberry Pi基板

internet-ir-aircon-raspberry-pi_3_s.jpg
クリックすると大きな画像で表示されます
ケースはテイシン電機のTB-54です。ほぼピッタリです。
一度、RG2(3.3V出力LDO)をこのページスイッチングレギュレータに交換してみましたが、供給電力不足でブート途中に必ずカーネルパニックに陥りました。で戻しました。

 

(2015-10-30追記)
今年の夏にヒートシンク(大と小)を付けました。でも通気性が悪いことも影響したからか、5度くらいしか下がりませんでした。同じヒートシンクをもう少し通気性が良い環境のラズパイ2の方に付けると10度くらい下がりました。なのでこちらの方はケースの下側にドリルでいくらか孔を開けてもっと通気性を良くするべきだと思います。

エアコンのON・OFFセンサ

internet-ir-aircon-raspberry-pi_4_s.jpg
Raspberry PiのPin 4(5V),6(GND),12(GPIO1)と接続しています。本来のパワーステータスを覆い隠してしまってるので、代替のパワーステータスLEDが付いています。

 

回路図
internet-ir-aircon-raspberry-pi_power-sensor_circt_s.png
クリックすると大きな画像で表示されます

 

internet-ir-aircon-raspberry-pi_5_s.jpg
製作中の写真です。スカスカです。
マイコンの下には5Vから3.3Vを作るレギュレータ基板があります。ジャンク箱から引っ張りだしたものです。なぜ5V入力なのかと言うと、当初Raspberry Piから引き出す際の簡潔さに拘っていて、電源ピンとGNDとGPIOの3ピンが詰まって並んでいるのはPin4,6,8しかないので、それを利用しようと思ったからです。でも結局、当初の予定が狂い、シリアル接続トランスミッターにPin8を奪われてしまったので、今考えるとPin1かPin17の3.3Vを2分岐して使うべきだったと思っています。なので回路図上ではレギュレータはなかったことにしています。

 

ところで、このページからは多くのファイルがダウンロードできるようにしてるんですが、ON・OFFセンサに使用しているマイコンのファームウェアのソースは公開してません。理由は想像つくと思うんですが、そもそもマイコンの必然性はない場面であって、普通は単体トランジスタとかコンパレータで用が済む場面だからです。私にとってこの場面でのマイコンは単体トランジスタ兼コンパレータみたいな感覚です。

 

シリアル接続赤外線リモコン・トランスミッター

(2015-12-6追記)確かにこのページのシステムではシリアル接続赤外線リモコン・トランスミッターを使っているのですが、現在は皆さんにお勧めしません。

 

私がお勧めするのは代わりにキットもしくは完成品のUSB接続赤外線リモコンを使う方法です。

 

何故これをお勧めするかというと、安いだけじゃなく、学習機能も持っているからです。
しかもWindowsだけでなく、x64 Linux、x86Linux、ラズベリーパイLinux、Mac OS Xでも学習も送信もおこなえます。多くのエアコンにも対応しています。

 

現時点までのAmazonのレビューはほぼ発売時の状態に対する内容で、AssemblyDeskこれでファームウェア等が様々アップデートされた現在の状態には全く合っていません。Amazonのレビューは完全に無視した方がいいと思います。

 

シリアル接続赤外線リモコントランスミッターの代わりにUSB接続赤外線リモコンを採用した場合、操作する方法を↓下記から少しだけ変更する必要があります。でもコマンドラインで操作できることには違いはないので問題にはならないでしょう。

 
 
 
 
 

(2015-11-14追記)↓下記のリモコン・トランスミッターではPIC18F2550とC18を用いていますが、このほど、PIC16F886とXC8を用いた、(意外なことに)機能的に上位の、新しいリモコン・トランスミッターを作成しました。上位互換なのでそのまま差し替えて使えます。

 

internet-ir-aircon-raspberry-pi_6_s.jpg
クリックすると大きな画像で表示されます
接続端子がピンソケット2列(本)になっているのは接続ケーブルを流用する為です。Raspberry PiのPin8(TXD),10(RXD),14(GND),17(3.3V)と接続しています。当初はGPIOのない普通のPCで使い回しが可能なものを作ろうと思いUSB接続を試みたんですが、どうやらRaspberry Pi(ARM)のCDCドライバがx86用のものと比べて簡素化版で、AVR-CDCが動作しなかったりMicrochipのUSBモジュールの動作が不完全だったのでGPIOのTXD,RXDを使う仕様に変更しました。Raspberry Piではむしろこの方がふつーですからこれはこれで良かったと思います。ちなみにこの基板はかなりテキトー工作です。
(2015-10-30追記)上記の内容に説明を加えます。上述におけるCDCドライバとはUSB・CDCクラスのドライバで/dev/ttyACM?を作るものです。これがARMアーキテクチャのLinux上では簡略化されているように見え、本物のモデムしか正しく動作しないような症状を見せたので使用を諦めました(最近もラズパイ2で動作確認しましたが同様の症状でした)。MicrochipのUSBモジュールとはかなり説明足らずで、Microchip製のUSB・HIDクラスのファームウェアのことを指しています。これはARMアーキテクチャ上で動作確認したわけではなくて、当時x86版Linux上で時々不具合が見られたのでARMのラズパイでも使用を控えました。これらの理由でGPIOのTXD,RXDを使う方式を選択したわけです。(ビット・トレード・ワン社USB接続赤外線リモコンの純正インターフェースである)USB・HIDクラスでの接続方式が絶対に選べなかったわけではありません。ちなみにARM版LinuxではCDCドライバが簡略化版で動作に問題があると既述しましたが、CDCドライバと違い、/dev/ttyUSB?を作るFTDI用のドライバの方はx86版・x64版Linuxと同様に全く問題なく動作します。

 

回路図
internet-ir-aircon-raspberry-pi_ir-transmitter_circt_s.png
クリックすると大きな画像で表示されます

 

Raspberry Piからの操作法
シリアル接続なので、シリアルポートに赤外線命令のデータ(16進文字列)を書き込むだけです。

echo 0A50504FB020DF900980000C154DB020DF900980000C15 > /dev/ttyMA0

こんな感じです。16進文字列の書式はビット・トレード・ワン社のUSB接続 赤外線リモコンと同じです。
ごくありふれた書式でして

1バイト目2バイト目3バイト目4バイト目以降
フォーマットID前半の命令長後半の命令長データ部

データ部は赤外線命令の1と0をそのまま格納したものです。
上記のechoコマンドによる操作はスクリプト化しています。そのスクリプトをphpやPerlから呼び出しています。
赤外線トランスミッターを操作するスクリプトです。
ダウンロード ctrl-hitachiAC.sh

 

ファームウェア
MPLAB C18用のソースです。
ダウンロード ir-transmitter.c  PIC18F2550用
ソースはこの中の「シリアルインターフェース版」から大半を流用しています。Raspberry Pi側からトランスミッターに引き渡す赤外線リモコンのデータとなる16進文字列は、同じくこの中にあるエクセルファイルで赤外線リモコン計測データから算出することができます。赤外線リモコンデータの計測環境としてはlirc受信環境の構築が簡単でお薦めです。Raspberry PiはGPIOがあるのでlirc受信環境が簡単に構築できます。lircのmode2コマンドで送信したいリモコンの波形計測データを取得し、数値部分だけエディタで矩形切り出しして前述のエクセルファイルに貼り付けるだけで赤外線リモコンのデータとなる16進文字列が瞬時に算出されます。ちなみにこのトランスミッターはlircが不得手な、非常に赤外線命令が長いエアコンに対応しています。赤外線の送出にlircでなく専用ハードを用いるのはそれなりに理由があるわけです。

 

赤外線リモコンデータの計測環境としてはlircの他にArduinoを用いる方法も簡単でお薦めです。これはこの中に詳しい説明画像やスケッチがあります。(2014-12-12追記)mbedもこのプログラムを使用すると、Arduinoの場合と同様にリモコンデータが取得できます。
あと(もちろん)16進文字列はソース流用元のUSB接続 赤外線リモコンでも一発で算出できます。
(2015-10-30追記)本項と直接関係ありませんが、今年に入ってソース流用元のUSB接続 赤外線リモコンに、上述のmbedでおこなえるような未知の赤外線リモコンフォーマットの生データを取得する機能が追加されました。

 

あと、USBを使ってないのにUSB内蔵PICであるPIC18F2550を使っている理由ですが、USB経由のファームウェア書き換えができない不良品PIC18F2550を消費したかったからです。普通はこの用途だったらPIC18F25K22あたりを選択するんじゃないかと思います。ソースの修正は殆ど必要ない筈です。(2014-11-18追記)不良品PIC18F2550を修復する方法があることを知りました。まだ試してませんがかなり可能性が高いでしょう。(2014-12-12追記)PICerFT Ver6.6の新機能「Force to erase Executive」を使って修復できましたが、ICSPで数回書き込むと再び元の状態に戻ってしまいました。やはり不良品は不良品です。

 

web画面

画面をPCのブラウザに表示したところです。
internet-ir-aircon-raspberry-pi_7_s.png
この画面のphpソースです。
ダウンロード onoff.php  2016-2-15更新(スマホに本格対応する為、フォントサイズ変更機能を追加しました)

 

php画面から呼び出されてエアコンを操作するスクリプトです。
ダウンロード ctrl-hitachiAC.sh
他にgpioコマンドの導入が必要です。

 

phpの中からsudoして呼び出すコマンドは当然/etc/sudoers.d内にこのように設定してパスワードなしで済むようにしています。

owner,www-data	ALL=(ALL) NOPASSWD: /usr/local/bin/get_temp
 

ところで、Raspberry Pi本体にあるのシリアル端子(TXD,RXD)は/dev/ttyMA0として認識されるんですが、
デフォルトでシリアルコンソール用として設定されています。このデフォルトの設定を基本的に変えないまま、
“ちょっと拝借します”みたいな感じでこのweb画面から使用可能とする設定がこのスクリプトです。
ダウンロード setup-ttyama0.sh 
私の場合/etc/rc.localから(sleepを使っているので&付きで)呼んでいます。

 

OSは最も一般的なRaspbianを使用しています。
webサーバはApache2です。(a2enmod,a2ensiteコマンドを使って)お手軽にSSL+BASIC認証にしています。

設定室温に達すると冷房をつけた上で携帯電話にメールを送信するPerlスクリプトのカスタマイズ(第3)版

こちらこちらに続く第3版です。今回WebサーバとネットワークIOが同一サーバ上になったので簡素化しました。cronで30分毎に起動するように設定しています。
ダウンロード rpi-check_and_warning_sendmail.pl
ダウンロード ctrl-hitachiAC.sh  これはPerlスクリプトから呼び出されてエアコンを操作するスクリプトです。
Perlスクリプトの中身

#!/usr/bin/perl
# このスクリプトはEUC-JPで保存されている必要があります。
# Debian, Ubuntu系の場合の追加インストールが必要なパッケージ
# libnet-smtpauth-perl libjcode-pm-perl libwww-perl libmath-round-perl
use Net::SMTP_auth;
use Jcode;
use Encode;
#use LWP::Simple;
use LWP::Simple qw($ua get);
use Math::Round;
$ua->timeout(10);
$smtpserver = 'smtp.hoge.ne.jp:587';               # SMTP認証でアクセスするサーバ
$smtpacount = 'fugafuga@hoge.ne.jp';               # SMTP認証用のアカウント
$smtppasswd = 'SECRET';                            # SMTP認証用のパスワード
$myrealmailaddress = 'fugafuga@hoge.ne.jp';        # 自分の本当のメールアドレス
$tomailaddress1 = 'foobar@docomo.ne.jp';           # 宛先アドレス
$tomailaddress2 = 'foobar@hoge.ne.jp';             # 宛先アドレス
$bccmailaddress = $smtpacount;
$fromaddress = $smtpacount;
#$fromaddress = 'remotecontroleradmin@dummy.com';   # 宛先側で個別の受信設定をおこな
                                                   # えば実在しないアドレスも可
$limittemp = 35;                                      # メールを送信し始める室温(摂氏)
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$nowdate = sprintf("%d年%d月%d日 %d時%d分%d秒", $year + 1900, $mon +1, $mday,
 $hour, $min, $sec);
# 室温
$Celcius = `sudo get_temp`;
chomp($Celcius);
$Celcius = nearest(0.1, $Celcius);
	if ( $Celcius >= $limittemp ) {
		system('/usr/local/bin/ctrl-hitachiAC.sh cool_on');
#		$Subject="室温が$Celcius度です。冷房をつけました。";
		$Subject="室温が$Celcius度です。冷房ON";
		$Body="$nowdate\n室温は現在$Celcius度です。\nたった今、冷房をつけました。";
		mailsend();
		exit;
	}
sub mailsend {
$smtp = Net::SMTP->new("$smtpserver");
$smtp->auth("$smtpacount", "$smtppasswd");
$smtp->mail("$myrealmailaddress");
$smtp->to("$tomailaddress1","$tomailaddress2");
$smtp->bcc("$bccmailaddress");
&Jcode::convert($Subject, 'jis', 'euc');
&Jcode::convert($Body, 'jis', 'euc');
$smtp->data();
$smtp->datasend("From:$fromaddress\n");
$smtp->datasend("To:$tomailaddress1\n");
$smtp->datasend("To:$tomailaddress2\n");
$smtp->datasend("Subject:".encode('MIME-Header-ISO_2022_JP', $Subject)."\n");
$smtp->datasend($Body);
$smtp->dataend();
$smtp->quit;
return;
}
 

ご要望、ご意見、質問を下のフォームにどうぞ
(でもここより、掲示板書き込みフォームのページに書いて頂いた方が気づき易いと思います。)