はじめに
ESP-WROOM32を使ってCO2濃度を計測してみます。
CO2センサーは、MH-Z19を使います。
CO2濃度データは、ESP-WROOM32からWi-Fiで飛ばして、パソコンから参照できるようにします。
ここでは、ESP-WROOM32をアクセスポイントとして使います。
ESP-WROOM32には、 技術適合基準(技適) マークがついているので、問題なく無線通信ができます。
技適マークがないと電波法違反の可能性がありますので、注意が必要です。
CO2センサーMH-Z19のライブラリのダウンロード
CO2の計測プログラムには、こちらのライブラリを利用させていただきました。
回路を接続する
MH-Z19の出力は、UARTとPWMがありますが、ここでは、UARTを使います。
ESP-WROOM32側は16Pin,17Pinを使用して通信することにします。
MH-Z19 | ESP-WROOM32 |
Txd | GPIO16 |
Rxd | GPIO17 |
V+ | 5V |
V- | GND |
プログラムをつくる
スケッチ例のWiFiAccessPointをベースとして作ります。
まず、Arduino IDEの[ファイル]-[スケッチ例]-[WiFi]からWiFiAccessPointを選択します。
このプログラムにMH-Z19のライブラリMHZ19.hをインクルードします。
#include <WiFi.h> | |
#include <WiFiClient.h> | |
#include <WiFiAP.h> | |
#include <Arduino.h> | |
#include "MHZ19.h" | |
#define RX_PIN 16 // Rx pin which the MHZ19 Tx pin is attached to | |
#define TX_PIN 17 // Tx pin which the MHZ19 Rx pin is attached to | |
#define BAUDRATE 9600 // Device to MH-Z19 Serial baudrate (should not be changed) | |
#define LED_BUILTIN 2 // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED | |
//prototype | |
void co2SensorModule(void); | |
MHZ19 myMHZ19; // Constructor for library | |
HardwareSerial mySerial(2); // (ESP32 Example) create device to MH-Z19 serial | |
unsigned long getDataTimer = 0; | |
int CO2; | |
int8_t Temp; | |
// Set these to your desired credentials. | |
const char* ssid = "tsunelab"; | |
const char* password = "tsunelabpass"; | |
WiFiServer server(80); | |
void setup() { | |
pinMode(LED_BUILTIN, OUTPUT); | |
Serial.begin(115200); | |
Serial.println(); | |
Serial.println("Configuring access point..."); | |
//CO2 sensor setup | |
mySerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN); // (ESP32 Example) device to MH-Z19 serial start | |
myMHZ19.begin(mySerial); // *Serial(Stream) refence must be passed to library begin(). | |
myMHZ19.autoCalibration(); // Turn auto calibration ON (OFF autoCalibration(false)) | |
// You can remove the password parameter if you want the AP to be open. | |
WiFi.softAP(ssid, password); | |
IPAddress myIP = WiFi.softAPIP(); | |
Serial.print("AP IP address: "); | |
Serial.println(myIP); | |
server.begin(); | |
Serial.println("Server started"); | |
} | |
void loop() { | |
//CO2 Sensor Module | |
co2SensorModule(); | |
WiFiClient client = server.available(); // listen for incoming clients | |
if (client) { // if you get a client, | |
Serial.println("New Client."); // print a message out the serial port | |
String currentLine = ""; // make a String to hold incoming data from the client | |
while (client.connected()) { // loop while the client's connected | |
if (client.available()) { // if there's bytes to read from the client, | |
char c = client.read(); // read a byte, then | |
Serial.write(c); // print it out the serial monitor | |
if (c == '\n') { // if the byte is a newline character | |
// if the current line is blank, you got two newline characters in a row. | |
// that's the end of the client HTTP request, so send a response: | |
if (currentLine.length() == 0) { | |
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) | |
// and a content-type so the client knows what's coming, then a blank line: | |
client.println("HTTP/1.1 200 OK"); | |
client.println("Content-type:text/html"); | |
client.println(); | |
// the content of the HTTP response follows the header: | |
client.print(String("CO2[ppm]:") +CO2+"<br>"); | |
// The HTTP response ends with another blank line: | |
client.println(); | |
// break out of the while loop: | |
break; | |
} else { // if you got a newline, then clear currentLine: | |
currentLine = ""; | |
} | |
} else if (c != '\r') { // if you got anything else but a carriage return character, | |
currentLine += c; // add it to the end of the currentLine | |
} | |
} | |
} | |
// close the connection: | |
client.stop(); | |
Serial.println("Client Disconnected."); | |
} | |
} | |
void co2SensorModule(void) | |
{ | |
if (millis() - getDataTimer >= 2000) | |
{ | |
/* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even | |
if below background CO2 levels or above range (useful to validate sensor). You can use the | |
usual documented command with getCO2(false) */ | |
CO2 = myMHZ19.getCO2(); // Request CO2 (as ppm) | |
Temp = myMHZ19.getTemperature(); // Request Temperature (as Celsius) | |
getDataTimer = millis(); | |
} | |
} |
計測してみる
プログラムをコンパイルして実行してみます。
シリアルモニタに出力されるAPのIPアドレスをメモしておいて、パソコンのWi-FI一覧を見てみます。
設定したSSIDの名前が表示されているはずです。ここでは、「tsunelab」でプログラムを作成しているので、tsunelabに接続します。パスワードは、tsunelabpassです。
接続が完了したら、ブラウザを立ち上げて、メモしておいたIPアドレスを入力します。
ESP-WROOM32から送信されたCO2データが表示されます。
CO2濃度のレベルです。
CO2濃度[ppm] | レベル |
350~450 | 外気レベル |
450~700 | 室内レベル |
700~1000 | 不快レベル |
1000~2000 | 眠気レベル |
計測時は、不快レベルでした。
このセンサーは、仕様にPreheat time3分とあるので、電源投入から安定するまで3分程度は必要です。電源投入時は、濃度値が大きく出ますが、徐々に下がっていって安定します。
まとめ
ESP-WROOM32のWi-Fiアクセスポイントを使ってMH-Z19センサーからCO2濃度値を取得して、パソコンからデータを参照してみました。
窓を開けて計測すると濃度値が下がっていくので、換気度合いの見える化ができそうです。
コメント