2. 開発編 - msyk9038/esp32_hello_world GitHub Wiki

3. 実現したいシステム

外気温が0℃を下回ったら、LINEで通知。 現在の外気温もWEBブラウザで確認できるようにする。

4. 必要なコンポーネント

4-1. 外気温を測る

外気温を測る上で、温度センサーを使う。温度センサーにはデジタルとアナログがあり、デジタルの方は測定温度値を通信を通して伝達してくれる。アナログの方は温度に応じた電圧値を返してくるので、ESP32の方で温度値に変換しないといけない。

比較は以下。

LM35 MCP9700A-E ADT7410 BME280
電源電圧 4 ~ 30 V 2.3 ~ 5.5V 2.7 〜 5.5V 1.71 〜 3.6V
出力タイプ アナログ アナログ デジタル デジタル
測定温度範囲 0 〜 +100℃ -40 〜 +125℃ -55 〜 +150℃ -40 〜 +85℃
精度 ±0.75℃(室温では±0.25℃) ±2℃/0〜70℃, ±4℃/-40〜125℃ ±0.5℃@-40℃~+105℃(2.7V~3.6V) ±1℃
備考 湿度も測れる
価格 190円 100円 600円 1,380円
購入先 スイッチサイエンス 秋月電子 秋月電子 秋月電子

この表から言えることは、

  • アナログセンサーの比較で言えば、LM35は 測定温度範囲が 0 ~ 100℃ であり、氷点下を計測できない。
    MCP9700A-Eは -40 ~ 125℃と氷点下もカバーしている。

  • BME280 は一番高いが、湿度も測れる。

  • コストで見ると、デジタルが 600 〜 1380円なのに対し、アナログは100 ~ 190円前後と非常に手軽である。

a. LM35 温度センサ

センサーを使うにあたって、センサーとESP32のピン配置(どのピンがどんな役割をしていて、どこに繋げれば良いか)を確認する。

1. センサーのピン配置

LM35DZ データシートを見てみよう。

image
2. ESP32 のピン配置

まず、購入元のAmazonでもピン配置の図が載っているが、残念ながら実物と合致しない。
image

Amazonの評価欄の情報を頼りにDOIT ESP32 DEVKIT V1 pinoutで検索。
pinout とはピン配置のことで、検索するときは、「DOIT ESP32 DEVKIT V1 ピン配置」よりも、「DOIT ESP32 DEVKIT V1 pinout」の方がより多くの検索結果を得られる。
image

image
出所: www.mischianti.org


アナログを読み取れるADCポート(ADCで始まるピンの数を数えてみよう)は全部で15個あることが分かる。
ここで ADC1 と ADC2 で何か違いがあるのか、が気になったので、調べてみた。
randomnerdtutorials.comによれば、ADC2 pins cannot be used when Wi-Fi is used.となっており、「WiFiを使うときはADC2は使えないよ」と書いてある。
加えて、知識ゼロから始めるIoTアプリ開発入門によれば、VN, VPピンも既に使用されていて使えないらしい。
結論、 ADCとして、使えるGPIOは 34, 35, 32, 33 の4つ である。

3. センサーとESP32を接続する

以上より、今回は以下のように配線する。
image

4. プログラムの作成

接続が出来たら、次にスケッチを作成する。

少し分かりづらい部分があるので解説。
image

まずこの部分→int reading = analogRead(analogPin)
ESP32のADC(アナログ値を読み取る部分)は、0〜3.3V までの入力を受け付ける。
analogRead() で読み取ると、0〜3.3V を 0〜4095 に変換した数字が得られる。
つまり、3.3V を入力すると 4095 が得られ、1.0V を入力すると 1241 (=4095/3.3) という数字が得られる。
reading という変数には、入力した電圧に応じて、0〜4095 の数字が入っている、ということなんだ。

でも、このままでは、温度表示に使えない(1000とか言われても「え?何℃なの?」ってなるよね)ので、このreadingの中の数字を温度に変換してあげる必要がある。
例えば、1000 と言われたら、何℃なのか。まず、入力されている電圧を計算する
1000 / 4095 * 3.3(V) = 0.81 (V)

次にこれを温度に変換するのだが、LM35のデータシートを見ると、0℃で 0 mV, 1℃上がる毎に 10mV 電圧が上がる事がわかっている。
0.81 V は 810 mV なので、
810(mV) / 10(mV/℃) = 81(℃)
つまり、analogRead()した結果(変数readingの中身)が1000であれば、それは81℃である。
以上の計算を行っているのが、

  float voltage = ((long)reading * Vcc * 1000) / ANALOG_MAX;
  float temp = voltage / 10; // +10mV/degree_Celsius

である。

※参考までに、「なぜ 0〜4095 の 4096個の数字(という中途半端な数字)で表されるのか」というと、 ESP32のADCの分解能が 12bit だからである。

  • 1bit で表現できる数字は 0 or 1 の2つ。
  • 2bit で表現できる数字は 00, 01, 10, 11 の4つ。
  • 3bit で表現できる数字は 000, 001, 010, 011, 100, 101, 110, 111 の8つ。
  • では12bit では? 2を12回掛けてみよう。2x2x2x2x2x2x2x2x2x2x2x2 = 4096 

b. MCP9700A-E 温度センサ

同じアナログ温度センサのMCP9700A-Eであるが、MCP9700A-E データシートを確認すると、

  • ピン配置はLM35と変わらない。
  • 測定可能温度範囲は -40 〜 125℃ と氷点下まで測定できるようになっている
  • 0℃のときの出力電圧が 500mV ということが分かる。
    なので、スケッチは一箇所、before: float temp = voltage / 10; を after: float temp = (voltage - 500) / 10; に変えるだけで良い。
    変更したら、「名前を付けて保存」を押して、先程のLM35のスケッチとは別に保存しよう。

シリアルモニタで数値を確認すると、先程のLM35よりも精度が悪いせいか、数値がなかなか安定しないことが分かる。
image

そこで直近10回のデータの平均を取り、データの変動を小さくする移動平均法を使う。

それを実装したスケッチがこちら

44行目のtemp = moving_average(temp); の部分をコメントアウト(行頭に//を付ける)することで、移動平均法を解除することができる。
このスケッチを書き込むと、シリアルプロッタ(シリアルモニタの下のメニューにある)というグラフで温度の変化を確認できるようになる。

image
fig. 移動平均法を使わない場合

image
fig. 移動平均法を使った場合


移動平均法を使う場合と使わない場合で、グラフのギザギザがどうなったのか確認してほしい。

4-2. WiFiで通信する

1. クレデンシャルファイルを作る

WiFiの通信に使用するSSIDやパスワードは直接スケッチに書いておくと、スケッチを公開する度に隠蔽しなくてはならず、非常に煩わしい。
なので、クレデンシャルファイルというファイルを作成し、スケッチがそれを読み込む形にしておく。
まず、ArduinoIDEをインストールしたディレクトリ(※1)にlibraries/_privateフォルダを作成する。
その中に、credential.hというファイルを作成し、

#ifndef CREDENTIAL_H
#define CREDENTIAL_H
const char *WiFi_SSID = "your SSID";
const char *WiFi_PASSWORD = "your PASSWORD";
#endif

のように記述する。
なお、#ifndef CREDENTIAL_Hは「もしCREDENTIAL_Hが定義されていなかったら」という意味で、ライブラリを2重で読み込まないようにする処理。
続く const char *WiFi_SSID = "your SSID"; では文字列ポインタ(※2)が使われており、Serial.print(WiFi_SSID);で中身の参照ができる。

credential.h の編集が終わったら、スケッチの冒頭に #include <credential.h>と記述する。
こうすることで、対象のスケッチでWiFiのSSIDやパスワード等の秘匿情報を安全に取り扱うことができる。

※1 MacOSだと、~/Documents/Arduino/, Windowsだと、C:\Users\username\Documents\Arduino\
※2 文字列ポインタの扱いについてはこちらが詳しいので参考のこと。

2. WiFiに接続してみる。

credential.h を作成できたら、このスケッチを書き込んでください。
うまく接続できると、下記のようにIPアドレスが表示されます。
image

4-3. LINEで通知する

4-4. WEBブラウザを稼働させる

5. 実装

⚠️ **GitHub.com Fallback** ⚠️