Подключение к 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, но я не могу понять, что это такое, или изолировать это.

Теперь я оставляю это сообществу. Какого черта здесь происходит?!

, 👍2

Обсуждение

Совет(ы): что может привести к сбою чтения 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


2 ответа


0

В своих скетчах я использовал библиотеку DHT11, а не библиотеку DHT. В наброске примера должно быть ясно, какие минимальные изменения вам нужно будет внести в свой код. У меня это всегда хорошо получалось.

,

Поэтому я буквально использовал код примера внутри своей более крупной программы. Он (за исключением вывода, который я использовал, а затем и имен переменных) полностью неизменен. Вы можете найти пример кода здесь: http://www.esp32learning.com/code/esp32-and-dht11-sensor-example.php Проблема не в том, что он не работает, он работает, но не в связке с MQTT. Как только мой ESP32 подключается к серверу MQ, чтение DHT прекращается. Нет кода MQTT, и он работает как шарм., @charrold303


1

Оставить это здесь на случай, если у кого-то возникнет аналогичная проблема, в качестве «ответа» на мой вопрос:

Проще говоря, используемая библиотека DHT11 и используемая библиотека MQTT конфликтуют. Вот он, это ответ.

Есть два варианта исправления в зависимости от ваших потребностей:

  • не используйте, не исследуйте и не перестраивайте одну из библиотек — честно говоря, для меня это было отрицательной рентабельностью, и оно того не стоило

  • Добавить ESP.restart(); в конце основного цикла программы и ПОСЛЕ таймера сна — это перезагружает ESP и позволяет DHT11 читать ДО того, как произойдет соединение MQTT и решение сработает.

На мой взгляд, это не «исправление», а обходной путь, но он решает основную проблему.

,

Я думаю, что это не конфликт, вы просто забыли сначала подписаться на тему, прежде чем отправлять данные., @abu-ahmed al-khatiri

Нет, вы можете видеть это в приведенном выше коде — подписки нет — только публикация. Я переместил публикацию и обмен сообщениями повсюду в логическом потоке, и буквально это не имеет значения. Как только вы публикуете сообщение через MQTT, DHT11 прекращает чтение. Единственный способ заставить его снова читать — перезапустить ESP32. Я не думаю, что это проблема с оборудованием или даже проблема с библиотекой для каждой библиотеки (поскольку они отлично работают сами по себе), это просто конфликт в двух библиотеках. Поэтому я оставил это здесь для других, которые могут испытать это., @charrold303