T12 温控先别调 PID:先让每一帧读数可信
温度数字越大,烙铁就越热——这句话听起来没什么可讨论的。但如果 ADC 只增加了一个计数,程序给出的“温度”反而下降 21,接下来该检查什么?
先别急着调 PID。
控制器只知道你交给它的数字。上游把输入算错了,后面的比例、积分、微分调得再漂亮,也是在认真追赶一个错误目标。下面以 ESP32-S2、PD 供电和 T12 烙铁头组成的手持工具为例,把测量链路拆开,重新实现一段可以在电脑上验证的采样诊断程序。
本文完成的是数据采集与可信度校验,附件默认回放合成输入,没有驱动发热体。硬件电路用来解释信号从哪里来;这里不把软件测试通过当作整机已经可以安全复刻。
一根线上,挤着两种完全不同的信号
这种方案最值得研究的地方,是 P+ 同时处在加热回路和测温入口。
加热时,MOSFET 把电源送向烙铁头。测温时,软件先关断加热,再读取经过运放处理的微弱信号。两者都发生在同一个端子附近,不能把任意时刻的 ADC 数字都解释成温度。

图 1:实际 EDA 原理图导出件的局部。P+ 经过 R12 进入 OPA333 测量通道,下方为功率开关。该图用于说明既有连接,未实施新版 PCB 修改。
原理图中,OPA333 的反馈电阻为 100kΩ 和 1kΩ,理想同相增益是 101。输入侧的 10kΩ 与 2.2nF 对应一个 22µs 的局部 RC 时间常数。看到这个数,很容易顺手写一句“等上几个时间常数就能采样”。
问题是,RC 只是其中一段。运放可能刚经历过大信号过载,输出还需要恢复;ADC 输入本身也有采样过程。TI 的 OPA333 数据手册给出的典型增益带宽积为 350kHz、压摆率为 0.16V/µs,还专门提供过载恢复和不同闭环增益下的稳定时间曲线。不能把其中任何一个数字,单独当作整板关断后的等待时间。
现有程序使用 950µs 等待。这个值可以作为核查线索,却不能因为它写在源码里,就成为所有器件、供电和烙铁头组合的实测结论。真正确定等待窗口,需要同步观察开关控制、测量输出与采样时刻。
还有一道硬件边界:图中运放由 +5V 供电,输出直接连到 ESP32-S2 的 ADC 输入。当前没有足够证据证明它在加热、拔插与过渡状态下都满足 MCU 的电气限制。软件识别“ADC 满量程”发生在读数之后,不能代替输入保护。因此,本例程不提供原板接上发热体后的上电调试步骤。
引脚号要对,但不能只盯着文字

图 2:主控局部。GPIO 编号与封装引脚编号不同,程序中填写的是 GPIO 编号。
实际网表核对结果如下:
| 用途 | ESP32-S2 GPIO | 原理图网络 |
|---|---|---|
| 加热控制 | GPIO5 | PWM |
| 测量输出 | GPIO6 | ADC0 |
| 输入电压采样 | GPIO7 | ADC1 |
图上控制网络有 PWM 与 pwm 的大小写差异。直接据此下结论说“这里断线了”,会闹出另一个错误。EDA 导出的真实网表把 U1 的 10 号脚和 R17 的 2 号脚归入了同一网络,连接关系是存在的。
检查开源工程时,截图适合定位,网表适合确认。两者出现疑点,就继续查证,不用猜测补齐结论。
一个计数,为什么能让结果掉下去
现有采样函数有两个很具体的问题。
首先,累加变量声明后没有赋初值,接下来却直接执行加法。期望它“每次刚好从零开始”没有依据。其次,同一次判断里多次调用 ADC:第一次决定走哪个分支,第二次参与计算,后续条件又可能读取新的值。信号恰好位于阈值附近时,分支依据与实际计算对象可能不是同一个样本。
即使先假定这些读取都得到相同数字,分段换算仍有问题。把固定输入代入程序的原有整数运算与系数,可得到:
| ADC 输入 | 程序换算结果 |
|---|---|
| 3099 | 200 |
| 3100 | 179 |
| 5999 | 348 |
| 6000 | 338 |

图 3:根据代码公式计算的曲线,不是实测温度曲线。两个边界存在负跳变,纵轴只能称为程序换算结果。
这时增加平均次数,并不能把错误公式变对。把下降点滤得更圆滑,只是让问题看起来不那么突然。
也不能轻率地把公式里的 8191 改成 4095。当前核对的 Arduino-ESP32 2.0.17 在 ESP32-S2 上默认返回宽度为 13 位,8191 有其上下文。新的诊断程序主动采用 12 位输入契约,且显式设置分辨率;它不继续套用原来的温度系数。要得到摄氏温度,还需要针对实际测量链路完成标定与验证。
先保存原始样本,再决定它能不能用
新实现把“读取”“统计”“换算”分开。第一步只收集 32 个原始样本,每次循环读一次:
for (size_t i = 0; i < kCount; ++i) {
frame.raw[i] = read();
}
第二步使用从零开始的 32 位累加器计算均值。32 个接近 12 位满量程的原始值,总和能超过 65535;因此,新实现保留 raw 数据后,不能仍然用 16 位总和。这里讨论的是新数据结构,不能倒过来宣称原函数先换算后的总和也一定溢出。
uint32_t sum = 0;
for (size_t i = 0; i < kCount; ++i) {
sum += frame.raw[i];
}
const float mean = float(sum) / kCount;
保存样本还有一个好处:均值失去的信息,可以重新找回来。假设 31 个值都正常,其中一个已经削顶。如果只看平均值,异常可能被稀释;逐点检查可以在平均之前留下明确原因。
本例检查超出 12 位范围的输入、满量程削顶、整帧最大最小值之差,以及前后半帧均值差。后一个指标用于暴露“这一帧还在明显爬升或下降”的现象。但它不是稳定性的充分证明:慢变化、稳定偏置和卡在某个正常数字上的故障,都可能通过这些检查。
所以,返回值叫数据可信状态,不能被解释成“已经证明烙铁温度准确”。
旧的好数据,也会过期
一个测量值除了数值本身,还需要时间和身份。
附件中的每帧包含完成采集的时间戳、递增序号和关断等待元数据。重复交入上一帧,不能算作又成功采集了一次;长时间没有新数据,也不能继续使用上一次留下的“通过”。
新模块需要连续三帧满足规则,才进入可信状态。出现削顶、超时或序号异常后,故障被锁存;后续正常值不会自动把问题清掉。只有调用显式复位,并重新收集有效帧,才能恢复数据可信状态。
guard.submit(frame, now_us);
if (!guard.trusted(now_us)) {
// 记录故障;不要消费这帧的均值作为有效测量。
return;
}
const auto stats = guard.stats();
这里刻意没有附上一句“恢复 PWM”。数据可信与允许加热之间,还隔着校准、温度上限、功率级、电源和独立保护等条件。当前例程没有实现这些条件,也没有连接加热输出。
时间比较采用无符号差值处理 micros() 的一次回绕。它不是任意时间长度都正确的魔法:比较间隔必须小于半个 32 位计数范围。系统停机很久后,应重新开始状态判断,不能把跨越多个回绕的时间当作一段短延迟。
示例配置为 2000µs 等待元数据、100ms 新鲜度、80 码跨度和 16 码半帧均值差。这些值用于演示与测试,尚未经过实物整定。程序知道的元数据,也不能证明 MOSFET 真的已经断开。
让错误输入先在电脑上走一遍

图 4:本次主机测试输出的排版记录。输入是合成数据,未连接烙铁或示波器。
回放先连续送入四帧 1200,第五帧加入一个满量程样本,随后再恢复正常。结果很直接:第三帧开始可信,第五帧报告削顶,第六、第七帧仍保留故障。稳定数字重新出现,不会悄悄抹掉已经发生的问题。
测试还覆盖初始化总和、恰好 32 次读取、数据范围、时间边界、重复与乱序帧、时间和序号回绕,以及新帧不能掩盖已经发生的采样间断。29 项检查通过,运行的就是附件使用的同一份 C++ 模块。
默认回放程序也完成了 ESP32-S2 目标编译:PlatformIO espressif32 6.9.0,Arduino-ESP32 2.0.17,板型 esp32-s2-saola-1。构建报告静态 RAM 26444 字节、Flash 248438 字节;这些数据不代表实机峰值内存或温控性能。
在附件工程目录执行 pio run 即可构建默认回放程序。主机逻辑验证可用支持 C++11 的编译器:
c++ -std=c++11 -Wall -Wextra -Werror -I include \
tests/test_sample_guard.cpp -o test_sample_guard
./test_sample_guard
默认程序不读取实体 ADC,也不输出 PWM。可选采集模式只用于独立开发板上已经确认电气范围的输入诊断,未做实体运行验证。不要把它刷进带着发热体的成品焊台,当作完整控制固件使用。
温控的起点,是知道眼前这一帧究竟读到了什么、何时读到、现在还能不能用。把这一层做清楚,后面的标定和控制参数才有值得讨论的基础。
创作来源与许可:立创开源广场《T12-PD-ESP32S2》,fuzongxian / SamFu,项目页标示 Public Domain;核对日期 2026-09-21。完整项目网址:https://oshwhub.com/fuzongxian/t12-pd-esp_copy 。原理图、源码及网表来自对应公开工程;图 1~2 为实际 EDA 导出件的裁剪排版,图 3 为代码公式计算图,图 4 来自实际主机测试日志。本文未改动原板,未进行实物加热、温度标定或输入保护验证。新采样模块独立编写,采用 MIT 许可。
参考资料:TI OPA333 数据手册,https://www.ti.com/document-viewer/OPA333/datasheet ;Arduino-ESP32 2.0.17 的 ADC 实现与本文固定版本构建记录。本文完成工程连接核对、公式边界分析、29 项主机检查和默认回放程序目标编译;不把这些结果当作整机验证。
代码下载:本文附件 T12-sample-diagnostic-20260921.zip,包含独立诊断源码、MIT 许可、使用说明及真实测试与编译记录。默认运行合成数据回放。
技术交流,欢迎关注微信公众号:美男子玩编程。



