您的位置:首页 > 其它

树莓派-通过Web控制GPIO针脚输出高低电平

2017-09-14 20:31 656 查看
接着上一篇树莓派-通过Web网页实现对树莓派的关机和重启操作的思路继续扩展,通过Web网页来控制GPIO针脚的电平输出。

实现思路

1.通过在树莓派上搭建一个http服务器,如:Apache,增加一个控制树莓派的页面。

2.通过在树莓派的控制页面,写入需要在终端执行的命令。

3.服务器端通过python,定时读取文件内容,执行终端命令。

效果图



实现步骤

1.搭建php+Apache环境:

本文主要描述程序编写,如何搭建php+Apache环境,可以网上查找资料,自行实现。
2.编写Web网页控制端:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>树莓派Web控制中心</title>
<script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
<script src="js/bootstrap.min.js" type="text/javascript"></script>
<link href="css/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="css/font-awesome-4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.page-header { margin: 20px 0; border-bottom: 1px solid #eee; padding-bottom: 0; text-align: center; }
.btn-item { text-align: center; }
i { margin-right: 3px; display: inline-block; }
h1 { text-align: center; }
.tip { font-weight: bold; color: black; }
.lead { font-size: small; }
.gpio-item { text-align: center; }
.btn-gnd, .btn-gpio { padding: 10px 5px; margin-bottom: 5px; width: 100%; font-size: small; }
.gpio .row { margin-top: 5px; }
</style>
</head>
<body>
<div class="container">
<div class="page-header">
<h3>
树莓派Web控制中心</h3>
<p class="lead">
用于控制连接到树莓派的各种传感器
</p>
</div>
<div class="panel panel-default">
<div class="panel-heading">
设备</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-3 btn-item">
</div>
<div class="col-xs-3 btn-item">
<a class="btn btn-danger btn-trigger"><i class="fa fa-power-off"></i>关机</a>
</div>
<div class="col-xs-3 btn-item">
<a class="btn btn-primary btn-trigger"><i class="fa fa-refresh"></i>重启</a>
</div>
<div class="col-xs-3 btn-item">
</div>
<script type="text/javascript">
var url = "ajax/pi.php";
$(function () {
$(".btn-test").click(function () {
$.ajax({
type: "POST",
url: url,
data: {
action: "excute-linux-shell",
cmd: "ls"
},
success: function (result) {
$(".tip").html(result);
}
});

});
$(".btn-trigger").click(function () {
var text = $(this).text().replace(/ /g, "").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "");
var cmd = "";
switch (text) {
case "关机":
cmd = "sudo shutdown -h now";
break;
case "重启":
cmd = "sudo reboot";
break;
}
if (confirm("确定要执行该命令吗?")) {
$.ajax({
type: "POST",
url: url,
data: {
action: "set-linux-cmd",
cmd: cmd
},
success: function (result) {
$(".tip").html(result);
}
});
}
});
});
</script>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
GPIO (蓝色->低电平,红色->高电平)</div>
<div class="panel-body gpio">
<div class="row">
<div class="col-xs-6 gpio-item">
左侧
</div>
<div class="col-xs-6 gpio-item">
右侧
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (9) 左05</button>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (6) 右03</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">17 (11) 左06</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">18 (12) 右06</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">27 (13) 左07</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (14) 右07</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">22 (15) 左08</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">23 (16) 右08</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (25) 左13</button>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">24 (18) 右09</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">05 (29) 左15</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (20) 右10</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">06 (31) 左16</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">25 (22) 右11</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">13 (33) 左17</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (30) 右15</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">19 (35) 左18</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">12 (32) 右16</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">26 (37) 左19</a>
</div>
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (34) 右17</button>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">20 (37) 右19</a>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">16 (36) 右18</a>
</div>
</div>
<div class="row">
<div class="col-xs-6 gpio-item">
<button disabled="disabled" class="btn btn-info btn-gnd">
GND (39) 右20</button>
</div>
<div class="col-xs-6 gpio-item">
<a class="btn btn-primary btn-gpio">21 (40) 右20</a>
</div>
</div>
<script type="text/javascript">
$(function () {
$(".btn-gpio").click(function () {
if ($(this).hasClass("btn-danger")) {
$(this).removeClass("btn-danger").addClass("btn-info");
} else {
$(this).removeClass("btn-info").addClass("btn-danger");
}
var gpio = $(this).text().replace(/ /g, "").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").split("(")[0];
var val = $(this).hasClass("btn-danger") ? 1 : 0;
$.ajax({
type: "POST",
url: url,
data: {
action: "set-linux-gpio",
gpio: gpio,
val: val
},
success: function (result) {
$(".tip").html(result);
}
});

});
})
</script>
</div>
</div>
<div class="panel panel-primary" style="border-color: #555">
<div class="panel-heading" style="background: #555">
终端</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<div class="alert alert-success" style="" role="alert">
执行:<span class="tip"> </span>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
请求处理代码(ajax/pi.php):

<?php
$action=$_POST["action"];
if($action=="set-linux-cmd"){
$cmd=$_POST["cmd"];
$myfile=fopen("../python/cmd.txt","w") or die("unable to open file!");
$txt=$cmd;
fwrite($myfile,$txt);
print_r($cmd);
}
else if($action=="set-linux-gpio"){
$gpio=$_POST["gpio"];
$val=$_POST["val"];

$text="import os\n";
$text=$text."import time\n";
$text=$text."import sys\n";
$text=$text."import RPi.GPIO as GPIO\n\n";

$text=$text."num=".$gpio."\n";
$text=$text."GPIO.setmode(GPIO.BCM)\n";
$text=$text."GPIO.setwarnings(False)\n";
$text=$text."GPIO.setup(num,GPIO.OUT)\n";
if($val=="1"){
$text=$text."GPIO.output(num,GPIO.HIGH)\n";
}else{
$text=$text."GPIO.output(num,GPIO.LOW)\n";
}
$text=$text."if(GPIO.input(num)==1):\n";
$text=$text."	print(\"HIGH\")\n";
$text=$text."else:\n";
$text=$text."	print(\"LOW\")\n";

$text=$text."\n";
$text=$text."#GPIO.cleanup()\n";
$text=$text."sys.exit(0)\n";

$myfile=fopen("../python/gpio/gpio-".$gpio.".py","w") or die("unable to open file!");
fwrite($myfile,$text);
print_r($gpio."-".$val);
}
else if($action=="excute-linux-shell"){
$last_line = system('ls', $retval);
echo '<hr />Last line of the output: ' . $last_line . '<hr />Return value: ' . $retval;
}
?>
3.服务器端Python脚本(autorun.py)

import os
import time
import RPi.GPIO as GPIO

while True:
file=open("/var/www/html/pi/python/cmd.txt","r")
text=file.read()
file.close()

if(text!=""):
file=open("/var/www/html/pi/python/cmd.txt","w")
file.write("")
file.close()
os.system(text)

dir="/var/www/html/pi/python/gpio"
list=os.listdir(dir)
for i in range(0,len(list)):
path=os.path.join(dir,list[i])
if os.path.isfile(path):
os.system("python "+path)
print("excute "+path)
os.remove(path)

time.sleep(.3)
大致思路:

1./var/www/html/pi/python/cmd.txt 文件用于控制树莓派的重启或关闭,每次通过php页面来写入shell命令,当然要传入其他命令,也是可以的。

2./var/www/html/pi/python/gpio 目录用于存放控制GPIO针脚的py脚本,上面的autorun.py将会设置为开机启动。

3.while True语句将一直循环执行,当发现cmd.txt中有命令时,读取cmd.txt文件,并执行语句,执行完后将cmd.txt置空,下次循环时将直接跳过。

接着继续遍历/var/www/html/pi/python/gpio目录,如果发现有python脚本,则调用python命令执行python脚本,执行完后,将其删除。

4.因为GPIO的针脚一旦设置为高电平或低电平后,如果没改变其输出电平,将保持设置的电平输出,所以执行完设置电平的脚本后,python自动退出就可以了。

2017-9-19 10:17:27 补充:

利用
Tornado 服务器创建http端口侦听,比轮询方式更好。 


1.tornado安装

方式1:pip 安装:

sudo pip install tornado

方式2:源代码安装:

wget https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
tar xvzf tornado-4.3.tar.gz

cd tornado-4.3

python setup.py build

sudo python setup.py install

2.编写http服务器代码

#coding: utf8
import sys
import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options
from tornado.options import define,options

class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html") #请在py脚本同一目录放置此页面
def post(self):
arg = self.get_argument('q')
self.write("your arg is:"+arg)

if __name__ == '__main__':
tornado.options.parse_command_line()
app = tornado.web.Application(handlers=[(r"/",IndexHandler)])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(8018)
tornado.ioloop.IOLoop.instance().start()
代码很简单,设置请求路径为"/"时,由IndexHandler处理,请求分get和post两种方式,可以根据传入的不同参数做不同的处理。

3.程序改进

将最初的实现方式结合到tornado服务器方式即可,思路已很清晰了,详情请参考:树莓派-通过Web控制GPIO针脚输出高低电平(改进版)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: