14. pwm(脉宽调制)¶
本章讲解Linux pwm相关应用层程序控制。
本章的示例代码目录为:base_linux/pwm
14.1. 脉宽调制¶
14.1.1. 什么是PWM¶
PWM(Pulse Width Modulation)简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术, 广泛应用在测量、通信、工控等方面。
14.1.2. PWM的频率¶
是指在1秒钟内,信号从高电平到低电平再回到高电平的次数,也就是说一秒钟PWM有多少个周期,单位Hz。
14.1.4. 占空比¶
是一个脉冲周期内,高电平的时间与整个周期时间的比例,取值范围为0-100%
一个周期的长度,如下图所示
其中,周期是一个脉冲信号的时间,1s内的周期T次数等于频率f,脉宽时间是指高电平时间。
上图中,脉宽时间占总周期时间的比例,就是占空比。
例如,假设周期的时间为10ms,脉宽时间为8ms,那么占空比是8/10= 80%,这就是占空比为80%的脉冲信号。
PWM就是脉冲宽度调制,通过调节占空比就可以调节脉冲宽度。
14.1.5. PWM原理¶
假设高电平为5V、低电平则为0V,那么要输出不同的模拟电压就要用到PWM。
通过改变IO口输出的方波的占空比,从而获得使用数字信号模拟成的模拟电压信号。
电压是以一种脉冲序列被加到模拟负载上去的,接通时是高电平1,断开时是低电平0。
接通时直流供电输出,断开时直流供电断开。通过对接通和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值5V的模拟电压。
比方说,占空比为50%那就是高电平时间一半,低电平时间一半。在一定的频率下,就可以得到模拟的2.5V输出电压。那么75%的占空比,得到的电压就是3.75V,如下图所示。
14.2. pwm引脚¶
LubanCat-H618系列板卡上集成了一个具有pwm功能的GPIO,该PWM引脚与板载的FAN接口共用。下图为鲁班猫A1的PWM引脚。
由于LubanCat-H618系列板卡的PWM控制器可能会不一样,具体引脚可以查看 — LubanCat-H618系列-26pin引脚对照图
14.3. 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。
14.4. cpu风扇案例(shell脚本)¶
下面操作以pwm1为例,案例内容为根据CPU温度调节风扇转速。
1 | base_linux/pwm/cpu_pwm.sh
|
代码较长复制粘贴容易乱序,可以下载我们提供的源码 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主动散热的运行结果:
14.5. 参考声明¶
本篇文章参考 《PWM原理及其应用》