Hi @Jaron0211 ,
After testing with your code, I have written my own from scratch.
My checksum validation works.
As far as I could find only the first chars are always the same: 0x42 0x4D.
I hope my code can help you.
Update: This code is tested on multiple modules.
#include <Arduino.h>
// Configuration for UART and sensor communication
// ESP32
const uint8_t uartPortNr = 0; // Hardware UART port number, 0 = default hardware serial
const int8_t sensorRxPin = -1; // -1 = Use default RX pin for the hardware UART, this is GPIO20 on ESP32-C3, GPIO3 on NodeMCU-32S
const int8_t sensorTxPin = -1; // -1 = Use default TX pin for the hardware UART, this is GPIO21 on ESP32-C3, GPIO1 on NodeMCU-32S
// ESP-12E, Wemos D1 mini
//const int8_t sensorRxPin = 13; // D7
//const int8_t sensorTxPin = 15; // D8
// ESP-01
//const int8_t sensorRxPin = 0; // GPIO0
//const int8_t sensorTxPin = 2; // GPIO2
// Arduino Nano
//const int8_t sensorRxPin = 4; // GPIO0
//const int8_t sensorTxPin = 5; // GPIO2
// other board?
//const int8_t sensorRxPin = 17;
//const int8_t sensorTxPin = 16;
// Define the frame for packets
const uint8_t frameHeader[2] = {0x42, 0x4D};
const size_t frameHeaderLen = sizeof(frameHeader); // Automatically determine header length
const int frameLength = 16;
// Global variables
static unsigned long lastCheck = 0; // Timestamp for checking sensor data periodically
#ifdef ESP32
HardwareSerial *sensorSerial = nullptr; // Pointer to the sensor serial interface
#else
#include <SoftwareSerial.h>
SoftwareSerial *sensorSerial = nullptr; // Pointer to the sensor serial interface
#endif
uint8_t buffer[16] = {0}; // Buffer for storing sensor data, initialized all 0.
void setup() {
// Initialize Serial (USB) for debugging
Serial.begin(9600);
// Short delay to allow Serial monitor to initialize
delay(500);
Serial.println("\nInitializing...");
// Initialize sensor UART communication
#ifdef ESP32
sensorSerial = new HardwareSerial(uartPortNr);
sensorSerial->begin(9600, SERIAL_8N1, sensorRxPin, sensorTxPin);
#else
sensorSerial = new SoftwareSerial(sensorRxPin, sensorTxPin);
sensorSerial->begin(9600);
#endif
// Allow some time for sensor UART initialization
delay(100);
if (!sensorSerial) {
Serial.println("Error: sensor serial port not initialized.");
return;
}
Serial.println("Setup done.");
}
// Function to check if the received bytes match the frame header
bool isFrameHeaderMatched() {
for (size_t i = 0; i < frameHeaderLen; i++) {
if (buffer[i] != frameHeader[i]) return false;
}
return true;
}
// Function to print a buffer as hexadecimal values
void serialHex(uint8_t* buffer, int length) {
for (int i = 0; i < length; i++) {
char hexStr[4]; // Space for "FF " and null terminator
sprintf(hexStr, "%02X ", buffer[i]);
Serial.print(hexStr);
}
}
// Function to calculate the checksum of a sensor data buffer
int calcChecksum(uint8_t* buffer)
{
uint8_t sum = 0;
for (int i = 0; i < 15; i++) {
sum += buffer[i];
}
return sum;
}
void loop() {
// Limit checking to every 10 milliseconds to prevent unnecessary CPU usage
if (millis() - lastCheck < 10) return;
lastCheck = millis();
// Safety check
if (!sensorSerial || sensorSerial->available() <= 0) return;
// Shift buffer left
for (size_t i = 0; i < frameHeaderLen - 1; i++) {
buffer[i] = buffer[i + 1];
}
// Read byte from the sensor serial port
buffer[frameHeaderLen - 1] = sensorSerial->read();
// Check if frame header matches
if (!isFrameHeaderMatched()) return;
// Read the remaining bytes
int remaining = frameLength - frameHeaderLen;
if (sensorSerial->readBytes(&buffer[frameHeaderLen], remaining) != remaining) {
Serial.println("ERROR: Incomplete data received.");
return;
}
// Print received data in hex format
serialHex(buffer, frameLength);
// Validate checksum
if (calcChecksum(buffer) != buffer[15]) {
Serial.println("ERROR: Checksum mismatch.");
return;
}
// Extract CO2 concentration in PPM from buffer
int ppm = (buffer[6] << 8) | buffer[7];
Serial.print("- CO2: ");
Serial.print(ppm);
Serial.println(" ppm");
}
Hi @Jaron0211 ,
After testing with your code, I have written my own from scratch.
My checksum validation works.
As far as I could find only the first chars are always the same:
0x420x4D.I hope my code can help you.
Update: This code is tested on multiple modules.