DHT22传感器读取失败:集成菜单代码后Serial输出NaN
箱体温度监测项目DHT22读取NaN问题排查
我是嵌入式开发领域的新手,正在开发一个箱体温度监测项目。尝试使用DHT22传感器读取温度时,单独运行简单测试代码可正常获取数据,但将传感器读取逻辑集成到带菜单功能的项目代码后,Serial Monitor始终输出NaN,无法读取温度。
菜单代码(问题代码)
#include "PinChangeInterrupt.h" #include "DHT.h" #include "Countimer.h" #define DHTPIN 5 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); Countimer timer; // 补全未定义的变量 int buah = 0; float set_temperature = 0.0; int buahPilih = 0; void setup() { Serial.begin(9600); dht.begin(); } void loop() { encoder_value(); int b = checkButton(); if (b == 1) clickEvent(); if (b == 2) doubleClickEvent(); if (b == 3) holdEvent(); } void encoder_value() { } int checkButton() { return 0; // 临时返回0避免编译报错 } void clickEvent() { } void doubleClickEvent() { if (buah == 1){ set_temperature = 60; timer.setCounter(0,0,10, timer.COUNT_DOWN, onComplete); timer.setInterval(refreshClock, 1000); refreshClock(); // 移除阻塞while循环,改为在主loop中处理 } else if (buah == 2){ } } void holdEvent() { } void refreshClock(){ Serial.println(timer.getCurrentTime()); } // 修改为非阻塞式读取 unsigned long lastReadTime = 0; const long readInterval = 10000; void PID(){ unsigned long currentTime = millis(); if (currentTime - lastReadTime >= readInterval) { lastReadTime = currentTime; float temperature_read = dht.readTemperature(); Serial.print(temperature_read); } timer.run(); // 处理定时器逻辑 } void onComplete(){ }
可正常运行的简单测试代码
#include "DHT.h" #include "LiquidCrystal_I2C.h" #define DHTPIN 5 #define DHTTYPE DHT22 #include "RBDdimmer.h" DHT dht (DHTPIN, DHTTYPE); LiquidCrystal_I2C lcd(0x27, 16, 2); int fan = 7; const int zeroCrossPin = 2; const int adcPin = 3; dimmerLamp adc(adcPin); int power; float set_temperature = 31.6; float temperature_read = 0.0; float suhu; float PID_error = 0; float previous_error = 0; float elapsedTime, Time, timePrev; float PID_value = 0; int kp = 90; int ki = 30; int kd = 80; int PID_p = 0; int PID_i = 0; int PID_d = 0; float last_kp = 0; float last_ki = 0; float last_kd = 0; int PID_values_fix = 0; void setup() { Serial.begin(9600); dht.begin(); lcd.init(); lcd.backlight(); lcd.clear(); pinMode(fan, OUTPUT); } void loop() { float t = dht.readTemperature(); float h = dht.readHumidity(); Serial.print("Suhu : "); Serial.print(t); Serial.println(" C"); Serial.print(" "); Serial.print("Kelembaban : "); Serial.print(h); Serial.println(" %"); Serial.print(" "); lcd.clear(); lcd.setCursor(0,0); lcd.print("Suhu: "); lcd.print(t); lcd.setCursor(0,1); lcd.print("kelem: "); lcd.print(h); PID_error = set_temperature - t; Serial.print("Error terbaca: "); Serial.println(PID_error); Serial.print(" "); PID_p = kp * PID_error; PID_i = PID_i +(ki * PID_error); timePrev = Time; Time = millis(); elapsedTime = (Time - timePrev) / 1000; PID_d = kd * ((PID_error - previous_error) / elapsedTime); PID_value = PID_p + PID_i + PID_d; Serial.print("PID_value adalah "); Serial.println(PID_value); Serial.print(" "); previous_error = PID_error; power = PID_value; if (power<0){ power = 0; } else if (power > 70){ power = 70; } adc.setPower(power); Serial.print("lampValue -> "); Serial.print(adc.getPower()); Serial.println("%"); Serial.print(" "); if (t > 31){ digitalWrite(fan, LOW); } delay(500); }
问题原因分析
- 阻塞式delay破坏传感器时序:菜单代码中
PID()函数的delay(10000)会导致程序阻塞10秒,DHT22传感器的通信对时序精度要求高,长时间阻塞会导致传感器信号读取超时,返回NaN。 - while循环阻塞主程序:
doubleClickEvent()中的while (!timer.isCounterCompleted())会完全阻塞主loop,导致编码器、按键等其他功能无法运行,同时反复调用timer.start()会打乱定时器逻辑,进一步影响传感器读取。 - 未定义变量导致运行异常:代码中
buah、set_temperature等变量未声明,编译时会产生警告或报错,可能导致运行时逻辑混乱。
修复方案
- 替换阻塞式delay为非阻塞定时:用
millis()实现定时读取传感器,避免长时间阻塞程序,保证传感器通信时序正常。 - 移除阻塞式while循环:将定时器逻辑移到主loop中处理,采用事件驱动方式,避免阻塞主程序的其他功能。
- 补全所有未定义变量:确保所有使用的变量都提前声明并初始化,避免编译和运行时错误。
内容的提问来源于stack exchange,提问作者itemeEL
相关产品推荐
相关产品推荐

