Nodemcu ESP8266搭配DHT22传感器出现nan值问题求助
DHT22运行数天后输出
nan异常的排查与解决建议 问题描述
我用NodeMCU ESP8266搭配DHT22传感器搭建的系统,运行数天后串口监视器输出的温湿度值变成了nan,这个异常值还干扰了Adafruit Dashboard的数据读取。截至2023年2月6日发帖前两日,系统仍能正常输出正确数值。
使用的库
- Adafruit Unified Sensor
- ArduinoHttpclient
- Ethernet
- WiFi101
- Adafruit IO Arduino及依赖库
系统代码
// Adafruit IO Temp e Hum com Switch // Tutorial Link: https://learn.adafruit.com/adafruit-io-basics-temperature-and-humidity /************************** Configuration ***********************************/ // edit the config.h tab and enter your Adafruit IO credentials #define IO_USERNAME "*****" #define IO_KEY "*****" // and any additional configuration needed for WiFi, cellular, #define WIFI_SSID "*****" #define WIFI_PASS "*****" // or ethernet clients. #include <AdafruitIO.h> #include <AdafruitIO_WiFi.h> #include <AdafruitIO_MQTT.h> #include "config.h" /************************ Comeca Aqui! *******************************/ //Sensor DHT #include <Adafruit_Sensor.h> #include <DHT.h> #include <DHT_U.h> // pin connected to DH22 data line #define DATA_PIN 2//D2 //Esp library #include <ESP8266WiFi.h> // create DHT22 instance DHT_Unified dht(DATA_PIN, DHT22); // set up the 'temperature' and 'humidity' feeds AdafruitIO_Feed *temperature = io.feed("temperature"); AdafruitIO_Feed *humidity = io.feed("humidity"); AdafruitIO_Feed *light = io.feed("lightfeed"); // Define correct feeds relays AdafruitIO_Feed *pumpfeed = io.feed("pumpfeed"); AdafruitIO_Feed *fanfeed = io.feed("fanfeed"); AdafruitIO_Feed *lightfeed = io.feed("lightfeed"); // Define pins relays int fanPin = 13; // Pin GPIO13 (D7) controll fanfeed relay int pumpPin = 5; // Pin GPIO5 (D1) controll pumpfeed relay int lightPin = 15; // Pin GPIO15 (D8) controll pumpfeed relay void setup() { // start the serial connection Serial.begin(9600); // wait for serial monitor to open while(! Serial); // connect to WiFi io.connect(); // Initialize pins as output pinMode(pumpPin, OUTPUT); pinMode(fanPin, OUTPUT); pinMode(lightPin, OUTPUT); // initialize dht22 dht.begin(); // connect to io.adafruit.com Serial.print("Connectando ao Adafruit IO"); io.connect(); // wait for a connection while(io.status() < AIO_CONNECTED) { Serial.print("."); delay(500); } // we are connected Serial.println(); Serial.println(io.statusText()); //-- // Define the callback functions for the feeds pumpfeed->onMessage(pumpChange); fanfeed->onMessage(fanChange); lightfeed->onMessage(lightChange); } void loop() { // io.run(); is required for all sketches. // it should always be present at the top of your loop // function. it keeps the client connected to // io.adafruit.com, and processes any incoming data. io.run(); Serial.println("Condições climáticas:"); //conditions sensors_event_t event; dht.temperature().getEvent(&event); float celsius = event.temperature; Serial.print("Celsius: "); Serial.print(celsius); Serial.println("°C"); // save or celsius to Adafruit IO temperature->save(celsius); dht.humidity().getEvent(&event); Serial.print("Umidade: "); Serial.print(event.relative_humidity); Serial.println("%"); // save humidity to Adafruit IO humidity->save(event.relative_humidity); // wait 5 seconds (5000 milliseconds == 5 seconds) delay(5000); } // Relays void pumpChange(AdafruitIO_Data *data) { int value = data->toInt(); //Serial.print("Valor recebido para pumpPin: "); //"value for pumpin" Serial.println(value); if (value == 1) { digitalWrite(pumpPin, HIGH); Serial.println("Bomba ligada!"); //ON } else { digitalWrite(pumpPin, LOW); Serial.println("Bomba desligada!"); //OFF } } void fanChange(AdafruitIO_Data *data) { int value = data->toInt(); Serial.println(value); //Serial.print("Valor recebido para fanPin: "); if (value == 1) { digitalWrite(fanPin, HIGH); Serial.println("Ventilador ligado!"); //ON } else { digitalWrite(fanPin, LOW); Serial.println("Ventilador desligado!"); //OFF } } void lightChange(AdafruitIO_Data *data) { int value = data->toInt(); Serial.println(value); //Serial.print("Valor recebido para lightPin: "); if (value == 1) { digitalWrite(lightPin, HIGH); Serial.println("Luz ligada!"); //ON } else { digitalWrite(lightPin, LOW); Serial.println("Luz desligada!"); //OFF } }
已尝试的排查操作
- 将DHT22的数据引脚更换为其他无复位功能的可用引脚
- 更换库的旧版本进行测试
- 更换传感器的跳线
排查与解决建议
1. 传感器硬件稳定性优化
- 检查供电稳定性:给DHT22的供电回路添加100uF电解电容+100nF陶瓷电容滤波,避免电压波动影响传感器工作;同时确认ESP8266的电源适配器功率足够(至少5V/1A),防止继电器启动导致电压骤降。
- 确认上拉电阻:DHT22数据引脚需要4.7k-10k的上拉电阻,部分模块自带但可能松动,可额外焊接一个上拉电阻测试。
- 更换传感器测试:DHT22长期运行可能出现元件老化,换全新传感器验证是否仍出现异常。
2. 代码层面修复与优化
- 添加异常值过滤:读取温湿度后判断是否为
nan,仅在数值有效时上传到Adafruit IO,避免干扰Dashboard。修改后的读取逻辑示例:sensors_event_t event; dht.temperature().getEvent(&event); float celsius = event.temperature; if (!isnan(celsius)) { Serial.print("Celsius: "); Serial.print(celsius); Serial.println("°C"); temperature->save(celsius); } else { Serial.println("温度读取失败"); } dht.humidity().getEvent(&event); float hum = event.relative_humidity; if (!isnan(hum)) { Serial.print("Umidade: "); Serial.print(hum); Serial.println("%"); humidity->save(hum); } else { Serial.println("湿度读取失败"); } - 添加软件看门狗:ESP8266长期运行可能假死,引入软件看门狗定期喂狗,防止系统挂起。
- 延长读取间隔:将当前5秒的读取间隔延长至10秒,减少传感器的工作负荷。
3. 电磁干扰排查
- 继电器抗干扰:给继电器线圈并联续流二极管,抑制开关时产生的电磁脉冲,避免干扰DHT22的信号传输。
- 物理隔离:将传感器与继电器模块的布线分开,减少电磁耦合干扰。
内容的提问来源于stack exchange,提问作者Fernando
相关产品推荐
相关产品推荐

