Example Code for Arduino-Read CO2 Value
This project demonstrates how to read CO2 concentration values from the RS485 Infrared CO2 Sensor (400-5000ppm) using an Arduino board. Users will learn to interface with the sensor via the RS485 protocol, implement Modbus-RTU communication, and process raw sensor data into readable CO2 values.
Hardware Preparation
- DFRduino UNO R3 (or similar) x 1
- Gravity: Active Isolated RS485 to UART Signal Adapter Module x 1
- RS485 Infrared CO2 Sensor(400-5000ppm) (SEN0659) x 1
Software Preparation
Wiring Diagram
If the power of the RS485 device is small and the required current is less than 12V-160mA, the RS485 to UART signal conversion module does not require a 12V external power supply, making wiring more convenient.
| Sensor | RS485 to UART Module |
|---|---|
| Brown wire | 12V |
| Black wire | GND |
| Yellow wire | A |
| Blue wire | B |
| RS485 to UART Module | Arduino UNO | Mega2560 | ESP32 |
|---|---|---|---|
| Red wire(+) | 5V | 5V | 5V |
| Black wire(-) | GND | GND | GND |
| Blue wire (RX) | D2 | D19 | D16 |
| Green wire (TX) | D3 | D18 | D17 |
Other Preparation Work
- Note: The CO2 concentration value output during the preheating time will gradually stabilize. Please ignore the CO2 concentration value within 5 minutes of preheating.
- This sample code is compatible with UNO R3, Mega2560, and ESP32 development boards.
Sample Code
// ---------------- Cross-Platform Serial Configuration ----------------
#if defined(__AVR_ATmega2560__)
// Arduino Mega 2560: Use hardware serial port Serial1
// Sensor TX connects to Mega Pin 18
// Sensor RX connects to Mega Pin 19
#define sensorSerial Serial1
#elif defined(ESP32)
// ESP32: Manually instantiate hardware serial port; compatible with all models including C3/S2/S3/WROOM, etc.
#include <HardwareSerial.h>
HardwareSerial mySensorSerial(1); // Consistently use internal UART 1
#define sensorSerial mySensorSerial
#else
// Arduino UNO: Software serial port
// Sensor TX connects to UNO Pin 3
// Sensor RX connects to UNO Pin 2
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
#define sensorSerial mySerial
#endif
// ------------------------------------------------
uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
float CO2;
void setup() {
Serial.begin(115200);
// Print a line of plain English text for testing. If this line appears clearly and without garbled characters,
// it indicates that communication between the computer and the development board is fully functional! Serial.println("");
Serial.println("--- System Start ---");
// Initialize the sensor serial port for different development boards
// (The sensor's baud rate must remain at 9600—do not change it)
#if defined(ESP32)
// ESP32 specific pins: RX connected to 16, TX connected to 17;
// pins can be customized based on the specific board model
sensorSerial.begin(9600, SERIAL_8N1, 16, 17);
#else
// UNO and Mega 2560
sensorSerial.begin(9600);
#endif
}
void loop() {
readCO2();
Serial.print("CO2 = ");
Serial.print(CO2, 0);
Serial.println(" ppm");
delay(4000);
}
void readCO2(void) {
uint8_t Data[10] = { 0 };
uint8_t ch = 0;
bool flag = 1;
long timeStart = millis();
long timeStart1 = 0;
while (flag) {
if ((millis() - timeStart1) > 100) {
while (sensorSerial.available() > 0) {
sensorSerial.read();
}
sensorSerial.write(Com, 8);
timeStart1 = millis();
}
if ((millis() - timeStart) > 1000) {
Serial.println("Time out");
return;
}
if (readN(&ch, 1) == 1) {
if (ch == 0x01) {
Data[0] = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x03) {
Data[1] = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x02) {
Data[2] = ch;
if (readN(&Data[3], 4) == 4) {
if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) {
CO2 = Data[3] * 256 + Data[4];
flag = 0;
}
}
}
}
}
}
}
}
}
}
uint8_t readN(uint8_t *buf, size_t len) {
size_t offset = 0, left = len;
int16_t Tineout = 500;
uint8_t *buffer = buf;
long curr = millis();
while (left) {
if (sensorSerial.available()) {
buffer[offset] = sensorSerial.read();
offset++;
left--;
}
if (millis() - curr > Tineout) {
break;
}
}
return offset;
}
unsigned int CRC16_2(unsigned char *buf, int len) {
unsigned int crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (unsigned int)buf[pos];
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
return crc;
}
Result
Serial monitor baud rate selection: 115200,Print the collected CO2 value.
Was this article helpful?
