HomeyDuino CO2 sensor

@Lars_Machiels, nice post and thanks for sharing !
Actually interested by this topic, I replied to a copy of your post by an usurper,
Funnily I was asking for more info, and every detail is available here in its original

It is so annoying, I’d like a moderator to check the issue, any idea on how to raise it to moderators ?
@Bram, here is the fraud below (raised it with the flag as spam)
https://community.homey.app/t/homeyduino-co2-sensor/28470

Many thanks

Hi Lars,

Sorry to bump up this topic, but i could not find anything similar with the TTGO ESP32 print in combination with the Senseair S8. Do you still have the code ?

The S8 works with UART (serial). Any device with UART should work with the S8. For reading the CO2 level use:

byte readCO2 = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};

Can somebody help me out?
I followed the wiring diagram and code as described, however I don’t get any input on my read out.

Was anybody able to get it work like described?

What exactly are you trying to achieve?

I try to create a multisensor for my ventilation system. Including a CO2 sensor with the Senseair S8.

I use a Wemos D1, which properly make connection to my wifi network, but than doesn’t give any further signal of CO2 level.

I see a comment in this toppic for using the
UART, does i have to add that libary?

I was looking in the code but didn’t saw any reference to this libary. But I just started using Arduino/Homeduino😅

Which platform are you using to program de D1? If Arduino you can use S8_UART library. Hook up the S8 to the Wemos (5V + GND + TX + RX), select an example program from the library (i.e. co2.cpp), compile & upload and off you go. Make sure to connect + and - for the S8 correctly otherwise you’ll blow it up.

If the sensor shows measurements (see in terminal) you’re 1 step further. To make it work with Homey/HomeyDuino you need to include the Homeyduino library as well. Here also you can use an example program to make sure everything works well. If so you’ll have to create your own program by merging the 2 example programs.

I am using Arduino for programming.

I already found the S8-UART Libary, but was wondering if that was included in te code as described by rindler, which I am using now.

I followed the wiring diagram as per

https://www.letscontrolit.com/wiki/index.php/S8

In the code as I understand the pin 13,15 are used to receive the Tx and Rx signal.

The power is working correctly since the led inside the sensor is blinking.

@D_S
Do you see measurements in the Termnal?

No in the serial monitor I don’t get any response from the sensor.

This means that there is something wrong in the communication between the Sensor and the Wemos, as you already mentioned, you are using pin 13 for Tx and pin 15 for Rx, are you sure you connect Tx (13) to the Rx of the sensor and 15 (Rx) to the Tx of the sensor? The wiring in your Link shows a different connection, but you must of course use the pins defined in your code.

Trying over and over, I followed the suggestion of Lars, and start with a code from the S8-UART library. That gives me now the co2 value in the serial monitor :sweat_smile:

But I don’t get the value in homey, end also combining with the DHT22 does’t work yet.

I understand that I have something to do with the Serial.print and Homey.setCapabilityValue. But I don’t understand how to get the correct value in this code.

Sorry for my stupidness, just started learning arduino/homeyduino.

If anybody know a good sort guideline how to start, please let me know.

Thanks for all the replies so far!

/*****************
   Get CO2 value 
 *****************/

#include <Arduino.h>
#include "s8_uart.h"
#include <Homey.h>

//SSID and Password of your WiFi router
const char* ssid = "smid";
const char* password = "ww";

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(")");
    }
  }
}



/* BEGIN CONFIGURATION */
#define DEBUG_BAUDRATE 115200

#if (defined USE_SOFTWARE_SERIAL || defined ARDUINO_ARCH_RP2040)
  #define S8_RX_PIN 5         // Rx pin which the S8 Tx pin is attached to (change if it is needed)
  #define S8_TX_PIN 4         // Tx pin which the S8 Rx pin is attached to (change if it is needed)
#else
  #define S8_UART_PORT  1     // Change UART port if it is needed
#endif
/* END CONFIGURATION */


#ifdef USE_SOFTWARE_SERIAL
  SoftwareSerial S8_serial(S8_RX_PIN, S8_TX_PIN);
#else
  #if defined(ARDUINO_ARCH_RP2040)
    REDIRECT_STDOUT_TO(Serial)    // to use printf (Serial.printf not supported)
    UART S8_serial(S8_TX_PIN, S8_RX_PIN, NC, NC);
  #else
    HardwareSerial S8_serial(S8_UART_PORT);   
  #endif
#endif


S8_UART *sensor_S8;
S8_sensor sensor;


void setup() {

  // Configure serial port, we need it for debug
  Serial.begin(DEBUG_BAUDRATE);
  
   // Wait port is open or timeout
  int i = 0;
  while (!Serial && i < 50) {
    delay(10);
    i++; 
  }
  Homey.begin("Multi-sensor1"); // Indien je meerdere sensoren wilt plaatsen, geef ze dan ieder een unieke naam
  Homey.setClass("sensor");
  Homey.addCapability("measure_co2"); // Co2 


  
  
  // First message, we are alive
  Serial.println("");
  Serial.println("Init");

  // Initialize S8 sensor
  S8_serial.begin(S8_BAUDRATE);
  sensor_S8 = new S8_UART(S8_serial);

  // Check if S8 is available
  sensor_S8->get_firmware_version(sensor.firm_version);
  int len = strlen(sensor.firm_version);
  if (len == 0) {
      Serial.println("SenseAir S8 CO2 sensor not found!");
      while (1) { delay(1); };
  }

  // Show basic S8 sensor info
  Serial.println(">>> SenseAir S8 NDIR CO2 sensor <<<");
  printf("Firmware version: %s\n", sensor.firm_version);
  sensor.sensor_id = sensor_S8->get_sensor_ID();
  Serial.print("Sensor ID: 0x"); printIntToHex(sensor.sensor_id, 4); Serial.println("");

  Serial.println("Setup done!");
  Serial.flush();
}


void loop() {
  
  //printf("Millis: %lu\n", millis());

  // Get CO2 measure
  sensor.co2 = sensor_S8->get_co2();
  printf("CO2 value = %d ppm\n", sensor.co2);

  //Serial.printf("/*%u*/\n", sensor.co2);   // Format to use with Serial Studio program

  // Compare with PWM output
  //sensor.pwm_output = sensor_S8->get_PWM_output();
  //printf("PWM output = %0.0f ppm\n", (sensor.pwm_output / 16383.0) * 2000.0);

  // Wait 5 second for next measure
  delay(5000);

}

 void homeyloop(){ 
  wifi(); // Beide
  Homey.loop(); // Beide
  Serial.print("PPMpwm: ");
  Homey.setCapabilityValue("measure_co2", sensor.co2); 

Serial.println("\n------------------------------");
  delay(5000);
 }



You should not use any delay() functions in your code. Handling Homey can be done in the main loop.
Homey.loop() should be called as much as possible so without being disturbed by delay(). Instead create your own delay with if (updateTime <= millis()) {}

This should theoretically work:

/*****************
   Get CO2 value
 *****************/

#include <Arduino.h>
#include "s8_uart.h"
#include <Homey.h>

//SSID and Password of your WiFi router
const char* ssid = "smid";
const char* password = "ww";

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(")");
    }
  }
}



/* BEGIN CONFIGURATION */
#define DEBUG_BAUDRATE 115200

#if (defined USE_SOFTWARE_SERIAL || defined ARDUINO_ARCH_RP2040)
#define S8_RX_PIN 5         // Rx pin which the S8 Tx pin is attached to (change if it is needed)
#define S8_TX_PIN 4         // Tx pin which the S8 Rx pin is attached to (change if it is needed)
#else
#define S8_UART_PORT  1     // Change UART port if it is needed
#endif
/* END CONFIGURATION */


#ifdef USE_SOFTWARE_SERIAL
SoftwareSerial S8_serial(S8_RX_PIN, S8_TX_PIN);
#else
#if defined(ARDUINO_ARCH_RP2040)
REDIRECT_STDOUT_TO(Serial)    // to use printf (Serial.printf not supported)
UART S8_serial(S8_TX_PIN, S8_RX_PIN, NC, NC);
#else
HardwareSerial S8_serial(S8_UART_PORT);
#endif
#endif


S8_UART *sensor_S8;
S8_sensor sensor;

uint32_t  updateTime = 0;

void setup() {

  // Configure serial port, we need it for debug
  Serial.begin(DEBUG_BAUDRATE);

  // Wait port is open or timeout
  int i = 0;
  while (!Serial && i < 50) {
    delay(10);
    i++;
  }
  Homey.begin("Multi-sensor1"); // Indien je meerdere sensoren wilt plaatsen, geef ze dan ieder een unieke naam
  Homey.setClass("sensor");
  Homey.addCapability("measure_co2"); // Co2




  // First message, we are alive
  Serial.println("");
  Serial.println("Init");

  // Initialize S8 sensor
  S8_serial.begin(S8_BAUDRATE);
  sensor_S8 = new S8_UART(S8_serial);

  // Check if S8 is available
  sensor_S8->get_firmware_version(sensor.firm_version);
  int len = strlen(sensor.firm_version);
  if (len == 0) {
    Serial.println("SenseAir S8 CO2 sensor not found!");
    while (1) {
      delay(1);
    };
  }

  // Show basic S8 sensor info
  Serial.println(">>> SenseAir S8 NDIR CO2 sensor <<<");
  printf("Firmware version: %s\n", sensor.firm_version);
  sensor.sensor_id = sensor_S8->get_sensor_ID();
  Serial.print("Sensor ID: 0x"); printIntToHex(sensor.sensor_id, 4); Serial.println("");

  Serial.println("Setup done!");
  Serial.flush();
}


void loop() {

  Homey.loop();
  
  if (updateTime <= millis()) {
    updateTime = millis() + 5000; // Update every 5 seconds

    wifi(); // (re)connect to WiFi network
    
    // Get CO2 measure
    sensor.co2 = sensor_S8->get_co2();
    Serial.print("CO2 Value: ");
    Serial.println(sensor.co2);
    
    Homey.setCapabilityValue("measure_co2", sensor.co2);
    
  }

}
1 Like

BTW, Homey probably did not work because you never called the homeyloop() function in the main loop(). If the Homey functions are never executed Homey will never receive the data.

Super this works perfect!
Will continue to integrate the DHT22 as well.

Thanks a lot!

You’re welcome. Good that it works now. Good luck with your Arduino projects.

I got it working including the DHT sensor. Only in the serial monitor the DHT sensor gives sometimes a error. (7184) However, for homey this will work. since not showing the error.

For those who are interested in the code see below:

/*****************
   Get CO2 value
 *****************/
#include <ESP8266WiFi.h>
#include <Arduino.h>
#include "s8_uart.h"
#include <Homey.h>
#include <SimpleDHT.h>
#include <SoftwareSerial.h>
#include <WiFiClient.h>

//SSID and Password of your WiFi router
const char* ssid = "smid";
const char* password = "password";



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(")");
    }
  }
}

#define PIN_DHT D5 // DHT22

SimpleDHT22 DHT22; // DHT22

unsigned long previousMillis = 0; // DHT22
const unsigned long interval = 5000; //Interval in milliseconds // DHT22


/* BEGIN CONFIGURATION */
#define DEBUG_BAUDRATE 115200

#if (defined USE_SOFTWARE_SERIAL || defined ARDUINO_ARCH_RP2040)
#define S8_RX_PIN 5         // Rx pin which the S8 Tx pin is attached to (change if it is needed)
#define S8_TX_PIN 4         // Tx pin which the S8 Rx pin is attached to (change if it is needed)
#else
#define S8_UART_PORT  1     // Change UART port if it is needed
#endif
/* END CONFIGURATION */


#ifdef USE_SOFTWARE_SERIAL
SoftwareSerial S8_serial(S8_RX_PIN, S8_TX_PIN);
#else
#if defined(ARDUINO_ARCH_RP2040)
REDIRECT_STDOUT_TO(Serial)    // to use printf (Serial.printf not supported)
UART S8_serial(S8_TX_PIN, S8_RX_PIN, NC, NC);
#else
HardwareSerial S8_serial(S8_UART_PORT);
#endif
#endif


S8_UART *sensor_S8;
S8_sensor sensor;

uint32_t  updateTime = 0;

void setup() {

  // Configure serial port, we need it for debug
  Serial.begin(DEBUG_BAUDRATE);

  // Wait port is open or timeout
  int i = 0;
  while (!Serial && i < 50) {
    delay(10);
    i++;
  }
  Homey.begin("Multi-sensor1"); // Indien je meerdere sensoren wilt plaatsen, geef ze dan ieder een unieke naam
  Homey.setClass("sensor");
  Homey.addCapability("measure_co2"); // Co2
  Homey.addCapability("measure_humidity"); // DHT22
  Homey.addCapability("measure_temperature");// DHT22



  // First message, we are alive
  Serial.println("");
  Serial.println("Init");

  // Initialize S8 sensor
  S8_serial.begin(S8_BAUDRATE);
  sensor_S8 = new S8_UART(S8_serial);

  // Check if S8 is available
  sensor_S8->get_firmware_version(sensor.firm_version);
  int len = strlen(sensor.firm_version);
  if (len == 0) {
    Serial.println("SenseAir S8 CO2 sensor not found!");
    while (1) {
      delay(1);
    };
  }

  // Show basic S8 sensor info
  Serial.println(">>> SenseAir S8 NDIR CO2 sensor <<<");
  printf("Firmware version: %s\n", sensor.firm_version);
  sensor.sensor_id = sensor_S8->get_sensor_ID();
  Serial.print("Sensor ID: 0x"); printIntToHex(sensor.sensor_id, 4); Serial.println("");

  Serial.println("Setup done!");
  Serial.flush();
}


void co2loop() { //void for co2

  Homey.loop();
  
  if (updateTime <= millis()) {
    updateTime = millis() + 5000; // Update every 5 seconds

    wifi(); // (re)connect to WiFi network
    
    // Get CO2 measure
    sensor.co2 = sensor_S8->get_co2();
    Serial.print("CO2 Value: ");
    Serial.println(sensor.co2);  

    Homey.setCapabilityValue("measure_co2", sensor.co2);

  }

}

void dhtloop() { // void for DHT22
  wifi(); 
  Homey.loop();
if (updateTime <= millis()) {
    updateTime = millis() + 10000; // Update every 10 seconds

    updateSensor(); // DHT22
  }
}

void updateSensor() { // DHT22
  byte temperature = 0; // DHT22
  byte humidity = 0; // DHT22
  int err = SimpleDHTErrSuccess; // DHT22
  if ((err = DHT22.read(PIN_DHT, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { // DHT22
    Serial.print("Read DHT22 failed, err="); Serial.println(err); // DHT22
    return; // DHT22
  }

  Serial.print((int)temperature); Serial.print(" *C, "); // DHT22
  Serial.print((int)humidity); Serial.println(" H"); // DHT22

  Homey.setCapabilityValue("measure_temperature", (int) temperature); // DHT22
  Homey.setCapabilityValue("measure_humidity", (int) humidity); // DHT22

}

void loop(){ // Beide
dhtloop();    //makes two separate voids, one per original code
co2loop();      //akes two separate voids, one per original code

} 


Probably you need 2 separate “updateTime” variables with 2 different names.
uint32_t updateTime1 = 0;
uint32_t updateTime2 = 0;

That was what I also thought, but couldn’t achieve with my knowledge so far.