NodeMCU+DHT22:OLED显示与Google Sheets同步多任务代码优化求助
代码修改方案
核心问题分析
原代码无法实现不同任务间隔的原因:
loop()里的delay(60000)强制阻塞程序1分钟,所有任务都被拖成1分钟执行- 两个任务共用同一个计时变量
previousMillis,无法独立控制间隔 - 重复读取DHT传感器,浪费资源且可能导致数据不一致
具体修改步骤
- 添加独立计时变量:分别为OLED显示和Google Sheets上传定义各自的上次执行时间和间隔
- 移除阻塞式delay:删除
loop()里的delay(60000),改用millis()实现非阻塞计时 - 复用传感器数据:在
loop()中仅读取一次DHT数据,传递给任务函数,避免重复读取 - 修正时间间隔:OLED更新间隔设为5000ms(5秒),Sheets上传间隔设为900000ms(15分钟)
- 简化任务函数:让显示和上传函数直接接收传入的温湿度数据,不再重复读取传感器
修改后的完整代码
#include <Wire.h> #include <ESP8266WiFi.h> #include <WiFiClientSecure.h> #include "DHT.h" #include <OneWire.h> #include <SPI.h> #define DHTTYPE DHT22 #include "SH1106Wire.h" SH1106Wire display (0x3C, D1, D2); // 独立计时变量:OLED显示 unsigned long previousOledMillis = 0; const long oledInterval = 5000; // 5秒间隔 // 独立计时变量:Google Sheets上传 unsigned long previousSheetMillis = 0; const long sheetInterval = 15 * 60 * 1000; // 15分钟间隔,转换为毫秒 const int DHTPin = 14; DHT dht(DHTPin, DHTTYPE); #define ON_Board_LED 2 const char* ssid = "OPPO F11 Pro"; const char* host = "script.google.com"; const int httpsPort = 443; WiFiClientSecure client; String GAS_ID = "AKfycbxoDW-7HxrMx90MH7ggsM_0DOTz3gIj-Z06kWTGOwOaoFoaUxW4xfGn_8L7WJh6LX3o"; void setup() { dht.begin(); delay(500); display.init(); display.flipScreenVertically(); Serial.begin(115200); WiFi.begin(ssid, NULL); pinMode(ON_Board_LED, OUTPUT); digitalWrite(ON_Board_LED, HIGH); while (WiFi.status() != WL_CONNECTED) { digitalWrite(ON_Board_LED, LOW); delay(250); digitalWrite(ON_Board_LED, HIGH); delay(250); } digitalWrite(ON_Board_LED, HIGH); client.setInsecure(); } void loop() { // 仅读取一次DHT数据 int h = dht.readHumidity(); float t = dht.readTemperature(); if (isnan(h) || isnan(t)) { Serial.println("Failed to read from DHT sensor !"); delay(500); return; } // 打印数据到串口 String Temp = "Temperature : " + String(t) + " °C"; String Humi = "Humidity : " + String(h) + " %"; Serial.println(Temp); Serial.println(Humi); // 检查OLED更新时间 unsigned long currentMillis = millis(); if (currentMillis - previousOledMillis >= oledInterval) { previousOledMillis = currentMillis; updateOled(t, h); } // 检查Google Sheets上传时间 if (currentMillis - previousSheetMillis >= sheetInterval) { previousSheetMillis = currentMillis; sendData(t, h); } // 这里不要加delay,让loop快速循环 } // 更新OLED显示的函数,接收温湿度参数 void updateOled(float t, int h) { display.setFont(ArialMT_Plain_16); display.clear(); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(60, 0, "Temperature (°C)"); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(60, 16, String(t)); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(60, 32, "Humidity (%)"); display.setTextAlignment(TEXT_ALIGN_CENTER); display.drawString(60, 48, String(h)); display.display(); } // 发送数据到Google Sheets的函数 void sendData(float tem, int hum) { if (!client.connect(host, httpsPort)) { Serial.println("connection failed"); return; } String string_temperature = String(tem); String string_humidity = String(hum, DEC); String url = "/macros/s/" + GAS_ID + "/exec?temperature=" + string_temperature + "&humidity=" + string_humidity; client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: BuildFailureDetectorESP8266\r\n" + "Connection: close\r\n\r\n"); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { break; } } String line = client.readStringUntil('\n'); }
关键说明
- 两个任务现在完全独立计时,OLED每5秒更新一次,Sheets每15分钟上传一次
- 移除了阻塞式
delay,程序可以快速响应所有任务 - 传感器数据只读取一次,减少硬件负担,保证数据一致性
- 函数职责更清晰:
updateOled专注于显示,sendData专注于上传
内容的提问来源于stack exchange,提问作者Jashanjot Kaur
相关产品推荐
相关产品推荐

