知的好奇心 for IoT

IoT関連の知的好奇心を探求するブログです

ESP32とESP8266でディープスリープを使って1時間毎にDHT20のデータをクラウドに送る持続テストのハードウェアとプログラム

今回は、前回の記事のハードウェアとプログラムについて書きたいと思います。

 

使ったもの(ハードウェア)

ESP32(M5Stamp Pico)+DHT20

ESP8266(ESP-WROOM-02)+DHT20

 

回路図&実装図

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     "ここをWiFiSSIDで置き換える"
#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 "に接続");  // ログにWiFiSSIDを表示
  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の接続に失敗した場合は再起動するようにしています。