5. PWM控制

5.1. PWM引脚

LubanCat-H618系列板卡上集成了一个具有pwm功能的GPIO,该PWM引脚与板载的FAN接口共用。下图为LubanCat-A1的PWM引脚。

未找到图片

由于LubanCat-H618系列的板卡的PWM控制器可能会不一样,具体引脚可以查看 — LubanCat-H618系列-pin引脚对照图

5.1.1. 使能PWM接口功能

PWM接口在默认情况是关闭状态的,需要使能才能使用, 下面的使能操作以 PWM1 为例

5.1.1.1. 方法一

可以通过打开 /boot/uEnv.txt 查看是否启用了pwm相关设备设备树插件。

编辑文件,选择需要开启的pwm设备树插件,粘贴到 overlays= 后面,多个设备树插件开启,设备树插件之间要用空格隔开,如下图:

未找到图片

然后重启激活设备

注解

如果是直接拔电源的方式重启,会有可能出现文件没能做出修改 (原因:文件未能及时从内存同步到存储设备中,解决方法,在终端上输入 “sync” 再拔电关机)

5.2. PWM控制方式(shell终端)

下面操作以pwm1为例

注意

在操作前必须先打开设备树插件,重启使能pwm1引脚

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#将pwm1导出到用户空间
echo 1 > /sys/class/pwm/pwmchip0/export

#设置pwm周期 单位为ns
echo 1000000 > /sys/class/pwm/pwmchip0/pwm1/period

#设置PWM周期中“ON”的时间,单位为ns,即占空比=duty_cycle/period=50%。
echo 500000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle

#设置pwm极性,正常normal,反相inversed
echo "normal" > /sys/class/pwm/pwmchip0/pwm1/polarity

#使能pwm
echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable

#取消将pwm1导出到用户空间
echo 1 > /sys/class/pwm/pwmchip0/unexport

提示

当设置period与duty_cycle值的时候需要注意在任何的情况下都得保证:0 ≤ duty_cycle ≤ period。

5.3. cpu风扇案例(shell脚本)

下面操作以pwm1为例,案例内容为根据CPU温度调节风扇转速。

代码位置
1
quick_start/pwm/cpu_pwm.sh

代码较长复制粘贴容易乱序,可以下载我们提供的源码 cpu_pwm.sh

quick_start/pwm/cpu_pwm.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash

tempstart=55  # 风扇启动的温度阈值,单位为摄氏度
period=1000000 #PWM周期
cpu_temp1=65 #节点1
cpu_temp1_pwm=50 #节点1占空比,%
cpu_temp2=75 #节点2
cpu_temp2_pwm=80  #节点2占空比,%
cpu_temp3=85 #节点3
cpu_temp3_pwm=100 #节点3占空比,%

#将pwm1导出到用户空间
echo 1 > /sys/class/pwm/pwmchip0/export
#设置pwm周期
sudo echo $period > /sys/class/pwm/pwmchip0/pwm1/period
#设置PWM周期中“ON”的初始时间
echo 0 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
#设置pwm极性
echo "normal" > /sys/class/pwm/pwmchip0/pwm1/polarity
#使能pwm
echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable

while true; do
   temp=$(cat /sys/class/thermal/thermal_zone0/temp)
   temp=$((temp/1000))  # 将温度转换为摄氏度
   
   if ((temp > tempstart)); then
      echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable
      if ((temp < cpu_temp1)); then
         cpu_pwm1=$(( cpu_temp1_pwm*(temp-tempstart)/(cpu_temp1-tempstart)*period/100 ))
         echo $cpu_pwm1 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
         # echo "CPU Temp: ${temp}℃ CPU PWM1: ${cpu_pwm1}"
      elif ((temp > cpu_temp1))&&((temp < cpu_temp2)); then
         cpu_pwm2=$(( ( (cpu_temp2_pwm-cpu_temp1_pwm)*(temp-cpu_temp1)/(cpu_temp2-cpu_temp1)+cpu_temp1_pwm)*period/100 ))
         echo $cpu_pwm2 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
         # echo "CPU Temp: ${temp}℃ CPU PWM2: ${cpu_pwm2}"
      elif ((temp > cpu_temp2))&&((temp < cpu_temp3)); then
         cpu_pwm3=$(( ( (cpu_temp3_pwm-cpu_temp2_pwm)*(temp-cpu_temp2)/(cpu_temp3-cpu_temp2)+cpu_temp2_pwm)*period/100 ))
         echo $cpu_pwm3 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
         # echo "CPU Temp: ${temp}℃ CPU PWM3: ${cpu_pwm3}"
      elif ((temp > cpu_temp3)); then
         cpu_pwm_end=$(( cpu_temp3_pwm*period/100 ))
         echo $cpu_pwm_end > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
         # echo "CPU Temp: ${temp}℃ CPU PWM_END: ${cpu_pwm_end}"
      fi

   else
      echo 0 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
      echo 0 > /sys/class/pwm/pwmchip0/pwm1/enable
      # echo "CPU Temp: ${temp}℃ CPU风扇关闭"
   fi

   sleep 30
done

为了更直观低展示CPU风扇控制效果,可以取消掉32、36、40、44行的注释,并将53行的sleep时间修改为3。

注意

实际使用时,为了减少CPU资源占用,sleep时间可以设置成30秒。

修改完成后,运行以下命令进行测试。

1
2
3
4
5
6
#移除之前导出的pwm1
echo 1 > /sys/class/pwm/pwmchip0/unexport
#赋予可执行权限
chmod +x cpu_pwm.sh
#运行
./cpu_pwm.sh

以下为CPU压测,且未安装CPU主动散热的运行结果:

未找到图片