固件 0.1.19~0.1.21-c5:配网热点(SoftAP + 网页)、风扇 40 ℃ 以下断电
- 0.1.19 配网热点:没配 WiFi / 连续 60 s 连不上时自己开 SoftAP,192.168.4.1 网页里加删 WiFi、改 MQTT; 配置拼成 wifi / mqtt 命令走唯一的命令处理器(新链路号 3 CMD_LINK_AP),MQTT 仍不收配置命令 - 0.1.20 热点口令固定 88888888 - 0.1.21 风扇:板温 >=40 ℃ 上电、<38 ℃ 断电,40~65 ℃ 线性调速;fan 命令加可选 sec(下限到点自动交回) - mqtt 命令加 keep_pass;net 回应加 ap;status 的 fan 加 left - 新增 test_prov(13 例),test_t_thermal +3;29 ctest 全绿 Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
+60
-2
@@ -25,6 +25,10 @@ static bool s_inited;
|
||||
/* 上位机 `fan` 命令给的下限(A12)。**跨任务**:命令处理器在执行器任务里写,
|
||||
本模块在热管理任务里读。一个对齐的 16 位量,Xtensa 上读写是原子的,不加锁。 */
|
||||
static volatile uint16_t s_floor;
|
||||
/* 下限的时限(`t_thermal_set_floor_for`)。写的顺序是「先 until、再 timed、最后 floor」,
|
||||
读的一侧最坏只会晚一圈(1 s)才认到新值。 */
|
||||
static volatile uint32_t s_floor_until;
|
||||
static volatile bool s_floor_timed;
|
||||
|
||||
/* 风扇侧占空比 → 真正写进 `hal_pwm` 的值。Q6 是低边管,栅极高 = 把风扇的
|
||||
PWM 线拉低 ⇒ 反相(`t_thermal.h` 硬件那三条的第 2 条)。 */
|
||||
@@ -107,6 +111,7 @@ hal_err_t t_thermal_init(thermal_snap_t *s, therm_temp_fn temp, therm_tach_fn ta
|
||||
return e;
|
||||
}
|
||||
s->fan_en = true;
|
||||
s->fan_starts = 1;
|
||||
s->en_ms = hal_time_now_ms();
|
||||
s->last_ms = s->en_ms;
|
||||
|
||||
@@ -133,6 +138,17 @@ static void tach_step(thermal_snap_t *s, int idx, uint32_t dt_ms, uint16_t duty)
|
||||
const uint32_t delta = now_edges - t->last_edges; /* uint32 相减,回绕安全 */
|
||||
t->last_edges = now_edges;
|
||||
|
||||
/* 风扇断着电:不累加、不判(惯性滑行那几圈的脉冲也不算数),转速如实报 0。
|
||||
`stalled` 不动 —— 见头文件「断电期间不判停转」。 */
|
||||
if (!s->fan_en) {
|
||||
t->win_edges = 0;
|
||||
t->win_on_ms = 0;
|
||||
t->win_ms = 0;
|
||||
t->rpm = 0;
|
||||
t->rpm_valid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 启动宽限期内一直重置窗口:这时候风扇还在起转,脉冲本来就没有或很稀。 */
|
||||
if (s->fan_en && hal_time_elapsed_ms(s->en_ms) < T_THERMAL_SPINUP_MS) {
|
||||
t->win_edges = 0;
|
||||
@@ -216,11 +232,37 @@ hal_err_t t_thermal_step(thermal_snap_t *s)
|
||||
s->temp_errors++;
|
||||
}
|
||||
uint16_t duty = t_thermal_duty_for(s->temp_max_mc, s->temp_valid);
|
||||
if (s_floor_timed && (int32_t)(now_ms - s_floor_until) >= 0) {
|
||||
s_floor = 0; /* 上位机给的时限到了:交回自动 */
|
||||
s_floor_timed = false;
|
||||
}
|
||||
const uint16_t floor_ = s_floor;
|
||||
if (floor_ > duty) {
|
||||
duty = floor_; /* 手动值只抬不压:曲线要得更高时照曲线来 */
|
||||
}
|
||||
(void)apply_duty(s, duty);
|
||||
|
||||
/* ---- 开还是关(`T_THERMAL_FAN_OFF_MC` 上的说明)----
|
||||
读不到温度、上位机要风:一律开。否则按迟滞:开着的掉到 OFF 以下才关,关着的到 ON 才开。 */
|
||||
bool want_on = true;
|
||||
if (s->temp_valid && floor_ == 0) {
|
||||
want_on = s->fan_en ? (s->temp_max_mc >= T_THERMAL_FAN_OFF_MC)
|
||||
: (s->temp_max_mc >= T_THERMAL_FAN_ON_MC);
|
||||
}
|
||||
if (want_on != s->fan_en) {
|
||||
/* 开:先把占空比写好再给 12V(同 init 的顺序);关:先断 12V。写失败就维持原状,下一圈再来。 */
|
||||
if (want_on) {
|
||||
(void)apply_duty(s, duty);
|
||||
}
|
||||
if (hal_gpio_write(BOARD_PIN_FAN_EN, want_on ? 1 : 0) == HAL_OK) {
|
||||
s->fan_en = want_on;
|
||||
if (want_on) {
|
||||
s->en_ms = now_ms; /* 启动宽限从这里重新算 */
|
||||
s->fan_starts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 断着电时占空比报 0:遥测里「duty 300、en false」会让人以为它在转。 */
|
||||
(void)apply_duty(s, s->fan_en ? duty : 0);
|
||||
|
||||
/* ---- 过温降载:本模块只**报**,关路是限功率那一包的事 ---- */
|
||||
if (s->temp_valid) {
|
||||
@@ -241,9 +283,25 @@ hal_err_t t_thermal_step(thermal_snap_t *s)
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
void t_thermal_set_floor(uint16_t permille)
|
||||
void t_thermal_set_floor(uint16_t permille) { t_thermal_set_floor_for(permille, 0); }
|
||||
|
||||
void t_thermal_set_floor_for(uint16_t permille, uint32_t ttl_ms)
|
||||
{
|
||||
const bool timed = ttl_ms > 0 && permille > 0;
|
||||
if (timed) {
|
||||
s_floor_until = hal_time_now_ms() + ttl_ms;
|
||||
}
|
||||
s_floor_timed = timed;
|
||||
s_floor = (permille > 1000u) ? 1000u : permille;
|
||||
}
|
||||
|
||||
uint16_t t_thermal_floor(void) { return s_floor; }
|
||||
|
||||
uint32_t t_thermal_floor_left_ms(void)
|
||||
{
|
||||
if (!s_floor_timed || s_floor == 0) {
|
||||
return 0;
|
||||
}
|
||||
const int32_t left = (int32_t)(s_floor_until - hal_time_now_ms());
|
||||
return left > 0 ? (uint32_t)left : 0;
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户