CO2 Sensor: Not working in whole project but in single script

I tried to make an air quality measurement station. It contains an lcd display, sensors for temperature, humidity, brightness, co2 and dust. It is based on an Arduino Nano.
However, the CO2 senesor works in a single script just for the sensor but not in the whole project. It always says "!Error: Timed out waiting for response".
Is it possible that the Arduino gets confused with the different baudrates? I have two times 9600 for the dust and co2 sensor aswell as 115200 for the serial. If so, is there a way to fix it in the code?

Here is the code that works:

#include <Arduino.h>
#include "MHZ19.h"                                        
#include <SoftwareSerial.h>                                // Remove if using HardwareSerial

#define RX_PIN 3                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 2                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             // Constructor for library
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial

unsigned long getDataTimer = 0;

void setup()
{
    Serial.begin(9600);                                     // Device to serial monitor feedback

    mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin(). 

    myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop()
{
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                

        int8_t Temp;
        Temp = myMHZ19.getTemperature();                     // Request Temperature (as Celsius)
        Serial.print("Temperature (C): ");                  
        Serial.println(Temp);                               

        getDataTimer = millis();
    }
}

And here the whole project where the CO2 sensor doesnt work anymore:

#include <Arduino.h>

//Display
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#include <Wire.h>
#define TFT_CS 7 //     Chip Select         P7 
#define TFT_DC 4 //   RS     nur pins D1-D4                   P6
#define TFT_RST 8 //Nano: D8 D1 mini: D6   //  Reset              P5     
//    #define TFT_MOSI D7 //Nano: D11 D1 mini: D7  // Data out MOSI / SDA  P4
//    #define TFT_SCLK D5 //Nano: D13 d1 mini: D5 // Clock out SCK / SPI  P3
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// For ST7735-based displays, we will use this call
// Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

//Luxmeter
#include <BH1750.h>
BH1750 lightMeter;

//SHT31 Temperature
#include <SHT31.h>
#define SHT31_ADDRESS   0x44
SHT31 sht;
float Tempr, Humd;
uint32_t start;
uint32_t stop;


//PMS
#include <SoftwareSerial.h>
#include <PMS.h>
SoftwareSerial pmsSerial(5, 6);
PMS pms(pmsSerial);
PMS::DATA data;


//CO2
#include "MHZ19.h"
#define RX_PIN 3                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 2                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)
MHZ19 myMHZ19;                                             // Constructor for library
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial
unsigned long getDataTimer = 0;
int CO2;




void setup(void) {

  Serial.begin(115200);
  Wire.begin();

  //Display
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.fillScreen(ST77XX_BLACK);
  tft.setRotation(1);

  //Luxmeter
  lightMeter.begin();

  //SHT31 Temperature
  sht.begin(SHT31_ADDRESS);
  uint16_t stat = sht.readStatus();

  //CO2
  mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start
  myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin().
  myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))


  //PMS
  pmsSerial.begin(9600);
  Wire.setClock(100000);


}

void loop() {


  if (pms.read(data))
  {

    Serial.print("PM 1.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_1_0);

    Serial.print("PM 2.5 (ug/m3): ");
    Serial.println(data.PM_AE_UG_2_5);

    Serial.print("PM 10.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_10_0);

    //CO2
    if (millis() - getDataTimer >= 2000)
    {
      

      CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)

      Serial.print("CO2 (ppm): ");
      Serial.println(CO2);

      int8_t Temp;
      Temp = myMHZ19.getTemperature();                     // Request Temperature (as Celsius)
      Serial.print("Temperature (C): ");
      Serial.println(Temp);

      getDataTimer = millis();
    }

    //SHT31 Temperature
    start = micros();
    sht.read();         // default = true/fast       slow = false
    stop = micros();
    Serial.print("T:");
    Serial.print(sht.getTemperature(), 1);
    Serial.print("H:");
    Serial.println(sht.getHumidity(), 1);
    Tempr = sht.getTemperature();
    Humd = sht.getHumidity();

    //Luxmeter
    float lux = lightMeter.readLightLevel();
    Serial.print("Light: ");
    Serial.print(lux);
    Serial.println(" lx");

  }
}

What does "doesn't work" mean, please?

I get the error message "!Error: Timed out waiting for response". for the CO2 values but any other value in the serial monitor works fine

What is "It" in this sentence?

id did a qoogling ( a quick googling)
https://www.google.de/search?q=arduino+using+two+software+serial+on+arduino+nano

and found this

the most important sentence is:

I would recommend a seeeduino XIAO instead of the Arduino Nano

a XIAO has two hardware serial interfaces and more interrupts than a Nano

or if you need more IO-pins take a teensy 3.0 which has 3 hardware serial interfaces
but is out of stock
so take a teensy 4.0 Teensy® 4.0

best regards Stefan

1 Like

I think you are onto something there! :wink:

maybe try something like this:
(compiles, not tested!)

#include <Arduino.h>

//Display
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#include <Wire.h>
#define TFT_CS 7 //     Chip Select         P7 
#define TFT_DC 4 //   RS     nur pins D1-D4                   P6
#define TFT_RST 8 //Nano: D8 D1 mini: D6   //  Reset              P5     
//    #define TFT_MOSI D7 //Nano: D11 D1 mini: D7  // Data out MOSI / SDA  P4
//    #define TFT_SCLK D5 //Nano: D13 d1 mini: D5 // Clock out SCK / SPI  P3
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// For ST7735-based displays, we will use this call
// Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

//Luxmeter
#include <BH1750.h>
BH1750 lightMeter;

//SHT31 Temperature
#include <SHT31.h>
#define SHT31_ADDRESS   0x44
SHT31 sht;
float Tempr, Humd;
uint32_t start;
uint32_t stop;


//PMS
#include <SoftwareSerial.h>
#include <PMS.h>
SoftwareSerial pmsSerial(5, 6);
PMS pms(pmsSerial);
PMS::DATA data;


//CO2
#include "MHZ19.h"
#define RX_PIN 3                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 2                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)
MHZ19 myMHZ19;                                             // Constructor for library
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial
unsigned long getDataTimer = 0;
int CO2;

void myMHZ19_start(){
  mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start
  myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin().
}

void setup(void) {

  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(100000);
  
  //Display
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.fillScreen(ST77XX_BLACK);
  tft.setRotation(1);

  //Luxmeter
  lightMeter.begin();

  //SHT31 Temperature
  sht.begin(SHT31_ADDRESS);
  uint16_t stat = sht.readStatus();

  //CO2
  myMHZ19_start();
  myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
  mySerial.end();										  //close MH-Z19 COM port

  //PMS
  pmsSerial.begin(9600);
  
  delay(10);

}

void loop() {


  if (pms.read(data))
  {

    Serial.print("PM 1.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_1_0);

    Serial.print("PM 2.5 (ug/m3): ");
    Serial.println(data.PM_AE_UG_2_5);

    Serial.print("PM 10.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_10_0);
	
    //CO2
    if (millis() - getDataTimer >= 2000)
    {
	  pmsSerial.end();									  //close PMS COM port
	  myMHZ19_start();									  //Open MH-Z19 COM port
	  delay(1);
      CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
	
      Serial.print("CO2 (ppm): ");
      Serial.println(CO2);

      int8_t Temp;
      Temp = myMHZ19.getTemperature();                     // Request Temperature (as Celsius)
      Serial.print("Temperature (C): ");
      Serial.println(Temp);

      getDataTimer = millis();
	  mySerial.end();									   //Close MH-Z19 COM port
	  pmsSerial.begin(9600);							   //Open PMS COM port
    }

    //SHT31 Temperature
    start = micros();
    sht.read();         // default = true/fast       slow = false
    stop = micros();
    Serial.print("T:");
    Serial.print(sht.getTemperature(), 1);
    Serial.print("H:");
    Serial.println(sht.getHumidity(), 1);
    Tempr = sht.getTemperature();
    Humd = sht.getHumidity();

    //Luxmeter
    float lux = lightMeter.readLightLevel();
    Serial.print("Light: ");
    Serial.print(lux);
    Serial.println(" lx");

  }
}

hope that helps....

1 Like

this actually works! :slight_smile:

I see that you put this out of setup and added id to the header:

void myMHZ19_start(){
  mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start
  myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin().
}

may I ask what is the background? Like what happens differently in the hardware when setting it up llike this?

Glad to hear that fixed it! :slight_smile:

only added this subroutine so that I would not have to repeat the code within in at multiple locations in the main code.
ie would work just the same as if you have put the code within the subroutine where it was required in the main code.

hope that helps...

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.