Подключение к MQTT приводит к тому, что датчик DHT11 перестает работать?
У меня есть проект, над которым я работаю, основанный на ESP32 от NodeMCU. У меня есть куча датчиков, подключенных к указанному ESP32 — все они работают, и сам код «работает» с небольшой причудой.
Проблема начинается с датчика DHT11. Я начал с базового кода DHT11 «hello world» (вы можете легко найти его с помощью поиска DHT11 в Google). Этот датчик работает в моем коде, который вы можете видеть ниже - я скопировал и вставил пример кода, и, за исключением изменения переменных, фактически вообще не изменил образец кода.
Проблема заключается в том, что, хотя пример кода будет точно считываться в каждом цикле, в моем коде он считывается с датчика только один раз при первом запуске цикла, а затем никогда больше.
Я полагаю, что изолировал проблему в этом фрагменте кода и соответствующей функции, которую он вызывает (раньше это не было функцией — это был шаг устранения неполадок):
if (!client.connected()) {
reconnectMQ();
} etc...
Переместив этот оператор и сгруппировав сообщения MQTT в конец, система выполняет полный цикл с правильными показаниями ровно один раз, но после вызова этой функции DHT11 начинает не читать.
Вещи, которые я пробовал:
- разные имена переменных для температуры и влажности (в случае, если в библиотеке MQ используются "t" и "h")
- порядок операций (цикл заработал один раз)
- изменение reconnectMQ() на полноценную функцию, а не просто на цикл в основном цикле
- изменение логики датчика DHT11, чтобы хотя бы не зависать вечно при попытке чтения - это значит, что он прошел эту часть, но с 0 значениями
- "отключение" MQ - это значит, что все работает, но, очевидно, это немного похоже на отсечение руки за вывихнутое запястье.
- БЕСКОНЕЧНЫЕ поиски в Google и Stack, прежде чем прибегнуть к этому сообщению.
Я ненавижу это делать, так как мой проект состоит из 200 строк, но я подозреваю, что нужен полный код, чтобы увидеть, что, возможно, происходит.
#include <time.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
//используем контакт 23 для считывания температуры и влажности
//наш датчик типа DHT11
//создает экземпляр датчика DHT
#define DHTPIN 23
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Определяем входящие аналоговые контакты для датчиков влажности почвы
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;
// определяем пин для считывания уровня освещенности
const int light = 36;
//Инициализируем массивы полезной нагрузки MQTT
char data0[50];
char data1[50];
char data2[50];
// объявляем наши соединения Wifi и MQTT и другие постоянные настройки для сети
const char* ssid = "*******"; // SSID (имя) сети Wi-Fi, к которой вы хотите подключиться
const char* password = "*******"; // Пароль сети Wi-Fi
const char* mqtt_server = "192.168.1.195"; // Целевой сервер mqtt
const char* input_string = "{\"Reporting\":\"GardenUnit1\", "; // Название этого садового монитора
String clientId = "GP1";
int lcount = 0;
// объявляем наши соединения Wifi и MQTT
WiFiClient espClient;
PubSubClient client(espClient);
//
// Повторно подключается к шине сообщений MQTT, если соединение прервано или мы
// иначе не подключен.
//
void reconnectMQ() {
digitalWrite(net, LOW); // выключаем синий светодиод NET
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Wifi not connected - configuring");
setup_wifi();
} else {
Serial.println("Wifi Connected - connecting MQTT");
}
// Попытка подключения
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");
// Подождите 5 секунд перед повторной попыткой
delay(5000);
}
}
// После подключения публикуем объявление...
String payload = String(input_string) + "\"MQTT\":\"Reconnected\"}";
payload.toCharArray(data1, (payload.length() + 1));
client.publish("control", data1); //тема "control" предназначена только для уведомлений - меняйте под свои нужды
digitalWrite(net, HIGH); // включить синий светодиод NET
delay(5000);
}
void setup_wifi() {
delay(10);
Serial.print("Connecting to ");
Serial.print(ssid); Serial.println(" ...");
WiFi.begin(ssid, password); // Подключаемся к сети Wi-Fi
while (WiFi.status() != WL_CONNECTED) // Подождите, пока Wi-Fi подключится
delay(1000);
Serial.print('.');
Serial.println('\n');
Serial.println("Connected!");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // Отправляем IP-адрес ESP32 на последовательный порт
}
void setup() {
Serial.begin(9600); // открываем последовательный порт, устанавливаем скорость передачи 9600 бит/с
// Эти параметры контролируют точность показаний и возможность снижения напряжения ESP32.
// Затухание номер 3 равно 11 дБ
analogSetWidth(10);
analogSetAttenuation((adc_attenuation_t)3);
// Определяем настройки подключения к серверу MQTT, а затем запускаем подключение MQTT
client.setServer(mqtt_server, 1883);
// Установить выходные и входные контакты в правильные режимы
pinMode (power, OUTPUT);
pinMode (exec, OUTPUT);
pinMode (net, OUTPUT);
// Включите зеленый индикатор питания
digitalWrite (power, HIGH);
//Подключаемся к беспроводной сети
setup_wifi();
//Этот вызов запускает экземпляр датчика dht11
dht.begin();
}
void loop() {
// Включите КРАСНЫЙ индикатор EXEC — это означает, что берется образец
digitalWrite (exec, HIGH);
// Чтение DHT11 Temp and Humidity — влажность в %, а температура в градусах Цельсия
float hum = dht.readHumidity();
float temp = dht.readTemperature();
// Проверяем, не завершились ли какие-либо операции чтения, но вставляем фиктивные данные, чтобы система продолжала работать
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 {
// вывод результата в Терминал
Serial.print("Humidity: ");
Serial.print(hum);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" *C ");
}
//Чтение значения и печать в серийный номер для S1
float s1 = analogRead(sm1Pin);
Serial.print("Sensor 1: ");
Serial.print(s1);
Serial.println();
//Чтение значения и печать в серийный номер для S2
float s2 = analogRead(sm2Pin);
Serial.print("Sensor 2: ");
Serial.print(s2);
Serial.println();
//Чтение значения и печать в серийный номер для S3
float s3 = analogRead(sm3Pin);
Serial.print("Sensor 3: ");
Serial.print(s3);
Serial.println();
//Чтение значения и печать в серийный номер для 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(".");
}
//Выключить КРАСНЫЙ индикатор EXEC — это означает, что образец готов
digitalWrite (exec, LOW);
lcount = lcount + 1;
delay(10000);
}
Что происходит, когда код, который у меня есть здесь, работает, так это то, что я вижу все сообщения на сервере Mosquito и в последовательном мониторе, и цикл работает, как и ожидалось. Из-за логики, которую я должен был использовать, чтобы программа продолжала работать, после первого считывания с DHT11 температура и шум навсегда возвращаются к 0. Это явно не то, чего я хочу.
Что очевидно: Что-то происходит между первым чтением DHT11 и следующим, что делает его несчастным.
Что не так: Что это такое. Это что-то происходит в соединении MQTT, но я не могу понять, что это такое, или изолировать это.
Теперь я оставляю это сообществу. Какого черта здесь происходит?!
@charrold303, 👍2
Обсуждение2 ответа
В своих скетчах я использовал библиотеку DHT11, а не библиотеку DHT. В наброске примера должно быть ясно, какие минимальные изменения вам нужно будет внести в свой код. У меня это всегда хорошо получалось.
Поэтому я буквально использовал код примера внутри своей более крупной программы. Он (за исключением вывода, который я использовал, а затем и имен переменных) полностью неизменен. Вы можете найти пример кода здесь: http://www.esp32learning.com/code/esp32-and-dht11-sensor-example.php Проблема не в том, что он не работает, он работает, но не в связке с MQTT. Как только мой ESP32 подключается к серверу MQ, чтение DHT прекращается. Нет кода MQTT, и он работает как шарм., @charrold303
Оставить это здесь на случай, если у кого-то возникнет аналогичная проблема, в качестве «ответа» на мой вопрос:
Проще говоря, используемая библиотека DHT11 и используемая библиотека MQTT конфликтуют. Вот он, это ответ.
Есть два варианта исправления в зависимости от ваших потребностей:
не используйте, не исследуйте и не перестраивайте одну из библиотек — честно говоря, для меня это было отрицательной рентабельностью, и оно того не стоило
Добавить ESP.restart(); в конце основного цикла программы и ПОСЛЕ таймера сна — это перезагружает ESP и позволяет DHT11 читать ДО того, как произойдет соединение MQTT и решение сработает.
На мой взгляд, это не «исправление», а обходной путь, но он решает основную проблему.
Я думаю, что это не конфликт, вы просто забыли сначала подписаться на тему, прежде чем отправлять данные., @abu-ahmed al-khatiri
Нет, вы можете видеть это в приведенном выше коде — подписки нет — только публикация. Я переместил публикацию и обмен сообщениями повсюду в логическом потоке, и буквально это не имеет значения. Как только вы публикуете сообщение через MQTT, DHT11 прекращает чтение. Единственный способ заставить его снова читать — перезапустить ESP32. Я не думаю, что это проблема с оборудованием или даже проблема с библиотекой для каждой библиотеки (поскольку они отлично работают сами по себе), это просто конфликт в двух библиотеках. Поэтому я оставил это здесь для других, которые могут испытать это., @charrold303
- Опубликовать чип в mqtt с помощью ESP32-CAM
- esp32 Stack canary watchpoint срабатывает
- Преобразование byte* в int в Arduino
- Почему функция server.on() из "ESPAsyncWebServer.h" выполняется на стороне setup(), а не на стороне loop()?
- esp32-cam публикует изображение в mqtt
- Публиковать данные json в mqtt
- Не удалось подключиться к брокеру MQTT через esp8266/32 и pub/sub client
- ESP32 отправляет данные на другой ESP32 без установления соединения Wi-Fi
Совет(ы): что может привести к сбою чтения DHT11? Предполагая, что 3,3 В VDD к DHT11: насколько большой подтягивающий резистор? Дополнительный конденсатор на VDD-GND на датчике? Очень длинные кабели? Проверяли логическим анализатором?, @Mikael Patel
Так что обычно я согласен с этой оценкой, и я попытался перенастроить аппаратное обеспечение любым способом, который я мог найти в Интернете, однако датчик ошибается только в том случае, если программное обеспечение подключается к MSMQ. Если я удалю весь код подключения из программы (возврат к простому тесту DHT11 работает нормально), то датчик безукоризненно считывает показания в течение нескольких часов подряд, подключенный как есть. (3 В, напрямую от контакта 3 В на ESP, на макетной плате, максимальная длина провода около 15 см в оба конца) Проблема в этом случае определенно в программном обеспечении, поскольку аппаратное обеспечение работает безупречно с другим кодом., @charrold303
Что произойдет, если вы попытаетесь напечатать hum и temp после этой строки: Serial.println("Не удалось прочитать с датчика DHT!");, @linhartr22
@ linhartr22 - Я думаю, вы можете быть гением - я думал, что когда я отправляю значения в MQTT, эти строки:
`
С++ String payload2 = String(input_string) + "\"Влажность\":\"" + гул + "\", \"Температура\":\"" + temp + "\", \"Свет\":\"" + L1 + "\"}"; полезная нагрузка2.toCharArray (данные2, (полезная нагрузка2.длина() + 1));`
Возможно, меняет тип переменной. Судя по ошибке при попытке их распечатать, я в этом уверен. недопустимые операнды типа 'const char [6] и float для бинарного оператора + Итак, вопрос в том, что такое объявление для повторного объявления этих переменных. НА МАШИНУ GOOGLE!, @charrold303Оказывается, это было не так. Я изменил свой строковый метод, чтобы использовать синтаксис sprintf(), и он по-прежнему демонстрирует ту же проблему - когда он возвращается к «верху» цикла, загорается красный светодиод, как указано в коде, а затем он сидит навсегда, указывая ошибка происходит при считывании влажности с DHT11. Я все еще думаю, что это может быть правильным путем, поскольку переменная влажности каким-то образом несовместима со вторым циклом, но добавленный мной код dtostrf() должен был исправить это. Так что я все еще на исходной проблеме - с включенным MQTT DHT11 не работает. Выключил, работает отлично., @charrold303
Это может быть конфликт между библиотекой DHT11 и библиотекой MQTT, пытающейся использовать один и тот же таймер или другой ресурс в MCU., @linhartr22
Я тоже так подозреваю, но это выше моих возможностей или желания исправить. Я просто сказал ESP сбрасываться после каждого цикла. Невероятно неэлегантный, но функциональный., @charrold303