【ESP32プログラム】無料のAmbientプラットフォームを利用してIoTシステムを構築してみよう
無料のAmbientというプラットフォームを利用して簡単なIoTシステムを構築してみたいと思います。今回のシステムは照度と湿度、気温をセンシングしてインターネット経由でAmbientのプラットフォームへデータを送るシステムを作ってみます。
Ambientの登録と設定
事前にAmbientへの登録や設定が必要なので、Ambientの登録や設定についてこちらを参照して無料の登録と設定をお願いします。
設定はチャンネルを新規に作成するだけでも、図1のチャンネルIDとライトキーがわかるのでデータを記録できます。記録されたデータはダウンロードを押すことでcsvデータをダウンロードすることができます。
なお、Ambientのページ上で時系列のグラフも表示させるためにはチャンネル名のリンクを押してボードのページ(図2)に移動してグラフの設定をする必要があります。
グラフの追加ボタンを押すと送られてきたデータを表示するウインドウが作られます。ここには複数のデータを重ね書きすることもできますが、今回は1つのグラフに1つのデータを表示させるようにします。今回hAmbientに照度、湿度、気温の3つのデータを送るので3つのウインドウを作成します。
ウインドウのタイトル部分を押すと設定変更ができるので、設定変更を押します。
図4は設定変更画面です。後で送信プログラムのところで説明しますが、送信データに番号をつけていますので、それぞれのウインドウに表示するデータの番号のラジオボタンをクリックしてアクティブにしておきます。
数値の左軸か右軸を選べばよいです。異なるデータを重ね書きさせるときは左軸に加えて右軸を使う場合もありますが、1つのデータなら左軸に設定します。あとは何のデータかをわかるようにチャート名を書いておくとよいでしょう。他は適宜設定してくれればよいですが、何も設定しなくても問題ありません。
3つのウインドウを設定すると図1のようになります。まだデータが送られてきていないとグラフは出てきません。送られてきたらデータが表示される準備がこれでできましたね。
結線図
図5に結線図を示します。
温度センサについては「温度・湿度センサー(DHT11)」の記事、光量検出センサについては「光量検出センサ (Cds)」の記事を参照ください。
注意)
WiFiや各種通信を使う場合に制約を受けるピンがあります。うまくセンサ値を取得できない、指令を出力できない場合には他のWiFiや各種通信等のプラグラムにより制約を受けている可能性がありますので、適宜変更してください。
ESP32のプログラム
下方にプログラムを記載してありますが、ポイントだけかいつまんで説明します。
WiFiのプログラム
インターネットにはルータ経由で接続します。
プログラムのコメントを見ればWiFiに関する部分はわかると思いますが、WiFiを使ってルータへの接続部分だけフォーカスしてみたい方は「WiFiに繋げてみよう!①ルータに繋げる方法」の記事を参照してください。
WiFiを使う場合に、特に接続状況をチェックして接続ができていない場合には再接続するところは重要です。
「if (WiFi.status() != WL_CONNECTED) 」で接続状態を見て、接続できていなければ後段で作成している「connectToWiFi()」を呼び出して再接続をしています。これをしておかない何らかによりWiFiと切断してしまうと以後はAmbientにデータを送ってくれなくなるので、とても重要です。
Ambientのプログラム
今回は「TAmbient」というライブラリを使いますのでライブラリをインストールします。
Arduino IDEのメニューから スケッチ → ライブラリを管理 をクリックします。検索欄に Ambientと入力。検索結果に「Ambient ESP32」が表示されたら、「インストール」をクリック。
あとはライブラリの関数を使うだけです。
AmbientのチャンネルIDを設定する「channelId」、ライトキーを設定する「writeKey 」を宣言して、各自でAmbient の設定で準備した値を入力しておきます。
「Ambient ambient;」でアンビエントのインスタンスを生成し、setup関数内で生成したインスタンスを初期化します「ambient.begin(channelId, writeKey, &client);」。
あとはAmbientに送りたいデータを番号順にセットします。例えば光量のデータを「1」つ目のデータとしてセットする場合には「ambient.set(1, cdsValue);」とします。
送りたいデータを番号順に全てセットしたら「ambient.send()」でAmbientに送ります。
#include <WiFi.h>
#include <Ambient.h>
#include <DHT.h>
// WiFi情報
const char* ssid = "WiFiのSSID"; // 各自のルータのSSIDを記入
const char* password = "WiFiのパスワード"; // 各自のルータのパスワードを記入
// Ambientの情報
unsigned int channelId = xxxxx; // AmbientのチャンネルIDを記入
const char* writeKey = "AmbientのwriteKey"; // AmbientのwriteKeyを記入
WiFiClient client;
Ambient ambient;
// DHTセンサーのピン番号とタイプ
#define DHTPIN 32 // DHT11のデータピンを接続するESP32のGPIOピン
#define DHTTYPE DHT11 // DHT11センサーを使用
DHT dht(DHTPIN, DHTTYPE);
// CdSセンサのピン設定
const int cdsPin = 33;
// データ送信の間隔(ミリ秒単位、600秒 = 10分)
const unsigned long sendInterval = 600000;
unsigned long lastSendTime = 0;
void setup() {
// シリアルモニタを初期化
Serial.begin(115200);
// WiFi接続
connectToWiFi();
// Ambient初期化
ambient.begin(channelId, writeKey, &client);
// DHTセンサーの初期化
dht.begin();
}
void loop() {
// 現在時刻を取得
unsigned long currentTime = millis();
// WiFi接続確認と再接続
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi disconnected. Reconnecting...");
connectToWiFi();
}
// 温度と湿度のデータ取得リトライ
float humidity = getDHTData([](DHT& dht) { return dht.readHumidity(); });
float temperature = getDHTData([](DHT& dht) { return dht.readTemperature(); });
// Cdsからアナログ値を取得
int cdsValue = analogRead(cdsPin);
// デバッグ用に読み取った値をシリアルモニタに表示
Serial.print("照度: ");
Serial.print(cdsValue);
Serial.print(" 湿度: ");
Serial.print(humidity == -1 ? "Error" : String(humidity));
Serial.print("% 温度: ");
Serial.println(temperature == -1 ? "Error" : String(temperature) + "°C");
// 前回送信から指定時間が経過したらデータを送信
if (currentTime - lastSendTime >= sendInterval) {
ambient.set(1, cdsValue);
ambient.set(2, humidity);
ambient.set(3, temperature);
if (ambient.send()) {
Serial.println("Data sent to Ambient!");
} else {
Serial.println("Failed to send data.");
}
// 最後に送信した時刻を記録
lastSendTime = currentTime;
}
// 1秒ごとにセンサー値を更新
delay(1000);
}
// WiFi接続処理
void connectToWiFi() {
WiFi.begin(ssid, password);
unsigned long startAttemptTime = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (millis() - startAttemptTime > 30000) { // タイムアウト30秒
Serial.println("\nFailed to connect to WiFi. Restarting...");
ESP.restart();
}
}
Serial.println("\nWiFi connected");
}
// DHTデータ取得リトライ用関数
float getDHTData(std::function<float(DHT&)> readFunction) {
const int maxRetries = 10;
for (int i = 0; i < maxRetries; i++) {
float data = readFunction(dht);
if (!isnan(data)) {
return data;
}
delay(200); // 少し待機して再試行
}
return -1; // 10回試しても取得できなかった場合は-1を返す
}
Ambientで収集したデータを見てみよう!
Ambientにデータを送ると時系列のグラフとして表示してくれるので、状況を見やすいです。私が作成したプログラムを少し見てみましょう。
照度は抵抗値の設定によって明るい側が頭打ちになっていますね。明るい側をもう少し詳しく分割したい場合には接続している抵抗値を小さくするとよいです。途中で夜にピークが経っているのはESP32を設置した部屋の照明を夜に付けているためです。
湿度はまぁまぁ見れてはいますね。20というセンサ値は下限なのでそのデータは取れていなかったのかもしれませんね。湿度は瞬間的なデータを見るものではないので、時間的なトレンドとして見れば十分に使えます。
温度も途中から急にピークになっていますね。冬の温度どはない高い気温になっています。直射日光の当たる、しかもフエルトの上に置いていたので温度が高く出てしまっているのだと思います。
言い訳ですが、今回は取れることの確認のために設置場所や抵抗の設定は雑にしてしまいましたが、IoTとして作成する場合には、これらのことをよく考えて回路設計や設置場所を考えるとよいでしょう。テストをしてみて「あれ?」っと思ったらトライアンドエラーで修正していけば個人の趣味なら十分です。
購入部品
最新情報は「電子工作お買い物一覧」の記事を参照ください。
リンク切対応や代替部品の紹介もしています。