Humidity control with Arduino UNO - problems with code

Hello everyone,

as my very first Arduino project, I want to build a humidity and temperature controller using the BME280 sensor (Adafruit breakout) and the Arduino UNO that controls a relay to automatically switch a humidifier and heater on and off.

My problem is, that the Arduino only reads the value of the last measurement. E.g. when the delay is specified with 10 seconds, it takes 20 seconds to control the relay whenever the threshold humidity is reached. How can I solve this problem in my code? Please find a detailed explanation of the problem below:

A frequently reported problem with the BME280 is, that it can run warm and therefore lead to temperature measurements that are too high (ca. 1°C). This is caused by the sensor constantly measuring in its default mode. A remedy is to put the sensor in "forced mode", so that it measures only when requested. It also works for me, at least I hope so (the reported temperature is still >1°C higher than measured with my cheap thermometer, but this might be tolerance). However, now the Arduino reads only the values form the last measurement, therefore the relay is controlled with a delay as specified with delay().

Please find the described piece of code below:

bme.setSampling(Adafruit_BME280::MODE_FORCED, 
                    Adafruit_BME280::SAMPLING_X1, // temperature 
                    Adafruit_BME280::SAMPLING_X1, // pressure 
                    Adafruit_BME280::SAMPLING_X1, // humidity 
                    Adafruit_BME280::FILTER_OFF   ); 
                        
     // suggested rate is 1/60Hz (1m) 
     delayTime = 60000; // in milliseconds

There is even a solution described for this problem, but I do not know how to implement it correctly in my code. The suggested piece of code below:

// set to forced mode, i.e. "take next measurement" 
         write8(BME280_REGISTER_CONTROL, _measReg.get()); 
        // wait until measurement has been completed, otherwise we would read 
      // the values from the last measurement 
        while (read8(BME280_REGISTER_STATUS) & 0x08) 
    delay(1);

How can I make this work?

This code can be found here: BME280: Current configuration leads to a too high temperature · Issue #164 · letscontrolit/ESPEasy · GitHub
and here (code lines 341-349): Allows force measurement without wait by SRGDamia1 · Pull Request #33 · adafruit/Adafruit_BME280_Library · GitHub

E.g. when implemented under void loop(), I just get the error message:
" '_measReg' was not declared in this scope"

This may be a very simple or even obvious problem to solve, as it seems that some definitions are missing in my code, but I don´t know how to do that (I actually thought that this is part of the Adafruit_BME280_Library and therefore e.g. "_measReg" should be defined already).

Since I fail to understand this, I am grateful for your feedback, suggestions, and help.

Please find the entire code below (I mainly copied the code pieces from different sources):

#include <Wire.h> 
#include <SPI.h> 
#include <LiquidCrystal_I2C.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>


//depending on which communication is used, select from below (
//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI

//defining the SPI pins
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11 
#define BME_CS 10

//defining setpoint and deadband for humidity control
#define SETPOINT 80
#define DEADBAND 5

//Define pins for relay
#define HUMIDIFIER 9
//define ON and OFF for relay
#define ON LOW
#define OFF HIGH

byte degree[8] = 
              {
                0b00011,
                0b00011,
                0b00000,
                0b00000,
                0b00000,
                0b00000,
                0b00000,
                0b00000
              };

//depending on which communication is used, select from below (I used SPI)
//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK); //defined SPI pins


// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

unsigned long delayTime;

void setup()
{

  pinMode(9, OUTPUT);
  digitalWrite(HUMIDIFIER, OFF);
  
  // initialize the LCD, turn on backlight, etc.
  lcd.begin();
  Serial.begin(9600);
  lcd.backlight();
  lcd.createChar(1, degree);


  //initializing sensor
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1); 

    }
     // weather monitoring (this is code I copied somewhere; it can be seen e.g. on pages linked above)
    Serial.println("-- Weather Station Scenario --");
    Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
    Serial.println("filter off");
    bme.setSampling(Adafruit_BME280::MODE_FORCED,
                    Adafruit_BME280::SAMPLING_X1, // temperature
                    Adafruit_BME280::SAMPLING_X1, // pressure
                    Adafruit_BME280::SAMPLING_X1, // humidity
                    Adafruit_BME280::FILTER_OFF   );
                      
    // suggested rate is 1/60Hz (1m) (I just changed it according to my needs)
    delayTime = 5000; // in milliseconds
    SPI.setClockDivider(SPI_CLOCK_DIV128);
  }

void loop()
{

bme.takeForcedMeasurement(); // since "foced mode" is used; has no effect in normal mode

// set to forced mode, i.e. "take next measurement" 
         //write8(BME280_REGISTER_CONTROL, _measReg.get()); 
        // wait until measurement has been completed, otherwise we would read 
      // the values from the last measurement 
       // while (read8(BME280_REGISTER_STATUS) & 0x08) 
   // delay(1);
  
  //safe meassured humidity value in h
  float h = bme.readHumidity();
  

//check if humidifyer is switched on right now
if(digitalRead(HUMIDIFIER) == ON)

//if humidity is higher than setpoint, switch off
{
  if (h > SETPOINT)
    {

      digitalWrite(HUMIDIFIER, OFF);
      }

//if humidity is lower than setpoiunt - deadband, switch off
}
else
{
  if(h < SETPOINT-DEADBAND)
    digitalWrite(HUMIDIFIER, ON);
    }

  //read temeprature and humidity
  Serial.print("Temp = ");
  Serial.print(bme.readTemperature());
  Serial.println("*C");

  Serial.print("Hum = ");
  Serial.print(bme.readHumidity());
  Serial.println("%");

  //show temeprature and humidity on LCD
  lcd.setCursor(0, 0);
  lcd.print("Temp: ");
  lcd.print(bme.readTemperature());
  lcd.write(1);
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Hum: ");
  lcd.print(bme.readHumidity());
  lcd.print("%");

  Serial.println();
  delay(delayTime);
  lcd.clear();


  }

Additional information:
Since I want to extend the reach of the sensor a bit (ca. 1.5m), I am planning to connect it through an Ethernet cable using SPI communication. I read several times that in this case, it would be a good idea to reduce the BUS speed. I tried this with "SPI.setClockDivider(SPI_CLOCK_DIV128);", but I don´t think it worked. Let me know if you have any idea, and also if I rather should open a new topic for that question. Also, for now I want to start with the humidification only. That's why heating control is not yet implemented in the code.

The BME280 are BMP280 that did not pass the factory tests. You are lucky if you get 1°C off absolute from the BMP, but you'll never get it from the BMEs. And if you read the datasheet, it says "estimate temperature".

zwieblum:
The BME280 are BMP280 that did not pass the factory tests.

Reference needed.

I don't think Bosch will intentionally remove the humidity sensing part (the main difference between the two) just because it doesn't measure temperature well enough.

The accuracy of the sensor is actually sufficient for my purposes. My problem is more connected to the implementation of the code.