基于 ESP32 系列芯片的 NTC 热敏电阻温度采集示例:从 ntc_driver 组件到实战应用
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
本指南围绕 esp-iot-solution 仓库中的 ntc_temperature_sensor 示例 展开,讲解如何在 ESP32-C2 / ESP32-C3 / ESP32 / ESP32-C6 / ESP32-S3 系列芯片上使用ntc_driver组件驱动 NTC 热敏电阻完成温度采集。读完本文,你将掌握 NTC 分压电路两种接法(CIRCUIT_MODE_NTC_VCC/CIRCUIT_MODE_NTC_GND)的选择方法、ntc_config_t全字段配置含义、idf.py编译烧写与串口监视的完整流程,以及驱动内部从 ADC 原始值到摄氏温度的完整换算链路与滤波机制。
示例概述
该示例演示了基于ntc_driver组件开发热敏电阻温度读取应用程序的三种典型能力:
- 基于最底层驱动 API 的控制:直接调用
ntc_driver.h暴露的ntc_dev_create/ntc_dev_get_temperature/ntc_dev_delete等接口,不依赖任何上层业务框架; - 基于热敏电阻 CMFA103J3950HANT 驱动的演示:示例以 CMFA103J3950HANT(B 值 3950K、25℃ 电阻 10kΩ)为默认传感器进行完整演示;
- 可选择配置不同的热敏电阻驱动:所有电参数均通过
ntc_config_t结构体配置,只需修改b_value、r25_ohm、fixed_ohm、vdd_mv等字段即可无缝切换到其他型号热敏电阻。
示例主体代码位于 ntc_temperature_example_main.c,依赖声明见 idf_component.yml,其中通过override_path将ntc_driver指向仓库内的 components/sensors/ntc_driver 组件。
硬件电路原理:两种分压接法
NTC(负温度系数)热敏电阻的阻值随温度升高而下降。驱动组件通过一个固定电阻Rref与热敏电阻Rt串联分压,将电阻变化转换为电压变化,再经 ADC 采样换算成温度。组件支持两种电路接法:
Vcc --------> Rt --------> Rref --------> GND 对应 CIRCUIT_MODE_NTC_VCC Vcc --------> Rref --------> Rt --------> GND 对应 CIRCUIT_MODE_NTC_GND
Rref是分压电阻;Rt是热敏电阻在当前温度下的电阻。
两种接法的电压极性相反,理解这一点对电路设计至关重要:
- NTC 在上方(NTC_VCC):温度升高 → NTC 电阻下降 → NTC 端电压下降、固定电阻端电压上升,采样点电压随温度升高而下降;
- NTC 在下方(NTC_GND):温度升高 → NTC 电阻下降 → NTC 端电压上升、固定电阻端电压下降,采样点电压随温度升高而上升。
因此在ntc_config_t中必须通过circuit_mode字段如实声明实际电路接法,驱动才能正确反推热敏电阻阻值(详见下文"电压到温度的换算"一节),这一点在 ntc_driver 组件文档 中有明确说明。
示例接线图(CMFA103J3950HANT)
示例文档给出基于 ESP8684-DevKitM-1(ESP32-C2)开发板的接线示意:
ESP8684-DevKitM-1 CMFA103J3950HANT -- [ADC1 CHANEL3] --------> | || NTC IO --即将 NTC 的信号引脚接入ADC1 的通道 3(ADC_UNIT_1+ADC_CHANNEL_3),与示例源码中的默认配置一致。
如何使用该示例
硬件需求与准备
- 驱动选择与配置:通过
idf.py menuconfig选择需要演示的驱动并进行配置。ntc_driver组件提供了独立的 Kconfig 菜单(见 Kconfig),可配置 ADC 滤波功能:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ENABLE_NTC_ADC_FILTER | bool | y | 使能 NTC 的 ADC 滤波,驱动会多次采样并滤波以抑制 ADC 噪声 |
NTC_FILTER_WINDOW_SIZE | int | 50 | 滤波前采集的 ADC 采样次数;取值越大,读数越稳定,但更新越慢 |
- 硬件连接:对于 CMFA103J3950HANT 驱动,仅需将信号端口连接到所配置的 GPIO 上即可(本例为 ADC1_CH3)。
编译与烧写
进入示例目录:
cd ./esp-iot-solution/examples/sensors/ntc_temperature_sensor使用idf.py工具设置目标芯片,随后编译下载:
# 设置编译芯片 idf.py set-target esp32c2 # 编译并下载 idf.py -p PORT build flash请将PORT替换为当前使用的串口端口号(如/dev/ttyUSB0)。项目根级构建配置见 CMakeLists.txt,示例要求 ESP-IDF 版本不低于 5.0(idf: ">=5.0")。
查看运行输出
编译烧写完成后,可使用monitor查看程序输出:
idf.py -p PORT monitor示例输出结果
以下为 CMFA103J3950HANT 驱动测试 log(示例 README_CN.md 原始输出):
I (333) app_start: Starting scheduler on CPU0 I (337) app_start: Starting scheduler on CPU1 I (337) main_task: Started on CPU0 I (347) main_task: Calling app_main() I (347) ntc driver: IoT Ntc Driver Version: 0.1.0 I (347) ntc driver: calibration scheme version is Line Fitting I (357) ntc driver: Calibration Success I (367) NTC demo: NTC temperature = 23.44 ℃ I (367) NTC demo: NTC temperature = 23.47 ℃ I (377) NTC demo: NTC temperature = 23.47 ℃ I (377) NTC demo: NTC temperature = 23.47 ℃ I (387) NTC demo: NTC temperature = 23.50 ℃ I (387) NTC demo: NTC temperature = 23.50 ℃ I (397) NTC demo: NTC temperature = 23.44 ℃ I (397) NTC demo: NTC temperature = 23.44 ℃ I (407) NTC demo: NTC temperature = 23.43 ℃ I (407) NTC demo: NTC temperature = 23.43 ℃日志中可以看到驱动版本号、ADC 校准方案类型、校准是否成功,以及每秒多次输出的温度读数。由于示例开启了默认的 ADC 滤波(滤波窗口 50 次采样),同一温度下多次读数的波动被抑制在小数点后两位以内。
示例源码逐段解析
示例的app_main完整实现了"初始化 → 创建驱动 → 循环读取 → 删除驱动"的典型生命周期:
#include "ntc_driver.h" const static char *TAG = "NTC demo"; void app_main(void) { //Select the NTC sensor and initialize the hardware parameters ntc_config_t ntc_config = { .b_value = 3950, .r25_ohm = 10000, .fixed_ohm = 10000, .vdd_mv = 3300, .circuit_mode = CIRCUIT_MODE_NTC_GND, .atten = ADC_ATTEN_DB_11, .channel = ADC_CHANNEL_3, .unit = ADC_UNIT_1 }; //Create the NTC Driver and Init ADC ntc_device_handle_t ntc = NULL; adc_oneshot_unit_handle_t adc_handle = NULL; ESP_ERROR_CHECK(ntc_dev_create(&ntc_config, &ntc, &adc_handle)); ESP_ERROR_CHECK(ntc_dev_get_adc_handle(ntc, &adc_handle)); float temp = 0.0; for (int i = 0; i < 10; i++) { if (ntc_dev_get_temperature(ntc, &temp) == ESP_OK) { ESP_LOGI(TAG, "NTC temperature = %.2f ℃", temp); } } ESP_ERROR_CHECK(ntc_dev_delete(ntc)); }配置结构体ntc_config_t字段详解
ntc_config_t定义于 ntc_driver.h,各字段含义如下:
| 字段 | 类型 | 示例值 | 含义与注意事项 |
|---|---|---|---|
circuit_mode | ntc_circuit_mode_t | CIRCUIT_MODE_NTC_GND | 分压电路接法,必须与实物电路一致,否则温度换算方向相反。枚举CIRCUIT_MODE_NTC_VCC = 1、CIRCUIT_MODE_NTC_GND = 2 |
unit | adc_unit_t | ADC_UNIT_1 | ADC 外设单元(ADC1/ADC2) |
atten | adc_atten_t | ADC_ATTEN_DB_11 | ADC 输入衰减,决定可测量电压量程;ADC_ATTEN_DB_11对应约 0~3.3V 量程 |
channel | adc_channel_t | ADC_CHANNEL_3 | ADC 采样通道,需与硬件接线一致 |
b_value | uint32_t | 3950 | NTC 的 B 值(单位 K),由传感器数据手册给出,用于温度换算 |
r25_ohm | uint32_t | 10000 | NTC 在 25℃ 时的标称电阻(单位 Ω) |
fixed_ohm | uint32_t | 10000 | 分压固定电阻Rref的阻值(单位 Ω),需与电路实物一致 |
vdd_mv | uint32_t | 3300 | 分压电路供电电压(单位 mV) |
更换其他型号热敏电阻时,只需按数据手册更新b_value与r25_ohm,并保证fixed_ohm、vdd_mv、circuit_mode与实际电路匹配,即可复用同一套代码。
驱动底层实现:从 ADC 原始值到摄氏温度
ntc_driver组件源码位于 ntc_driver.c,下面拆解其关键实现,帮助你理解示例日志背后的完整链路。
1. 创建驱动并初始化 ADC(ntc_dev_create)
- 打印驱动版本号
IoT Ntc Driver Version: %d.%d.%d(对应示例日志第一行); - 分配并保存
ntc_config_t配置; - 若调用方未传入有效的
adc_handle,驱动内部通过adc_oneshot_new_unit创建 ADC 单次采样单元,并将句柄回传给调用方(这就是示例中ntc_dev_create之后又调用ntc_dev_get_adc_handle的原因); - 通过
adc_oneshot_config_channel配置通道衰减atten与位宽ADC_BITWIDTH_DEFAULT; - 调用内部函数
adc_calibration_init创建 ADC 校准句柄。
2. ADC 电压校准(adc_calibration_init)
校准方案按芯片能力自动选择,与示例日志输出一一对应:
- 优先尝试Curve Fitting(
ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED),失败或未支持时回退到Line Fitting(ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED); - 校准成功打印
Calibration Success;若芯片 eFuse 未烧录校准参数,则打印eFuse not burnt, skip software calibration。
示例日志中calibration scheme version is Line Fitting+Calibration Success说明目标芯片走的是线性拟合校准路径且校准成功。
3. 电压到温度的换算(ntc_voltage_to_temperature)
这是温度计算的数学核心,其实现与circuit_mode直接相关:
if (ndd->s_ntc_config.circuit_mode == CIRCUIT_MODE_NTC_VCC) { r_ntc_ohm = (vdd_mv - voltage_mv) * fixed_ohm / voltage_mv; } else if (ndd->s_ntc_config.circuit_mode == CIRCUIT_MODE_NTC_GND) { r_ntc_ohm = voltage_mv * fixed_ohm / (vdd_mv - voltage_mv); } *temperature = 1.0 / (log(1.0 * r_ntc_ohm / r25_ohm) / b_value + 1.0 / 298.15) - 273.0;- 先由采样电压与已知的
vdd_mv、fixed_ohm反推当前热敏电阻阻值r_ntc_ohm(两种接法的公式互为倒数关系,接法配置错误会直接导致温度方向颠倒或数值异常); - 再代入B 值公式(β 参数方程)计算温度:
T = 1 / (ln(Rt/R25)/B + 1/298.15) - 273.15(源码中以 298.15 为 25℃ 的开尔文温度、273.0 为偏移做近似换算)。
4. 温度读取(ntc_dev_get_temperature)
每次调用按以下链路执行:
- 开启滤波时(
CONFIG_ENABLE_NTC_ADC_FILTER,默认开启):调用adc_oneshot_get_filtered_result连续采样CONFIG_NTC_FILTER_WINDOW_SIZE(默认 50)次,先计算均值与标准差,再将偏离均值超过一个标准差的异常采样丢弃后重新求平均,从而滤除 ADC 噪声尖峰; - 关闭滤波时:单次
adc_oneshot_read读取原始值 →adc_cali_raw_to_voltage校准为电压; - 最终校验电压非零后调用电压转温度函数。源码对
adc_raw == 0、voltage == 0等边界情况均有显式保护(返回ESP_FAIL并打印告警)。
5. 资源释放(ntc_dev_delete)
按创建顺序的逆序清理:删除校准方案句柄(Curve Fitting / Line Fitting 二选一)→ 若 ADC 单元由驱动内部创建则adc_oneshot_del_unit释放 →free驱动结构体。组件还配套了内存泄漏测试(见 test_ntd_driver.c),通过setUp/tearDown对比MALLOC_CAP_8BIT/MALLOC_CAP_32BIT堆变化来断言驱动创建-删除循环不产生泄漏,开发者可据此放心在长时间运行的固件中反复创建/释放 NTC 设备。
API 一览
ntc_driver对外仅暴露 4 个 API(定义见 ntc_driver.h):
| API | 功能 | 返回值 |
|---|---|---|
ntc_dev_create(config, ntc_handle, adc_handle) | 初始化 NTC 与 ADC 通道配置,创建驱动句柄 | ESP_OK/ESP_FAIL/ESP_ERR_INVALID_ARG/ESP_ERR_NO_MEM |
ntc_dev_get_adc_handle(ntc_handle, adc_handle) | 从驱动句柄取出内部 ADC 句柄,供上层复用 | ESP_OK/ESP_ERR_INVALID_ARG |
ntc_dev_get_temperature(ntc_handle, temperature) | 读取当前温度(单位 ℃),结果写入float * | ESP_OK/ESP_FAIL/ESP_ERR_INVALID_ARG |
ntc_dev_delete(ntc_handle) | 删除驱动设备并释放 ADC 资源 | ESP_OK/ESP_FAIL/ESP_ERR_INVALID_ARG |
组件结构速览
- 组件文档:电路原理、两种接法说明与最小示例代码;
- 公共头文件:类型定义与 API 声明;
- 驱动实现:ADC 初始化、校准、滤波与温度换算全流程;
- Kconfig:ADC 滤波开关与窗口大小配置;
- 测试应用:与示例完全相同的默认配置(CMFA103J3950HANT,B=3950),并附带内存泄漏检测;
- 构建配置:依赖
esp_adc组件。
常见问题与排查建议
- 温度读数方向相反或数值异常:优先核对
circuit_mode是否与实际电路一致(NTC 在 Rref 上方选CIRCUIT_MODE_NTC_VCC,下方选CIRCUIT_MODE_NTC_GND); - 日志提示
eFuse not burnt, skip software calibration:芯片 eFuse 未烧录校准数据,驱动会跳过软件校准,温度精度可能下降; - 读数跳动较大:确认
ENABLE_NTC_ADC_FILTER已开启(默认开启),可适当调大NTC_FILTER_WINDOW_SIZE换取更稳定读数,代价是更新周期变长; - 更换开发板/芯片:通过
idf.py set-target切换目标芯片(示例已覆盖 ESP32-C2 / ESP32-C3 / ESP32 / ESP32-C6 / ESP32-S3),并核对unit/channel/atten是否在目标芯片上可用。
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考