144Lab

 
2018/04/09

Makuake「ハッカーコース」利用の手引き

Info

Makuake「ハッカーコース」とは

Makuake「うんこボタン」プロジェクトにおいて、インターネットボタンの自作キットとして用意したコースです。

ブロック図

block diagram

  • IO0,IO2,IO4,IO15のLEDはHi出力にすると点灯します。
  • LBOOT(IO5)とRBOOT(IO13)はデバイスがウェイクアップした要因を知らせる信号です。
  • LBOOT(IO5)=Loであれば左ボタンが押されて活動を開始したことを示します。
  • RBOOT(IO13)=Loであれば右ボタンが押されて活動を開始したことを示します。
  • LBTN(IO14),RBTN(IO12)はLoのときに押されていることを示します。
  • プログラムが起動したらACTIVE(IO16)をLoにしてください(Reset-Blockの初期化用)
  • PGMはLoのときに電源ON(リセット)するとファーム書き換え用モードです。

別途必要なもの

  1. PCとArduinoIDE
  2. USBシリアル変換アダプター
  3. 電池による電源供給または3.0~3.3V(能力2.6W以上)の電源供給

ArduinoIDEセットアップ

ボード、プラグイン、ライブラリのインストール
  • 設定にて「追加のボードマネージャのURL」に以下を追加する。
    • http://arduino.esp8266.com/stable/package_esp8266com_index.json
  • ボードマネージャーから 「esp8266 by ESP8266 Community Version 2.3.0」(esp8266:esp8266:2.3.0) をインストール
  • ライブラリマネージャから 「ArduinoJson 5.11.2」(ArduinoJson:5.11.2)をインストール

注:バージョンは動作確認時のものです。最新安定板をご利用ください。

ESP8266向けセットアップ

ArduinoIDEの設定を行います。

  • ボードマネージャにて「Generic ESP8266」(上の方)を選択する
  • ボード用設定
    • CpuFrequency=160
    • FlashFreq=80
    • FlashMode=qio
    • UploadSpeed=230400
    • FlashSize=2M
    • ResetMethod=none
  • シリアルモニタ設定
    • ボーレート 74800(推奨値)
  • シリアルポートはPC環境ごとに適切に選択

ファーム書き換え時の結線

  • 「JP1」と「FTDI USBシリアル変換アダプター Rev.2」を以下の配線でつなぐ
    • JP1:GND-アダプタ:GND
    • JP1:TXD-アダプタ:RXD
    • JP1:RXD-アダプタ:TXD
    • JP1:VIN-3V電源(電池を繋いでる場合は不要)
  • JP2をショートした状態で電源を通電
  • コードを用意してArduinoIDEからマイコンへの書き込みを実行する

参考画像

img_4816

ピンヘッダを立てる際、基板面から8mm高さ以下になるようにしてください(長い場合ピン先端をカットしてください)

PCと接続時の様子 img_4815

動作時

  • JP2をオープンにした状態で電源を通電
  • 左または右ボタンを押すとスリープからウェイクアップ

出荷時のサンプル

押したボタンのそばのLEDをしばらく点灯して終了


#include <ArduinoJson.h>

#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

// IOピン宣言
#define LEFT_BTN 14
#define RIGHT_BTN 12
#define ACTIVE 16
#define RBOOTED 13
#define LBOOTED 5
#define LEFT_RED_LED 15
#define RIGHT_RED_LED 4
#define LEFT_GREEN_LED 2
#define RIGHT_GREEN_LED 0

bool lBooted;
bool rBooted;
int batteryLevel;
HTTPClient http;
ESP8266WiFiMulti wifiMulti;

// 定形初期化処理(理解するまでは変更しないで)
void boot() {
  Serial.begin(74800);
  // pin setup
  pinMode(LBOOTED, INPUT_PULLUP);
  pinMode(RBOOTED, INPUT_PULLUP);
  pinMode(LEFT_RED_LED, OUTPUT);
  pinMode(RIGHT_RED_LED, OUTPUT);
  pinMode(LEFT_BTN, INPUT);
  pinMode(RIGHT_BTN, INPUT);

  // スリープから復帰するのに押されてたボタン状態を取得
  lBooted = digitalRead(LBOOTED) == LOW;
  rBooted = digitalRead(RBOOTED) == LOW;

  // アクティブモードへ移行
  digitalWrite(ACTIVE, LOW);
  pinMode(ACTIVE, OUTPUT);

  // ACTIVE==LOWのあとでしか緑LEDを使えない
  pinMode(LEFT_GREEN_LED, OUTPUT);
  pinMode(RIGHT_GREEN_LED, OUTPUT);

  // バッテリーレベル取得(アクティブモードでないとダメ)
  batteryLevel = analogRead(A0) * 3000 / 1024;  // [mV]

  // 電池が消耗していたり、通電のみだった場合はすぐにスリープする
  if (batteryLevel < 2300 || !lBooted && !rBooted) {
    ESP.deepSleep(0);
    delay(500);
  }
}

void setup() {
  boot();  // 必ずsetup関数の最初に実行

  Serial.println();
  Serial.println("left: " + String(lBooted) + " right: " + String(rBooted));

  if (lBooted) {
    digitalWrite(LEFT_GREEN_LED, HIGH);  // left green on
  }
  if (rBooted) {
    digitalWrite(RIGHT_GREEN_LED, HIGH);  // right green on
  }
  delay(1000);
  ESP.deepSleep(0);
  delay(500);
}

void loop() {}

サンプル

押したボタンに応じたメッセージをSlackにポストするサンプル


#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

// Wi-Fi接続パラメータ
const char* ssid = "********";
const char* password = "********";

// SlackのIncoming WebHooksにて取得したURLをココに記述します。
const char* uri =
    "https://hooks.slack.com/services/#######/#######";
// ブラウザでHTTPSサイト(上記URL)のサーバ証明書を表示して
// SHA1 fingerprint(指紋)をここに貼り付けること。
const char* fingerprint =
    "C1 0D 53 49 D2 3E E5 2B A2 61 D5 9E 6F 99 0D 3D FD 8B B2 B3";

// IOピン宣言
#define LEFT_BTN 14
#define RIGHT_BTN 12
#define ACTIVE 16
#define RBOOTED 13
#define LBOOTED 5
#define LEFT_RED_LED 15
#define RIGHT_RED_LED 4
#define LEFT_GREEN_LED 2
#define RIGHT_GREEN_LED 0

bool lBooted;
bool rBooted;
int batteryLevel;
HTTPClient http;
ESP8266WiFiMulti wifiMulti;
DynamicJsonBuffer jsonBuffer;

// 定形初期化処理(理解するまでは変更しないで)
void boot() {
  Serial.begin(74800);
  // pin setup
  pinMode(LBOOTED, INPUT_PULLUP);
  pinMode(RBOOTED, INPUT_PULLUP);
  pinMode(LEFT_RED_LED, OUTPUT);
  pinMode(RIGHT_RED_LED, OUTPUT);
  pinMode(LEFT_BTN, INPUT);
  pinMode(RIGHT_BTN, INPUT);

  // スリープから復帰するのに押されてたボタン状態を取得
  lBooted = digitalRead(LBOOTED) == LOW;
  rBooted = digitalRead(RBOOTED) == LOW;

  // アクティブモードへ移行
  digitalWrite(ACTIVE, LOW);
  pinMode(ACTIVE, OUTPUT);

  // ACTIVE==LOWのあとでしか緑LEDを使えない
  pinMode(LEFT_GREEN_LED, OUTPUT);
  pinMode(RIGHT_GREEN_LED, OUTPUT);

  // バッテリーレベル取得(アクティブモードでないとダメ)
  batteryLevel = analogRead(A0) * 3000 / 1024;  // [mV]

  // 電池が消耗していたり、通電のみだった場合はすぐにスリープする
  if (batteryLevel < 2300 || !lBooted && !rBooted) {
    ESP.deepSleep(0);
    delay(500);
  }
}

void setup() {
  boot();  // 必ずsetup関数の最初に実行

  if (lBooted) {
    digitalWrite(LEFT_GREEN_LED, HIGH);  // left green on
  }
  if (rBooted) {
    digitalWrite(RIGHT_GREEN_LED, HIGH);  // right green on
  }

  Serial.println();
  Serial.println("left: " + String(lBooted) + " right: " + String(rBooted));

  // Wi-Fi connect
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(ssid, password);
}

void loop() {
  if (wifiMulti.run() != WL_CONNECTED) {
    delay(500);
    return;
  }
  String message;
  if (lBooted && !rBooted) {
    message = "左を押した";
  } else if (!lBooted && rBooted) {
    message = "右を押した";
  } else if (lBooted && rBooted) {
    message = "両方を押した";
  }
  if (message.length() == 0) {
    return;
  }

  // TLS通信においてルート証明書チェインの検証機能をESPは持っていない。
  // サーバー証明書のsha-1指紋(fingerprint)が合致するか簡易の検証を行う。
  // なのでsha-1指紋を予めコードに埋めておく必要がある。
  Serial.println(uri);
  JsonObject& json = jsonBuffer.createObject();
  json["username"] = String("button[") + String(ESP.getChipId()) + String("]");
  json["text"] = message;
  json["icon_emoji"] = ":ghost:";
  String buff;
  if (!json.printTo(buff)) {
    Serial.println("json encode failed");
    return;
  }
  http.begin(uri, fingerprint);
  int code = http.POST(buff);
  String content = http.getString();
  http.end();
  Serial.println(String(code));
  Serial.println(content);

  // parse json
  JsonObject& resp = jsonBuffer.parseObject(content);
  // タスクが終了したら必ずディープスリープすること。
  ESP.deepSleep(0);
  delay(500);
}

定形処理内容の解説

  • ディープスリープからのウェイクアップはリセットブートのことです。
  • lBootedとrBootedはウェイクアップ要因が左ボタンか右ボタンかを示すフラグです。
  • ブートしたら上記フラグを読みだしたあと必ずACTIVEにLOWを出力すること(回路の仕様です)。
  • 両方押された場合は双方trueになります。
  • 双方falseの場合はなにもタスクを実行することなくスリープするのが推奨です。
  • バッテリー電圧チェックはACTIVE==LOWである必要があります。
  • 緑LEDを灯すためにはACTIVE==LOWである必要があります。

その他の注意点

  • HTTPSクライアントはTLSバージョン1.1相当です。一部のサイトでTLS1.2以降でないと接続拒否される事があります。
  • ESP8266-SDKの2.4.0ではTLS1.2が実装済みですが、まだ安定版がリリースされていないので注意が必要です。
  • HTTPS通信ではメモリを大量に使うので送受信に数百キロバイトのコンテンツを扱おうとすると暴走する場合があります。
一覧に戻る