Using a DHT11 sensor with a dimmer to control temperature

Hi

I am trying to use a DHT11 sensor in combination with a RBD Dimmer to control a incandescent bulb and maintain temperature (99F - 102F) in an incubator. I did this successfully with a TMP36 sensor before but that one is giving wrong readings and started overheating the eggs so I tried this one instead. The sensor is definitely working since I tried the DHTtester example in the DHT sensor library, but when I combine it with my dimmer control code it doesn't work. The sensor just does not read anything and I get 'NAN' in the LCD display I have attached.
I understand that this is a slow sensor and so I am using the millis() function to avoid using delay() but no use.
Please help!
Code:

#include <DHT.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <RBDdimmer.h>//

//#define USE_SERIAL  SerialUSB //Serial for boards whith USB serial port
#define USE_SERIAL  Serial
#define outputPin  12 //dimmer output
#define DHTTYPE DHT11
#define DHTPIN 3
#define DELAY 1000
// #define zerocross  2 // for boards with CHANGEBLE input pins

//temperature measurement and averaging
const int numReadings = 10;
float tempreadings[numReadings];      // the readings from the temp sensor analog input
int readIndex = 0;              // the index of the current reading
int totaltemp = 0;                  // the running total of temp values
int averagetemp = 0;
uint32_t last_dht11_reading_ms = 0;
float temp;
float hum;

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

DHT dht(DHTPIN, DHTTYPE);// Initialize DHT sensor.

int outVal = 0;
dimmerLamp dimmer(outputPin); //initialase port for dimmer 



void setup() {
  lcd.begin(); //initialize the lcd
  lcd.backlight(); //open the backlight 
 
  dimmer.begin(NORMAL_MODE, ON); //dimmer initialisation: name.begin(MODE, STATE)

  dht.begin();// Initialize DHT sensor.
  
   // initialize all readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
     tempreadings[thisReading] = 0;
  } 
  
}

void loop() 
{     
  // subtract the last reading:
   totaltemp = totaltemp - tempreadings[readIndex];
   uint32_t current_ms = millis();
    // read from the sensor:
   if( current_ms - last_dht11_reading_ms > DELAY ) {
    tempreadings[readIndex] = dht.readTemperature(true);// read PRIMARY temperature sensor
    temp = tempreadings[readIndex];
    hum = dht.readHumidity(); // read Humidity
    last_dht11_reading_ms = current_ms;
    if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
    }
   }
   else {
      if (readIndex == 0 && millis() <=1000){
        tempreadings[readIndex] = 72;
        }
        else {
          tempreadings[readIndex] = tempreadings[readIndex-1];
          }      
     }
    totaltemp = totaltemp + tempreadings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;
 
// if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }
  float TempF = totaltemp / numReadings; // calculate the average temperature value:
  if (TempF <= 99){
   outVal = 70;
  }
   else {
    if (TempF >99 && TempF <= 102)
    outVal = 50;
  }
  if (TempF > 102)
    while (TempF > 102){
     outVal -= 5;
     delay(DELAY);
    }
    
  dimmer.setPower(outVal); // name.setPower(0%-100%)
  lcd.setCursor(0, 0); // Set the cursor on the first column and first row.
  lcd.print("T1 ");
  lcd.print(TempF);
  lcd.setCursor(9, 0); // Set the cursor on the 10th column and first row.
  lcd.print("Hu");
  lcd.print(hum);
  lcd.setCursor(0, 1); // Set the cursor on the first column and second row.
  lcd.print("Dim:");
  lcd.print(outVal);
  lcd.print(" % ");
}

Temp_based_dimmer_control2.ino (2.49 KB)

DHT_based_dimmer.ino (3.18 KB)

Do you use the Adafruit DHT library ?

That library reads the temperature once per 2 seconds, regardless how often you call dht.readTemperature().
Do you use a pullup resistor ? How long are the wires ? Do you use a cable ?

I have many doubts about the structure of the code and the code in the loop().
I think you should start over. Can you first make a sketch without the moving average filter ?

How does this work:

if (TempF > 102)
{
  while (TempF > 102)
  {
    outVal -= 5;
    delay(DELAY);
  }
}

This seems to be initializing code. It is not okay. If you need to initialize something, then you should do that in the setup() function.

if (readIndex == 0 && millis() <= 1000)
{
  tempreadings[readIndex] = 72;
}

The moving average filter is always used in the loop(), even if there was not a new temperature. It does mathematically make no sense.

According to the official reference of millis() and according to the source code of millis(), it returns a 'unsigned long'. Please use 'unsigned long' for millis() values and not 'uint32_t'.

How often do you want to call dimmer.setPower() ? Can you call that as often as your read the temperature ? Once per second or once per two seconds ?

Yes, I am using the Adafruit DHT library. I did try 2 seconds but that didn't work either. The DHT11 sensor I am using came with a pullup resistor included. The cables are about two feet long.

I will try running the code without the averaging.

if (TempF > 102)
{
while (TempF > 102)
{
outVal -= 5;
delay(DELAY);
}
}

This is for when the temperature goes above 102, and instead of just bouncing back to the previous level (50%), it tries to find a number at which it steadies itself. I used the averaging and the dimmer adjustments succesfully with the previous version of my incubator, the one with the TMP36.

I will change the millis data type as suggested and try. I guess I only need to call the dimmer.setPower() when i measure the temperature, so I will change that and try. Thank you for all your questions and inputs.

getsidgo:
The sensor is definitely working since I tried the DHTtester example in the DHT sensor library, but when I combine it with my dimmer control code it doesn't work. The sensor just does not read anything and I get 'NAN' in the LCD display I have attached.

Wait a minute ... is the sensor working or not? When you say "The sensor just does not read anything," that suggests not (likely a code problem).

A suggestion: Break your project up. First get the sensor working properly such that it displays the correct temperature on the LCD. Make sure the reading changes when you warm or cool the sensor. Have it also print values to the serial monitor, just for an independent check on operation. Eliminate parts of the code which are not relevant to what you are doing, since increased complexity means increased probability of error. When the temperature measurement and display part is working properly and you understand its operation, then insert your statements which use the temperature values to control the heater.
S.

I broke it up as you suggested and removed all unnecessary code. When I used the DHT11 with the LCD it works just fine:

#include <DHT.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#define USE_SERIAL  Serial
#define DHTTYPE DHT11
#define DHTPIN 3
#define DELAY 2000

unsigned long last_dht11_reading_ms = 0;
float temp;
float hum;

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

DHT dht(DHTPIN, DHTTYPE);// Initialize DHT sensor.

void setup() {
  Serial.begin(9600);
  lcd.begin(); //initialize the lcd
  lcd.backlight(); //open the backlight 
  dht.begin();// Initialize DHT sensor.

void loop() 
{  
    unsigned long current_ms = millis();
//    // read from the sensor:
  if( current_ms - last_dht11_reading_ms > DELAY ) {

    temp = dht.readTemperature(true);
    hum = dht.readHumidity(); // read Humidity
    last_dht11_reading_ms = current_ms;
    if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
    }
 }
  lcd.setCursor(0, 0); // Set the cursor on the first column and first row.
  lcd.print("T1 ");
  lcd.print(temp);
  lcd.setCursor(9, 0); // Set the cursor on the 10th column and first row.
  lcd.print("Hu");
  lcd.print(hum);
}

I see the temp and humidity values on the LCD. The minute I initialise the dimmer though (dimmer.begin), I get NAN values on the LCD for the temp and humidity. I tried finding this on other forums and there was something about interrupts that the dimmer uses which cannot work with the DHT11. Is there a way around this?

getsidgo:
I see the temp and humidity values on the LCD. The minute I initialise the dimmer though (dimmer.begin), I get NAN values on the LCD for the temp and humidity. I tried finding this on other forums and there was something about interrupts that the dimmer uses which cannot work with the DHT11. Is there a way around this?

There are always ways around. Unless you want to track down the source of the interrupt conflict, you could simply switch to an analog temperature sensor. The LM335, for example, has a nice, well-characterized linear output and requires only one resistor for operation. Feed its output into one of the Arduino's analog input pins and measure using the analogRead function. You can even test compatibility with the dimmer by adding the analogRead statement by itself; you'll just get nonsense readings until the sensor is attached.
S.

Or there's the DS18B20.

getsidgo:
When I used the DHT11 with the LCD it works just fine

That is a good start.

Have you told us which Arduino board you use ?
Which Robodyn dimmer do you use ?
Is this the library that you use ? GitHub - RobotDynOfficial/RBDDimmer: The following library is used for work with dimmer, it gives ability to control large ammoun of dimmer. This lib uses with Leonardo, Mega, UNO, ESP8266, ESP32, Arduino M0, Arduino Zero, Arduino Due, STM32..
Can you give a link to your DHT11 module ? Preferably a link to where you bought it. How is a pullup resistor include ? What is its value ? How did you connect it ?
How long are the wires between the Arduino and the DHT11 ?

getsidgo:
there was something about interrupts that the dimmer uses which cannot work with the DHT11. Is there a way around this?

Maybe not. We can have a look at it if we have enough information. There are other temperature sensors. The TMP36 with a better reference voltage is also a option.

The DHT11 library stops interrupts for a short time. That might interfere with the dimmer. The dimmer uses a lot of interrupts, that might influence the DHT11 signals, but perhaps there are other libraries that work better.

getsidgo:
Hi

I am trying to use a DHT11 sensor in combination with a RBD Dimmer to control a incandescent bulb and maintain temperature (99F - 102F) in an incubator.

The accuracy of that sensor is +/- 2°C, that's over twice the range you're asking for (if it says 100F it could be anywhere from 97F to 103F). You need a sensor that's +/- 0.5° if you want to keep your incubator within that narrow a range.

The DS18B20 sensor as suggested above does give you the accuracy you need (it's rated +/- 0.5°C).

The TMP36 should do the job as well - provided you use the internal 1.1V ADC reference to read the sensor,and calibrate this reference (it's stable but has a 10% tolerance).

The DHT11 is a toy, barely good enough for a demo project. Not something to use for anything serious.

wvmarle:
The accuracy of that sensor is +/- 2°C, that's over twice the range you're asking for (if it says 100F it could be anywhere from 97F to 103F). You need a sensor that's +/- 0.5° if you want to keep your incubator within that narrow a range.

Accuracy (of a temperature sensor) is easily compensated by calibration. What is more important is precision and reproducibility, lack of hysteresis, low thermal mass, and high thermal conductivity. It is likely that, given the relatively simple approach being employed, there will be some offset anyway, the "degree" :slight_smile: of which will depend on the heat transfer characteristics of the system. Of course, there is nothing wrong with using a sensor that also incorporates high accuracy, but that alone will not ensure that the system arrives at its setpoint.
S.

Koepel:
That is a good start.

Have you told us which Arduino board you use ?
Which Robodyn dimmer do you use ?
Is this the library that you use ? GitHub - RobotDynOfficial/RBDDimmer: The following library is used for work with dimmer, it gives ability to control large ammoun of dimmer. This lib uses with Leonardo, Mega, UNO, ESP8266, ESP32, Arduino M0, Arduino Zero, Arduino Due, STM32..
Can you give a link to your DHT11 module ? Preferably a link to where you bought it. How is a pullup resistor include ? What is its value ? How did you connect it ?
How long are the wires between the Arduino and the DHT11 ?
Maybe not. We can have a look at it if we have enough information. There are other temperature sensors. The TMP36 with a better reference voltage is also a option.

The DHT11 library stops interrupts for a short time. That might interfere with the dimmer. The dimmer uses a lot of interrupts, that might influence the DHT11 signals, but perhaps there are other libraries that wor

The board is Arduino Uno. The dimmer is the RBD Dimmer. The DHT11 sensor is from Robotdyn and came with the pullup resistor included. Before this go around, I was using the TMP36 but it started giving very wrong values (5 degrees off), and I am not quite sure how to calibrate it. I have ordered a DS18b20 and will try that one instead.

Not sure what you mean by value? I connected it with the pins provided (you can see in the link that it has just the data pin, grnd and vcc).

srturner:
Accuracy (of a temperature sensor) is easily compensated by calibration. What is more important is precision and reproducibility, lack of hysteresis, low thermal mass, and high thermal conductivity.
S.

Does the DS18b20 have these characteristics? I have read and reread the datasheets but its all a little complicated to be honest.
Thank you to everyone for the answers. You guys are amazing for taking the time to read this stuff and answer.

The DallasTemperature is the library to use with the DS18B20. However, the library for the DS18B20 also turn off interrupts and also are influenced by the Dimmer interrupt. You might end up with the same problem :confused:

The dimmer code for the Arduino Uno is here: RBDDimmer/RBDmcuAVR.cpp at master · RobotDynOfficial/RBDDimmer · GitHub.
I can not say how that conflicts with other code. Timer2 is used and the interrupt of digital pin 2.

At this moment I don't know if the problem is hardware (noise from the dimmer) or software (interrupts) :frowning:

Adafruit has a tutorial for the TMP36 and they use the 3.3V for better precision.

You already had a filter in software for the TMP36. That is good, I would always use a software filter in these situations.
I suggest you try to make both work good (TMP36 with 3.3V and DS18B20).

There is a problem with your code, how often things are done, with millis() and timing. That can be fixed.

There's actually no need for phase cutting (and dealing with the ZC & timer interrupts) when controlling a heater. Just switch it on/off for a few seconds at a time. Thermal mass is probably more than enough to stabilise the temperature.

Likely more important is to set up a proper PID control. The Arduino PID library even can do bang-bang control, perfect for heaters.

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