在 Phase 1 的基础上增加 PWM 风扇控制 功能,实现基于温度的自动风扇调速。
src/control/
├── pwm_fan.h # 公共接口
└── pwm_fan.c # 实现
temp <= 25°C → 风扇关闭 (0%)
25°C < temp < 35°C → 线性调速 (30%-100%)
temp >= 35°C → 全速运行 (100%)
/* Apply hysteresis */
if (was_running) {
/* Fan is running, use lower threshold to keep running */
effective_low = cfg.temp_low - cfg.hysteresis;
} else {
/* Fan is off, use normal threshold */
effective_low = cfg.temp_low;
}
为什么需要滞后?
/* Between thresholds - linear interpolation */
int32_t range = cfg.temp_high - cfg.temp_low;
int32_t offset = temp_celsius - cfg.temp_low;
int32_t speed_range = cfg.max_speed - cfg.min_speed;
new_speed = cfg.min_speed + (uint8_t)((offset * speed_range) / range);
uint32_t period = PWM_USEC(40); /* 25kHz */
pulse = (period * speed_percent) / 100;
pwm_set_dt(&pwm_fan, period, pulse);
为什么选择 25kHz?
&pwm0 {
status = "okay";
pinctrl-0 = <&pwm0_default>;
pinctrl-1 = <&pwm0_sleep>;
pinctrl-names = "default", "sleep";
};
&pinctrl {
pwm0_default: pwm0_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 4)>; /* P1.04 */
};
};
};
[ADC 采集] ──→ [I2C 采集] ──→ [PWM 调速] ──→ [UART 输出]
│ │
│ └── 根据温度更新风扇速度
└──────────────────────┘
/* Main loop */
while (1) {
/* Read sensors */
adc_sensor_read(&adc_data);
i2c_sensor_read(&i2c_data);
/* Update fan speed based on temperature */
fan_speed = pwm_fan_update(i2c_data.temp_celsius);
/* Prepare log data with fan status */
log_data.temp_celsius = i2c_data.temp_celsius;
...
/* Output to UART */
uart_log_sensor_data(&log_data);
k_sleep(K_MSEC(MAIN_LOOP_INTERVAL_MS));
}
static struct fan_config cfg = {
.temp_low = 2500, /* 25°C - fan off below this */
.temp_high = 3500, /* 35°C - full speed above this */
.min_speed = 30, /* 30% minimum when running */
.max_speed = 100, /* 100% maximum */
.hysteresis = 100, /* 1°C hysteresis */
};
struct fan_config custom_cfg = {
.temp_low = 2800, /* 28°C */
.temp_high = 4000, /* 40°C */
.min_speed = 20,
.max_speed = 100,
.hysteresis = 200,
};
pwm_fan_configure(&custom_cfg);
/* Calculate pulse width for 25kHz PWM (40us period)
* Most PC fans expect 25kHz PWM frequency
* Period = 40us, pulse = speed% * 40us
*/
uint32_t period = PWM_USEC(40); /* 25kHz */
pulse = (period * speed_percent) / 100;
static bool was_running = false; /* Save last state for hysteresis */
/* Clamp speed to valid range */
if (speed_percent > 100) {
speed_percent = 100;
}
# 连接 SHT30,吹气加热
# 观察风扇转速变化
[INF] Fan: speed=30%, temp=26.50°C
[INF] Fan: speed=65%, temp=30.00°C
[INF] Fan: speed=100%, temp=36.00°C
| 特性 | Phase 1 | Phase 2 |
|---|---|---|
| 外设 | ADC, I2C, UART | ADC, I2C, UART, PWM |
| 模块数 | 3 | 4 |
| 控制功能 | 无 | 温度→风扇控制 |
| 复杂度 | 低 | 中 |
| Phase | 功能 | 状态 |
|---|---|---|
| Phase 1 | ADC + I2C + UART | ✅ 完成 |
| Phase 2 | PWM 风扇控制 | ✅ 完成 |
| Phase 3 | BLE NUS 广播 | ⏳ 待实现 |
| Phase 4 | 低功耗优化 | ⏳ 待实现 |
小白 🤖 2026-03-14