ESP32でIoT機器を作成してみた（温度ロガー）

# はじめに
ESP32とは、Wi-FiとBluetoothを内蔵する低コスト、低消費電力なマイコンです。
お値段は、だいたい1,000円～2,000円くらいでしょうか。
このESP32に自由にモジュールを配線しプログラミングすることで、お手軽にIoTを開発することが可能です。

ということで、今回はマイコンの定番である**温度ロガー**を作成してみました。
ESP32に温湿度センサーを取り付け、計測した温湿度をWi-Fi経由で定期的にクラウド上のDBに登録します。

# 準備するもの
## ESP32-DevKitC WROOM-32E（Espressif Systems）
マイコン本体です。
ネットで簡単に買えます。
秋月電子通商さんのネット通販サイトから購入しました。
1,600円くらいでした。

![ESP32-DevKitC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/4f32a198-db30-0b66-8c20-48cca3548c6a.png)

## DHT11（Aosong Guangzhou Electronics Co., Ltd.）
温湿度センサーモジュールです。
秋月電子通商さんのネット通販サイトから購入しました。
500円くらいでした。
![DHT11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/a40eb41a-a094-f997-70f4-20481ec71d69.png)

## ブレッドボード（サンハヤト SAD-101）
ESP32と各種モジュールを直接ハンダで配線することも可能だと思いますが、ブレッドボードであればピンを刺すだけで配線できるため、ブレッドボードがあると便利でしょう。
Amazonで500円くらいでした。
**※！！注意！！※<br>　よく知らずにEIC-801のブレッドボードを買ったら、ESP32-DevKitCが大きすぎて配線できませんでした。<br>　SAD-101なら無事配線できたので、こちらをおすすめします。**

![ブレッドボード SAD-101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/f064dc87-9bf3-f963-cd66-b455840241e9.png)

## ジャンパーワイヤ（オス－オス）セット 10cmセット
ブレッドボード上で電気回路間をつなぐ電線です。
秋月電子通商さんのネット通販サイトから購入しました。
180円くらいでした。

![ジャンパーワイヤ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/c4b38fe5-d9bf-23eb-0f49-4d65774fcb02.png)

## USBケーブル 2.0 A-microB
ESP32の電源用と、ESP32とPCを繋いで開発を行います。
充電専用のケーブルではデータ通信できないので、データ通信に対応したケーブルを購入しましょう。
Amazonで250円くらいでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/38cd4f8a-ec83-0d03-08e0-5c98674e51c9.png)


# 開発環境

### Arduino（Windows）
Arduino IDEを使用してESP32の開発を行います。
環境構築は下記サイトを参考に行いました。
https://interface.cqpub.co.jp/esp32-arduino-ide-2/

### データベース
Azure SQL Databaseを使用。
下記のテーブル「temperatures」を用意し、そこに測定した温度湿度を記録していきます。

| Column Name | Data Type | 備考 |
| ---         | ---       | ---  |
| id          | bigint    | ID   |
| chipid      | nvarchar(50) | ESP32デバイス識別用
| temperature | float | 気温 |
| humidity | float | 湿度 |
| create_at | datetime | 計測した日時 |

### データベース操作用API
Azure Functionsを使用。
REST APIで作成し、Json形式の温度、湿度のデータをPUTメソッドでアップロード。
なぜPUTかというと、頻繁にデータをアップして10分間の平均値としてデータを更新する仕様にしたためです。
また、GETメソッドで温度、湿度のデータを取得するAPIです。
メインテーマじゃないため詳細は割愛。

### 温度グラフ表示用サイト
React react-chartjs-2を使用。
上記APIから取得した温度湿度のデータをグラフ表示させます。
メインテーマじゃないため詳細は割愛。

# 配線
こんな感じで配線しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/78fdb71d-31ab-b652-fe4c-3637d08cc6c7.png)
- DHT11の1番ピンとESP32の3V3（電源）を接続。
- DHT11の2番ピンがデータI/O用のピンなので、ESP32の4番ピンと接続。
- DHT11の3番ピンはEmptyなので使用しない。
- DHT11の4番ピンとESP32のGNDを接続。
---
赤のワイヤーが電源。
黒のワイヤーがGND。
緑のワイヤーがデータI/O。

![20230703_021220000_iOS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/87a2de6b-227c-90c1-bb99-c26dfbe2010c.jpeg)

ESP32にUSBを接続すると、電源LEDが赤く光ります。
![photo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/8fcc427c-3543-ef4e-8f3d-2cec5d5fb2e1.jpeg)

# Arduino IDEで実装
ESP32をWi-Fiにつなぎ、DHT11から取得した温度湿度をHTTPでデータをPUTするプログラムです。

## Arduino IDEにDHT11ライブラリをインストール
Auduino IDEのライブラリマネージャにて、「DHT」と検索して、「DHT-sensor-library」をインストールします。
このライブラリを利用して、DHT11から計測数値を取得します。

## ソースコード
```diff_c 
#include "DHT.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include "ArduinoJson.h"

// APIのURL
#define API_URL "https://???.azurewebsites.net/api/tempratures"

#define DHTPIN 4        // DHT11の通信ピンを繋いだピン番号
#define DHTTYPE DHT11   // DHT 11

// DHTセンサーの初期化
DHT dht(DHTPIN, DHTTYPE);

// Wi-Fi接続情報を入力(IPアドレス自動取得)
const char* ssid = "****";
const char* password = "****";

uint64_t chipid;  // ESP32固有のチップID保管用

void setup() {
  // シリアル通信のデータレート設定
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  // センサー初期化
  dht.begin();

  // チップID取得
  chipid = ESP.getEfuseMac();
  Serial.println(F("getEfuseMac"));
  Serial.println(chipid);

  // Wi-FiのモードをSTAに設定
  WiFi.mode(WIFI_STA);
}

void loop() {
  // 10秒待つ
  delay(10000);

  // 温度の読み込みに250ミリ秒 ～ 2秒かかるらしい
  float h = dht.readHumidity();      // 湿度の取得
  float t = dht.readTemperature();   // 温度の取得

  // データチェック
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  Serial.println(F("read from DHT sensor!!"));

  // APIの仕様にあわせてJsonデータを作成
  StaticJsonDocument<200> doc;
  doc["chipid"] = chipid;
  doc["temprature"] = t;
  doc["humidity"] = h;

  String json;
  serializeJson(doc, json);

  // APIをコールしてJsonデータをアップロード
  HTTPClient http;
  if( !http.begin(API_URL) ) {
    Serial.println(F("Failed HTTPClient begin!"));
    return;
  }
  http.addHeader("Content-Type", "text/plain");

  // Wi-fiが切れやすいので、毎回接続を試みる
  int retry_count = 0;
  int httpResponseCode = -1;
  while(httpResponseCode < 0 && retry_count++ < 50) {
    wifi_connect(false);
    // データをPUTする
    httpResponseCode = http.PUT(json);
    if( httpResponseCode < 0 ) {
      Serial.println(F("PUT Failed"));
      Serial.println(httpResponseCode);
      wifi_connect(true);
    }
    delay(500);
  }
  Serial.println(httpResponseCode);
  Serial.println(WiFi.status());
}

void wifi_connect(bool reconnect) {
  if( !reconnect && WiFi.status() == WL_CONNECTED ) {
    Serial.println(F("wifi already connected"));
    return;
  }

  if( reconnect ) {
    WiFi.disconnect();
    delay(500);
    Serial.println(F("wifi reconnect"));
    WiFi.reconnect();
  }
  else {
    Serial.println(F("wifi connect"));
    WiFi.begin(ssid, password);
  }

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // 取得したローカルIPアドレスをシリアルに出力
  Serial.println(F(""));
  Serial.println(F("WiFi connected."));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());
}

```

# Arduino IDEからESP32に書き込み
IDEの左上のボタンから書き込みを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/3cb4755c-1bcf-c17c-1966-3269455d2393.png)
コンパイルに少し時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/91348778-5a0a-e62f-a4df-715c5cae8e81.png)
エラーなく書き込みが終わると、コードが実行されます。
Serial.printで出力した文字がシリアルモニタに表示されたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/841f17bd-f775-8815-6167-abb4ec55179b.png)
Wi-FiにつながるとローカルIPが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/4b60fcca-89b5-aa0d-df39-b653a628b090.png)

データも無事に書き込まれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/97c1eda7-9122-3d5c-2c82-1aede55fd2cc.png)

ということで、DBのデータをreact-chartjs-2でグラフ表示してみました。
※created_atがUTCのため、グラフは日本時間表記です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602022/a14e3fc9-6a8d-45bc-03b5-29d8c59c337e.png)