はじめに
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濃度値を取得して、パソコンからデータを参照してみました。
窓を開けて計測すると濃度値が下がっていくので、換気度合いの見える化ができそうです。
コメント