联系管理员

开通文章发布权限

扫码 添加微信
微信图片
电话: QQ:1602036736

给泰山派 1M 风扇做「自动调速」

给泰山派 1M 风扇做「自动调速」

记录日期:2026-10-09
板子:泰山派 1M(芯片 RK3566)
读完你会明白:这个功能是怎么做的、为什么之前一直没做好、以及每一个命令到底在干什么。

第 0 章 一句话说清这件事

这块主板跑起来会发热,我们在上面装了个小风扇吹它。

但风扇不能一直傻转 —— 一直全速又吵又费电。我们希望它自己看温度决定转速:

主板温度风扇力度听感
45 °C 以下35%慢悠悠,几乎听不见
45 ~ 50 °C55%有点声音
50 ~ 55 °C75%明显在吹
55 °C 以上90%全力吹

这个"自己看温度调转速"的活儿,就是温控调速。

这次要解决的问题是:之前风扇不管多凉都快转(一直全速),上面的表格根本没生效。我们把它修好了。


第 1 章 先搞懂 7 个词

不用背,看不懂就跳过去,后面遇到再回来查。

① 开发板 / 主板

一台小电脑。我们这台用的是泰山派 1M,芯片是瑞芯微的 RK3566。

② PWM(脉宽调制)

这是全文最重要的概念。

想象你要控制水龙头的水流大小,但水龙头只有"全开"和"全关"两个状态,没有中间档。
怎么办?快速地开、关、开、关。开的时间占的比例越大,平均水流就越大。

  • 一秒钟开 1000 次,其中 350 次是开的 → 平均水流 35%

  • 一秒钟开 1000 次,其中 1000 次都是开的 → 平均水流 100%

这个"开的时间占的比例"就叫 占空比(duty cycle)。
"一秒钟开关多少次"就叫 频率。

  • 占空比 = 力度(35% 55% 75% / 90%)

  • 频率 = 开关的快慢(这次的关键就是它)

③ 设备树(dts / dtb)

主板上的硬件那么多,内核怎么知道"哪个引脚接了什么"?
靠一张说明书,就叫设备树。

  • .dts = 人看的说明书(纯文本,能直接改)

  • .dtb = 机器看的说明书(把上面的翻译成二进制)

改硬件配置 = 改 .dts → 翻译成 .dtb。

④ boot.img 和 boot 分区

主板开机时,会先从一个叫 boot 分区 的小区域里读一个 boot.img 包裹。
这个包裹里装着:内核(系统的心脏)+ 设备树(硬件说明书)。

所以"改硬件配置"的完整链条是:

改 .dts 说明书  →  翻译成 .dtb  →  重新打包成 boot.img  →  写进 boot 分区  →  重启

⑤ /sys —— 内核的"控制面板"

Linux 里有个特殊的文件夹 /sys,里面的东西看起来是文件,其实不是文件,而是内核开出来的控制面板:

  • 读它 = 问内核"现在什么情况?"

  • 写它 = 命令内核"改成这样!"

比如:

cat /sys/class/thermal/thermal_zone0/temp     # 问:现在多少度?
echo 90 > /sys/class/hwmon/hwmon2/pwm1        # 命令:风扇力度调成 90

(cat 是"显示内容",echo xxx > 是"把 xxx 写进去",下面会细讲)

⑥ 调速器(thermal governor)

内核里管温控的"大脑",有好几种性格:

  • power_allocator(功耗分配型):按功耗预算分配降温资源

  • step_wise(逐级型):超温就一档一档往上加

  • user_space:内核不管,让用户自己控制

这次出事的正是这个"大脑"。

⑦ 占空比 vs 频率 —— 用一句话记住

占空比决定"多大劲",频率决定"开关多快"。
这次的毛病是"开关太快",不是"劲不对"。

第 2 章 硬件是怎么接的

风扇不是直接插在主板上的,中间加了一小块电路。用户提供的电路图我们读出来是这样:

        +5V 电源
          │
     ┌────┴────┐
     │  R298   │ 20kΩ(把开关默认拉到"关")
     │  20k    │
     └────┬────┘
          │
   +5V ───┼──── Q9 (AO3407,P沟道MOS管,当"电子开关"用)
          │            │
          │            └──── 风扇正极 (CN15 第1脚)
          │                        │
          │                     风扇
          │                        │
          │                     GND 地
          │
   Q10 (NPN三极管,负责"把开关拉下来打开")
          │
   R299 1kΩ ── PWM0_M0(主板引脚 GPIO0_B7)
          │
   R300 10kΩ ── GND

用大白话说这套电路在干嘛:

  1. 主板引脚 PWM0_M0 输出"开/关"信号(就是 PWM 波)

  2. 引脚高电平 → 三极管 Q10 导通 → 把 MOS 管 Q9 的"闸门"拉低 → Q9 打开 → 风扇通电

  3. 引脚低电平 → Q10 关闭 → 电阻 R298 把"闸门"拉回 +5V → Q9 关闭 → 风扇断电

所以:引脚高电平的时间比例 = 风扇通电的时间比例 = 风扇力度。逻辑是对的。

顺带说:AO3407 是 P 沟道 MOS 管,做"高边开关"(控制电源正极)时必须源极接 +5V、漏极接风扇。如果装反了,它内部那个"寄生二极管"会一直给风扇供电,怎么调都没用。这一点我们后来专门验证过,没装反。

第 3 章 症状:风扇一直全速

用户的原话是"一直全速"。我们上板子一看:

cat /sys/class/thermal/thermal_zone0/temp
# 输出:36666      ← 意思是 36.666°C,很凉快
cat /sys/class/thermal/cooling_device0/cur_state
# 输出:4          ← 风扇档位被拉到最高档(一共 0~4 五档)

36.7°C 却全力吹 —— 明显不正常,凉快的时候应该是 0 档才对。


第 4 章 排查过程:一步一步找出真凶

排查思路是"从软件到硬件,一层层往下剥"。

第 1 步:确认软件链路有没有问题

先证明"主板引脚确实在输出 PWM 波"。 查了三个地方:

① 引脚有没有被正确"复用"成 PWM 功能

芯片的引脚是多功能复用的,得先设置成"PWM 模式"。

grep pwm /sys/kernel/debug/pinctrl/*/pinmux-pins
# 输出里有:
# pin 15 (gpio0-15): fdd70000.pwm (GPIO UNCLAIMED) function pwm0 group pwm0m0-pins

翻译:15 号引脚(就是 GPIO0_B7)现在归 fdd70000.pwm 这个 PWM 控制器管,工作模式是 pwm0m0。
✅ 引脚复用是对的。

② PWM 控制器的时钟有没有开

设备没时钟就等于没通电,什么都不会输出。

grep pwm0 /sys/kernel/debug/clk/clk_summary
# 输出里有:
# clk_pwm0   1   1   0   12000000   0   0   50000   Y   fdd70000.pwm   pwm

翻译:clk_pwm0 这个时钟被启用了(第一个数字 1 = 启用次数),频率 12000000 = 12 MHz。
✅ 时钟是开着的。

③ 直接看 PWM 控制器的寄存器(最硬的证据)

寄存器就是芯片内部的小格子,里面存着"周期设成多少、占空比设成多少、开没开"。

cat /sys/kernel/debug/fdd70000.pwm
# 输出第一行:
# fdd70000:  00000000 000001e0 000000a9 0000000b

这 4 个数按顺序是:计数器 周期 占空比 / 控制字

  • 周期 = 0x1e0 = 480

  • 占空比 = 0xa9 = 169

  • 控制字 = 0x0b = 二进制 1011 → 最低位是 1,表示已使能

换算一下:时钟 12 MHz ÷ 480 = 25 kHz(一秒开关 25000 次);169 ÷ 480 = 35.2%。

0x 开头表示这是十六进制(电脑里常用的一种计数法)。0x1e0 换成我们熟悉的十进制就是 480。

✅ 结论:主板这边完全正确。 芯片确实在老老实实输出一个 25 kHz、35% 的波形。

所以问题不在软件,在别处。

第 2 步:那是不是"温控大脑"没在管风扇?

查了一下当前用的"大脑":

cat /sys/class/thermal/thermal_zone0/policy
# 输出:power_allocator

而 dmesg(内核的"工作日志")里赫然写着:

thermal thermal_zone0: power_allocator: pwm-fan is not a power actor

翻译:power_allocator 这个"大脑"看了风扇一眼,说"你不是我的菜",然后完全不管它。

真相浮出水面:

  • 主板开机默认用 power_allocator

  • 这个大脑拒绝管理风扇

  • 于是风扇就一直保持驱动自己开机时设的初始值 —— 100% 满速

  • 再也没有任何东西去把它调下来

前任同事以为"power_allocator 会把风扇推到满速",其实更简单也更荒诞:它压根不碰风扇。

顺带发现一个更离谱的:之前有人写了个开机脚本想修这个问题,脚本里写的是:

[ "$(cat $z/type)" = "soc_thermal" ] && echo step_wise > $z/policy

但板子上那个"温度区"的真名是 soc-thermal(中间是横杠),脚本里写的是下划线。
→ 条件永远不成立 → 脚本三个多月来一次都没真正执行过。
更坑的是脚本最后写了 exit 0(表示"我成功了"),于是系统还显示服务正常运行,属于"无声失败" —— 看日志一切正常,实际啥也没干。

第 3 步:找到正确的做法

翻内核源码时发现这个 SDK(芯片厂商给的开发套件)的 pwm-fan 驱动有个隐藏功能:

if (有 "rockchip,temp-trips" 这个配置 && 系统监控开着) {
        注册温度通知器;     // 驱动自己看温度设档
        return 0;           // 直接返回,不注册成"温控设备"
}
... 否则才走老路(注册成温控设备,交给"大脑"管)

翻译成人话:只要在设备树里写上 rockchip,temp-trips(一张"多少度对应几档"的表),
驱动就会自己盯着温度调风扇,完全绕过那个不靠谱的"大脑"。

而前任同事删掉的那个旧节点,用的恰恰就是这个写法 —— 方向本来就是对的。

第 4 步:软件都对了,为什么风扇还是不变速?

按上面的思路改完,理论上应该好了。但用户反馈:测的时候风扇没有一档一档变速。

于是我们做了两个"运行时实验"(不用刷机、随时能改回来)。

实验 A:静态开关测试 —— 判断 MOS 开关有没有坏

思路:把风扇变成"一直开"和"一直关"两个极端状态。如果"一直关"的时候风扇还在转,说明电路有旁路。

echo user_space > /sys/class/thermal/thermal_zone0/policy  # 让内核别插手
echo 255 > /sys/class/hwmon/hwmon2/pwm1                    # 一直开 → 全速
echo 0   > /sys/class/hwmon/hwmon2/pwm1                    # 一直关 → 应该停

同时看寄存器:

状态周期占空比控制字结果
一直开4804800x0b(使能)风扇全速
一直关48000x08(使能位=0)风扇停了 ✅

结论:MOS 开关通路完全正常,源漏没装反,没有旁路。问题只在"动态"上。

实验 B:扫频测试 —— 换个开关速度试试

思路:把风扇驱动"请走",我们手动接管 PWM,用不同频率试。

echo pwm-fan > /sys/bus/platform/drivers/pwm-fan/unbind   # 让风扇驱动让出 PWM
echo 0 > /sys/class/pwm/pwmchip0/export                   # 申请使用 PWM0
# 然后逐个频率、逐个占空比设置,让用户听

结果:

频率35% vs 100% 的听感
25 kHz(原来)听不出差别
1 kHz(新试的)能清楚听出分档 ✅
250 Hz也能,但 1 kHz 已经够了

真凶找到了。

第 5 步:为什么会这样?两个原因叠加

原因一:开关的"手"太慢

控制 MOS 管开关的"闸门"(栅极)靠一个 20 kΩ 电阻充电。算一下:

  • 闸门电容约 650 pF,电阻 20 kΩ

  • 充电时间常数 = 20000 × 0.00000000065 ≈ 13 微秒

而 25 kHz 下一个完整周期只有 40 微秒。35% 档的"关"的时间只有 26 微秒(才 2 倍时间常数)。

结果:闸门电压从 0 只爬到 4.2 V(本该爬到 5 V),MOS 管停在"半开半关"的线性区。
更糟的是,从"全开"退到"关"需要 10~22 微秒,这段时间里管子还是通的。

算总账:你要 35%,管子实际通了 62%~91%。
→ 想要 35% 和想要 100%,实际差别很小 → 听不出来。

原因二:风扇自己有个"小水桶"

风扇内部有个小电容(可以理解成蓄水池)。25 kHz 时"关"只有 26 微秒,
池子里的水(电)根本来不及放掉,风扇看到的电压几乎还是满的。

这就好比你想用快速开关水龙头控制水流,但水管中间有个大水桶把水存着 ——
水龙头开关得再快,水桶里的水也不少。

降到 1 kHz 后:

  • "关"的时间从 26 微秒变成 650 微秒,是充电时间常数的 50 倍 → 闸门有充足时间完全关严

  • 风扇那个"水桶"有 650 微秒放水 → 真正放到空 → 电压真的降下来了

一个数字改动,两个问题同时解决。


第 5 章 最终改了什么

改动只有一个文件

SDK 目录/kernel-6.1/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dts

改前(有问题):

&pwm0 {
	status = "okay";
};

/ {
	pwm0_fan: pwm-fan {
		compatible = "pwm-fan";
		#cooling-cells = <2>;
		pwms = <&pwm0 0 40000 0>;        /* 40000 纳秒 = 25 kHz */
		cooling-levels = <90 140 190 230 255>;
	};
};

&soc_thermal {                            /* 这一大段是前任加的,基于错误推断 */
	/delete-property/ sustainable-power;
	trips { fan_trip: trip-point-fan { temperature = <45000>; ... }; };
	cooling-maps { fan_map0 { ... }; };
};

改后(正确):

&pwm0 {
	status = "okay";
};

/ {
	pwm0_fan: pwm-fan {
		compatible = "pwm-fan";
		pwms = <&pwm0 0 1000000 0>;      /* 1000000 纳秒 = 1 kHz ← 关键改动 */
		cooling-levels = <90 140 190 230 255>;   /* 五档力度:35% 55% 75% 90% 100% */
		rockchip,temp-trips = <          /* 多少度 → 用第几档 */
			45000	1
			50000	2
			55000	3
			60000	4
		>;
	};
};

具体改了三件事:

  1. 40000 → 1000000:PWM 频率从 25 kHz 降到 1 kHz(最关键的一改)

  2. 删掉 #cooling-cells,加上 rockchip,temp-trips:让风扇驱动自己管温度,不再交给那个不靠谱的"大脑"

  3. 整段删掉 &soc_thermal { ... }:这段是前任基于错误推断加的。删掉后主板自动恢复出厂设置(CPU/内存的温控回到原厂行为),风扇和它们彻底解耦


第 6 章 操作全流程(每个命令都讲解)

用到的三台机器

名字是什么怎么连
开发板要动手术的对象adb 连 192.168.137.130:5555
编译服务器干重活的地方(编译很吃 CPU)ssh liguoyi@192.168.165.66
本机(Windows)你坐的地方,当"中转站"—

0. 准备知识:adb 是什么

adb = Android Debug Bridge,安卓调试桥。虽然板子跑的是 Linux,但这类芯片板子一般都用它来远程操作。

命令什么意思
adb devices列出都连上了哪些设备。看到 192.168.137.130:5555 device 就说明连上了
adb connect 192.168.137.130:5555主动连接板子。:5555 是端口号(像门牌号)
adb shell在板子上开个命令行。后面跟着的命令都是在板子上跑的
adb push 本地文件 板上路径把文件从电脑传到板子上
adb pull 板上路径 本地路径把文件从板子取回电脑
adb reboot重启板子

1. 改设备树

在编译服务器上操作:

# 先备份原文件(万一改坏了能还原)
cp tspi-rk3566-user-v10-linux.dts  tspi-rk3566-user-v10-linux.dts.bak-260909-fan-v2

# 然后编辑 dts,按第 5 章的内容改
命令讲解
cp A B复制文件。把 A 复制成 B。这里就是备份
文件名里的 .bak-260909-fan-v2我们自己起的后缀,内容就是原文件,方便以后找回

2. 编译 + 打包

⚠️ 这一步有个大坑,必须用 ./build.sh,不能直接 make。

cd ~/EX_DISK_2T/tspi-1m-linux-kernel6-1-sdk/extracted_sdk
./build.sh kernel
命令讲解
cd 目录切换当前所在目录(change directory)
./build.sh kernel运行 SDK 自带的构建脚本,参数 kernel 表示"构建内核+boot.img"

为什么不能直接 make?
编译要用交叉编译器(在 x86 电脑上编出 ARM 板子能跑的代码)。这个工具链藏在 SDK 的 prebuilts/gcc/... 目录里,要由 build.sh 把它加到 PATH 里。
我中途偷懒直接跑了 make,结果系统找不到交叉编译器,用了电脑自己的 gcc,把配置文件的编译器信息写错了。虽然最后恢复好了,但绕了一大圈 —— 记住这个教训。

PATH 是什么?可以理解成"电脑去哪些文件夹里找命令"。没加到 PATH 里,电脑就找不到那个交叉编译器。

跑完会看到什么?

Running 10-kernel.sh - build_kernel succeeded.

看到 succeeded 就成了。产物在 kernel-6.1/boot.img。

3. 验证新固件(刷之前一定要验)

# 看 boot.img 里到底装了什么
~/EX_DISK_2T/.../u-boot/tools/mkimage -l kernel-6.1/boot.img

输出里会列出三样东西:fdt(设备树)、kernel(内核)、resource(资源)。

最关键的验证:确认新设备树真的装进去了。

sha256sum kernel-6.1/arch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dtb

把这个值和 mkimage -l 输出里 Image 0 (fdt) 的 Hash value 对一下。两个一样就说明装对了。

命令讲解
sha256sum 文件算文件的"指纹"。内容只要差一个字节,指纹就完全不同。用来判断两个文件是不是一模一样
md5sum 文件同上,另一种指纹算法,更快但稍弱
mkimage -l 文件-l = list,列出这个镜像的清单

4. 传到板子上并写入

① 先把镜像从服务器拿到本机

scp liguoyi@192.168.165.66:~/.../boot.img  C:\...\boot-1khz-260909.img
命令讲解
scp安全复制(secure copy),通过网络在两台电脑间传文件

② 从本机传到板子

adb push boot-1khz-260909.img /root/T16/boot-1khz-260909.img
/root/T16/ 是板子上专门放东西的目录。千万别用 /tmp —— 那是内存盘,一重启就全没了(这个项目已经因此丢过数据)。

③ 备份板子现在的 boot 分区(最重要的一步!)

adb shell 'dd if=/dev/mmcblk0p3 of=/root/T16/boot-p3-backup-260909.img bs=1M count=64'
命令讲解
dd原样搬运数据(disk dump)。最危险的命令之一,if 和 of 写反了会毁数据
if=...input file,从哪读。这里是分区 /dev/mmcblk0p3
of=...output file,写到哪。这里是备份文件
bs=1M每次搬 1 兆字节(block size)。越大越快
count=64搬 64 次。64 × 1M = 64MB,正好是整个分区大小
/dev/mmcblk0p3板子上的第 3 个分区,也就是 boot 分区
mmcblk0 是板子上的 eMMC 存储芯片,p3 表示第 3 个分区。
用 cat /proc/partitions 可以列出所有分区。

④ 写入新镜像

adb shell 'dd if=/root/T16/boot-1khz-260909.img of=/dev/mmcblk0p3 bs=1M'
adb shell 'sync'
命令讲解
sync强制把缓存里的数据真正写到磁盘上。不敲这个,数据可能还在内存里,一断电就没了

⑤ 回读校验(确认真的写进去了)

adb shell 'dd if=/dev/mmcblk0p3 of=/tmp/readback.img bs=512 count=81169'
adb shell 'md5sum /tmp/readback.img'

把新镜像的指纹和回读的指纹对比:一样就说明写入成功。

为什么是 count=81169?因为镜像正好 41558528 字节,除以 512 正好等于 81169。这只是为了让回读长度和镜像一样,多读的尾部是旧数据不用管。

⑥ 重启

adb shell reboot

重启后 adb 会断开,等大约 45 秒再 adb connect 重连。

5. 验证效果

# 内核版本变了吗?(应该看到新日期)
adb shell cat /proc/version

# 新配置进去了吗?
adb shell ls /proc/device-tree/pwm-fan/

# 风扇现在多大力度?
adb shell cat /sys/class/hwmon/hwmon2/pwm1

# 实际占空比(看寄存器)
adb shell cat /sys/kernel/debug/fdd70000.pwm

我们的实测结果:

检查项结果
内核#8 SMP Fri Oct 9 11:05:55(原来是 #7 … Oct 8 13:38)✅
设备树有 rockchip,temp-trips ✅
PWM 周期0x2ee0 = 12000,12000 ÷ 12MHz = 1 kHz ✅
36°C 时的力度pwm1 = 90(35%),不再满速 ✅
加载后的分档45°C→55%,50°C→75%,55°C→90%,停载后自动回落 ✅

6. 加载测试(看它真的会自己加速)

我们开了 8 个"死循环"把 CPU 跑满,让板子热起来:

实测记录(挑几行):

03:14:37  temp=46111  pwm1=90     ← 46.1°C,还没到 45 档?其实刚要跨过
03:14:39  temp=51250  pwm1=190    ← 51.2°C,跳到 75%
03:14:57  temp=53750  pwm1=230    ← 53.7°C,跳到 90%
...
03:16:17  temp=45555  pwm1=140    ← 停载后掉到 45.5°C,回落到 55%
03:16:25  temp=42500  pwm1=90     ← 42.5°C,回落到 35%

温度一档档上去,风扇一档档跟上,凉下来自动回落。 ✅

命令讲解
cat显示文件内容(concatenate 的缩写,这里当"查看"用)
ls列出目录里有什么
grep 关键词 文件在文件里搜关键词,只显示匹配的行
dmesg显示内核的工作日志,排查驱动问题的第一去处
echo xxx > 文件把 xxx 写进文件。> 是"覆盖写入"
systemctl is-active 服务名看某个服务在不在运行

第 7 章 出问题了怎么回滚

一条命令写回备份:

adb shell 'dd if=/root/T16/boot-p3-backup-260909.img of=/dev/mmcblk0p3 bs=1M && sync && reboot'
符号讲解
&&前一个命令成功了,才执行下一个

为什么不会变砖? 因为 boot 分区只是"启动包裹",坏了最多是开不了机,
用上面这条命令把备份写回去就能恢复,主板本身的底层固件没动。

设备树也回滚:

cp tspi-rk3566-user-v10-linux.dts.bak-260909-fan-v2  tspi-rk3566-user-v10-linux.dts
./build.sh kernel
# 然后重新走第 6 章的刷机流程

第 8 章 名词速查表

名词大白话解释
PWM用"快速开关"模拟"中间档位"的技术
占空比一秒钟里"开"占的比例 → 决定力度
频率一秒钟开关多少次 → 这次的关键
设备树 dts dtb给内核看的"硬件接线说明书"(文本版 / 二进制版)
boot 分区 / boot.img存"启动包裹"的地方 / 包裹本身(内核+说明书)
PWM 寄存器芯片里存"周期设多少、占空比设多少"的小格子
调速器 / governor内核里管温控的"大脑",有不同性格
cooling_device"降温设备",比如风扇、CPU 降频,统一登记在册
hwmon"硬件监控"子系统,风扇在这里登记,露出 pwm1 等接口
MOS 管电子开关,用电压控制通断
栅极MOS 管的"闸门",给它电压就能开/关
时间常数 τ电容充电快慢的指标。充到 63% 需要 1 个 τ
dmesg内核的工作日志
sysfs / /sys内核开出来的"控制面板",读=问情况,写=下命令
交叉编译在 A 种电脑上编出 B 种电脑能跑的程序

第 9 章 这次的三个"坑",记住能省很多时间

坑 1:soc_thermal 和 soc-thermal 差一个字符

脚本里判断"温度区叫什么名字"时用了下划线,实际是横杠。
条件永远不成立,脚本啥也没干,但因为写了 exit 0,系统还显示"服务正常"。

教训:这类脚本不要无脑 exit 0,匹配失败时应该报错或打日志,否则就是无声失败。

坑 2:以为 power_allocator 会推满速,其实它压根不管

前任的推断是"这个大脑会把风扇推到最大",实际是"这个大脑拒绝管理风扇"。
结果一样(都是满速),但原因完全不同,导致修的方向也完全不同。

教训:查问题要看证据(dmesg 原话),不要靠推理猜。

坑 3:想控制"电压型负载",频率不能太高

25 kHz 是四线风扇的标准控制频率(那是数字信号,直接进风扇内部芯片)。
我们用的是两线风扇,靠"降低平均电压"调速,标准做法是 几十 Hz ~ 1 kHz。
用了 25 kHz,风扇内部的电容把斩波全平滑掉了,等于没调。

教训:同一个技术(PWM),用在不同的负载上,参数要求完全不一样。


第 10 章 还留下的两个小尾巴

尾巴 1:45°C 附近会来回跳档

空载时主板温度就在 41~46°C,正好压在第一个触发点上。
而这套"温度→档位"的映射是纯阈值判断,没有滞环(就是"过了 45 就升,低于 45 就降",没有缓冲带)。
所以风扇会在 35% 和 55% 之间来回切。

可以怎么调(改哪一项都行):

  • 把第一个触发点从 45°C 抬到 50°C

  • 或者把最低档从 35% 提高到 47%(让空载更凉,离开触发点)

尾巴 2:那个没用的开机脚本

thermal-governor-fix.service 现在已经完全没用了(风扇不再走温控框架那条路),
但它还是开机自启。建议关掉:

systemctl disable thermal-governor-fix.service
命令讲解
systemctl disable 服务名取消开机自启(不会立刻停掉,只是下次开机不启动)

尾巴 3(可选):一个硬件小改进

给 MOS 管栅极充电的那个电阻 R298 是 20 kΩ,偏大。
改成 1 kΩ 会让开关关得更干脆。1 kHz 下不改也能用,但改了以后即使以后想提高频率也站得住。


附录:常用命令一句话速查

命令一句话
adb devices看连上了哪些设备
adb connect IP:端口主动连板子
adb shell '命令'在板子上执行命令
adb push 本地 板上电脑 → 板子
adb pull 板上 本地板子 → 电脑
adb reboot重启板子
ls 目录列出目录内容
cat 文件显示文件内容
cd 目录切换目录
cp A B复制 A 成 B
grep 关键词 文件在文件里搜关键词
echo 值 > 文件把值写进文件
dmesg看内核日志
md5sum / sha256sum算文件指纹,比对是否一致
dd if=源 of=目标 bs=块大小 count=次数原样搬运数据(危险,别写反)
sync强制把数据写到磁盘
ssh 用户@主机远程登录另一台电脑
scp 源 目标两台电脑间传文件
./build.sh kernel编译内核并打包 boot.img
systemctl is-active 服务看服务在不在跑
systemctl disable 服务取消开机自启

一句话总结

风扇之前一直全速,是因为内核的温控"大脑"根本不管它,
而唯一想管它的那个脚本写错了字、从来没生效过。
换用驱动自带的温度联动、并把 PWM 频率从 25 kHz 降到 1 kHz 之后,
风扇终于能按温度一档一档地自己变速了。

评论

快捷导航

把好文章收藏到微信

打开微信,扫码查看

关闭

还没有账号?立即注册