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?!
2 Answers 2
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– abu-ahmed al-khatiri2019年10月04日 10:50:45 +00:00Commented Oct 4, 2019 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– charrold3032019年10月05日 22:12:25 +00:00Commented Oct 5, 2019 at 22:12
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– charrold3032019年06月14日 14:12:43 +00:00Commented Jun 14, 2019 at 14:12
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!