前言
自己组装了一台mmdvm的热点板,因为购买的外壳是铝合金的,不方便开孔,而且盒子里边塞满了元件,要想再安装开关就比较吃力,所以萌发了使用MOS管来控制风扇及屏幕电源的想法。
1.电源控制基础机理
以上关于MOS管的论述是我自己的理解不喜勿喷。MOS管有三个管脚:G,D,S;G极接控制电压就可以控制DS的通断,相当于DS端就是开关的两极,G端就是开关的按钮。树莓派上有很多的输入输出引脚称为GPIO,这些引脚都有自己的编号且有两种命名方式BCM编码及wiringPi编码,我们这里用到的都是BCM编码。我们此次电源控制用到了两个引脚,物理引脚31BCM编码6用于控制风扇电源,物理引脚32BCM编码12用于控制屏幕电源。我们使用的方法是将GPIO的引脚接至MOS管的G极,S极接电源负极,D极接负载端的电源负极,负载端的电源正极接+5V,通过软件控制GPIO引脚的电平做高低变化即可控制负载的通断,如果控制电平高低变化的频率即可控制风扇的转速。
这里的MOS管你可以使用你的拆机零件,比如报废锂离子电池的保护板或一些电源板上的MOS管,我是在淘宝上购买的10个/3.5元,还包邮。
2.GPIO引脚的初始状态控制
树莓派启动后这些GPIO引脚都处于一个初始状态,我们可以使用下面的命令来查看GPIO引脚的状态
这些引脚处于何种初始状态控制的方法很多,通常的方法是修改/boot/config.txt文件,重定义GPIO引脚的状态,对于v4版本的pi-star,这种方法是有效的,例如:
#控制GPIO12引脚开机处于输出状态且输出高电平
gpio=12=op,dh
#控制GPIO6引脚开机处于输出状态且输出低电平
gpio=6=op,dl
但是对于v3版本的pi-star,此种方法无效,要使用开机后的自动执行功能,比如使用rc.local,init.d等,这里我使用的是通过rc.local的方法。
这里有个坑,我们要使用的gpio6,12,启动后的初始状态是input模式,且gpio6是高电平,gpio12是低电平 。对于gpio的定义可以通过config.txt,也可以通过rc.loca,二者的顺序是先读取config.txt,后读取rc.local。对于gpio12,可以在config.txt添加下面的语句来设置
dtoverlay=gpio-poweroff,gpiopin=12,active_low
# gpiopin指定定义的引脚,添加active_now参数,表示这个引脚开机处于高电平,关机处于低电平
# 启动后通过gpio readall可以发现12引脚已经是out模式,且开机是高电平,关机是低电平
dtoverlay=gpio-poweroff,gpiopin=6,active_low
#至于要添加这个参数是因为关机时,如果不加这条参数则风扇会处于高速旋转状态,只有关闭电源
而同样应用于gpio6就不行,引脚6仍然处于input模式,所以需要在/etc/rc.local中定义引脚6
首先安装raspi-gpio软件来使用命令控制GPIO引脚代码如下
sudo apt install raspi-gpio
#安装完成后可以使用命令控制gpio的状态
#比如将gpio6设为输出状态且电平为低电平
sudo raspi-gpio set 6 op dl
#比如将gpio12设为输出状态且电平为高电平
#sudo raspi-gpio set 12 op dh
使用这些命令验证gpio的状态后即可修改rc.local文件设定gpio端口的状态,在exit 0的前面添加以下内容。
经过这样的处理,盒子启动后就可以将自己需要的gpio置于符合要求的状态。
3.散热风扇控制
3.1接线
因为接的是电机,风扇停转后会产生一个反电动势可能会造成击穿MOS管,所以我们要在电机 的正负极之间并一个二极管,二极管的正极接风扇的负极,二极管负极接风扇正极,pi物理引脚32接MOS管的G极,S极接电源负极,D极接风扇的负极,+5V接风扇的正极,如下图
3.2关于python库
因为后续的python程序需要使得到RPi.GPIO库,使用python -V查看你的python版本,pi-star是v3版本已经安装了python2所需的库,可以不用再安装了,如果使用python3则需要安装所需的库。安装指令sudo apt-get install rpi.gpio
3.3风扇启动校正
这里参考了这位外国朋友的文章,我们使用的不是PWM专用风扇,这风扇有4条电源线比较贵,我们使用的是2条线的普通风扇,所以需要对风扇的启动参数做一个测试,测出你的风扇能够顺畅启动的最小占空比,程序如下,将代码存为cal_fan.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO #gpio控制库
import sys
FAN_PIN = 6 #控制风扇的gpio引脚
WAIT_TIME = 1
PWM_FREQ = 25 #控制风扇的频率
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
fan=GPIO.PWM(FAN_PIN,PWM_FREQ)
fan.start(0)
try:
while 1:
fanSpeed=float(input("Fan Speed: ")) #输入风扇的占空比
fan.ChangeDutyCycle(fanSpeed) #使用指定的占空比启动风扇
except(KeyboardInterrupt):
print("Fan ctrl interrupted by keyboard")
fan.stop()
GPIO.cleanup()
sys.exit()
finally:
print("Fan ctrl Program exit")
fan.stop()
GPIO.cleanup()
sys.exit()
使用下面的指令运行python程序
输入占空比,一般是20,我的风扇需要22,使用0停止,使用ctrl + c停止或直接回车退出程序,记住这个数值,后面的控制程序需要。
3.3风扇控制程序
程序如下,将代码存为ctrl_fan.py
pi-star@pi-star-2b(ro):python_script$ more ctrl_fan.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import sys
# Configuration
GPIO.setwarnings(False)
FAN_PIN = 6 # BCM pin used to drive transistor's base
WAIT_TIME = 5 # [s] Time to wait between each refresh #温度刷新的频率
FAN_MIN = 0 # [%] Fan minimum speed. #这是温度低于你的控制温度你的风扇转速最小值
PWM_FREQ = 25 # [Hz] Change this value if fan has strange behavior
# Configurable temperature and fan speed steps
tempSteps = [40, 50] # [°C] #这里的温度即是你需要控制的温度上下限
speedSteps = [25, 100] # [%] #这里的25就是你的风扇启动的最小占空比
# Fan speed will change only of the difference of temperature is higher than hysteresis
hyst = 1
# Setup GPIO pin
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
fan = GPIO.PWM(FAN_PIN, PWM_FREQ)
fan.start(0)
i = 0
cpuTemp = 0
fanSpeed = 0
cpuTempOld = 0
fanSpeedOld = 0
# We must set a speed value for each temperature step
if len(speedSteps) != len(tempSteps):
print("Numbers of temp steps and speed steps are different")
exit(0)
try:
while 1:
# Read CPU temperature
cpuTempFile = open("/sys/class/thermal/thermal_zone0/temp", "r")
cpuTemp = float(cpuTempFile.read()) / 1000
# print ("cputemp:",cpuTemp, " fanspeed:", fanSpeed) 你调试时可以将这条语句取消注释,即可察看实时的CPU温度和风扇转速占空比
cpuTempFile.close()
# Calculate desired fan speed
if abs(cpuTemp - cpuTempOld) > hyst:
# Below first value, fan will run at min speed.
if cpuTemp < tempSteps[0]:
#fanSpeed = speedSteps[0]
fanSpeed = FAN_MIN #这里当实际温度低于控制温度时风扇停止转动
# Above last value, fan will run at max speed
elif cpuTemp >= tempSteps[len(tempSteps) - 1]:
fanSpeed = speedSteps[len(tempSteps) - 1]
# If temperature is between 2 steps, fan speed is calculated by linear interpolation
else:
for i in range(0, len(tempSteps) - 1):
if (cpuTemp >= tempSteps[i]) and (cpuTemp < tempSteps[i + 1]):
fanSpeed = round((speedSteps[i + 1] - speedSteps[i])
/ (tempSteps[i + 1] - tempSteps[i])
* (cpuTemp - tempSteps[i])
+ speedSteps[i], 1)
if fanSpeed != fanSpeedOld:
if (fanSpeed != fanSpeedOld
and (fanSpeed >= FAN_MIN or fanSpeed == 0)):
fan.ChangeDutyCycle(fanSpeed)
fanSpeedOld = fanSpeed
cpuTempOld = cpuTemp
# Wait until next refresh
time.sleep(WAIT_TIME)
# If a keyboard interrupt occurs (ctrl + c), the GPIO is set to 0 and the program exits.
except KeyboardInterrupt:
print("Fan ctrl interrupted by keyboard")
GPIO.cleanup()
sys.exit()
程序的原理是读取CPU的温度再与控制温度比较,根据温度范围对应不同的风扇转速,实时调节风扇的占空比,即温度低转速慢,温度高转速高,低于控制温度,风扇停转。
3.4开机启动风扇控制程序
这里使用修改/etc/rc.local来执行开机启动
# Run fan control program at startup
sudo python /home/pi-star/python_script/ctrl_fan.py &
exit 0
在exit 0前面添加上述语句,即可完成开机启动,那个&符号表示程序运行在后台不退出
4.屏幕电源控制
4.1接线
pi物理引脚31接MOS管的G极,S极接电源负极,D极接屏幕的负极,+5V接屏幕的正极即可
4.2屏幕电源的控制方法
当我们的热点盒子启动后,有一个仪表板可以通过web网页进行访问,然后在web网页添加控制屏幕电源的菜单即可控制MOS管的通断。
4.3修改网页代码实现功能
4.3.1修改index.php添加菜单
deshboard的网页位于/var/www/dashboard/,文件名为index.php,使用你的编辑工具编辑index.php,找到下面的代码并在其后添加Power与Screen选项。
<a href="/admin/configure.php" style="color: #ffffff;"><?php echo $lang['configuration'];?></a> |
<a href="/admin/power.php" style="color: #ffffff;"><?php echo 'Power';?></a> | //增加Power电源菜单
<a href="/admin/screen.php" style="color: #ffffff;"><?php echo 'Screen';?></a> //增加Screen屏幕电源菜单
4.3.2复制并修改power.php
power.php位于/var/www/dashboard/admin/,复制power.php为screen.php并修改如下
<?php
// Load the language support
require_once('config/language.php');
// Load the Pi-Star Release file
$pistarReleaseConfig = '/etc/pistar-release';
$configPistarRelease = array();
$configPistarRelease = parse_ini_file($pistarReleaseConfig, true);
// Load the Version Info
require_once('config/version.php');
// Sanity Check that this file has been opened correctly
if ($_SERVER["PHP_SELF"] == "/admin/screen.php") {
// Sanity Check Passed.
header('Cache-Control: no-cache');
session_start();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" lang="en">
<head>
<meta name="robots" content="index" />
<meta name="robots" content="follow" />
<meta name="language" content="English" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="Author" content="Andrew Taylor (MW0MWZ)" />
<meta name="Description" content="Pi-Star Power" />
<meta name="KeyWords" content="Pi-Star" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="pragma" content="no-cache" />
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
<meta http-equiv="Expires" content="0" />
<title>Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['power'];?></title>
<link rel="stylesheet" type="text/css" href="css/pistar-css.php" />
</head>
<body>
<div class="container">
<div class="header">
<div style="font-size: 8px; text-align: right; padding-right: 8px;">Pi-Star:<?php echo $configPistarRelease['Pi-Star']['Version']?> / <?php echo $lang['dashboard'].": ".$version; ?></div>
<h1>Pi-Star <?php echo $lang['digital_voice']." - ".$lang['power'];?></h1>
<p style="padding-right: 5px; text-align: right; color: #ffffff;">
<a href="/" style="color: #ffffff;"><?php echo $lang['dashboard'];?></a> |
<a href="/admin/" style="color: #ffffff;"><?php echo $lang['admin'];?></a> |
<a href="/admin/update.php" style="color: #ffffff;"><?php echo $lang['update'];?></a> |
<a href="/admin/config_backup.php" style="color: #ffffff;"><?php echo $lang['backup_restore'];?></a> |
<a href="/admin/configure.php" style="color: #ffffff;"><?php echo $lang['configuration'];?></a>
</p>
</div>
<div class="contentwide">
<?php if (!empty($_POST)) { ?>
<table width="100%">
<tr><th colspan="2"><?php echo $lang['screen'];?></th></tr>
<?php
if ( escapeshellcmd($_POST["action"]) == "reboot" ) {
echo '<tr><td colspan="2" style="background: #000000; color: #00ff00;"><br /><br />Poweron has been sent to your Pi,
<br />please watch the screen to verify<br />
<br />You will be re-directed back to the
<br />dashboard automatically in 5 seconds.<br /><br /><br />
<script language="JavaScript" type="text/javascript">
setTimeout("location.href = \'/index.php\'",5000);
</script>
</td></tr>';
shell_exec('sudo raspi-gpio set 12 op dh > /dev/null &' );
};
if ( escapeshellcmd($_POST["action"]) == "shutdown" ) {
echo '<tr><td colspan="2" style="background: #000000; color: #00ff00;"><br /><br />Shutdown command has been sent to your Pi,
<br /> please watch the screen to verify<br />
You will be re-directed back to the<br />
dashboard automatically in 5 seconds.<br /><br /><br />
<script language="JavaScript" type="text/javascript">
setTimeout("location.href = \'/index.php\'",5000);
</script>
</td></tr>';
shell_exec('sudo raspi-gpio set 12 op dl > /dev/null &');
};
?>
</table>
<?php } else { ?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" onsubmit="return confirm('Are you sure?'
);">
<table width="100%">
<tr>
<th colspan="2"><?php echo 'screen power';?></th>
</tr>
<tr>
<td align="center">
Poweron screen<br />
<button style="border: none; background: none;" name="action" value="reboot"><img src="/images/on.png" border="0" alt="Reboot" /></button>
</td>
<td align="center">
shutdown screen<br />
<button style="border: none; background: none;" name="action" value="shutdown"><img src="/images/off.png" border="0" alt="Shutdown" /></button>
</td>
</tr>
</table>
</form>
<?php } ?>
</div>
<div class="footer">
Pi-Star web config, © Andy Taylor (MW0MWZ) 2014-<?php echo date("Y"); ?>.<br />
Need help? Click <a style="color: #ffffff;" href="https://www.facebook.com/groups/pistarusergroup/" target="_new">here for
the Support Group</a><br />
Get your copy of Pi-Star from <a style="color: #ffffff;" href="http://www.pistar.uk/downloads/" target="_blank">here</a>.<br />
<br />
</div>
</div>
</body>
</html>
<?php
}
?>
这是screen.php的完整代码
在网上找了两个开关机的图标放在/var/www/dashboard/images/,命名为on.png与off.png
下面是做好的页面效果
5.后记
至此使用mos管来进行散热风扇与屏幕电源的控制全部完成