今回は、前回の記事のハードウェアとプログラムについて書きたいと思います。
使ったもの(ハードウェア)
ESP32(M5Stamp Pico)+DHT20
- M5Stamp Pico Mate
- 温湿度センサモジュール DHT20
- XCL103使用3.3V出力昇圧DCDCコンバーターキット
- ミニブレッドボード BB-601
- ブレッドボード・ジャンパーワイヤ 14種類×10本
- 電池ボックス 単3×2本 Bスナップ・背中合わせ
- ジャンパーワイヤ付バッテリースナップ(縦型)
- EBL 単3 充電池充電器セット 8スロット充電器+単三電池(2800mAh*8)セット
ESP8266(ESP-WROOM-02)+DHT20
- Wi-Fiモジュール ESP-WROOM-02 DIP化キット
- 温湿度センサモジュール DHT20
- カーボン抵抗(炭素皮膜抵抗) 1/4W10kΩ(100本入)
- ミニブレッドボード BB-601
- ブレッドボード・ジャンパーワイヤ 14種類×10本
- 電池ボックス 単3×2本 Bスナップ・背中合わせ
- ジャンパーワイヤ付バッテリースナップ(縦型)
- EBL 単3 充電池充電器セット 8スロット充電器+単三電池(2800mAh*8)セット
回路図&実装図
ESP32(M5Stamp Pico)+DHT20
ポイント
- ディープスリープ時はDTH20の電源を遮断するために、GOIO25をDHT20の電源としています。(プログラムでGPIO25をHIGHにして電源に利用しています。)
- Batteryの入力をGPIO36につなぐことで、GPIO36のADCを利用してBatteryの電圧を取得しています。
ESP8266(ESP-WROOM-02)+DHT20
ポイント
- ディープスリープ時はDHT20の電源を遮断するために、GPIO4をDHT20の電源としています。(プログラムでGPIO4をHIGHにして電源に利用しています。)
- ディープスリープからの復帰時にプログラムを動作させるため、GPIO16とRSTをつないでいます。
- 10kΩ抵抗2つはESP-WROOM-02のデータシートに従ってプルアップ/プルダウン用に付けていますが、コンデンサーは省略しています。
使ったもの(ソフトウェア)
ESP32(M5Stamp Pico)+DHT20
ESP8266(ESP-WROOM-02)+DHT20
使ったもの(IoTプラットフォーム)
Ubidotsには教育目的や個人向けに無料のSTEM契約が用意されていて、今回はそれを利用しています。
事前に送信するデータの設定する必要がないところはIIJのMachinistに似ていますが、Ubidotsの方がMachinistのエージェントに相当するデバイスも事前に設定しておく必要がないのでより柔軟です。
更に、データの送信方法もHTTP、MQTT、ソケット通信と3種類も用意されてAPIも豊富です。
ダッシュボードで表示できるウィジットの種類も豊富で、かなり高機能なサービスとい印象です。
唯一の難点はSTEMの制約が細かくて厳しいことぐらいでしょうか?
プログラム
Ubidots.ino
#define M5STAMP // M5Stamp Picoの時はコメントを外す //#define ESPWROOM02 // ESP-WROOM-02の時はコメントを外す // WiFiの資格情報 (2.4GHzのみ) #define WIFI_SSID "ここをWiFiのSSIDで置き換える" #define WIFI_PASS "ここをWiFiのパスワードで置き換える" // Ubidotsの資格情報 #define UBIDOTS_TOKEN "ここをUbidotsのTokenで置き換える" #define MESURE_PERIOD 60 // 計測間隔(分単位) #include <DFRobot_DHT20.h> // DHT20用のライブラリ // M5Stamp Pico用の定義 #ifdef M5STAMP #define PIN_ADC 36 // ADCのGPIO #define PIN_PWR 25 // DHT20の電源に使うピン番号 #define PIN_SDA 21 // I2CのSDAに使うピン番号 #define PIN_SCL 22 // I2CのSCLに使うピン番号 #define DEVICENAME "M5STAMP" // Ubidots用のデバイス名 #endif // ESP-WROOM-02用の定義 #ifdef ESPWROOM02 #define PIN_PWR 4 // DHT20の電源に使うピン番号 #define PIN_SDA 12 // I2CのSDAに使うピン番号 #define PIN_SCL 13 // I2CのSCLに使うピン番号 #define DEVICENAME "WROOM02" // Ubidots用のデバイス名 #endif #ifdef M5STAMP #include <WiFiClientSecure.h> // TLS WiFiライブラリ WiFiClientSecure client; // TLS接続用オブジェクト #else #include <ESP8266WiFi.h> BearSSL::WiFiClientSecure client; // TLS接続用オブジェクト ADC_MODE(ADC_VCC); // 電源電圧を測る設定 #endif DFRobot_DHT20 dht20; // DHT20用オブジェクト float temperature = -50; // 温度の変数(値はダミー) float humidity = -50; // 湿度の変数(値はダミー) int voltage; // 電圧の変数 // WiFi接続 void initWiFi() { Serial.print(WIFI_SSID "に接続"); // ログにWiFiのSSIDを表示 WiFi.begin(WIFI_SSID, WIFI_PASS); // WiFiに接続 int i = 1; while (WiFi.status() != WL_CONNECTED) { // WiFiが繋がるまでループ if (i > 10) { // 10秒でタイムアウト Serial.println("\n=== タイムアウトしました。再起動します。 ==="); ESP.restart(); // 再起動 } delay(1000); // 1秒待つ Serial.print("."); // ログに「.」を表示 i++; } Serial.println("完了"); // ログに「完了」を表示 } // 計測 void measurement() { // 温度と湿度の計測 pinMode(PIN_PWR, OUTPUT); // DHT20の電源ピンを出力に設定 digitalWrite(PIN_PWR, HIGH); // 電源を入れる Wire.begin(PIN_SDA, PIN_SCL); // I2Cの初期化 dht20.begin(); // DHT20の初期化 while (temperature < -40 || temperature > 80 || humidity < 0) { temperature = dht20.getTemperature(); // 温度取得 humidity = dht20.getHumidity() * 100; // 湿度取得 delay(10); } // 電圧の計測 #ifdef M5STAMP voltage = analogReadMilliVolts(PIN_ADC); #else voltage = ESP.getVcc(); #endif Serial.printf("\n温度:%.2f 湿度:%.2f 電圧:%d\n", temperature, humidity, voltage); } // データ送信(Ubidots用) void sendData() { // メッセージ作成(JSON) String msg = "{"; msg += String("\"temperature\": ") + String(temperature).c_str() + ","; msg += String("\"humidity\": ") + String(humidity).c_str() + ","; msg += String("\"voltage\": ") + String(voltage).c_str() + "}"; //Serial.println(msg); // ログにメッセージを表示 // コマンド作成 String cmd = "POST /api/v1.6/devices/" DEVICENAME "/ HTTP/1.1\r\n"; cmd += "Host: industrial.api.ubidots.com\r\n"; cmd += String("X-Auth-Token: ") + UBIDOTS_TOKEN + "\r\n"; cmd += "Content-Type: application/json\r\n"; cmd += String("Content-Length: ") + String(msg).length() + "\r\n\r\n"; //Serial.println(cmd); // ログにコマンドを表示 // POSTリクエスト送信 Serial.print("Ubidotsに接続..."); client.setTimeout(10000); // 10秒でコネクションタイムアウト client.setInsecure(); // 証明書の検証を行わないTLS接続を利用する if (client.connect("industrial.api.ubidots.com", 443)) { // サーバーに接続 Serial.println("成功\nメッセージを送信"); client.print(cmd); // コマンドを送信 client.print(msg); // メッセージを送信 while (!client.available()) { // サーバーからのレスポンスを待つ delay(10); } Serial.println(client.readStringUntil('\n')); // レスポンスを表示 client.stop(); // セキュアコネクション接続終了 } else { Serial.println("失敗\n=== 再起動します ==="); WiFi.disconnect(true); // WiFi切断 ESP.restart(); // 再起動 } } void setup() { #ifdef M5STAMP Serial.begin(115200); // シリアルモニタの通信速度 #else Serial.begin(74880); // シリアルモニタの通信速度 #endif delay(10); measurement(); // 計測 initWiFi(); // WiFiに接続 sendData(); // データ送信 Serial.printf("%d分寝ます。\n", MESURE_PERIOD); WiFi.disconnect(true); // WiFiの切断 ESP.deepSleep(MESURE_PERIOD * 60 * 1000 * 1000UL); // Deep Sleepを実行(マイクロ秒) } void loop() { }
ポイント
- 条件コンパイルでM5Stamp PicoとESP-WROOM-02の両方に対応しています。
- Ubidotsでアカウントを作り、「API Credentials」に記載されているTokenをプログラムに埋め込むとデータを登録できます。
- ESP.deepSleep()の引数はマイクロ秒で指定しますが、ESP8266では64bit、ESP32では32bitで定義されています。そのため、ESP8266では約36分(0x7FFFFFFF秒)以上の値を指定するときには、定数に接尾辞のUL(Unsigned Long)を付けてあげる必要があります。
- WiFiやUbidotsの接続に失敗した場合は再起動するようにしています。