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

NodeMCU+DHT22:OLED显示与Google Sheets同步多任务代码优化求助

代码修改方案

核心问题分析

原代码无法实现不同任务间隔的原因:

  • loop()里的delay(60000)强制阻塞程序1分钟,所有任务都被拖成1分钟执行
  • 两个任务共用同一个计时变量previousMillis,无法独立控制间隔
  • 重复读取DHT传感器,浪费资源且可能导致数据不一致

具体修改步骤

  1. 添加独立计时变量:分别为OLED显示和Google Sheets上传定义各自的上次执行时间和间隔
  2. 移除阻塞式delay:删除loop()里的delay(60000),改用millis()实现非阻塞计时
  3. 复用传感器数据:在loop()中仅读取一次DHT数据,传递给任务函数,避免重复读取
  4. 修正时间间隔:OLED更新间隔设为5000ms(5秒),Sheets上传间隔设为900000ms(15分钟)
  5. 简化任务函数:让显示和上传函数直接接收传入的温湿度数据,不再重复读取传感器

修改后的完整代码

#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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:05:14