In this article, we will thoroughly examine the process of connecting the MH-Z19B carbon dioxide sensor to the MEGA 2560 microcontroller and using the VizIoT platform to monitor CO2 levels in real-time.
Power:
VCC
of the SIM800L module from a 4.2V-4.4V power source. The SIM800L module can be sensitive to voltage, so it's better to use a separate power source.GND
of the SIM800L module to the GND
of the power source and the GND
of Arduino Mega.
Control the module according to the following connection scheme:
TX
pin of the SIM800L module to the RX2
(#17) pin on Arduino Mega.RX
pin of the SIM800L module to the TX2
(#16) pin on Arduino Mega via a voltage divider (resistors of equal value in the range of 1-10 kOhm).
Connection Diagram:
Example Code:
Here is a simple example code to check the connection and send AT commands to the SIM800L module:
void setup() {
// Start communication with Serial Monitor
Serial.begin(9600);
// Start communication with SIM800L using Serial2
Serial2.begin(9600);
// Pause to allow the module to initialize
delay(1000);
Serial.println("Sending AT command...");
Serial2.println("AT");
// Wait for a response
delay(1000);
// Check if data is available
if (Serial2.available()) {
while (Serial2.available()) {
char c = Serial2.read();
Serial.print(c);
}
} else {
Serial.println("No response from SIM800L.");
}
}
void loop() {
// Empty loop as all the work is done in setup()
}
Testing the Setup:
Connecting the MH-Z19B sensor to Arduino Mega 2560:
Required components:
Connection Diagram:
Power:
VCC
of the MH-Z19B sensor to 5V
on Arduino Mega 2560.GND
of the MH-Z19B module to GND
of the power source and GND
of Arduino Mega.Signal lines:
TX
of the MH-Z19B sensor to RX3
(pin 15) on Arduino Mega 2560.RX
of the MH-Z19B sensor to TX3
(pin 14) on Arduino Mega 2560.Example code to read data from the MH-Z19B sensor:
void setup() {
// Start communication with Serial Monitor
Serial.begin(9600);
// Start communication with MH-Z19B using Serial3
Serial3.begin(9600);
// Pause to allow the module to initialize
delay(1000);
Serial.println("Requesting data from MH-Z19B...");
}
void loop() {
// Send command to request data
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
Serial3.write(cmd, 9);
// Pause to receive data
delay(1000);
// Check if data is available
if (Serial3.available()) {
byte response[9];
for (int i = 0; i < 9; i++) {
response[i] = Serial3.read();
}
if (response[0] == 0xFF && response[1] == 0x86) {
int co2 = response[2] * 256 + response[3];
Serial.print("CO2 Concentration: ");
Serial.print(co2);
Serial.println(" ppm");
} else {
Serial.println("Invalid response from MH-Z19B.");
}
} else {
Serial.println("No response from MH-Z19B.");
}
// Pause before next request
delay(5000);
}
Testing the Response:
If you receive a CO2 concentration value, the sensor is successfully connected and working correctly.
At this stage, we have discussed the key steps for connecting the MH-Z19B carbon dioxide sensor and the SIM800L module to the Arduino Mega 2560. We reviewed the required components, connection diagrams, and provided example code to test the communication with the SIM800L module and to read data from the MH-Z19B sensor.
Adding and configuring the device:
The process of connecting new devices to the VizIoT server has been detailed in previous articles. Here’s a brief overview of how to do this using today's example:
Arduino firmware:
#define TINY_GSM_MODEM_SIM800
#define USED_MH_Z19B true
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
#include <Wire.h>
#define SerialMon Serial
// Use the physical Serial port for Mega, Leonardo, Micro
#define SerialAT Serial2
//access point settings which is required to connect the GSM module to the GPRS network
const char apn[] = "www.kyivstar.net";
const char user[] = "";
const char pass[] = "";
// VizIoT Device access key and password (can be found in the device settings)
String VizIoT_Device_key = "XXXX";
String VizIoT_Device_pass = "XXXX";
// Server address and port
const char server[] = "VizIoT.com";
const int port = 80;
TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
HttpClient http(client, server, port);
void setup() {
// Set baud rate for Serial Monitor
SerialMon.begin(9600);
Serial3.begin(9600); // Serial3 port for communication with the MH-Z19B sensor
Serial.println("MH-Z19B CO2 Sensor Test");
delay(10);
// Set baud rate for GSM module
SerialAT.begin(9600);
delay(3000);
SerialMon.println(F("Initializing modem..."));
modem.restart();
String modemInfo = modem.getModemInfo();
SerialMon.print(F("Modem: "));
SerialMon.println(modemInfo);
}
void loop() {
SerialMon.print(F("Waiting for network..."));
if (!modem.waitForNetwork()) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.println(" OK");
SerialMon.print(F("Connecting to access point "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, user, pass)) {
SerialMon.println(" failed");
delay(10000);
return;
}
SerialMon.println(" OK");
SerialMon.print(F("Sending HTTP GET request... "));
int err = http.get(getResource().c_str());
if (err != 0) {
SerialMon.println(F("connection error"));
delay(10000);
return;
}
// Reading and displaying the response
int statusCode = http.responseStatusCode();
SerialMon.print(F("HTTP "));
SerialMon.println(statusCode);
if (statusCode == 200) {
String response = http.responseBody();
SerialMon.print(F("Response: "));
SerialMon.println(response);
}
http.stop();
SerialMon.println(F("Disconnected from server"));
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
// Sleep for 5 minutes
//delay(0.3 * 60 * 1000);
delay(5.0 * 60 * 1000);
}
String getResource() {
// Reading data from the MH-Z19B sensor
int CO2 = readCO2();
String resource = String("/update?key=") + VizIoT_Device_key + "&" + "pass=" + VizIoT_Device_pass;
resource += String("&co2=") + CO2;
return resource;
}
int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0, 0, 0, 0, 0, 0x79};
byte response[9];
// Clear the serial port buffer before sending the command to avoid reading old data
while (Serial3.available()) {
Serial3.read();
}
Serial3.write(cmd, 9);
// Waiting for data with timeout
unsigned long startTime = millis();
while (Serial3.available() < 9) {
if (millis() - startTime > 1000) { // 1000 ms = 1 second timeout, waiting for data (1 second) to prevent the program from getting stuck if there is no response
SerialMon.println("Error: CO2 read timeout");
return -1;
}
}
// Reading data, checking the number of bytes read before processing
Serial3.readBytes(response, 9);
// Check the response header
if (response[0] != 0xFF || response[1] != 0x86) {
SerialMon.println("Error reading CO2");
return -1;
}
// Calculate CO2 value
int CO2 = (response[2] << 8) + response[3];
// Output the CO2 value to the monitor
SerialMon.print("CO2: ");
SerialMon.println(CO2);
return CO2;
}
Install the following libraries:
To ensure the correct operation of the code, specify the values for the following variables:
apn
– Name of the GSM access point. In this context, apn
is used to store the access point name (Access Point Name), which is required to connect the GSM module to the GPRS network.VizIoT_Device_key
– copied Device Access Key.VizIoT_Device_pass
– copied Device Access Password.Connect the Arduino to the computer and upload the sketch.
Adding Widgets:
Set the following parameters:
After successfully setting up the connection, you can monitor CO2 concentration data in real-time on the VizIoT dashboard. You also have the ability to configure charts, alert settings, and other elements for convenient and efficient monitoring.
For a more detailed analysis, you can expand the widget by clicking on "Open in full screen" in the upper right corner, where a detailed chart will appear:
The graph shows the CO2 concentration in the room from July 13 to July 15, 2024. Let's look at the main points:
CO2 Concentration:
Time Analysis:
Ventilation Recommendations:
Comment on the Graph
The graph shows changes in CO2 levels during the analyzed period. Key observations include:
Personal (Apartment/House):
Commercial (Office/Public Places):
To improve indoor conditions, it is recommended to monitor CO2 levels using sensors and ventilate the room when the concentration exceeds 1000 ppm.
How to manage notifications and connect to the VizIoT Telegram Bot is discussed in the article VizIoT Notifications. In this section, we will look at setting up a custom message about permissible CO2 levels and alerts about high carbon dioxide concentration.
Create methods for receiving messages via Telegram bot and VizIoT website in the notification constructor, as shown in the screenshot.
Examples of received messages in the Telegram bot look like this.
Connecting the MH-Z19B sensor and SIM800L module to Arduino Mega 2560 using the VizIoT platform is a simple and effective solution for CO2 monitoring. The main advantages of this approach include remote real-time monitoring via GSM network, making it ideal for smart homes, offices, and industrial premises. The VizIoT platform provides convenient data display and analysis, as well as the ability to set up notifications and charts for effective air quality control.
This solution can be useful for organizations and individuals aiming to improve indoor environment conditions and ensure safe and comfortable occupancy of people in the premises.