文件
zhou yang和Claude Opus 5.5 c37c08aa43 固件 A16:风扇闭环接进任务体 + NTC / TACH 真实采样(已上板)
- ntc.{h,c}(宿主机可测):分压端 mV → Ω → NCP18XH103F03RB 的 R-T 表插值;
  开路 / 短路 / 表外一律「读不到」(t_thermal 因此满速)
- thermal_esp.{h,c}(仅 IDF):ADC1 oneshot + 曲线校准读两路 NTC;两个 PCNT 单元数 TACH 边沿
- app_main:task_thermal 任务体、t_thermal_init 放在上电恢复之前、status 带热管理快照
- test_ntc.c 4 例;全工程 429 例全绿;版本 0.1.0-a16
- 板 B:两路 NTC 38.2 / 34.0 °C;风扇两路 rpm 0 报停转(拉满电流不涨,疑未插风扇,待确认)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 13:31:32 +08:00

87 行
3.5 KiB
C

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/* A16:NTC 换算(ntc.h)。两条最要紧的:
⭐ 方向 —— NTC 在下臂,**越热电压越低**;写反了闭环照样有数,只是反着转;
⭐ 开路 / 短路判「读不到」—— 读不到时 t_thermal 会满速(§10.10),
而把开路算成 −40 °C 的后果是「风扇按最低速转、机器在烤」。 */
#include "ntc.h"
#include "unity.h"
void setUp(void) {}
void tearDown(void) {}
/* 分压端电压(与 ntc.c 的反算互为逆运算,单独写一遍免得自己证明自己)。 */
static int32_t mv_at(uint32_t ohm) { return (int32_t)(3300ull * ohm / (NTC_PULLUP_OHM + ohm)); }
static void test_table_points(void)
{
int32_t mc = 0;
TEST_ASSERT_TRUE(ntc_mc_from_ohm(10000, &mc));
TEST_ASSERT_EQUAL_INT32(25000, mc);
TEST_ASSERT_TRUE(ntc_mc_from_ohm(4161, &mc));
TEST_ASSERT_EQUAL_INT32(50000, mc);
TEST_ASSERT_TRUE(ntc_mc_from_ohm(195652, &mc));
TEST_ASSERT_EQUAL_INT32(-40000, mc);
TEST_ASSERT_TRUE(ntc_mc_from_ohm(531, &mc));
TEST_ASSERT_EQUAL_INT32(125000, mc);
/* 格内插值:10000 与 8315 的正中间 ≈ 27.5 °C。 */
TEST_ASSERT_TRUE(ntc_mc_from_ohm((10000 + 8315) / 2, &mc));
TEST_ASSERT_INT32_WITHIN(20, 27500, mc);
}
/* ⭐ 方向:电压从高扫到低,温度必须一路**不降**;电阻从大到小同理。 */
static void test_hotter_means_lower_voltage(void)
{
int32_t prev = -1000000, mc = 0;
int n = 0;
for (int32_t mv = 3300 - NTC_RAIL_MARGIN_MV - 1; mv > NTC_RAIL_MARGIN_MV; mv -= 7) {
if (ntc_mc_from_mv(mv, 3300, &mc)) {
TEST_ASSERT_TRUE_MESSAGE(mc >= prev, "电压降低时温度必须升高(NTC 在下臂)");
prev = mc;
n++;
}
}
TEST_ASSERT_TRUE(n > 300);
/* 两个现实点:25 °C 正好一半(1650 mV);60 °C ≈ 0.76 V。 */
TEST_ASSERT_TRUE(ntc_mc_from_mv(1650, 3300, &mc));
TEST_ASSERT_INT32_WITHIN(100, 25000, mc);
TEST_ASSERT_TRUE(ntc_mc_from_mv(mv_at(3014), 3300, &mc));
TEST_ASSERT_INT32_WITHIN(200, 60000, mc);
}
/* ⭐ 开路(贴 +3V3)/ 短路(贴地)/ 表外:一律「读不到」,而且不动输出。 */
static void test_open_and_short_are_not_temperatures(void)
{
int32_t mc = 12345;
TEST_ASSERT_FALSE(ntc_mc_from_mv(3300, 3300, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_mv(3290, 3300, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_mv(0, 3300, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_mv(10, 3300, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_mv(-5, 3300, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_mv(1650, 0, &mc));
TEST_ASSERT_FALSE(ntc_mc_from_ohm(200000, &mc)); /* < −40 °C */
TEST_ASSERT_FALSE(ntc_mc_from_ohm(500, &mc)); /* > 125 °C */
TEST_ASSERT_EQUAL_INT32(12345, mc);
TEST_ASSERT_FALSE(ntc_mc_from_mv(1650, 3300, NULL));
}
/* 比例式:+3V3 偏 1 %(3.267 V),只要把实际值传进来,读数不变;
传错成 3300 时误差约 0.6 °C(25 °C 附近)—— 对风扇闭环无所谓。 */
static void test_ratiometric(void)
{
int32_t a = 0, b = 0;
TEST_ASSERT_TRUE(ntc_mc_from_mv(1650, 3300, &a));
TEST_ASSERT_TRUE(ntc_mc_from_mv(1634, 3267, &b));
TEST_ASSERT_INT32_WITHIN(50, a, b);
TEST_ASSERT_TRUE(ntc_mc_from_mv(1634, 3300, &b));
TEST_ASSERT_INT32_WITHIN(700, a, b);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_table_points);
RUN_TEST(test_hotter_means_lower_voltage);
RUN_TEST(test_open_and_short_are_not_temperatures);
RUN_TEST(test_ratiometric);
return UNITY_END();
}