Raspberry Pi 3 をエアコン(その他)のリモコンにして外から操作できるようにした話(その2)

投稿者: | 2017年4月18日

pull upとかについて備忘

昨日書いてたpull up が要るか要らないかは結局よく考えれば、どっちでも良いという話でした。

  • PL-IRM2121のVoutがHi-Zになる場面は仕様から見つからなかった
  • VoutはActive lowで通常状態がHIGHになってることからVhighかVlowのどっちかが常に印加されてそう
  • Raspberry Pi側はpull up/downにしてどっちかに寄せてしまえば良い
  • Vhighは今回Raspberry Piからとっていて5vである。多分Raspberry Piのpull upの電圧もそれと大きくは違わないはず

上記を整理した結果どうでも良いというのが結論……。
PL-IRM2121の電圧が低い場合でも、4.5vくらいなので入力電圧が足りないということも無さそうです。
というわけで、自分の考え過ぎという話でした。

そもそも、PICとかで入力を取ると端子はオープンドレイン出力に普通なってると思うので無料でpull up出来るのだからやって仕舞えば良いという話はありそうです。

リモコン信号の学習方法について

標準的なリモコンを覚えさせる場合には、irrecord コマンドを使えば様々なサポート機能を利用して手軽に色々覚えさせることが出来ます。TVなどのリモコンの場合はirrecordの指示に従えば学習させることが出来ます。ただし、エアコンのリモコンは特殊なためirrecordでは記録出来ません。

実際にエアコンのリモコンの信号を記録する場合は以下のような手順で記録することが出来ます。

sudo /etc/init.d/lirc stop
sudo mode2 -m -d /dev/lirc0 > output.conf
## ここで実際に受光モジュールに向けてリモコン操作する
## その後、Ctrl+Cで終了する

こうして出来たoutput.confの中身にリモコンの信号が記録されています。
この内容をlircの設定ファイルになるように変更します。

begin remote

   name  MY_REMOTE
   flags RAW_CODES
   eps            30
   aeps          100

   frequency    38000
       begin raw_codes
       name "リモコンのボタンに対応する名前"
       <<ここに上記ファイルの内容を追加する>>
    end raw_codes
end remote

この内容を/etc/lirc/lirc.confに追記すれば学習完了します。

エアコンのリモコンについて

エアコンのリモコンは複雑な信号をエアコンに送出しています。

どういうことかというと、TVのリモコンなどはボタンと信号は完全に対応しています。例えば音量UPボタンを押してでる信号は毎回「音量UP」という信号になっています。ですので、TVに反応しないように音量UPを押したあと、次はTVが反応するように音量UPを押した場合で挙動に違いはありません。

ところがエアコンのリモコンはそうではありません。エアコンのリモコンを明後日の方向に向けて「電源ON/OFF」のボタンを押したのち再度エアコンに向けて「電源ON/OFF」のボタンを押してみます。すると、電源OFF状態のエアコンが反応して、電源OFFになったり、また電源ONから電源ONになってみたりリモコンの状態に応じて様々な動作をすることが分かるでしょう。

これはエアコンの動作として、リモコンが全ての状態を保持しておりエアコンはそれを受けとって次状態を決めるだけという動作になっている為だと思われます。このため、エアコンのリモコンが送出する信号はエアコンの次状態を決めるのに十分な情報を持っている必要があるため、他のリモコンと比較して信号が長かったり共通化されてなかったりします。このため、irrecordでは上手く学習出来ないことが多いです。

リモコン信号の送出

リモコン信号の送出は、irsendコマンドで簡単に実行することが出来ます。

irsend SEND_ONCE aircon heater_on

というような感じです。
今回自分の利用した赤外線LEDだと2mくらいしか光が届かないのでテストの時には少し苦労しました。
また、LED光は指向性が強かったりするので色々試してみて下さい。

wifiなど外部ネットワークからのリモコン操作

自分は手抜きでnode.jsのexpressを使った超簡単なREST APIサーバを作ってirsendを実行させるようにしています。
もっと真面目にやるほうが良いです。

// 暖房をつけるAPIの実装
router.get('/heater_on', function(req, res, next) {
  const exec_program = `ssh -t -t -o StrictHostKeyChecking=no \
                        -o UserKnownHostsFile=/dev/null \
                        -i ${server_key_path} \
                        -l ${server_user} \
                        ${server_host} \
                        irsend SEND_ONCE aircon heater_on`;
  aa(function* () {
    const result = yield exec(exec_program);
    res.json({success: true});
  });
});

あとは、操作画面用のUIもMaterial UI + React + Reduxで一緒に実装して外から操作できるようにしました。
こんな感じのUIです。

componentのソースは以下のような感じです。

import React from "react";
import AppBar from 'material-ui/AppBar';

const AirConAppBar = () => ();

class TopPage extends Component {
  handlePowerOff(e) {
    this.props.power_off();
  }

  handleCoolerOn(e) {
    this.props.cooler_on();
  }

  handleHeaterOn(e) {
    this.props.heater_on();
  }

  render() {
    const style={
      root: {
        "display": "flex",
        "flex-direction": "row",
        "flex-wrap": "wrap",
        "justify-content": "center",
        "align-items": "center",
        "width": "100%"
      },
      header: {
        "width": "100%",
        "text-align": "center",
        "margin-top": "0px",
        "margin-bottom": "0px"
      },
      button: {
        "width": "100px",
        "margin": "5px"
      }
    };

    return (
      

エアコン

); } } const server_name = "http://remocon-server"; function execPowerOff(dispatch) { $.ajax({url: server_name + "/power_off", type: "GET"}); } function execHeaterOn(dispatch) { $.ajax({url: server_name + "/heater_on", type: "GET"}); } function execCoolerOn(dispatch) { $.ajax({url: server_name + "/cooler_on", type: "GET"}); } export default connect(state => ({server_status: state.server_status}), (dispatch) => { return { cooler_on: execCoolerOn, heater_on: execHeaterOn, power_off: execPowerOff }; })(TopPage);

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です