ほぼコピペで済ますIoTなCO2濃度計を作って遊ぶ
始めに
自動化が好きなので、何故か家に2台もあったCO2センサの値を自動で取得したいと思います。
↑の動画の内容を補足説明していきます。
まずは動画を見よう、な!
材料
・マイコン
親の顔よりみたM5Stack、だいたいの電子工作にちょうどいい。
CoreInkやM5StickCとかでもOKです。
・環境センサ
温度・湿度・気圧はこれで十分。
・CO2センサ
今回使ったのはMH-Z14Aという型番のやつ、一応Amazonとかでも買えます。
後継のMH-Z19シリーズの方が最近は入手しやすいかもしれません。
TVOC/eCO2タイプはCO2以外にも反応しちゃいますが、傾向を見るだけなら十分かと。
基板製作
正真正銘の基板
Ambientを使う
データの可視化はAmbientというIoTサービスに文字通り丸投げします。
データをぶん投げたらいい感じのグラフを勝手に作ってくれます。
スマホでも見られるし、データをCSVでダウンロードすることもできるんで至れり尽くせりですね。
プログラム
センサの値を取得するのはサンプルコードをコピペしてくればほぼ終わります。脳の活動は1ミリも必要ないですね。
Ambientにデータを投げる手順も公式のサンプルコードをコピペしてくれば済むので、実質自分で考えることはほぼ無いと言っていいでしょう。
コピペとコピペのマリアージュ。かくありたい。
ほぼ1分起きにデータを取得してAmbientにぶん投げます。特にリトライ処理とかないのでたま失敗するかもしれませんけど細かいことはいいんだよ!
#include <M5Stack.h>
#include <WiFi.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_SHT31.h>
#include <Ambient.h>
Adafruit_SHT31 sht3x = Adafruit_SHT31(&Wire);
Adafruit_BMP280 bme = Adafruit_BMP280(&Wire);
//センサ関連
float tmp = 0.0;
float hum = 0.0;
float pres = 0.0;
byte addArray[] = { 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 };//CO2センサに投げるコマンド
char dataValue[9];
String dataString = "";
String ppmString = " ";
//ネットワーク関連
const char* ssid = "WiFi_SSID"; // 使うWiFiのSSID
const char* password = "WiFi_Password";//使うWiFiのパスワード
const char* ntpServer = "pool.ntp.org";
//表示はchar型らしい?
char tmp_buff[64];
char hum_buff[64];
char pres_buff[64];
char ppm_buff[64];
// Ambientの設定
unsigned int channelId = channelId;//チャンネルIDを取得して書き換え
const char* writeKey = "ambient_writekey";//ライトキーを取得して書き換え
WiFiClient wifi_client;
Ambient ambient;
uint16_t measure_interval = 1000; // 測定間隔(msec)
uint32_t ambient_interval = 60 * 1000; // ambientに送る間隔(msec)
uint32_t last_millisec;
void setup() {
M5.begin();
M5.Power.begin();
Serial2.begin(9600, SERIAL_8N1, 16, 17);//TX RXをそれぞれ16 17pinへ配線
dacWrite(25, 0);//スピーカノイズ対策にOFF
Wire.begin(21, 22);
Serial.println(F("ENV Unit(SHT30 and BMP280) test..."));
while (!bme.begin(0x76)) {
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");
}
while (!sht3x.begin(0x44)) {
Serial.println("Could not find a valid SHT3X sensor, check wiring!");
M5.Lcd.println("Could not find a valid SHT3X sensor, check wiring!");
}
M5.Lcd.fillScreen(BLACK);
//WiFi接続
Serial.printf("Connecting to %s ", ssid);
if (strlen(ssid) != 0) {
WiFi.begin(ssid, password);
} else {
WiFi.begin();
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
ambient.begin(channelId, writeKey, &wifi_client); // チャネルIDとライトキーを指定してAmbientの初期化
last_millisec = millis();
}
void loop() {
//環境センサ値読み込み
pres = bme.readPressure();
tmp = sht3x.readTemperature();
hum = sht3x.readHumidity();
//CO2濃度要求ここから
Serial2.write(addArray, 9);
Serial2.readBytes(dataValue, 9);
int resHigh = (int) dataValue[2];
int resLow = (int) dataValue[3];
int ppm = (256 * resHigh) + resLow;
ppmString = String(ppm);//ここまで
//charにぶち込め
sprintf(tmp_buff, "Temp:%2.2f*C", tmp);
sprintf(hum_buff, "Humi:%2.2f%%", hum);
sprintf(pres_buff, "Prs :%2.0fhPa", pres / 100);
sprintf(ppm_buff, "CO2 :%sppm", ppmString);
//シリアルモニタ
Serial.printf("Temperatura:%2.2f*C Humedad:%0.2f%% Pressure:%0.2fhPa CO2:%sppm\r\n", tmp, hum, pres / 100, ppmString);
//センサ値表示更新
M5.Lcd.setCursor(0, 0, 4);
M5.Lcd.setTextColor(WHITE, BLACK);
M5.Lcd.println(tmp_buff);
M5.Lcd.println(hum_buff);
M5.Lcd.println(pres_buff);
M5.Lcd.println(ppm_buff);
// 一定時間経過でAmbientに送信
if ((millis() - last_millisec) > ambient_interval) {
//Ambientに送信
ambient.set(5, tmp);
ambient.set(6, hum);
ambient.set(7, pres / 100);
ambient.set(8, ppmString.c_str());
if (ambient.send()) {
Serial.println("Send Success");
} else {
Serial.println("Send Fail");
}
last_millisec = millis();
}
delay(measure_interval);
}
まとめ
・データの可視化を自分でやるのが無理と思ったら外部に丸投げしよう
・IoTの始め方、もっと雑でいい
※机の上は片付けた方がいい
以上