isakon が 2019年10月18日18時02分57秒 に編集
初版
タイトルの変更
圧力センサーで圧力を検知してESP-WROOM-02でSlackに投稿する
タグの変更
ESP-WROOM-02
ESP8266
Wi-Fi
本文の変更
elchika運営です! 今回はESP8266と圧力センサーを使って、センサーに圧力が加わっているかどうかを監視し、結果をSlackのメッセージとして投稿するものを作っていこうと思います。 ## 使用したもの - [ESPr® One(Arduino Uno同一形状 ESP-WROOM-02開発ボード)](https://www.switch-science.com/catalog/2620/) - [圧力センサーFSR402](http://akizukidenshi.com/catalog/g/gP-04002/) - [カーボン抵抗 1/4W 10kΩ](http://akizukidenshi.com/catalog/g/gR-25103/) - [Arduino用アクリルベースセット(透明青)](http://akizukidenshi.com/catalog/g/gP-10710/) - [丸ピンIC用ソケット 1×2](http://akizukidenshi.com/catalog/g/gP-00673/) - 熱収縮チューブ - ジャンパー線 Arduino IDEはv1.8.9を使用しています。 ESP8266の後継品としてBluetoothを内蔵しているESP32があるので、そちらを買ったほうが色々なことができます。 ## ESP-WROOM-02にArduino IDEのスケッチを書き込めるように設定する ### 環境設定 ESP-WROOM-02はArduinoマイコンとしても使えるWi-Fiモジュールです。 モジュール自体は400円ほどで買えますが、ブレッドボードなどで扱いやすい2.54mmにピッチ変換されたものも流通しています。 今回はあらかじめArduinoと同一形状の基盤にESP-WROOM-02が搭載されている、スイッチサイエンス様のESPr® Oneを使ってみました。 給電やUSB接続ができるようになっているので、Arduino系のマイコンボードのように使える優れものです。 ただし、動作電圧が $3.3V$ なことには気をつけましょう。 ボードを購入したスイッチサイエンス様で「[ESP-WROOM-02開発ボードをArduino IDEで開発する方法](http://trac.switch-science.com/wiki/esp_dev_arduino_ide)」が公開されているので、参考にしながら設定していきます。 Arduino IDEを起動し、上部のツールバーから「ファイル → 環境設定」を選択します。 環境設定のウインドウが開くので、下部にある「追加のボードマネージャのURL」に`https://arduino.esp8266.com/stable/package_esp8266com_index.json`を追加してOKボタンを押します。  これでボードマネージャにesp8266が出現するようになりました。 ツールバーから「ツール → ボード → ボードマネージャ」を選択します。 ボードマネージャのウインドウが開くので「esp8266」で検索し、出てきたパッケージをインストールします。  その後、ツールバーの「ツール → ボード → Generic ESP8266 Module」を選択し、下図のように設定を行いました。  これでESP-WROOM-02に対してArduino IDEでスケッチを書き込めるようになりました:clap: ### 動作確認 早速動かしてみましょう!試しにESPr® OneのビルトインのLEDをチカチカさせてみます。 ピッチ変換済みモジュールなどを使っている場合は、LEDと抵抗を回路に組み込んでよしなにしてください。 今回は以下のスケッチを書き込みました。 ```arduino:Lチカ #define LED_PIN 14; void setup() { pinMode(LED_PIN, OUTPUT); } void loop() { digitalWrite(LED_PIN, HIGH); delay(1000); digitalWrite(LED_PIN, LOW); delay(1000); } ``` LED1の部分が点滅していればスケッチが書き込めています:bulb:  ## 圧力センサーを使う ### 回路を組む 今回はFSR402という圧力センサーを使います。 圧力センサーは普段は $1 M\Omega$ 程度の抵抗値がありますが、センサー部に指などで圧力をかけると抵抗値が下がっていきます。 購入時に付属してくるデータシートによれば、 $1kg$ の圧力を加えると $1 k\Omega$ 程度の抵抗値になるようです。 圧力センサーですが、このままだとブレッドボードに直接挿したりして使うしかなく、少し扱いづらいです。 そこで、少し取り回しを良くするために丸ピンICソケットとジャンパー線をはんだ付けして、熱圧縮チューブで絶縁したものに圧力センサーを挿して使っています。 以下のような回路を組みました。   圧力センサーは $V_{cc}$ に繋ぎ、もう片方は $10 k\Omega$ の抵抗を使ってプルダウンしています。 アナログ入力がA0のみなので、A0ピンと電圧を読み取りたい部分をジャンパー線で繋いでいます。 (ESPr® Oneの場合、入力範囲は $0$ ~ $3.3V$ で、基板上で $0$ ~ $1.0V$ に変換してくれます) オームの法則により電圧降下は抵抗値に比例するので、A0の電圧を $V_{out}$ とすると、 $$ V_{cc} : V_{out} = (R_x + R) : R $$ $$ V_{out} = \frac{ R }{ R_ x + R } V_{cc} $$ $R_x$ が非常に大きい(圧力を加えていないとき)と $V_{out} \fallingdotseq 0$ となり、非常に小さい(十分な圧力を加えているとき)と $V_{out} \fallingdotseq V_{cc}$ と見なせます。 圧力を加えると電流が流れるスイッチのようなイメージです。 ### 動作確認 Arduino IDEのツールバーの[ツール] → [シリアルモニタ]を選択してシリアルモニタを開き、右下の転送速度を115200bpsに合わせます。 その後、次のスケッチを書き込みます。 ```arduino:アナログピンを読み取る void setup() { // ESP8266の転送速度である115200bpsに設定する Serial.begin(115200); } void loop() { int value = analogRead(A0); Serial.println(value); delay(1000); } ``` 圧力センサーを指でつまんだり離したりすると、シリアルモニタに0 ~ 1024(ESP8266だと1023ではないようです)の値が表示されます。  ## Slackにメッセージを送信する センサーと連動してSlackなどのサービスに通知したくなることがあると思います。 ESP8266やESP32などのWi-Fiモジュールを組み込むと、モノの状態をセンサーなどで調べつつ、インターネット経由で状態を送信して知ることができるようになります。 まずはセンサーの回路とつながずに、Slackの特定のチャンネルに通知する方法から考えていきます。 ### Wi-Fiルーターに接続する ESP8266はライブラリを使えば数行を書くだけで簡単にWi-Fiルーターに接続できます。 [ESP8266WiFi library](https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html#)を読みながら接続の設定をします。 ```arduino:ESP8266でWi-Fiルーターに接続する #include <ESP8266WiFi.h> // 各自設定する static const String WIFI_SSID = "ssid"; static const String WIFI_PASSWORD = "password"; void setupWifi() { WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // 接続に数秒かかるので接続されるまでループする while (WiFi.status() != WL_CONNECTED) { delay(500); } // DHCPによって割り当てられたIPアドレスを出力する Serial.println(WiFi.localIP()); } void setup() { Serial.begin(115200); setupWifi(); } void loop() { // noop } ``` シニアルモニタにIPアドレスが表示されれば接続成功です。 ### SlackのIncoming Webhookの設定 https://slack.com/services/new/incoming-webhook にアクセスします。 投稿したいチャンネルを選択して「Incoming Webhook インテグレーションの追加」を押します。  遷移先のページにWebhook URLが書いてあるのでこれを後ほど使います。 このURLを知られると他人でもメッセージを送れてしまうので、管理には気をつけましょう。  また、このページの下部でSlackで表示される名前やアイコンをカスタマイズできます。 ### メッセージを送信するスケッチを書き込む 先ほど表示されたWebhook URLに対して、POSTリクエストで文字列のJSONを送信すると、指定したチャンネルに投稿されます。 単純なメッセージを送信するだけなら`payload={"text": "送信したいメッセージ"}`の文字列を送信すれば投稿できます。 投稿ごとにユーザー名を変えたければ`username`を、アイコンを変えたければ`icon_emoji`を送信するJSONに含めれば変えられます。 ```arduino:IncomingWebhookでSlackにメッセージを送信する #include <ESP8266WiFi.h> #include <WiFiClientSecure.h> #include <WiFiUdp.h> static const String WIFI_SSID = "ssid"; static const String WIFI_PASSWORD = "password"; static const String SLACK_HOST = "hooks.slack.com"; static const String SLACK_URL = "webhook url"; static const int PORT = 443; // https通信に使うSlackの2021/02/12まで有効な証明書の拇印 // Chromeのアドレスバーの鍵マーク → 証明書 → 詳細タブ → 拇印の行 の値をコピーする static const char* FINGERPRINT = "c10d5349d23ee52ba261d59e6f990d3dfd8bb2b3"; void setupWifi() { WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); } Serial.println(WiFi.localIP()); } void submitSlack() { WiFiClientSecure client; client.setFingerprint(FINGERPRINT); if (!client.connect(SLACK_HOST, PORT)) { Serial.println("Slackとの接続に失敗しました"); } String message = "ESP8266からの送信テスト"; String payload = "payload={\"text\": \"" + message + "\"}"; Serial.println(payload.c_str()); String request = "POST " + SLACK_URL + " HTTP/1.1\n" + "Host: " + SLACK_HOST + "\n" + "User-Agent: ESP8266\n" + "Connection: close\n" + "Content-Type: application/x-www-form-urlencoded\n" + "Content-Length: " + payload.length() + "\n\n" + payload; client.println(request); delay(7000); while (client.available()) { // 終端文字まで文字列を読む(終端文字は破棄される) String line = client.readStringUntil('\r'); Serial.print(line); } Serial.println(""); client.stop(); } void setup() { Serial.begin(115200); setupWifi(); submitSlack(); } void loop() { // noop } ``` スケッチを書き込んでしばらくすると、Slackの指定したチャンネルにメッセージが投稿されます。  ## 圧力検知とSlackへの投稿を組み合わせる Wi-Fiルーターがあって給電さえできれば圧力を検知した結果をSlackに送信できるようにします。 圧力センサーを使ったスケッチとSlackにメッセージを送信するスケッチを組み合わせます。 ```arduino:圧力センサーに圧力がかかったときにSlackにメッセージを送信する // 同様の実装なので省略(以下...で既存のコードと同じなので省略の意味) static const int THRESHOLD = 512; boolean isEnabled = false; // ... void submitSlack() { // ... String message = isEnabled ? ":nauseated_face:" : ":face_vomiting:"; // ... } void setup() { Serial.begin(115200); setupWifi(); } void loop() { int value = analogRead(A0); boolean isPressing = value >= THRESHOLD; if (isEnabled != isPressing) { isEnabled = isPressing; submitSlack(); } delay(1000); } ``` これで圧力センサーに一定以上の圧力を加えているときと、圧力を加えるのをやめたときにSlackにメッセージが投稿されます:tada: 