You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:47:38