>>> Join Us in the Fight Against Air Pollution

AirGradient Forum

S8 CO2 reading of -1

I built the DIY Air Quality kit. The temp/humidity and PM sensors return valid values but the S8 CO2 reading is -1. I checked my connections and they seem fine, I also get a blinking amber led from it so it is getting power. I will try the manual calibration to see if it will fix it.

Has anyone seen this issue?

Judging from the sample code in the AirGradient library, a value of -1 could be an indication that there are communication problems. -1 is returned if the read CO2 command times out or if reading the response fails.

Thanks, I guess I need to recheck my connections. The manual calibration did not change anything.

@Richardg
The CO2 sensor needs a very stable power supply. Please also ensure that you run it from a high quality power brick.
Feel free to post some pictures of the built here and we can have a look.

My Rx connection was not soldered properly. Fixed it and it’s working now, Thanks.

I have build a DIY device and see also -1 readings without an obvious reason. It can be okay for 12-14 hours and than several drops within a couple minutes. I checked the solderings and even resoldered the connections. Power supply is stable. I use the “Jeff Geerling” setup to export to Prometheus and visualize with Grafana. The error occurs on the Wemos D1 as far as can see. Readings are alway around 500ppm CO2 when it occurs.

Anyone a suggestion how to analyze this further?

How many Amps is your power supply?

The powersupply is 3.0A. The power draw is about 120-150mA.

I also tested with the sensor connected to the PC directly and also to a powerbank.
Your question gave me an idea: the steady component I used in all the test is the microUSB cable.

In an ADSB setup I am running on a Raspberry, this was one of the cullprits I addressed some years ago and maybe this is a smilar topic. The impact of a poor microUSB should not be underestimaed.

I just completed some measurements.
Voltage at powersupply: 5.241V
Voltage at board with cable 1: 4.61V
Voltage at board with cable 2: 4.73V
Voltage at board with cable 3: 4.82V

According the spec sheet of the Senseair S8 the required voltage is between 4.5V and 5.25V.

So I will do some more tests with the cable with the lowest voltage drop and see if this avoid the failed CO2 measurement.

In order to avoid this problem, I made a change to the Airgradient library and increased the retry delay from 50ms to 500ms, which seems to do the trick. I will revert the change to see if it works without adaptation.

Does this mean, changing to 500ms does fix the issue with the “-1”?

At least it gives enough time and retries to get a valid reading. What I see in the code is that in case of an invalid reading, there are 10 retries in 10x 50ms = 500ms. The chance that there is a valid reading is more likely.

The -1 readings did disappear.

After setting it back to 50ms and with the best cable, I see again -1 results. As a next test I changed it to 250ms. The next 24hrs will tell if this is a solution.

nice finding @ttielemans! my AirGradient also reports -1 for co2 every now and then. didn’t look into it yet and simply filtered it out in grafana but will give your fix a try :+1:

This night I had a single -1 reading. I just increased the delay from my previous test from 250ms to 500ms. I also changed one of the return codes to -2 to get a better idea where it is going wrong, also when the sensor is running not connected to my arduino ide serial monitor screen.
Another test starting. Since the error is intermittent and sporadic, it is a tricky to analyze.
Still I have the idea that I am trying to solve the symptom, not the cause but it could work for now.

The changes I made in airgradient.cpp

while(!(_SoftSerial_CO2->available())) {
    retry++;
    // keep sending request until we start to get a response
    _SoftSerial_CO2->write(CO2Command, 7);

   //added serial output for analysis and increased delay from 50ms to 500ms
  Serial.print("Retry count ");
  Serial.println(retry);**
  delay(500);
    if (retry > 10) {
  	Serial.println("Error while requesting");
        return -1;
    }
}

int timeout = 0; 
    while (_SoftSerial_CO2->available() < 7) {
    timeout++; 
    if (timeout > 10) {
        while(_SoftSerial_CO2->available())  
          _SoftSerial_CO2->read();
       Serial.println("Error while accessing");
        break;                    
    }
   //increased delay from 50ms to 500ms
    delay(500);
}

for (int i=0; i < 7; i++) {
    int byte = _SoftSerial_CO2->read();
    if (byte == -1) {
        result.success = false;
   //added serial output for analysis and retun value -2 to differenciate and make visible in Grafana where things go wrong
  	Serial.println("Error while decoding");
        return -2;
    }
    CO2Response[i] = byte;
}

@ttielemans please let us know the results. If we can improve it, I’ll update the Arduino library.

I will share the results when I am confident I have a good solution. At this moment I am still testing with the orignal airgradient.cpp library and changes to the “Jeff Geerling” sketch. Testing is slow due to the intermittent occurance.

After quite some testing different improvement options, I now have stable values and no drop-outs anymore. I think the problem occured due to timing issues reading serial data. I have simplified the code and this seems to work fine.

This is the code I am currently using in the function “getCO2_Raw()” in the library airgradient.cpp

int AirGradient::getCO2_Raw(){
  const byte CO2Command[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};
  byte CO2Response[] = {0,0,0,0,0,0,0};
  
  _SoftSerial_CO2->write(CO2Command, 7);
  delay(100);  //give the sensor a bit of time to respond

  if (_SoftSerial_CO2->available()){
    for (int i=0; i < 7; i++) {
      int byte = _SoftSerial_CO2->read();
      CO2Response[i] = byte;
      if (CO2Response[0] != 254) {
        return -1;  //error code for debugging
      }
    } 
    unsigned long val = CO2Response[3]*256 + CO2Response[4];  
    return val;	
  }	
  else
  {
  return -2; //error code for debugging
  }
}

In my main sketch I loop this function in case I receive an exit code -1 or -2 but in the last 24hrs this did not happen once.

I hope that someone else can have an advantage of this change.

Thank you very much for supporting this.

I committed the code to the library and will test it on my devices for a few days. If it also runs stable for me, I will release an updated Arduino library.

Great work @ttielemans, I’ve also noticed the odd spike to -1 occurring at random times which is annoying to someone who wants perfection in their graphs lol. Further I’m also getting the CO2 spiking down to 515 at random times, so not sure what’s causing that at the moment.

@Znook I had the same occasional 515 (also 514 and 516 readings). What I could see was a left shift of the data package, resulting in a reading of 2*256 + 2 (or 3 or 4) resulting in values 514, 515 or 516. In my analysis I could see that the first byte was not the expected 0xFE but that this was shifted the second place.

I am pretty confident that this is also solved since I check in my code if 0xFE is in the first element of the response array. If this is not the case, I return -1 and do a re-read in the main loop.

 if (hasCO2) {
    int stat = -1; 
    while (stat <=0){
      stat = ag.getCO2_Raw();
     }
    message += "# HELP CO2 value, in ppm3\n";
    message += "# TYPE s8_co2 gauge\n";
    message += prefix;
    message += deviceId;
    message += "_";    
    message += "s8_co2";
    message += idString;
    message += String(stat);
    message += "\n";
  }

I also had some serial monitor checks in my code to see if the function ag.getCO2_Raw()
would get any retries. Until now it did not :grinning:.

1 Like

Thank you all for your contributions. I released an update for the AirGradient Arduino library.

Version 1.4.2 includes the above fix.

Hi @Achim_AirGradient ,

I have tried 1.4.2 version, but now it shows me random -1 value and also values of 65XXX.

Currently i’m testing 1.4.1 if there will be any better results…