2. 開発編 - msyk9038/esp32_hello_world GitHub Wiki
外気温が0℃を下回ったら、LINEで通知。 現在の外気温もWEBブラウザで確認できるようにする。
外気温を測る上で、温度センサーを使う。温度センサーにはデジタルとアナログがあり、デジタルの方は測定温度値を通信を通して伝達してくれる。アナログの方は温度に応じた電圧値を返してくるので、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円前後と非常に手軽である。
センサーを使うにあたって、センサーとESP32のピン配置(どのピンがどんな役割をしていて、どこに繋げれば良いか)を確認する。
LM35DZ データシートを見てみよう。
まず、購入元のAmazonでもピン配置の図が載っているが、残念ながら実物と合致しない。
Amazonの評価欄の情報を頼りにDOIT ESP32 DEVKIT V1 pinout
で検索。
pinout とはピン配置のことで、検索するときは、「DOIT ESP32 DEVKIT V1 ピン配置」よりも、「DOIT ESP32 DEVKIT V1 pinout」の方がより多くの検索結果を得られる。
出所: 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つ である。
以上より、今回は以下のように配線する。
接続が出来たら、次にスケッチを作成する。
少し分かりづらい部分があるので解説。
まずこの部分→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
同じアナログ温度センサのMCP9700A-Eであるが、MCP9700A-E データシートを確認すると、
- ピン配置はLM35と変わらない。
- 測定可能温度範囲は -40 〜 125℃ と氷点下まで測定できるようになっている
- 0℃のときの出力電圧が 500mV
ということが分かる。
なので、スケッチは一箇所、before:float temp = voltage / 10;
を after:float temp = (voltage - 500) / 10;
に変えるだけで良い。
変更したら、「名前を付けて保存」を押して、先程のLM35のスケッチとは別に保存しよう。
シリアルモニタで数値を確認すると、先程のLM35よりも精度が悪いせいか、数値がなかなか安定しないことが分かる。
そこで直近10回のデータの平均を取り、データの変動を小さくする移動平均法を使う。
それを実装したスケッチがこちら。
44行目のtemp = moving_average(temp);
の部分をコメントアウト(行頭に//
を付ける)することで、移動平均法を解除することができる。
このスケッチを書き込むと、シリアルプロッタ(シリアルモニタの下のメニューにある)というグラフで温度の変化を確認できるようになる。
fig. 移動平均法を使わない場合
fig. 移動平均法を使った場合
移動平均法を使う場合と使わない場合で、グラフのギザギザがどうなったのか確認してほしい。
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 文字列ポインタの扱いについてはこちらが詳しいので参考のこと。
credential.h
を作成できたら、このスケッチを書き込んでください。
うまく接続できると、下記のようにIPアドレスが表示されます。