K33 ELG CO2 module by Senseair - Not Updating Real-Time Values (Stuck at 500 ppm)

Hello everyone,

I'm new to the world of Arduino and currently working on a project to monitor real-time CO2 levels in ppm.

I’m facing two main issues and would really appreciate your help:

1. Sensor Output Stuck:
After I short C + D for a quick start, the sensor outputs a value around 500 ppm. However, this value doesn’t change over time, even after waiting 15 minutes for the sensor to warm up. The only way the value changes is if I short C + D again, but then it gets stuck at the new value. It does not seem to update in real-time after that.

2. Sensor Reads 0 ppm After Power Off:
When I power off the sensor and turn it back on, it starts reading 0 ppm and doesn’t recover or show any CO2 value unless I short C + D again.

This the Code I have used: // AN-126 Demo of K-30 using Software Serial
#include <SoftwareSerial.h>
/*
 Basic Arduino example for K-Series sensor
 Created by Jason Berger
 Co2meter.com
*/
#include "SoftwareSerial.h"
SoftwareSerial K_30_Serial(10,11); //Sets up a virtual serial port
//SoftwareSerial K_30_Serial(12,13); //Sets up a virtual serial port
 //Using pin 12 for Rx and pin 13 for Tx
byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25}; //Command packet to read Co2 (see app note)
byte response[] = {0,0,0,0,0,0,0}; //create an array to store the response
//multiplier for value. default is 1. set to 3 for K-30 3% and 10 for K-33 ICB
int valMultiplier = 1;
void setup()
{
 // put your setup code here, to run once:
 Serial.begin(9600); //Opens the main serial port to communicate with the computer
 K_30_Serial.begin(9600); //Opens the virtual serial port with a baud of 9600
 Serial.println(" Demo of AN-126 Software Serial and K-40 Sensor");
}
void loop()
{
 sendRequest(readCO2);
 unsigned long valCO2 = getValue(response);
 Serial.print("Co2 ppm = ");
 Serial.println(valCO2);
 delay(2000);
}
void sendRequest(byte packet[])
{
 while(!K_30_Serial.available()) //keep sending request until we start to get a response
 {
  Serial.println("waiting for Software.serial port availability");
 K_30_Serial.write(readCO2,7);
 delay(50); 
 }
 int timeout=0; //set a timeout counter
 while(K_30_Serial.available() < 7 ) //Wait to get a 7 byte response
 {
 timeout++;
 if(timeout > 10) //if it takes too long there was probably an error
 {
 while(K_30_Serial.available()) //flush whatever we have
 K_30_Serial.read();
 break; //exit and try again
 }
 delay(50);
 }
 for (int i=0; i < 7; i++)
 {
 response[i] = K_30_Serial.read();
 }
}
unsigned long getValue(byte packet[])
{
 int high = packet[3]; //high byte for value is 4th byte in packet in the packet
 int low = packet[4]; //low byte for value is 5th byte in the packet
 unsigned long val = high*256 + low; //Combine high byte and low byte with this formula to get value
 return val* valMultiplier;
}

Output:

waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability Co2 ppm = 532
waiting for Software.serial port availability

If anyone has experienced this or knows what might be going wrong, I’d be grateful for your guidance.

Thank you in advance!

Site and PDFs I have referred to:

Hi, @bara12
Welcome to the forum.
Thanks for the information.

If you are using a 9V PP3 smokedetector battery, it will not be supplying enough current.

Do you have a DMM? (Digital MultiMeter)

Thanks.. Tom.... :smiley: :+1: :coffee: :australia:

What does that mean? No C nor D in the wiring.

That's fully okey as the device is not initialized (K_30_Serial.begin(9600):wink: like it is in setup().

In general, don't connect or disconnect single devices when other devices, like the controller, is powered.

Thanks Railroader for the quick reply.

Just to clarify, I'm using a single jumper wire to momentarily connect the C and D pins on the sensor, as mentioned in the datasheet for a quick start.

Noted: I won’t connect/disconnect parts while the controller is powered on. I’ll be more careful going forward.

i have referred to this PDF.

Thank you for the quick reply!

I've now replaced the 9V battery with a 9V, 1A power adapter and also switched from using an Arduino to a Raspberry Pi 5. However, I'm still getting the same repeated CO₂ value—it doesn't seem to update in real time.

Here’s the updated code: 

import time
import serial

ser = serial.Serial("/dev/ttyAMA0", baudrate=9600, timeout=0.5)

def read_co2():
    # Correct Modbus RTU request for register 0x0003 (CO₂ concentration)
    command = b'\xFE\x04\x00\x03\x00\x01\xD5\xC5'
    ser.flushInput()
    ser.write(command)
    time.sleep(0.1)  # Wait for response

    resp = ser.read(7)  # Should receive 7 bytes

    if len(resp) == 7:
        high = resp[3]
        low = resp[4]
        co2 = (high << 8) | low
        return co2
    else:
        print("Incomplete response:", resp)
        return None

while True:
    co2 = read_co2()
    if co2 is not None:
        print('CO₂ Value [ppm]:', co2)
    else:
        print('Failed to read CO₂')
    time.sleep(2)

Hi, @bara12
From the indestructible link;

2. Power. While the Arduino's 5V power is theoretically able to power the K-30, the sensor needs 300mA minimum to operate the light inside the sensor. The problem is, if you power the Arduino from your PC's USB port, the K-30 has to share power with the Arduino, your mouse, and any other devices on the USB bus. The power to the sensor will drop under 300mA, and it won't operate properly.
You have 2 options:

  1. Use a powered USB hub as shown in Step 3.
  2. Power the K-30 with a separate 6-9VDC, 500mA external power supply. If you don't have a wall adapter like this around, you can use a 4 doubleAA battery box

Tom.... :smiley: :+1: :coffee: :australia:

Hello Tom,

Previously, I was powering the Arduino through the USB port of my PC, while the K33 sensor was powered separately using an adapter. I'm not sure if this setup is causing the issue or where I might be going wrong.

I’m stuck.:hot_face:

Noted: to use a 4 double AA battery box.

Does the CO2 sensor need a warmup time and a calibration?

What are the values of high and low before any math or shifting?