I was already looking for a long time for a good CO2 meter but either they were too expensive or too unreliable. So finally I decided to create one myself with the help of Homeyduino. The sensor itself is from Senseair (S8, auto calibrating), a reliable company when it concerns these type of sensors. The sensor is connected (via UART) to a TTGO ESP32 with display so the CO2 value can also be read directly. When the CO2 value exceeds 1000 parts per million I will be notified by my Google Home.
I must admit the enclosure looks horrible but by the lack of some good tools and patience it became what it is. At least it works perfectly well.
Cool! I also planned to go that way, bought a senseair s8 sensor, but never put it together. Have now three Netatmo healthy home coaches as CO2-sensors which is connected through Homey to control my roof fan.
The code was flashed to the ESP32 with the Arduino IDE. The libraries used are: TFT_eSPI and HomeyDuino. The TTGO communicates via UART/Serial2 to the Senseair sensor. If you’re handy with Arduino programming and soldering you can easily do it yourself. Most of the code I just borrowed from some samples and adapted it for my own purpose.
The total costs were about 50 Euro which is not much compared to what is available on the market. The sensor was most expensive but I wouldn’t recommand cheap Chinese rubbisch. They are not very accurate, brake easily or are not auto calibrating. Maybe there are some good ones but I haven’t seen any.
With Homey Insights every measurement is logged which can be seen in some nice graphics. When the CO2 values become too high the ventilation system is switched on automatically which prevents me from hallucinating (only when I am not on other stimulants of course) and other nasty things.
With some help (thanks to maxxie01 on Slack) I did a Homeyduino CO2 sensor myself. Also a Senseair S8-sensor, connected to a wemos like described here https://www.letscontrolit.com/wiki/index.php/S8.
Here’s the Arduino code if anyone is interested. This is just the code for the board (wemos) and the sensor, no fancy display.
/*
Basic Arduino example for K-Series sensor
Created by Jason Berger
Co2meter.com
Adjusted to Homeyduino by maxxie01/rindlerblabla
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <SoftwareSerial.h>
#include <Homey.h>
SoftwareSerial S8_Serial(13,15); //Sets up a virtual serial port
//Using pin 13 for Tx and pin 15 for Rx
unsigned long prevReadTime = 0;
unsigned int ReadTimeInterval = 300000; //Update interval in ms
unsigned long valCO2 = 0;
byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};
byte response[] = {0,0,0,0,0,0,0};
int valMultiplier = 1;
void wifi() {
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin("SSID", "PASSWORD");
uint8_t timeout = 30;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (timeout<1) break;
}
if (WiFi.status() == WL_CONNECTED) {
//Print IP address
Serial.print("Connected to WiFi! (");
Serial.print(WiFi.localIP());
Serial.println(")");
}
}
}
void setup()
{
Serial.begin(115200);
S8_Serial.begin(9600);
Homey.begin("senseair-s8");
Homey.setClass("sensor");
Homey.addCapability("measure_co2");
}
void loop()
{
wifi();
Homey.loop();
//to check not every loop use this interval method
if(millis() - prevReadTime > ReadTimeInterval){
prevReadTime = millis();
sendRequest(readCO2);
unsigned long tmpValCO2 = getValue(response);
if(tmpValCO2 != valCO2){
valCO2 = tmpValCO2;
Serial.print("CO2 ppm = ");
Serial.println(valCO2);
Homey.setCapabilityValue("measure_co2", (int) valCO2 );
}
}
}
void sendRequest(byte packet[])
{
while(!S8_Serial.available()) //keep sending request until we start to get a response
{
S8_Serial.write(readCO2,7);
delay(50);
}
int timeout=0; //set a timeoute counter
while(S8_Serial.available() < 7 ) //Wait to get a 7 byte response
{
timeout++;
if(timeout > 10) //if it takes to long there was probably an error
{
while(S8_Serial.available()) //flush whatever we have
S8_Serial.read();
break; //exit and try again
}
delay(50);
}
for (int i=0; i < 7; i++)
{
response[i] = S8_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;
}
Just finished my second version. This time in a 3D printed enclosure and a Bosch BME680 (with official Bosch library). So now I can read CO2/Temp/Humidity/Pressure/VOC/IAQ. The BME680 can also act as a smoke detector. I tried it with setting a piece of paper on fire. The IAQ readings immediately went up to over 400 (range 0-500),
One can do the (WiFi) setup via a WiFi access point to fill in the parameters for WiFi/Homey and a MQTT client. Still need to calibrate the CO2 sensor by the way.
If you want to use the Bosch library you indeed need to go through the steps as described. Including a library for the ESP32 is slightly different. To include it it was little bit tricky but it can be done. Once you edit the Arduino files for the ESP32 the library is added for all projects so keep the originals.
I just use the IAQ (indoor air quality) index, I don’t think there is PPB value. There is a VOC resistence value though.
Maybe I did something wrong, but the code above just spammed my Homey with several alerts every second that there were no fire, ha! For sure it depends on were you put the setCapabilityValue-code. Anyhow, the code below solved it for me.