工作と競馬

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

タグ:RaspberryPi

概要

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


背景と目的

 前回までで、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で、リモコンコードを出力するためのソフトウェアを書く。


概要

 Raspberry Pi(以下、ラズパイ)に関する記事。GPIOをPythonで制御してみた。


背景と目的

 前回、ラズパイの起動に成功した。今回は、電子工作の第一歩としてGPIOを制御してみる。


詳細

1.GPIOの制御

 まず、簡単なGPIOの制御例としてお馴染みのLEDの点滅をやってみた。やり方は、Web上にいろいろ載っているがプログラミング言語としてPythonを使用したいので、今回はこちらを参考とさせていただいた。他にも、こちらこちらも参考になった。
初めに、PythonでGPIOを制御するモジュールがインストールされているかチェックしたのが図1.1。とりあえずこれはOK。

s-IMG_1640
図1.1 PythonのGPIO制御用モジュール

 次にプログラムを作成。参考サイトほぼそのままである。RPi.GPIOというモジュールがあり、これをimportすればよいようだ。使用する端子は、基板上の4番ピン(GPIO4)と5番(GND)。LEDは手持ちのVF=2Vくらいのもの。抵抗は750Ω。

s-IMG_1644
図1.2 作成したLED点滅プログラム

 動作させた様子が以下。写真なので点滅の様子はわからないがプログラムどおり約1秒周期で点滅を繰り返すことが確認できた。とりあえず、制御は成功だ。

s-IMG_1643
図1.3 LED点滅の様子。

2.PWMで明るさ制御

 さすがに、LED点滅だけでは面白くないので、これまたよくあるPWMによるLED明るさ制御をやってみた。これは、こちらを参考にさせてもらった。プログラムは以下。ハード構成は全く同じ。
 動作を確認するため、オシロスコープでGPIO4の出力波形を観測した。たしかに、約50Hzで70%デューティの波形が出力されている。ただ、この発振周期は結構ふらついている。実際、LEDを見ると少し明るさがふらつく。厳密な制御はむずかしいのだろうか?

pwm
図2.1 PWM波形

 最後に、明るさを連続的に変えてみた。ゆっくりと明るくなったり暗くなったりするプログラムだ。参考サイトの「An example to brighten/dim an LED」ほぼそのままなのでソースコードは省略。動画があればわかりやすいのだが・・・


まとめと今後の課題

 GPIOピンを使ってLEDの点滅およびPWMによる明るさ制御ができた。次回は、Bluetoothにでも挑戦してみたいと思う。

概要

 Raspberry Pi(以下、ラズパイ)に関する記事。初回起動を行った。


背景と目的

 前回、初回起動準備を行った。今回は、電源を入れ、ラズパイを立ち上げてみる。


詳細

1.接続

 起動に必要なUSBケーブル、USBマウス、USBキーボード、SDカード、HDMIケーブルを接続したのが、写真1の様子。電源は5V1Aが必要ということで、手元にあったiPhone充電用ACアダプタが役に立った。USBキーボードは、YDKBU02BKという格安機種。ディスプレイはテレビを使用。

s-IMG_1632
図1 起動前の接続

2.起動、OSインストール

 電源を入れると、画面に図2.1のような画面が表示された。どうやら無事起動したようだ。ここで、インストールするOSとしてRaspbianを選択。

s-IMG_1633
図2.1 起動直後のOS選択画面

 インストール中は、図2.2のようにプログレスバーが伸びていき、完了すると図2.3のようにOKボタンが出る。ここでOKボタンを押すと、再起動される。

s-IMG_1634
図2.2 インストール中

s-IMG_1635
図2.3 インストール完了

 再起動後、Setup Optionが表示された。ここで何をすればいいのかよくわからなかったのだが、2の項目で、起動方法としてデスクトップとコマンドラインの選択ができるようなので、デスクトップを選択し設定官僚とした。

s-IMG_1636
図2.4 Setup Option

 その後、無事デスクトップが表示された。(図2.5)馴染みのあるPythonのアイコンがある。試しにPythonシェルを立ち上げてみた。(図2.6)アプリケーションの起動は、ややタイムラグがある印象だ。まあ、PCとしてはそんなにパワーがあるわけではないので仕方ないところか。それより、電子工作ファンとしては直接出ているピンが制御できることが重要だ。
というわけで、無事起動できた。

s-IMG_1637
図2.5 デスクトップ

s-IMG_1638
図2.6 Pythonシェル


まとめと今後の課題

 ラズパイを起動することができた。次回は、GPIOピンを使ってLEDでも点灯させてみたいと思う。

概要

 Raspberry Piに関する記事。初回起動に向けたSDカードの準備を行った。


背景と目的

 諸事情により、Raspberry Pi(以下、ラズパイ)をいじる機会を得た。そこで、ラズパイで遊んでみようと思う。今回は、初回として、SDカードにOSのデータを入れ起動できる準備を行った。


詳細

1.情報集め

 ラズパイを初回起動するための手順は、
http://readwrite.jp/archives/4603
を参考とさせてもらった。ここから飛べるPDFファイルhttp://www.raspberrypi.org/wp-content/uploads/2012/04/quick-start-guide-v2_1.pdfも有用だ。

2.必要なもの

 ラズパイを動かすのに必要なものは、以下の通り。本体はやはり数㎝角の基板だけで非常に小さい。

  • 本体(図2.1)
  • USBケーブル(A-microB)
  • HDMIケーブルまたはRCAケーブル
  • ディスプレイ
  • SDカード
  • USBマウス
  • USBキーボード
s-IMG_1619
図2.1 ラズベリーパイ(タイプB)

3.SDカードにOSをインストール

 ラズパイは外部記憶装置としてSDカードを使う。SDカードには、OSをインストールしておく必要がある。そこで、参考サイトの手順にしたがい、インストールを行った。今回使用したSDカードは、写真3の東芝製8GB、Class10品。ラズパイ公式には、4GB、Class4が必須とのことなので十分条件を満たす。

s-IMG_1616
写真3 使用したSDカード

3.1 フォーマット

 まず、SDカードのフォーマットが必要らしいので、https://www.sdcard.org/downloads/formatter_4/eula_windows/にあるSD Formatterというソフトでフォーマットする。その際の様子が図3.1。オプションで論理サイズ調整ONにして、フォーマットする。作業自体はすぐ終わる。

フォーマット
図3.1 フォーマット作業

3.2 OSのデータをSDカードにコピー

 次に、OSイメージをdownloads.raspberrypi.org/noobsからダウンロードした。これが、1.4GBと非常に大きいため時間がかかった。巷には、これが入ったSDカード自体が売られているらしい。自分でやることはなかったかもしれない。
このファイルを解凍し、SDカードにコピーして作業完了。

SDカード
図3.2 SDカードにデータコピー完了

3.3 装着

 SDカードをラズパイに装着してみた。基板裏側のカードリーダに差せばよい。今回はここまで。

s-IMG_1620
図3.3 ラズパイにSDカードを装着。

4.感想

 数年前まで電子工作ファンはワンチップマイコンで遊んでいたが、今はこんな小型PCやらスマートフォン、タブレットに確実に主流が移ってきたし、できることがどんどん広がっていると感じる。これから、いろいろ楽しめそうだ。


まとめと今後の課題

 ラズパイの起動準備を行った。次回は、起動してみたい。

このページのトップヘ