2

I have a project I am working on, based on an ESP32 from NodeMCU. I have a bunch of sensors connected to said ESP32 - they all work and the code itself "works" with a minor quirk.

The issue in question starts with a DHT11 sensor. I started from the basic "hello world" DHT11 code (you can find it easily with a DHT11 search in google). That sensor works in my code that you can see below - I copied and pasted the sample code, and except for changing variables, did not alter the sample code really at all.

The issue I have is that while the sample code will read accurately on every loop, in my code, it reads from the sensor exactly once the first time the loop runs, and then never again.

I believe I have isolated the issue to this bit of code and the corresponding function it calls (it didn't used to be a function - that was a troubleshooting step):

  if (!client.connected()) {
    reconnectMQ();
  } etc...

By moving this statement and grouping the MQTT messaging to the end, the system runs a full loop with correct readings, exactly once, but after that function is called the DHT11 begins failing to read.

Things I have tried:

  • different variable names for temp and humidity (in case "t" and "h" are in use in the MQ library)
  • order of operations (made the loop work once)
  • changing the reconnectMQ() to a full function and not just a loop in the main loop
  • changing the logic of the DHT11 sensor to at least not hang forever trying to read - this meant it got through this part, but with 0 values
  • "turning off" MQ - this means that everything works, but obviously is a bit like cutting off your arm for a sprained wrist.
  • ENDLESS Google and Stack searches before resorting to this post.

I hate to do this as my project is 200 lines long, but I suspect the full code is needed to see what's possibly happening.

#include <time.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>

//use pin 23 to read temp and humidity
//our sensor is DHT11 type
//creates an instance of DHT sensor
#define DHTPIN 23
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

//Define the analog pins inbound for the Soil Moisture sensors
const int sm1Pin = 33;
const int sm2Pin = 34;
const int sm3Pin = 35;
const int sm4Pin = 32;

const int power = 22;
const int exec = 21;
const int net = 19;

//define the pin for the light level reading
const int light = 36;

//Init MQTT payload arrays
char data0[50];
char data1[50];
char data2[50];

// declare our Wifi and MQTT connections and other constant settings for the network
const char* ssid     = "*******";            // The SSID (name) of the Wi-Fi network you want to connect to
const char* password = "*******";                          // The password of the Wi-Fi network
const char* mqtt_server = "192.168.1.195";                             // The target mqtt server
const char* input_string = "{\"Reporting\":\"GardenUnit1\", ";       // The name of this garden monitor unit
String clientId = "GP1";
int lcount = 0;

// declare our Wifi and MQTT connections
WiFiClient espClient;
PubSubClient client(espClient);

//
// Reconnects to the MQTT message-bus if the connection died, or we're
// not otherwise connected.
//
void reconnectMQ() {

  digitalWrite(net, LOW);  // turn the Blue NET LED Off

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Wifi not connected - configuring");
    setup_wifi();
  } else {
    Serial.println("Wifi Connected - connecting MQTT");
  }

  // Attempt to connect
  Serial.println("Attempting to connect to MQTT Server...");
  while (!client.connected()) {
    if (client.connect(clientId.c_str())) {
      Serial.println("connected to MQTT server");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }

  // Once connected, publish an announcement...
  String payload = String(input_string) + "\"MQTT\":\"Reconnected\"}";
  payload.toCharArray(data1, (payload.length() + 1));
  client.publish("control", data1); //the "control" topic is just for notifications - change to fit your needs

  digitalWrite(net, HIGH);  // turn the Blue NET LED on
  delay(5000);
}

void setup_wifi() {
  delay(10);
  Serial.print("Connecting to ");
  Serial.print(ssid); Serial.println(" ...");

  WiFi.begin(ssid, password);             // Connect to the wifi network

  while (WiFi.status() != WL_CONNECTED) // Wait for the Wi-Fi to connect
    delay(1000);
    Serial.print('.');

  Serial.println('\n');
  Serial.println("Connected!");  
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());         // Send the IP address of the ESP32 to the serial port

}

void setup() {
  Serial.begin(9600); // open serial port, set the baud rate as 9600 bps
  // These Options control the precision of the reading, and the voltage reduction capability of the ESP32
  // Attenuation number 3 is 11DB
  analogSetWidth(10);
  analogSetAttenuation((adc_attenuation_t)3);

  // Define the MQTT Server connection settings and then launch the MQTT Connection
  client.setServer(mqtt_server, 1883);

  // Set output and input pins to correct modes
  pinMode (power, OUTPUT);
  pinMode (exec, OUTPUT);
  pinMode (net, OUTPUT);

  //Turn on Green Power light
  digitalWrite (power, HIGH);

  //Connect to the wireless network
  setup_wifi();

  //This call starts the dht11 sensor instance
  dht.begin();
}

void loop() {
  //Turn on RED EXEC light - this means a sample is being taken
  digitalWrite (exec, HIGH);

  //Read DHT11 Temp and Humidity - Humidity is a % and temp is in Celcius 
  float hum = dht.readHumidity();
  float temp = dht.readTemperature();
  // Check if any reads failed but insert bogus data so system continues
    if (isnan(hum) || isnan(temp)) {
        Serial.println("Failed to read from DHT sensor!");
        client.publish("garden1", "{\"Error\":\"Humidty/Temp Sensor Offline!\"}");
        hum = 0;
        temp = 0;
    } else {
        // print the result to Terminal
        Serial.print("Humidity: ");
        Serial.print(hum);
        Serial.print(" %\t");
        Serial.print("Temperature: ");
        Serial.print(temp);
        Serial.println(" *C ");
    }

  //Read value and print to serial for S1
  float s1 = analogRead(sm1Pin); 
  Serial.print("Sensor 1: ");
  Serial.print(s1); 
  Serial.println();
  //Read value and print to serial for S2
  float s2 = analogRead(sm2Pin); 
  Serial.print("Sensor 2: ");
  Serial.print(s2); 
  Serial.println();
  //Read value and print to serial for S3
  float s3 = analogRead(sm3Pin); 
  Serial.print("Sensor 3: ");
  Serial.print(s3); 
  Serial.println();
  //Read value and print to serial for S4
  float s4 = analogRead(sm4Pin); 
  Serial.print("Sensor 4: ");
  Serial.print(s4); 
  Serial.println();

  float L1 = analogRead(light);
  Serial.print("Light level: ");
  Serial.print(L1);
  Serial.println();


  if (!client.connected()) {
    reconnectMQ();
  }

  String payload = String(input_string) + "\"S1\":\"" + s1 + "\", \"S2\":\"" + s2 + "\", \"S3\":\"" + s3 + "\", \"S4\":\"" + s4 + "\"}";
  payload.toCharArray(data0, (payload.length() + 1));
  Serial.println("Publishing message 1:");
  while (!client.publish("garden1", data0)) {
    Serial.print(".");
  }
  String payload2 = String(input_string) + "\"Humidity\":\"" + hum + "\", \"Temperature\":\"" + temp + "\", \"Light\":\"" + L1 + "\"}";
  payload2.toCharArray(data2, (payload2.length() + 1));
  Serial.println("Publishing message 2:");
  while (!client.publish("garden1", data2)){
    Serial.print(".");
  }

  //Turn off RED EXEC light - this means a sample is done
  digitalWrite (exec, LOW);
  lcount = lcount + 1;
  delay(10000);
}

What happens when the code I have here runs is that I see all the messages at the Mosquito server and in serial monitor, and the loop runs as expected. Due to the logic I had to put in to keep the program running, after the first reading from the DHT11, temp and hum come back as 0 forever. This is obviously not what I want.

What is obvious: Something happens between the first reading of the DHT11 and the next that makes it unhappy.

What is not: What that something is. That something occurs in the MQTT connection, but for the life of me I cannot figure out what it is or isolate it.

So now I leave it to the community. What the heck is happening here?!

  • Hint(s): What could make the DHT11 read fail? Assuming 3.3V VDD to DHT11: How large pullup resistor? Extra capacitor on VDD-GND at the sensor? Extra long cables? Checked with logic analyzer? – Mikael Patel Jun 13 at 12:23
  • So normally I would agree with this assessment, and I tried rejiggering the hardware every way I could find online, however, the sensor only errors if the software connects to MSMQ. If I remove all connection code from the program (going back to the simple DHT11 test works fine) then the sensor reads flawlessly for hours on end, wired as is. (3v, direct from the 3v pin on the ESP, on a breadboard, maximum wire length of about 15 CM total roundtrip) The issue in this case is definitely software as the hardware works flawlessly with different code. – charrold303 Jun 13 at 19:40
  • What happens if you try to print hum and temp after this line: Serial.println("Failed to read from DHT sensor!"); – linhartr22 Jun 14 at 1:36
  • @linhartr22 - I think you might be a genius - I was thinking that when I send the values to MQTT, that these lines: c++ String payload2 = String(input_string) + "\"Humidity\":\"" + hum + "\", \"Temperature\":\"" + temp + "\", \"Light\":\"" + L1 + "\"}"; payload2.toCharArray(data2, (payload2.length() + 1)); Might be changing the variable type. Based on the error when I try to print them, I am sure of it. invalid operands of type 'const char [6] and float to binary operator + So the question is, what is the declaration to redeclare those variables. TO THE GOOGLE MACHINE! – charrold303 Jun 14 at 14:27
  • Turns out that wasn't it. I changed my string method to use sprintf() syntax and it still exhibits the same issue - when it loops back to the "top" of the loop, the red LED comes on as instructed in the code, and then it sits forever, indicating the error is happening on the read of the humidity from the DHT11. I still think this might be the right track, in that the humidity variable is somehow not compatible on the second loop, but the dtostrf() code I added should have remedied that. So I am still at the original issue - with MQTT turned on, DHT11 does not work. Turned off, works great. – charrold303 Jun 14 at 21:29
1

Leaving this here in case anyone else has a similar issue as an "answer" to my own question:

Simply put - DHT11 library as used, and MQTT library as used conflict. That's it, that's the answer.

There are two options for correcting this depending on your needs:

  • don't use or deeply examine and rebuild one of the libraries - frankly this was a negative ROI for me and not worth it

  • Add an ESP.restart(); at the end of the main program loop and AFTER the sleep timer - this reboots the ESP and allows the DHT11 to read BEFORE the MQTT connection happens and the solution works.

This, in my mind is not "a fix" it is a workaround, but it does address the primary issue.

  • I think that's not a conflict, you just forgot to subscribe the topic first before sending the data. – abu-ahmed al-khatiri Oct 4 at 10:50
  • No you can see it in the code above - there is no subscribe - it is a publish only. I moved the publish and messaging all over the place in the logical flow and literally it does not matter. The second you publish a message via MQTT, the DHT11 stops reading. The only way to get it to read again is to restart the ESP32. I do not believe this is a hardware issue, or even a library issue for each library (as they work fine on their own) it is just a conflict in the two libraries. Thus I left this here for others who might experience this. – charrold303 Oct 5 at 22:12
0

I've used the DHT11 library, not the DHT library in my sketches. The Example sketch should make it clear what minimal changes you'll need to make to your code. It always worked well for me.

  • So I literally used the example code inside my larger program. It is (except for the pin I used, and later the variable names) completely unmodified. You can find the example code here: esp32learning.com/code/esp32-and-dht11-sensor-example.php The issue is not that it doesn't work, it does work, but not in conjunction with MQTT. As soon as my ESP32 connects to the MQ server, the DHT stops reading. No MQTT code, and it works like a charm. – charrold303 Jun 14 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.