一、硬件介绍(Hardware)
1.1 主控板
Arduino Nano RP2040 ConnectMCU:Raspberry Pi RP2040(双核 ARM Cortex-M0+,133 MHz)
封装:Arduino Nano 经典尺寸(18 × 45 mm),兼容 Grove 扩展板
工作电压:3.3 V(逻辑电平 3.3 V,Grove 模块同电平域)
数字 IO:20 个,全部支持 INPUT_PULLUP
模拟输入:8 个 12-bit ADC(本次用 A2 作为 NTC 输入)
开发框架:ArduinoCore-mbed(PlatformIO platform = raspberrypi)
1.2 Grove 模块清单
板上 DHT11 数字温湿度传感器,预校准输出;
单一信号线串行协议(单总线):MCU 拉低 ≥18 ms 启动 → 拉高 20-40 µs → 传感器响应 → 40 bit 数据(湿度整数 / 湿度小数 / 温度整数 / 温度小数 / 校验和);
测量范围:温度 0~50℃ ±2℃,湿度 20~90% RH ±5%;
重要约束:DHT11 不能测负温(0℃ 以下数据无效),低温段必须靠 NTC 兜底;
采样周期 ≥ 1 s(上电后建议等 ≥ 1 s 再读第一次)。
板上 NTC 热敏电阻 + LM358 运放;
输出电压 = Vcc × Rref / (Rref + Rntc),Rref = 10 kΩ 板上分压;
测温范围 -40~125℃ ±1.5℃(覆盖 DHT11 的盲区);
用 Steinhart 1-系数近似反算温度:参数取 R0=100 kΩ @ 25℃、β=4250(Grove 默认)。
1.3 接线总览
Arduino Nano RP2040 Connect ┌────────────────────────────────┐ │ D2 ──┼──► DHT11 (SIG, 单总线) │ A2 ──┼──► NTC (SIG, 模拟输出) └────────────────────────────────┘

二、软件设计(Software Design)
程序结构总览
PlatformIO Project (seeedtest) ├── platformio.ini ├── src/ │ └── main.cpp ← 主程序 └── lib/ ├── ChainableLED/ ← 旧项目残留, 本次未使用 └── SeeedDHT/ ← DHT11 驱动库 (RP2040 适配) ├── DHT.h ← COUNT=10 for ARDUINO_ARCH_RP2040 └── DHT.cpp ← Adafruit 边沿计数法main.cpp 整体扁平结构:
main.cpp ├── 文件头注释(接线、行为、ADC 范围、NTC 公式) ├── 引脚 / 参数常量(NTC Steinhart 参数) ├── 全局状态 (NTCState + DHT 对象) ├── ntcSample() ← A2 ADC → Steinhart 温度 ├── setup() ← 串口 + DHT.begin + NTC 引脚 └── loop() ├── 1) 1 s 节流 ├── 2) dhtSensor.readTemperature() / readHumidity() ├── 3) ntcSample() └── 4) 串口打印一行
数据流
DHT11 (D2) ──单总线──► SeeedDHT 库 ──► readTemperature / readHumidity │ ▼ NTC (A2) ──ADC──► ntcSample() ──► Steinhart 公式 ──► ℃ │ ▼ Serial.println 一行: T_dht=24.5C RH=58.0% T_ntc=33.2C V_ntc=0.42V
关键算法:NTC Steinhart 1-系数近似
// 1) 读 ADC, 折算电压 ntc.voltage = ntc.raw * (Vcc / 4095); // 2) 分压电阻算 NTC 电阻 R_ntc = Rref × (Vcc - Vadc) / Vadc // 3) β 方程反算温度 T_K = 1 / (1/T0 + (1/β) × ln(R_ntc / R0)) T_℃ = T_K - 273.15
R0 = 100 kΩ @ T0 = 298.15 K(25℃)
β = 4250(Grove 默认)
范围:-40~125℃,覆盖 DHT11 盲区
2DHT 协议实现(SeeedDHT/DHT.cpp)
// 启动
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20); // >= 18 ms
digitalWrite(_pin, HIGH);
delayMicroseconds(20); // 20-40 us
pinMode(_pin, INPUT); // 释放, 外部上拉拉高
// 1us 轮询 digitalRead 数电平长度
for (i = 0; i < MAXTIMINGS; i++) {
counter = 0;
while (digitalRead(_pin) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255) break;
}
laststate = digitalRead(_pin);
if (counter == 255) break;
// 跳过前 4 次跳变 (启动高 + 响应低 + 响应高 + bit0 低)
if ((i >= 4) && (i % 2 == 0)) { // 偶数次 = bit 高电平段
data[j/8] <<= 1;
if (counter > _count) data[j/8] |= 1;
j++;
}
}
// 校验
if (j >= 40 && data[4] == (data[0]+data[1]+data[2]+data[3]) & 0xFF) ...时间参数
三、功能展示

附:全部代码
#include <Arduino.h>
#include <DHT.h>
const uint8_t PIN_DHT = 2; // 丝印 D2, DHT11 SIG (单总线)
const uint8_t PIN_NTC = A2; // 丝印 A2, NTC 模拟输出
const float NTC_VCC = 3.3f;
const float NTC_RREF = 10000.0f;
const float NTC_R0 = 100000.0f;
const float NTC_T0_K = 298.15f;
const float NTC_BETA = 4250.0f;
const uint32_t LOOP_PERIOD_MS = 1000;
DHT dhtSensor(PIN_DHT, DHT11);
struct NTCState {
float temperature = 0.0f;
float voltage = 0.0f;
uint16_t raw = 0;
} ntc;
uint32_t loopStartMs = 0;
static void ntcSample() {
ntc.raw = analogRead(PIN_NTC);
ntc.voltage = (float)ntc.raw * (NTC_VCC / 4095.0f);
if (ntc.raw == 0 || ntc.raw >= 4095) {
ntc.temperature = -127.0f;
return;
}
const float rNtc = NTC_RREF * (NTC_VCC - ntc.voltage) / ntc.voltage;
const float tK = 1.0f / (1.0f / NTC_T0_K + (1.0f / NTC_BETA) * log(rNtc / NTC_R0));
ntc.temperature = tK - 273.15f;
}
void setup() {
Serial.begin(115200);
uint32_t t0 = millis();
while (!Serial && (millis() - t0) < 2000) { /* 等待 USB CDC */ }
pinMode(PIN_NTC, INPUT);
dhtSensor.begin(); // 上电稳定 + 设引脚
Serial.println();
Serial.println("=== Greenhouse Telemetry Probe ===");
Serial.println(" DHT11 -> D2 (Seeed library, 1 Hz)");
Serial.println(" NTC -> A2 (Analog, Steinhart)");
Serial.println(" Format: T_dht(C) RH(%) T_ntc(C) V_ntc(V)");
Serial.println();
loopStartMs = millis();
}
void loop() {
const uint32_t now = millis();
if ((uint32_t)(now - loopStartMs) < LOOP_PERIOD_MS) {
delay(10);
return;
}
loopStartMs = now;
const float t = dhtSensor.readTemperature();
const float rh = dhtSensor.readHumidity();
ntcSample();
Serial.print("T_dht=");
if (isnan(t) || isnan(rh)) {
Serial.print("ERR RH=ERR");
} else {
Serial.print(t, 1);
Serial.print("C RH=");
Serial.print(rh, 1);
}
Serial.print("% T_ntc=");
Serial.print(ntc.temperature, 1);
Serial.print("C V_ntc=");
Serial.print(ntc.voltage, 2);
Serial.println("V");
}
我要赚赏金
