工作と競馬

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

タグ:家電操作

概要

 当初の目的であるエアコンの電源を出先のスマホから操作可能となり、システムが完成した。


背景と目的

 前回までで、AWS上のLambdaからRaspberry Piへトピックをパブリッシュしてエアコンの電源を操作することができた。今回は、いよいよスマートフォン等から操作可能にし、システムを完成させる。


詳細

1.方法

 システムを完成させるには、

  • AWSのAPI Gatewayにて、操作情報を受け取りとLambdaの駆動をするWebエンドポイントを用意する
  • スマホ側の操作インターフェースとして、電源ボタン操作インターフェースとWebエンドポイントへの操作情報を送信機能を持つWebアプリを作成する

 が必要。それぞれ順にやっていく。

2.Webエンドポイントの作成

 API Gatewayにて、POSTメソッドを用意し、統合タイプを前回作成したLambda関数呼び出しとする。パラメータは、何でもよいが、Webアプリ側の実装が簡単なJSONでの受け渡しになるようにした。

3.操作用Webアプリ

 図3.1、3.2のように、電源ボタンの図をタップすると、ON/OFFが切り替わり、それに応じて2で作成したエンドポイントへリクエストを送るようになっている。

IMG_3363

 図3.1 OFF状態

IMG_3368

 図3.2 ON状態

4.動作確認

 最後に、動作確認を行った。スマホで、操作用Webアプリを開き、電源ボタンを押したところ、1秒程度で無事エアコンの電源が入った!結構素早い動きで驚いた。


 以上で、エアコンの電源をインターネット経由で操作することができるようになった。作業に要したのはおよそ2日だったが、出来上がったときはさすがにちょっと感動した。作ってよかった。

概要

 Raspberry PiがAWSから操作情報を受け取るためのプログラムの実装と、LambdaからRaspberry PiでON/OFF操作情報を送信するテストを行った。


背景と目的

 前回までで、疑似赤外線リモコンが完成した。今回は、Rapsberry PiがAWSから操作情報を受け取って疑似赤外線リモコンへ送信指示を出せるようにする。


詳細

1.方法

 AWSとRaspberry Piを連携させるには、AWS IoTを使う。操作情報を含むトピックをRaspberry Piがサブスクライブすればよさそう。

2.AWS IoTのコンソールでデバイスの作成

 デバイス作成は、AWS IoT上のコンソールのウイザードに従ってやった。コンソールのconnectから、Configuring a deviceのGet startedをクリックし、プラットフォームとSDKを選択する。プラットフォームはRaspbianなのでLinuxを選択。SDKは、いつの間にやらPythonができているのでPythonを選択。

SDK選択
図2.2 プラットフォームとSDKの画面

 次に、Thingの名前を決めてNext Stepに進むと、Download connect kitというものダウンロードボタンが現れるので、ダウンロード。

connection_kit
図2.3 connect kitのダウンロード画面

 次に、コマンドの指示がでるので、ダウンロードしたzipファイルをFTPでRaspberry Piに転送し、コマンドを実行。Start.shがうまく動けば、以下のようにコンソールに表示が出る。同時に、図2.5のようにAWSのコンソールにも表示が出る。

test
図2.4 コマンドを実行させた様子

command2
図2.5 通信がうまくいってるときのコンソール

 ここまでで、Raspberry PiとAWS IoTの接続ができた。

3.Raspberry Piで、トピックをサブスクライブする

 以下のリンク等を参考に、トピックをサブスクライブするためのコードを作成。

 最初、END_POINTというパラメータは何を指定すればいいか分からなかったが、こちらを見て、InteractのHTTPSという欄にあるRest API EndpointでOKだということが分かった。

# Import SDK packages
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

CLIENT_ID = "Thing名"
END_POINT = "xxx.iot.リージョン名.amazonaws.com"
PATH_CA = "配置先ディレクトリ/root-CA.crt"
PATH_KEY = "配置先ディレクトリ/Thing名.private.key"
PATH_CRT = "配置先ディレクトリ/Thing名.cert.pem"

# For certificate based connection
myMQTTClient = AWSIoTMQTTClient(CLIENT_ID)

# Configurations
myMQTTClient.configureEndpoint(END_POINT, 8883)
myMQTTClient.configureCredentials(PATH_CA, PATH_KEY, PATH_CRT)

# 接続
myMQTTClient.connect()

# サブスクライブ開始
myMQTTClient.subscribe("$aws/things/Thing名/shadow/update", 0, subscribe_callback)

# 受信待ち
while True:
    time.sleep(1)

 そして、subscribeメソッドの引数に渡したコールバック関数は、トピックが到着したときの処理を書けばよい。ここでは、詳細は省略するが、到着したペイロードの中に、ON/OFF操作情報があるとして、それに応じてGPIO18にパルスを送るようにしている。

def subscribe_callback(client, userdata, message):
    # データを受け取る
    payload = json.loads(message.payload)
    # payloadの内容に応じて、GPIO18にパルスを送る
    :
    :
4.Lambdaによる確認

 最後に、LambdaでAWS IoTのThing Shadowに、トピックをパブリッシュしてみた。実装は、boto3を使った。参考になったサイトは以下。payloadという辞書に、送信したいデータを入れる。

# coding: utf-8
import boto3
import json

iot = boto3.client("iot-data", リージョン名)

def lambda_handler(event, context):

    # 送信データを作成
    payload = {
        "state": {
            "desired": {
                キー : 値,
                :
            },
            "reported": {
                キー : 値,
                :
            }
        }
    }
    
    # パブリッシュする
    iot.publish(
        topic='$aws/things/Thing名/shadow/update',
        qos=0,
        payload=json.dumps(payload)
    )

    # TODO implement
    return {}

 この結果、正しくトピックが受信され、無事エアコンがON/OFFできた!

 というわけで、AWS IoTとRaspberry Piが接続され、操作情報を載せたトピックをパブリッシュすればエアコンの電源がON/OFFできるところまできた。次回は、最終段階であるAPI Gateway⇒Lambda部分を構築し、スマホの操作を完成させる。

概要

 疑似赤外線リモコンのソフトウェアコーディングと動作確認を行った。


背景と目的

 前回に続き、疑似赤外線リモコンのソフトウェアコーディングと動作確認を行う。


詳細

1.概要
  • TrinketというArduino互換マイコンを使い、GPIOから赤外LEDを駆動する。そのため、コーディングはArduino言語。Arduino開発環境セットアップは、以前行ったのでOK。
  • 私の家のエアコンのリモコンコードは、手持ちの赤外線リモコン受信モジュールとオシロスコープを使って調べたところ、家電協会フォーマットのようだ。(フォーマットは、こちらが詳しい。)
2.疑似赤外線リモコン ソフトウェアのコーディング

 まず、38kHzのサブキャリアとなるパルスを出力する関数。

// 38kHz, デューティ1/3のパルスを出力
// delayMicrosecondsの精度がいまいちなので26usになっていない
void output_pulse(){

  digitalWrite(PIN_DRIVE, HIGH);
  delayMicroseconds(4);
  digitalWrite(PIN_DRIVE, LOW);
  delayMicroseconds(7);
  
}

 次に、データ1ビット分を出力する関数。

// データビット1つを出力する
void output_databit(int high_or_low){

  int i;

  // HIGH期間
  for (i = 0; i < DATABIT_PULSE_COUNT; i++){
    output_pulse();
  }

  // LOW期間
  if(high_or_low){
    delayMicroseconds(DATABIT_PULSE_T * DATABIT_PULSE_COUNT * 3); // 3周期
  } else {
    delayMicroseconds(DATABIT_PULSE_T * DATABIT_PULSE_COUNT); // 1周期
  }
  
}

 リモコンコード先頭のリーダー部を出力する関数。

// リーダーを出力
void output_leader(){

  int i;
  
  // HIGH期間
  for (i = 0; i < DATABIT_PULSE_COUNT * 8; i++){
    output_pulse(); // 8周期 * 8T
  }

  // LOW期間
  delayMicroseconds(DATABIT_PULSE_T * DATABIT_PULSE_COUNT * 4); // 4T
}

 1バイト分のデータを出力する関数。

// データを出力
void output_data(byte databits, int bits_len){

  // 上位ビットからbits_len個を出力
  int i;
  for (i = 0; i < bits_len; i++){
    int x = (databits & B10000000) >> 7; // 最上位を取り出す
    output_databit(x);
    databits = databits << 1; // 1ビットシフト
  }
  
}

 リモコンコード1フレーム分を出力する関数。

// フレームを出力
// customercode = { 上位8bit, 下位8bit };
// parity = パリティ4bit + 0000;
// data_bytes = { data0, data1, ... };
void output_aeha_frame(byte customercode[], byte parity, byte data_bytes[], int data_len){

  int i, k;

  // リーダー
  output_leader();

  // カスタマーコード
  output_data(customercode[0], 8);
  output_data(customercode[1], 8);
  
  // パリティ
  output_data(parity, 4);

  // データ
  for(i = 0; i < data_len; i++){
    if (i == 0){
      k = 4;
    } else {
      k = 8;
    }
    output_data(data_bytes[i], k);
  }

  // ストップビット
  output_data(B10000000, 1);
  
}

 入力を検出する関数が以下。これは、Raspberry Piからの送信指示がGPIO#0に来たかを検出する。パルス幅5msecならON、パルス幅10msecならOFF、それ以外は無視という単純な送信指示パルスなので、ノイズによる誤動作もなくはないが、問題になったら改めるとして、とりあえずこれにする。

// 入力を検出
// 戻り値 : ONのときは1, OFFのときは0, 検出なしは-1
int detect_input(){

  int pw;
  int result;

  // いきなりHIGHのときは検出なし
  if (digitalRead(PIN_INPUT) == HIGH){
    return -1;
  }

  // 開始検出
  while (digitalRead(PIN_INPUT) == LOW) {
    delay(1);
  }

  // パルス幅をカウント
  int i;
  pw = 0;
  for(i = 0; i < 15; i++){
    if(digitalRead(PIN_INPUT) == HIGH) {
      pw += 1;  
    }
    delay(2);
  }
  if(4 <= pw && pw <= 6) {
    result = 1; // 5msecのときON
  } else if (9 <= pw && pw <= 11){
    result = 0; // 10msecのときOFF
  }
  
  return result;
  
}

 定数と初期設定たち。

const int DATABIT_PULSE_T = 26; // 26us
const int DATABIT_PULSE_COUNT = 15; // 26us*15周期
const int PIN_DRIVE = 1; // LED駆動
const int PIN_INPUT = 0; // 送信指示信号入力

// 送信データ
byte CC_FUJITSU[] = { B00101000, B11000110 }; // カスタマーコード
byte data_on[] = { B00000000, B00001000, B00001000, B01111111, B10010000, B00001100, B10000010, B00100000, B00000000, B00000000, B00000000, B00000000, B00000100, B11010110 };
byte data_off[] = { B00000000, B00001000, B00001000, B01000000, B10111111 };

boolean on_off = true;
 
// the setup routine runs once when you press reset:
void setup() {
  pinMode(PIN_DRIVE, OUTPUT);
  pinMode(PIN_INPUT, INPUT);
}

 メインのループ

// the loop routine runs over and over again forever:
void loop() {

  int input;

  // 入力検出
  input = detect_input();
  if (input == 1) {
    output_aeha_frame(CC_FUJITSU, B00000000, data_on, 14);
  } else if (input == 0){
    output_aeha_frame(CC_FUJITSU, B00000000, data_off, 5);
  } else {
    delay(100);
  }
  
}
3.動作確認

 動作確認は、Raspberry PiのGPIO18から送信指示のパルスを出力することで行った。
その結果、送信指示を受け取り正しいリモコンコードが発出され、エアコンの電源がON/OFFできた。

 ということで、リモコン部分は完成。次は、AWS側の設計・製作に入る。


概要

 エアコンの電源を出先のスマホから操作するためのシステム構想とハードウェア製作を行った。


背景と目的

 私の家のエアコンは、オンタイマーが30分刻みでしかセットできない。なので、何か解決案はないかといろいろ考えを巡らせるうちに、インターネット経由で電源をON/OFFできるようにしたくなった。そこで、まずシステム構想とハードウェア部の製作を行う。


詳細

1.システム構想

 今回は、手持ちのラズベリーパイと、アカウントがあるAmazon Web Service(以下、AWS)とを使ってシステムを構成した。ポイントを書き出すと、以下の感じ。

  • エアコンの操作は、疑似赤外線リモコンでリモコンコードを送信することで行う
  • ラズベリーパイでAWS側からエアコン操作情報を取得し、それに基づき疑似赤外線リモコンに送信指示を出す
  • AWSでは、Webエンドポイントを用意し、リクエストに応じてAWS IoTを経由してラズベリーパイに操作情報を与える
  • スマートフォン等にて、WebエンドポイントにアクセスできるようにWebサイトを用意しておく
システム図
図1 システム構成図

2.疑似赤外線リモコン ハードウェアの設計・製作

 疑似赤外線リモコンは、以前遊んだTrinket(Arduino互換マイコン)と赤外LEDを使って構成する。また、リモコンに対する送信指示をRaspberry Piから出すようにした。Trinketを併用する理由は、Raspberry PiのGPIOではリモコンコードの再現に必要な時間精度を出すのが難しいから。

回路
図2.1 回路図

 また、回路への実装パターンは図2.2のような感じ。

回路パターン
図2.2 回路パターン図

 製作した疑似赤外線リモコン部は以下。そこそこ小さく作れた。

IMG_3362
図2.3 疑似赤外線リモコン部

 というわけで、ハードウェアは完成。次は、Trinketで、リモコンコードを出力するためのソフトウェアを書く。


このページのトップヘ