2017年1月31日火曜日

ESP-WROOM-02 で赤外線 LED を制御してエアコンを操作してみた

概要

前回 Arduino で赤外線 LED を使って Panasonic のエアコンを制御しました
今回は同じように赤外線 LED を ESP-WROOM-02 (ESPr) で使って制御してみました

環境

ライブラリのインストール

Arduino のときに IRremote というライブラリを使いましたが、これは ESPr だと使えません
IRremoteESP8266 という専用のライブラリがあるのでこれを使います

Arduino IDE からインストールすることはできないので、Github から zip ファイルをダウンロードしましょう
そして

スケッチ -> ライブラリをインクルード -> .ZIP 形式のライブラリをインストール

でダウンロードした zip ファイルを選択してインストールしましょう
インストールが完了すると IRremoteESP8266.h が include できるようになります

配線

今回の配線は以下の通りです

上から
try_ir_with_espr_circuit1.jpg

サイドから
try_ir_with_espr_circuit2.jpg

逆サイドから
try_ir_with_espr_circuit3.jpg

基本は Arduino ときと同じなのですが、スイッチを 2 つ (冷房の起動と停止) にしたのとトランジスタを使って赤外線 LED の出力を増幅しています

これはあとで気づいたのですが、Arduino と ESPr では ESPr のほうが赤外線の出力が弱いです
なので、ESPr のときはトランジスタを使って赤外線の出力強度をあげています

送信用スケッチ

今回のスケッチは以下の通りです
440 バイト分の配列 start と stop はそれぞれエアコンの冷房ボタンと停止ボタンを学習した信号になります
赤外線の信号の学習は赤外線受信モジュールを使って事前に Arduino で行いました
Arduino + 赤外線受信モジュールを使って信号を学習する方法はこちらを参考にしてください

#include <IRremoteESP8266.h>

int START = 12;
int STOP = 14;
int khz = 38;
IRsend irsend(4);
unsigned int stop[440] = {3568, 1680, 512, 400, 476, 1244, 512, 404, 476, 408, 476, 404, 480, 372, 508, 404, 476, 408, 476, 404, 476, 404, 476, 376, 508, 376, 508, 372, 508, 1244, 512, 400, 476, 380, 504, 408, 476, 404, 476, 404, 476, 408, 476, 404, 476, 1244, 512, 1244, 508, 1252, 508, 376, 504, 376, 504, 1244, 512, 408, 476, 404, 476, 404, 476, 408, 472, 412, 476, 404, 476, 376, 504, 404, 476, 380, 504, 376, 508, 404, 476, 404, 476, 380, 504, 404, 476, 376, 504, 408, 472, 380, 508, 372, 508, 404, 476, 376, 504, 380, 504, 376, 504, 408, 476, 372, 508, 380, 504, 376, 504, 376, 504, 408, 476, 408, 476, 372, 508, 1244, 508, 1248, 508, 408, 476, 404, 476, 408, 472, 376, 508, 372, 504, 9976, 3564, 1684, 508, 376, 504, 1248, 508, 376, 504, 408, 476, 408, 472, 376, 504, 380, 504, 408, 476, 404, 476, 404, 476, 376, 504, 380, 508, 404, 472, 1248, 508, 376, 508, 380, 504, 376, 504, 376, 504, 376, 504, 380, 504, 404, 476, 1244, 512, 1244, 508, 1252, 508, 404, 476, 404, 476, 1248, 508, 380, 504, 404, 476, 408, 472, 408, 476, 408, 476, 376, 504, 404, 476, 404, 476, 380, 504, 376, 504, 376, 508, 404, 476, 380, 504, 376, 504, 408, 472, 376, 508, 408, 472, 1248, 508, 1248, 508, 404, 476, 380, 504, 408, 472, 376, 504, 1248, 508, 408, 476, 1244, 508, 1248, 508, 404, 476, 380, 508, 372, 508, 404, 476, 404, 476, 408, 476, 408, 476, 404, 476, 404, 472, 1256, 508, 404, 476, 1248, 508, 404, 476, 408, 476, 408, 476, 372, 504, 1248, 508, 408, 476, 408, 476, 404, 472, 408, 476, 380, 504, 376, 504, 404, 480, 372, 508, 408, 476, 404, 476, 404, 476, 404, 476, 380, 508, 404, 476, 404, 476, 376, 504, 380, 504, 404, 476, 1244, 512, 1244, 508, 380, 508, 404, 476, 376, 504, 372, 508, 408, 476, 408, 476, 404, 476, 404, 476, 408, 476, 404, 476, 1244, 508, 1244, 512, 408, 476, 408, 472, 376, 508, 404, 476, 380, 504, 404, 476, 408, 472, 408, 476, 408, 476, 404, 476, 372, 508, 404, 476, 412, 476, 372, 508, 404, 476, 372, 508, 408, 476, 404, 476, 404, 476, 408, 476, 408, 476, 376, 504, 404, 476, 404, 476, 1248, 512, 404, 476, 404, 476, 408, 476, 408, 480, 404, 476, 376, 504, 404, 476, 380, 508, 404, 472, 1244, 512, 1244, 512, 412, 476, 404, 476, 372, 508, 404, 476, 412, 476, 376, 504, 404, 476, 404, 476, 1252, 508, 1248, 508, 404, 476, 404, 476, 376, 508};
unsigned int start[440] = {3584, 1664, 532, 352, 524, 1228, 528, 388, 492, 392, 496, 384, 492, 388, 492, 392, 488, 396, 492, 388, 492, 388, 492, 388, 492, 392, 492, 388, 492, 1224, 528, 392, 492, 392, 492, 388, 492, 388, 492, 388, 492, 364, 520, 388, 492, 1228, 524, 1228, 528, 1232, 528, 388, 492, 388, 488, 1228, 532, 360, 524, 388, 488, 360, 524, 388, 492, 360, 524, 388, 492, 388, 496, 388, 488, 360, 524, 360, 524, 388, 492, 388, 412, 472, 492, 388, 492, 388, 492, 360, 520, 364, 520, 392, 492, 388, 488, 360, 524, 392, 492, 392, 488, 388, 496, 388, 416, 468, 412, 468, 412, 436, 524, 388, 492, 392, 492, 388, 488, 1232, 528, 1228, 524, 392, 492, 392, 412, 468, 488, 360, 520, 388, 492, 9956, 3584, 1660, 528, 392, 412, 1304, 528, 388, 492, 360, 524, 360, 520, 392, 492, 356, 444, 440, 520, 392, 488, 360, 524, 388, 416, 440, 520, 388, 492, 1228, 524, 392, 492, 392, 492, 388, 488, 396, 412, 468, 412, 472, 488, 392, 488, 1228, 524, 1228, 528, 1232, 528, 388, 492, 388, 488, 1232, 524, 364, 520, 392, 416, 464, 492, 388, 416, 468, 492, 392, 488, 360, 520, 360, 520, 364, 520, 360, 524, 388, 492, 388, 416, 468, 416, 1304, 448, 468, 488, 392, 488, 396, 488, 1228, 452, 1304, 448, 436, 448, 472, 412, 468, 412, 464, 492, 1228, 528, 360, 520, 1228, 452, 1304, 448, 468, 492, 360, 520, 392, 488, 396, 412, 468, 412, 472, 488, 356, 448, 468, 488, 392, 488, 1240, 524, 388, 416, 1304, 452, 464, 488, 364, 520, 360, 448, 464, 416, 1304, 524, 364, 448, 468, 412, 468, 488, 388, 492, 364, 520, 392, 412, 468, 412, 468, 416, 468, 488, 364, 444, 436, 444, 468, 488, 396, 412, 468, 412, 468, 488, 360, 448, 436, 448, 464, 412, 1304, 452, 1304, 528, 360, 524, 388, 416, 468, 412, 468, 412, 440, 444, 468, 412, 468, 416, 432, 448, 472, 412, 464, 488, 1228, 452, 1304, 452, 472, 412, 468, 412, 468, 488, 392, 412, 472, 412, 468, 488, 364, 444, 464, 416, 472, 412, 468, 412, 468, 412, 468, 412, 472, 416, 468, 412, 432, 448, 468, 412, 440, 444, 468, 412, 468, 412, 468, 412, 472, 416, 464, 416, 468, 412, 464, 416, 1308, 524, 396, 412, 464, 416, 468, 412, 472, 416, 468, 412, 468, 412, 468, 412, 472, 416, 464, 416, 1304, 448, 1304, 524, 400, 416, 432, 448, 464, 416, 468, 412, 472, 412, 1308, 448, 468, 412, 468, 412, 1308, 452, 1304, 452, 468, 412, 468, 412, 468, 412};

void setup() {
  irsend.begin();
  pinMode(START, INPUT);
  pinMode(STOP, INPUT);
  Serial.begin(115200);
}

void loop() {
  if (digitalRead(START) == HIGH) {
    Serial.println("START");
    irsend.sendRaw(start, sizeof(start) / sizeof(start[0]), khz);
  } else if (digitalRead(STOP) == HIGH) {
    Serial.println("STOP");
    irsend.sendRaw(stop, sizeof(stop) / sizeof(stop[0]), khz);
  }
  delay(500);
}

赤外線 LED の信号送信は 4 ピンで制御しています
タクトスイッチはそれぞれ 12, 14 ピンで制御しています

Arduino とほぼ同じように使えるのですが、若干違うところもあります
IRsend irsend(4); という感じで赤外線を送信するピンを指定することができます
Arduino のときは 3 ピン固定でした
また、irsend.begin(); で赤外線 LED を使うことを宣言する必要があります

動作確認

スケッチを書き込んでエアコンに向けてスイッチを押してみましょう
リモコンの信号がちゃんと学習できていればエアコンの起動と停止ができるはずです
今回はトランジスタで信号を増幅しているので距離は数メートル離れても大丈夫でした
自宅で試した感じだと 4 - 5m は全然大丈夫でした

最後に

ESPr で赤外線 LED を制御してみました
ほぼ Arudino と同じように制御できますが、完全互換では動作しませんでした
また、信号の出力が弱いのでトランジスタを挟んだほうが良いです

あとはこれに MQTT を Subscribe する機能を設けて扇風機のときのようにネットから制御できるようにしたいと思います

参考サイト

Hubot + Slack で自作の扇風機を制御してみた

概要

Hubot で自作の扇風機を制御してみました
具体的には Hubot に「扇風機の電源を入れろ」というと扇風機が回りだし「止まれ」というと扇風機が止まります

システム全体の概要図は以下の通りです
slack_with_fan_system_fig.png

環境

  • Slack 2016/07/04 時点
  • heroku-toolbelt 3.43.4
  • node 6.2.0
  • npm 3.8.9

iotbot のインストール

Hubot はすでにあるものを使います
Hubot を Heroku 上にデプロイして、それを Slack から呼び出せるようにします

まず iotbot を自分の Heroku アカウント配下にデプロイします
アクセスすると Heroku ボタンがあるのでこれをクリックすれば自分の Heroku アカウント配下にデプロイすることができます

Heroku へのデプロイが完了したら必要な環境変数を設定していきます
今回は Slack とも連携するので設定が必要な環境変数は以下となります

  • HUBOT_SLACK_TOKEN・・・Slack Integration から発行されたトークン
  • HUBOT_MQTT_PORT・・・MQTT ブローカのポート
  • HUBOT_MQTT_HOST・・・MQTT ブローカのホスト名
  • HUBOT_MQTT_USERNAME・・・MQTT ブローカにアクセスするためのユーザ名
  • HUBOT_MQTT_PASSWORD・・・MQTT ブローカにアクセスするためのパスワード
  • HUBOT_MQTT_PUBTOPIC・・・Publish するトピック
  • HUBOT_MQTT_SUBTOPIC・・・Subscribe するトピック

これらを Heroku 上にデプロイしたアプリに heroku コマンドを使って設定します

  • heroku config:set HUBOT_SLACK_TOKEN=xxxx-nnnnnnnnnnn-xxxxxxxxxxxxxxxxxxxxxxxx HUBOT_MQTT_PORT=1883 HUBOT_MQTT_HOST=”your.mqtt.broker” HUBOT_MQTT_USERNAME=username HUBOT_MQTT_PASSWORD=password HUBOT_MQTT_PUBTOPIC=put_t HUBOT_MQTT_SUBTOPIC=sub_t –app iotbot

「–app」の部分は Heroku にデプロイしたアプリ名を指定してください

Hubot と Slack 自体の連携方法がいまいちよくわからないという場合はこちらの記事を参考にしてみてください

自作扇風機の紹介

今回は ESPr を使ってモータを制御することで Wifi 付きの扇風機っぽいものを作って見ました
作成した扇風機の全体図は以下の通りです
slack_with_fan_circuit.jpg

ESPr は Arduino 化しています
ESPr で DC モータを制御する回路にタクトスイッチを組み合わせています
DC モータの制御に関してはこちらを御覧ください

作成したスケッチは以下の通りです

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "ssid";
const char* password = "ssid-password";
const char* mqtt_server = "your.mqtt.broker";
const int mqtt_port = 1883;
const char* mqtt_sub_topic = "topic";
const char* mqtt_username = "mqtt-user";
const char* mqtt_password = "mqtt-pass";

WiFiClient espClient;
PubSubClient client(espClient);
int ON = 4;
int OFF = 5;
int MOTOR = 2;

void setup() {
  pinMode(ON, INPUT);
  pinMode(OFF, INPUT);
  pinMode(MOTOR, OUTPUT);
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
}

void callback(char* topic, byte* payload, unsigned int length) {
  if ((char)payload[0] == '3') {
    digitalWrite(MOTOR, HIGH);
  } else {
    digitalWrite(MOTOR, LOW);
  }
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) {
       client.publish(mqtt_sub_topic, "Start MQTT Motor");
       client.subscribe(mqtt_sub_topic);
    } else {
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (digitalRead(ON) == HIGH) {
    digitalWrite(MOTOR, HIGH);
  } else if (digitalRead(OFF) == HIGH) {
    digitalWrite(MOTOR, LOW);
  }
  delay(200);
}

Wifi に接続し MQTT ブローカに接続します
Slack から Publish するトピックを ESPr 側では Subscribe します
これにより Slack から扇風機の ON/OFF を実現します
具体的には Subscribe したペイロード情報がモータを制御するためのピン番号 (今回は 3 or 5) であれば、そのままピンを HIGH or LOW にします

また、今回は手元のスイッチでも扇風機を ON/OFF できるようにタクトスイッチを 2 つ (ON/OFF) 実装しました
タクトスイッチは ESPr の 4, 5 ピンで制御しています

スケッチが書き込めて問題なくモータが回ることが確認できたら Slack を絡めて動作確認してみましょう

動作確認

チャネルに iotbot の invite まで済んでいるのであれば Slack から

  • @iotbot: fan on

と実行してみましょう
すると扇風機を ON するための情報が Publish され扇風機が回り始めると思います

  • @iotbot: fan off

とすると扇風機が止まると思います
今度は、Slack から扇風機を ON にして手元のスイッチで OFF できることを確認してみてください

最後に

Slack からデバイスを制御してみました
バックエンドは MQTT を使っているだけなので非常に単純な構成になっています

実用性があるレベルまで作りこんでいないので何とも言えませんが、本当に使おうとしたらエビデンス的なものが必要になると思っています
具体的に言うと fan off したときにちゃんと扇風機が止まっているのか、というのを確認できる仕組みがないと実用レベルまでは行かないかなと思っています

ESP-WROOM-02 と Arduino Pro mini で DC モータを制御してみた

概要

前回 Arduino を使って制御しましたが、今回は例のごとく「ESP-WROOM-02」と「Arduino Pro mini」で制御してみました
完全互換で動作したので配線だけ紹介します

環境

  • ESP-WROOM-02
  • Arduino Pro mini
  • Arduino IDE 1.6.9
  • トランジスタ 2N5088 x 1
  • 一般用整流ダイオード 1N4007 x 1
  • 抵抗 1kΩ x 1

ESP-WROOM-02 と DC モータの配線

esp_with_dcmotor_circuit.jpg

Arduino Pro mini と DC モータの配線

promini_with_dcmotor.jpg

最後に

久しぶりに完全互換で動作しました
ともに 5v の出力もできるので、モータの動きが鈍い場合は電源を 5v にあげてみてください

Arduino で DC モータを制御してみる

概要

Arduino で DC モータを制御してみました
作成した回路とスケッチを紹介します

環境

  • Arduino Uno
  • Arduino IDE 1.6.9
  • トランジスタ 2N5088 x 1
  • 一般用整流ダイオード 1N4007 x 1
  • 抵抗 1kΩ x 1

とりあえず DC モータを回す

スイッチを押すとモータが回る回路です
arduino_with_dcmotor_circuit1.jpg

電池とスイッチとジャンパケーブルだけです
これを Arduino から制御できるようにします

電源を Arduino から取る回路

電源を電池 2 本から Arduino に変更した回路です
arduino_with_dcmotor_circuit2.jpg

電源を変更しただけなのでこれでもモータは回ります

デジタルピンで制御する回路 (誤)

2 番ピンを使って制御してみます
まずはバカ正直に回路を組んでみます
arduino_with_dcmotor_circuit3.jpg

スケッチは以下の通りです

void setup() {
  pinMode(2, OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);
  delay(2000);
  digitalWrite(2, LOW);
  delay(2000);
}

これだとモータが回らないのがわかると思います
電圧は足りているのですが、電流が足りていないためモータが回りません
これにトランジスタを加えることでモータを制御してみます

デジタルピンで制御する回路 (正)

トランジスタ+ダイオードを使った回路は以下の通りです
arduino_with_dcmotor_circuit4.jpg

トランジスタの配線部分だけ拡大しました
arduino_with_dcmotor_circuit5.jpg

スケッチは前述のとおり 2 ピンを制御するスケッチを使っています
これで正しく動作すると 2 秒おきにモータが起動/停止を繰り返します

ポイントはトランジスタとダイオードの配線です

  • エミッタ (写真一番左) は GND に接続します
  • ベース (写真真ん中) は Arduino 2 ピンの信号を 1kΩ の抵抗を挟んで接続します
  • コレクタからジャンパケーブルを出してモータと整流ダイオードを並列に接続します

整流ダイオードはプラスとマイナスの区別があるのでプラス側に Arduino の 3.3v を接続します
トランジスタはものによってエミッタ、ベース、コレクタのピンの順番が異なるので適宜電気特性のシートなどを見ながら確認してください

また、今回モータ用の電源は Arduino の 3.3v から取得していますが電池から取得しても問題ありません

最後に

Arduino で DC モータを制御してみました
今回のポイントはトランジスタとダイオードでしたがそれぞれの働きは

  • トランジスタ・・・電流を増幅させる
  • ダイオード・・・電流の流れを一方向にする

ですが、実際に回路を組んでみると更に動きを理解することができました

あとは電圧の増幅 (昇圧) とかもやってみたいと思っています

参考サイト

Slack と Hubot を連携してみた

概要

Slack の Hubot Integration を使って連携してみました
Hubot サーバは Heroku で管理してみたいと思います

環境

  • Slack 2016/06/30 時点
  • Mac OS X 10.11.5
  • nodejs 5.9.1
  • npm 3.7.3
  • yo 1.8.4
  • heroku-toolbelt 3.43.2

ローカルで Hubot の作成

まずはローカルの Mac で Hubot を作成します

  • mkdir test-bot
  • cd test-bot
  • npm install -g yo generator-hubot
  • yo hubot

とすると Hubot のセットアップがはじまります
hubot_chain_heroku_slack_setup_bot.png

この後、Hubot の作成に必要な情報を入力します
今回は以下のように入力しました

? Owner hawksnowlog
? Bot name test-bot
? Description Test bot
? Bot adapter slack

ポイントはアダプタのところで「slack」と入力するところです
これで Slack と Hubot を連携することができるようになります

とりあえずインストール後にローカルでテストしたい場合は

  • ./bin/hubot -a shell -n test-bot

で動作させることができます

Heroku にローカルで作成した Hubot を登録する

ローカルで作成した Hubot を Heroku に登録します
事前に Heroku のアカウント登録と toolbelt の設定は済ませておいてください (heroku login など)
今回はとりあえず動かすことが目的なのでさくっと登録します

  • git init
  • git add .
  • git commit -m “Initial Commit”
  • heroku create
  • git push heroku master

で OK です
これで Heroku のアプリ一覧を確認するとアプリが作成されていると思います
今回はアプリの名前を「test-bot」に変更しました
名前が被った場合は適宜変更してください

Slack に Hubot Integration を追加する

Slack から Hubot Integration を追加しましょう
ログインした状態で https://testorg.slack.com/apps/manage にアクセスしてください
( Organization は testorg となっているので、各自の状況に合わせて適宜変更してください )

Hubot があるので選択します
hubot_chain_heroku_slack_select_app.png

Configure で新しい Hubot を追加します
hubot_chain_heroku_slack_add_app.png

Slack 上で Hubot に話かける名前を設定します
hubot_chain_heroku_slack_input_name.png

すると Hubot に設定するためのトークンがもらえるのでメモしておきます
hubot_chain_heroku_slack_make_token.png

このトークンを Heroku 上の Hubot に設定してあげます
設定はコマンドから行います

  • heroku config:set HUBOT_SLACK_TOKEN=xxxx –app test-bot

xxxx の箇所を取得できたトークンに変更してください

チャネルに Hubot を招待する

あとは Hubot を動かしたいチャネルに Hubot を招待するだけです
招待は Slack 上で

  • /invite @test-bot

という感じで入力すれば OK です
ボットの名称はさきほど Integration を追加するときに Hubot に設定した Username を指定してください

動作確認

以下のような感じで Slack 上で Hubot に話かけてみましょう

  • @test-bot: help
  • @test-bot: echo hoge

Hubot が応答してくれるはずです

最後に

ローカルで Hubot を作成して、Heroku にデプロイして Slack に連携という流れを紹介しました
もちろん、Heroku にデプロイしなくてもローカルのまま Slack に連携することも可能です

何点か Tips も紹介しておきます

  • invite 時に指定した Username から変更すると Hubot が反応しなくなる

これはもしかするとバグかもしれないのですが、Hubot Integration の Customize Name を変更すると Hubot が反応してくれなくなりました
名前を変更したい場合は再度 Integration を作成し直す必要がありそうです

  • Heroku 上の Hubot がスリープになると応答しなくなる

Heroku を無料枠で使っている場合アプリへのアクセスが一定時間ないとアプリはスリープしてしまいます
再度アクセスすれば起動するのですが、Hubot の場合 Slack からコマンドを投げただけだとスリープから復帰してくれません
ブラウザなどでアプリにアクセスすると起動できますが、毎回そんなことするのも面倒なので別途 cron 的な仕組みが必要そうです

  • HUBOT_SLACK_TEAM, HUBOT_SLACK_BOTNAME などの変数がなくなった

これらは Slack の Hubot Integration 上で設定する感じになりました
なので、直接 Hubot に設定するのは HUBOT_SLACK_TOKEN だけになります
確かにこっちのほうが綺麗だとは思いますが、代わりにチャネル設定等が「/invite」になっているので、その辺が見落としがちなポイントです

参考サイト

Arduino で赤外線信号を学習してエアコンを制御してみた

概要

Arduino + 赤外線受信モジュールを使ってリモコンの赤外線信号を学習しました
そして、その信号を赤外線 LED を使って送信することでエアコンを制御してみました
今回学習したリモコンは Panasonic の A75C3639 という型番になります

環境

対象のリモコン

信号を学習するリモコンは以下の通りです
とりあえず今回は冷房をつけたいので冷房ボタンを学習します
try_arduino_infrared_remocon.jpg

配線

  • Arduino と赤外線受信モジュール
  • Arduino と赤外線 LED
  • Arduino とタクトスイッチ

を配線します
タクトスイッチを押した時に赤外線を送信するようにします
try_arduino_infrared_circuit1.jpg

ブレッドボード側のアップです
try_arduino_infrared_circuit2.jpg

赤外線受信モジュールは 5V, GND, 2 番ピンを使っています
あとで説明しますが、赤外線受信モジュールは必ず 2 番ピンを使ってください
赤外線 LED は GND, 3 番ピンを使っています
これもあとで説明しますが、赤外線の送信は必ず 3 番ピンを使ってください
タクトスイッチはプルダウンで接続し 3V, GND, 7 番ピンを使っています

IRremote のインストール

Arduino IDE で赤外線を操作することができるライブラリをインストールします

スケッチ -> ライブラリをインクルード -> ライブラリを管理 -> IRremote と検索

するとライブラリが見るかるので選択してインストールしてください
try_arduino_infrared_install_lib.png

リモコンの信号を学習する

では、まずリモコンの赤外線信号を学習します
スケッチは以下の通りです

#define maxLen 800

volatile  unsigned int irBuffer[maxLen];
volatile unsigned int x = 0;

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);
}

void loop() {
  Serial.println(F("Press the button on the remote now - once only"));
  delay(5000);
  if (x) {
    Serial.println();
    Serial.print(F("Raw: ("));
    Serial.print((x - 1));
    Serial.print(F(") "));
    detachInterrupt(0);
    for (int i = 1; i < x; i++) {
      // if (!(i & 0x1)) Serial.print(F("-"));
      Serial.print(irBuffer[i] - irBuffer[i - 1]);
      Serial.print(F(", "));
    }
    x = 0;
    Serial.println();
    Serial.println();
    attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);
  }

}

void rxIR_Interrupt_Handler() {
  if (x > maxLen) return;
  irBuffer[x++] = micros();
}

これを Arduino に書き込んで赤外線受信モジュールにリモコンを向けてボタンを押すと信号の情報がシリアルモニタに表示されます
try_arduino_infrared_receive_ir.png

事前の配線で受信モジュールは 2 番ピンを使うようにしましたが上記のコードは暗黙で 2 番ピンを使うことになっています
( コード上でピン番号を指定している部分がないと思います )

送信時にこの情報を使用するのでメモしておいてください

ちょっとここで詳細に説明したいのですが、実はリモコンの学習はインストールした IRremote ライブラリを使ってもできます
ですが、101 個以上の信号を送信するリモコンを IRremote で学習することができません
https://github.com/z3t0/Arduino-IRremote/issues/137

IRremoteInt.h というファイル内で RAWBUF という変数を管理しており、これが受信できる信号の個数の MAX 値なのですが、この値をデフォルトの 101 から変更してもうまくそれ以上の信号が受信できないのです

なので、別途赤外線の信号を学習するスケッチを作成して、そこで学習できた信号の情報を使うことにしました

学習した信号を送信する

信号を学習できたら送信してみましょう
送信用のスケッチは以下の通りです

#include <IRremote.h>

int ON = 7;
int khz = 38;
IRsend irsend;

void setup() {
  pinMode(ON, INPUT);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(ON) == HIGH) {
    Serial.println("ON");
    unsigned int irSignal[440] = {3584, 1664, 532, 352, 524, 1228, 528, 388, 492, 392, 496, 384, 492, 388, 492, 392, 488, 396, 492, 388, 492, 388, 492, 388, 492, 392, 492, 388, 492, 1224, 528, 392, 492, 392, 492, 388, 492, 388, 492, 388, 492, 364, 520, 388, 492, 1228, 524, 1228, 528, 1232, 528, 388, 492, 388, 488, 1228, 532, 360, 524, 388, 488, 360, 524, 388, 492, 360, 524, 388, 492, 388, 496, 388, 488, 360, 524, 360, 524, 388, 492, 388, 412, 472, 492, 388, 492, 388, 492, 360, 520, 364, 520, 392, 492, 388, 488, 360, 524, 392, 492, 392, 488, 388, 496, 388, 416, 468, 412, 468, 412, 436, 524, 388, 492, 392, 492, 388, 488, 1232, 528, 1228, 524, 392, 492, 392, 412, 468, 488, 360, 520, 388, 492, 9956, 3584, 1660, 528, 392, 412, 1304, 528, 388, 492, 360, 524, 360, 520, 392, 492, 356, 444, 440, 520, 392, 488, 360, 524, 388, 416, 440, 520, 388, 492, 1228, 524, 392, 492, 392, 492, 388, 488, 396, 412, 468, 412, 472, 488, 392, 488, 1228, 524, 1228, 528, 1232, 528, 388, 492, 388, 488, 1232, 524, 364, 520, 392, 416, 464, 492, 388, 416, 468, 492, 392, 488, 360, 520, 360, 520, 364, 520, 360, 524, 388, 492, 388, 416, 468, 416, 1304, 448, 468, 488, 392, 488, 396, 488, 1228, 452, 1304, 448, 436, 448, 472, 412, 468, 412, 464, 492, 1228, 528, 360, 520, 1228, 452, 1304, 448, 468, 492, 360, 520, 392, 488, 396, 412, 468, 412, 472, 488, 356, 448, 468, 488, 392, 488, 1240, 524, 388, 416, 1304, 452, 464, 488, 364, 520, 360, 448, 464, 416, 1304, 524, 364, 448, 468, 412, 468, 488, 388, 492, 364, 520, 392, 412, 468, 412, 468, 416, 468, 488, 364, 444, 436, 444, 468, 488, 396, 412, 468, 412, 468, 488, 360, 448, 436, 448, 464, 412, 1304, 452, 1304, 528, 360, 524, 388, 416, 468, 412, 468, 412, 440, 444, 468, 412, 468, 416, 432, 448, 472, 412, 464, 488, 1228, 452, 1304, 452, 472, 412, 468, 412, 468, 488, 392, 412, 472, 412, 468, 488, 364, 444, 464, 416, 472, 412, 468, 412, 468, 412, 468, 412, 472, 416, 468, 412, 432, 448, 468, 412, 440, 444, 468, 412, 468, 412, 468, 412, 472, 416, 464, 416, 468, 412, 464, 416, 1308, 524, 396, 412, 464, 416, 468, 412, 472, 416, 468, 412, 468, 412, 468, 412, 472, 416, 464, 416, 1304, 448, 1304, 524, 400, 416, 432, 448, 464, 416, 468, 412, 472, 412, 1308, 448, 468, 412, 468, 412, 1308, 452, 1304, 452, 468, 412, 468, 412, 468, 412};
    irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
  }
  delay(500);
}

学習した信号情報をそのまま配列に格納すれば OK です
今回はこの配列の情報がリモコンの冷房ボタンの信号になります
なので、別のボタンを送信したい場合はここの配列の情報をそのまま書き換えてください

今回はタクトスイッチが HIGH になったときに赤外線の信号を送信するようにしています
赤外線情報を送信するときはインストールした IRremote を使用しています
で、配線時に赤外線 LED を 3 番ピンに接続しましたが、IRremote の sendRaw は勝手に 3 番ピンを使っています
なので、3 番ピンに接続しておかないと IRremote で信号がうまく送信できないということになってしまいます

動作確認

赤外線 LED をエアコンに向けてスイッチを押してみましょう
ちゃんと信号が学習できていれば、エアコンが反応するはずです
ちなみに今回紹介した信号の配列で送信してみたところ、ちゃんとエアコンが冷房ボタンと認識し冷房が付きました
なので、これで Arduino からエアコンをつけれるようになりました

最後に

紹介は以上です

やはり一番ハマったのは信号を学習する部分でした
初めはずっと IRremote の学習するスケッチを使っていたのですが、どうも信号が 101 個以上増えなく、エアコンもその情報だと反応しませんでした
おかしいなと思い、いろいろ調べたところ送信する赤外線の信号が 101 個以上長いケースがあるということがわかり、別途信号を学習するスケッチを作るということになりました

ただ、この方法はおそらくどのリモコンにも応用可能だと思います
学習用のスケッチで学習したデータを配列に突っ込んで、そのデータをそのまま送信しているだけなので、同じことを別のリモコンでやれば良いだけです

IRremote の関数とかを見ると Sony や NEC などメーカごとに用意された関数があるのですが、これはライブラリ内部ですでにリモコンの情報を持っているため、少しでも対応していないリモコンだと動かなくなります

そんな場合でも今回の方法を知っていれば簡単に対応できるようになる、と思います

あと、停止の信号を学習するのと ESPr 対応ができれば家の外からでもエアコンを制御できるようにできそうです
それもできたら紹介したいと思います

参考サイト

2017年1月30日月曜日

Slack から Heroku 上でスリープしてしまったアプリを起こすテクニック

概要

Heroku の無料枠を使っている場合デプロイしたアプリに 30 分アクセスがないとアプリはスリープしてしまいます
スリープした状態でアクセスが来るとアプリは起動するのですが、いちいちブラウザなどで URL にアクセスするのは面倒です
今回は、そんなスリープしてしまった Heroku アプリを Slack から起こす方法を紹介します

環境

  • Slack 2016/07/14 時点
  • Heroku 2016/07/14 時点

Slack の Slash Commands を作成する

Slash Commands は任意の URL に GET or POST のリクエストを送信することができる機能です
これを使って Heroku アプリを起こすようにしてみます

まず、Custom Integrations に Slash Commands を追加します
まだない場合は Apps Directory から検索して Slash Commands を追加してください

追加できたら Slash Commands を作成しましょう
作成の際のポイントは以下の通りです

  • Integration Settings の URL を Heroku 上にデプロイしたアプリに設定する

サンプルとしては以下の通りです
wackup_heroku_app_configration_sc.png

Method はデプロイした Heroku アプリに合わせて変更してください
Command は好きなコマンドを設定してください

要するに Slash Command を実行したときに Heroku アプリに起こす用のリクエストを送信するだけです

あとはお好みに合わせて「Customize Icon」や「Autocomplete help text」を設定してください

動作確認

では、作成した Slash Command で Heroku アプリを起こしてみましょう
wackup_heroku_app_ret.png

という感じでアプリのルートにアクセスしたときのレスポンスが返ってくれば OK です
( 今回のアプリがリクエスト情報をダンプするアプリだったのでトークンやらなんやらがいろいろで出てしまっていたのでモザイクにしました )

Heroku 側の起動がすぐには終わらなく Slash Command がタイムアウトした場合でもリクエストは Heroku 側に行っているので 2 回目のアクセスではちゃんとレスポンスが返ってくると思います

最後に

Slack の Slash Command を使ってアクセス Heroku のアプリを起こしてみました
まぁ要するにアクセスしているだけなのですが、いちいち URL を確認したりするのが面倒な場合にはいいかもしれません

特にこれが必要になるのは cron を使った Hubot かもしれません
Heroku 上でスリープしてしまった Hubot は cron も回りません
なので、アクセスする必要があるのですが Slash Command で簡単に起こせるようになっているとちょっと便利かもしれません

2017年1月29日日曜日

ESP-WROOM-02 のピッチ変換フル版を Arduino 化してみた

概要

前回フル版で AT コマンドが送信できるまでやってみました
今回はフル版を Arduino 化して Arduino スケッチが動作するようにしてみたいと思います

環境

Arduino IDE で ESP8266 を扱えるようにする方法はこちらを参考に事前にセットアップしておいてください

配線

ほぼ前回と同じですが違う点が 2 点あります
try_esp_full_ver_arduino_circuit.jpg

Arduino のスケッチを書き込むために「UART Download Mode」にする必要があります
これにするには

  1. IO0 ピンを GND に接続
  2. RST ピンを GND に接続 -> 抜く

ということを行う必要があります
これをすることで ESP-WROOM-02 のモードが変わります

スケッチ

Wifi に接続して MQTT に Publish できるか確認するスケッチです
ここは各自で確認しやすいスケッチにしてください

単純に GPIO (IO14) とかを制御して LED を点滅させるだけでも OK です

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "ssid";
const char* password = "ssid password";
const char* mqtt_server = "your.mqtt.broker";
const int mqtt_port = 1883;
const char* mqtt_pub_topic = "pub_topic";
const char* mqtt_username = "broker username";
const char* mqtt_password = "broker password";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) {
      client.publish(mqtt_pub_topic, "hello world");
    } else {
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 10000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 75, "hello world #%ld", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish(mqtt_pub_topic, msg);
  }
}

Arduino IDE から書き込めるか確認してみましょう
ちゃんとモードが変わっている場合は問題なく書き込めると思います
モードが変わっていないと以下のようなエラーが発生すると思います

warning: espcomm_sync failed
error: espcomm_open failed
error: espcomm_upload_mem failed

最後に

ESP-WROOM-02 のフル版を Arduino 化してみました

面倒なのはスケッチを一度書き込むと実行するためにモードが「Flash Boot Mode」に戻ってしまいます
なので再度スケッチを書き込む場合は RST ピンをまた GND に接続させて抜く必要があります
この辺は開発ボードを使っているとわかるのですが、スイッチ等を実装しておくと押すだけでモードを切り替えられるようになるので楽です

まだフル版でガッツリ開発していないので何とも言えないのですが、フル版はいろいろ面倒です
もし、今回の配線を崩してしまった場合、またフル版で開発したいと思ったら同じ配線をブレッドボード上にしなければなりません
開発ボードの場合、スケッチを書き込むだけであればそんなことは必要ありません
このままブレッドボード上に配線しっぱなししてもいいのですが、それもちょっと、、、

大量に使う場合とか、スケッチをもう書き換える必要がない場合などはフル版の方が安くて小型なので、良いと思います
ゴリゴリスケッチを書き換えたり配線を変える場合は、やはりフル版よりかは開発ボードのほうが断然簡単なのでオススメです

ESP-WROOM-02 を Arduino 化して Wifi に接続してみる

概要

前回 WROOM が Mac で動作するところまで実施しました
今回は Arduino IDE で Wifi に接続するスケッチを作成して WROOM に書き込み実際に Wifi に接続するところまで確認してみます
また、この作業を実施すると WROOM が Arduino 化され前回実施した AT コマンドでの操作ができなくなるので注意してください

環境

Arduino core for ESP8266 のインストール

まずは Arduino IDE に ESP8266 を開発するためのボードタイプを追加します

Arduino -> Preferences -> Settings -> Additional Boards Manager URLs

に以下を記載します

http://arduino.esp8266.com/stable/package_esp8266com_index.json

OK で追加した

ツール -> マイコンボード -> ボードマネージャー

から esp8266 で検索して新規のボードタイプをインストールします
wroom_con_wifi_install_esp8266_board.png

インストールボタンをクリックするとダウンロードが始まります
プログレスバーが 100% になりダウンロードが完了すればインストール完了です

Arduino core for ESP8266 の設定

各種設定していきます
「ツール」から以下のように設定しましょう

wroom_con_wifi_settings_esp8266.png

  • マイコンボード -> Generic ESP8266 Module
  • Flash Mode -> QIO
  • Flash Frequency -> 80MHz
  • Upload Using -> Serial
  • CPU Frequency -> 160MHz
  • Flash Size -> 4M (3M SPIFFS)
  • Debug port -> Disabled
  • Debug Level -> None
  • Reset Method -> nodemcu
  • Upload Speed -> 115200
  • シリアルポート -> それぞれの環境に合わせてポートを選択してください
  • 書き込み装置 -> USBasp

を設定しました
細かい設定の意味までは確認できていませんが、とりあえず上記の設定で普通の Arduino スケッチを書き込むように WROOM にスケッチを書き込むことができるのを確認しています

スケッチの作成

Arduino IDE の設定ができたらスケッチを作成しましょう
全体は以下の通りです

#include <Arduino.h>
#include <ESP8266WiFi.h>

const char* ssid = "Please input your SSID";
const char* password = "Please input your SSID's password";

boolean continuousResponseFlag = true;

WiFiServer server(80);
WiFiClient client;

void responseHTML() {
  client = server.available();
  delay(1);
  String req;

  while (client) {
    if (client.available()) {
      req = client.readStringUntil('\n');
      Serial.println(req);
      if (req.indexOf("GET / HTTP") != -1) {
        Serial.println("-----from Browser FirstTime HTTP Request---------");
        Serial.println(req);
        while (req.indexOf("\r") != 0) {
          req = client.readStringUntil('\n');
          Serial.println(req);
        }
        req = "";
        delay(10);

        // Headers
        client.print(F("HTTP/1.1 200 OK\r\n"));
        client.print(F("Content-Type:text/html\r\n"));
        client.print(F("Connection:close\r\n\r\n"));
        // Body
        client.println(F("<!DOCTYPE html>"));
        client.println(F("<html>"));
        client.println(F("<font size=30>"));
        client.println(F("Hello World"));
        client.println(F("</html>\r\n"));

        delay(1);
        client.stop();

        Serial.println("\nGET HTTP client stop--------------------");
        req = "";
        continuousResponseFlag = true;
      }
    }
  }
}

void setup() {
  Serial.begin(115200);
  // Connect to WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  if (continuousResponseFlag == true) {
      responseHTML();
  } else if (client.available()) {
    Serial.print(client.read());
  }
  delay(1);
}

スケッチを作成したら検証が成功するか確認しましょう

ポイント説明

setup() で指定した SSID への Wifi 接続を試みます
接続が成功すると取得できた IP アドレスをシリアルモニタに出力します
指定した SSID やパスワードが間違っている場合はここで IP が表示されないので、SSID やパスワードがあっているかと、Wifi ルータの設定があっているかなど確認してください

loop() でメインの処理を実行します
loop()responseHTML メソッドを呼び続けます
responseHTML はレスポンス用のクライアントオブジェクトを生成し HTTP のヘッダとボディを生成してレスポンスを返却します

今回は GET / HTTP で GET アクセスのみレスポンスを返却するようにしています
GET リクエストがきたら、リクエスト情報をシリアルに 1 行ずつ出力し、その後 client.print でヘッダ情報とボディ情報を返却します

1 リクエストごとにレスポンス用のクライアントオブジェクトは stop され、すぐに次のクライアントオブジェクトが生成されます

動作確認

検証が成功したら WROOM にアプリを書き込みます
書き込みは普通の Arduino スケッチと同じような書き込みます
シリアルモニタを起動しておきましょう

書き込み中は WROOM の TX と RX 用の LED が点滅します
点滅が終了しシリアルモニタに WROOM が取得した IP アドレスが表示されれば OK です
wroom_con_wifi_get_ip.png

今回は WROOM にアクセスすると HTML を返却するようなアプリにしたので実際にブラウザでアクセスしてみましょう
wroom_con_wifi_responsing.png

こんな感じで「Hello World」が表示されば OK です
もちろんブラウザではなく curl コマンドなどでも OK です
シリアルモニタには以下のように表示されていると思います
wroom_con_wifi_debug_response.png

最後に

ESP-WROOM-02 を Arduino 化してスケッチを作成し、そのスケッチを書き込むことで Wifi につながるところまで確認しました
あとは開発ボード上のピン情報を使って、センサなどと連携し、データが取得できたらクラウドに保存するなどができるといいなと思っています

あと、今回の作業をすると AT コマンドが使えなくなると記載しました
確かに起動すると Arduino スケッチが自動で起動してしまうので、シリアルモニタで AT コマンドは実行できなくなります
AT コマンドでも Wifi の設定などを WROOM に書き込めるので頑張ればできますが、プログラマブルに WROOM を操作できたほうが断然楽だし応用が効くので Arduino 化することをオススメします

Arduino 化を解除して出荷時の状態に戻すことってできるのだろうか・・・

Tips

ハマった点があるので紹介します

  • ESP-WROOM-02 を Mac の USB ポートに接続してもシリアルポートとして認識しない

原因は不明ですが接続しても /dev/cu.usbserial-DA01OF0S が現れずハマリました
解決できた方法は Mac の再起動だけでした
とりあえず発生したら再起動してみてください
なおシリアルポートとして認識していなくても WROOM 自体に書き込んだスケッチは問題なく動作していることは確認しました

参考サイト