程序要求:我们需要让电脑和树莓派处于同一局域网,也就是连接同一个wifi,然后我们在电脑登录一个小车web控制网页,通过网页上的按钮给树莓派发送相关指令,然后树莓派做出对应的反应。提前声明,我做的项目是树莓派+CC3200共同控制小车,所以树莓派仅仅对外发出串口通信。但是原理是相通的,只要你能用网页控制树莓派发出串口指令,那发出高低电平控制车轮也是可以完成的。
首先,我在树莓派桌面建立了一个car文件夹,car文件夹里新建index.html、index.py、main.py三个文件,实际起作用的是index.html+index.py或者index.html+main.py两种组合。main.py和index.py都是python文件,起到的作用是一样。只是从难度上,我先从main.py文件讲起,比较容易理解。
1. main.py文件代码解读
以下为main.py文件的代码。
#!/usr/bin/env python2.7
from bottle import route,run,request,template
@route("/",method=”GET”)
def index():
return template("index")
@route("/cmd",method=”POST”)
def cmd():
print("press the button: "+request.body.read().decode())
return "OK":
run(host="localhost,port=”8010”,debug=True,reloader=True)
- 第1行指明执行这个脚本文件的解释器,大概就是告诉shell这是段python代码的意思,详情可看#!/usr/bin/env python
有什么用?。 - 第2行就是从bottle里面引入一些组件、方法,可以理解为一些封装好的函数,我们利用这些函数实现一些功能。
- 第3-5定义了第一个路由,斜杠代表就是根目录,也就是本地的IP地址+端口号。我们需要访问的就是【192.168.1.105:8010】,然后这是个GET请求。当我们登录这个URL的时候,服务器就会执行第四行的定义函数,这个函数的作用就是返回一个index模板(heml文件)。这个html就是展示界面的源代码,就是网站的外在皮肤,如下图。
- 第6-9行定义了第二个路由,也就是第二个URL地址,这个地址就是【192.168.1.105:8010/cmd】,这是POST请求,GET和POST请求都是HTTP请求中的一种,那他们有何区别呢?具体可看99%的人都理解错了HTTP中GET与POST的区别。这个路由也是有一个cmd函数,然后输出一段字符,返回【OK】。
- 第10行,调用run方法,建立一个HTTP服务器,让我们可以通过浏览器访问我们的界面。debug代表启动了调试功能,如果出现错误,浏览器就会出现错误信息。reloader代表启动了刷新功能,这样我们改完代码,就不用重启服务器,直接刷新浏览器就可以看到改动的部分。
2. index.html文件代码解读
这个就是我们常说的前端,也就是网页长什么样子,如果需要调整网页样式,就要改这个文件。之前那个main.py是后端文件,主要是实现功能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>遥控树莓派</title>
<link href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" media="screen">
<script src="http://code.jquery.com/jquery.js"></script>
<style type="text/css">
#up {
font-size:
margin-left: 55px;
margin-bottom: 3px;
}
#down {
margin-top: 3px;
margin-left: 55px;
}
</style>
<script>
$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
});
});
</script>
</head>
<body>
<div id="container" class="container">
<div>
<button id="up" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"></button>
</div>
<div>
<button id='left' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"></button>
<button id='stop' class="btn btn-lg btn-primary glyphicon glyphicon-stop"></button>
<button id='right' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"></button>
</div>
<div>
<button id='down' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"></button>
</div>
</div>
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
js脚本代码解释:
$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
});
});
第1,2行给所有的按钮(button)绑定了一个点击的事件,第三行调用jquery的post方法把this.id,也就是被单击按钮的id,发送到“/cmd”这个路径下,这个路径就是我们之前定义的第二个路由。第二个路由接收到了id,然后打印“press the buttonXX”
2.1 html style标签
style标签用于为 HTML 文档定义样式信息。
在 style 中,您可以规定在浏览器中如何呈现 HTML 文档。
type 属性是必需的,定义 style 元素的内容。唯一可能的值是 "text/css"。
style 元素位于 head 部分中。
style可以调整样式的大小、颜色、边距、边框等等,非常多的属性。具体可参考HTML CSS的使用以及style标签和属性 在示例代码中,我们针对up、down等用到了front-size字体大小、margin-left左边距、margin-bottom底部边距。
2.2 POST请求
$.post() 方法通过 HTTP POST 请求向服务器提交数据。语法如下:
$.post(URL,data,callback);
- 必需的 URL 参数规定您希望请求的 URL,就是数据发给谁。
- 可选的 data 参数规定连同请求发送的数据,发什么数据。 可选的
- callback 参数是请求成功后所执行的函数名。
一般网页前端使用POST发出请求,然后请求成功后去执行另外一个函数,但示例中的函数是空的,所以POST在这里起到的作用就是将按下的按钮ID发放服务器,让服务器去做某件事,比如前进后退。至于为什么这里请求成功后执行的是空函数?是因为这个脚本是个通用的脚本,每个按钮都加载了这个脚本,所以没有统一的执行函数。
2.3 jQuery解释
这句代码引入 jQuery 库,jQuery是一个JavaScript的函数库,利用它我们可以便捷地使用一些javascript实现比较复杂的操作。上面讲到POST请求就是jQuery库里面的一个函数。
<script src="http://code.jquery.com/jquery.js"></script>
2.4 bootstrap解释
Bootstrap是基于html、css、Javascript的一个前端开发的框架,定义了许多CSS样式和js插件,开发者可以直接引用这些样式和插件。详情可参考BootStrap的简单介绍 具备以下优点:
- 它为开发人员创建接口提供了一个简洁统一的解决方案。
- 它包含了功能强大的内置组件,易于定制。
- 它还提供了基于 Web 的定制。
- 它是开源的。
以下就是部分图标列表,参考自
<div>
<button id="up" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"></button>
</div>
我们可以看到calss的值是“btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up”,由上图可知【btn】代表原始样式按钮,【btn-lg】代表大按钮,【btn-primary】代表提交按钮,【glyphicon glyphicon-circle-arrow-up】就是代表加粗的上箭头。组合在一起就形成了我们看到的按钮,这个大家也可以自由组合。
3. 网站效果测试
首先前面两个文件main.py、index.html是要放在同一个文件夹的,像我就是放在桌面,新建了一个car文件夹。
输入命令行python main.py
,应该可以看到以下的文字,正在监听8010端口,按Ctrl+C退出。
我们在360安全浏览器输入192.168.1.105:8010的时候,打开的特别慢,用微软自带的MIcrosoft Edge浏览器打开得就挺快的。打开浏览器可以看到方向键,这个就是我们从bootstrap里面引用的图标样式。按下对应图标,可以看到终端界面输出对应的方向。
到了这里为此,网页的基本交互已经完成了,但是我们达成的效果仅仅只是在终端输出了一段话 ,还没有完成控制树莓派GPIO口的目标,接下来我们继续改进代码。
4. index.py文件代码解析
#!/usr/bin/env python2.7
from bottle import route,run,request,template
import wiringpi as pi
@route("/",method=”GET”)
def index():
return template("index")
@route("/cmd",method=”POST”)
def cmd():
print("press the button: "+request.body.read().decode())
serial = pi.serialOpen('/dev/ttyAMA0',9600)
arg = request.body.read().decode()
if(arg=='up'):
pi.serialPuts(serial,"forward")
elif(arg=='down'):
pi.serialPuts(serial,"down")
elif(arg=='left'):
pi.serialPuts(serial,"left")
elif(arg=='right'):
pi.serialPuts(serial,"right")
elif(arg=='stop'):
pi.serialPuts(serial,"stop")
else:
return False
#return "OK"
run(host="192.168.1.105",port="8010",debug=True,reloader=True)
4.1 wiringpi库的安装
python是有自己树莓派的GPIO库,叫做python GPIO。它是一个小型的python库,可以帮助用户完成raspberry相关IO口操作。但是python GPIO库还没有支持UART、SPI、I2C或者1-wire等总线接口。如果想实现控制GPIO简单的高低电平输出,直接用GPIO库也是可以的。因为我的项目涉及到UART,所以我只能去下载C语言编写的wiringpi库。
首先安装一下wiringpi库
pip install wiringpi
下载完成后可以通过以下命令查看,我们可以看到wiringpi已经安装成功了。
pip list
所以index.py里面这句话,其实就是引入wiringpi这句话,然后定义wiringpi=pi,这样主要方便编辑函数。比如wiringpi.A函数就可以写成,pi.A函数。
import wiringpi as pi
4.2 wiringpi函数的应用
串口驱动库主要提供以下接口函数:
- extern int serialOpen (const char *device, const int baud) ;//打开串口,输入设备描述符和串口波特率,返回串口的设备ID
- extern void serialClose (const int fd) ;//关闭串口,
- extern void serialFlush (const int fd) ;//清空缓存区
- extern void serialPutchar (const int fd, const unsigned char c) ;//输出一个字符
- extern void serialPuts (const int fd, const char *s) ;//输出字符串
- extern void serialPrintf (const int fd, const char *message, …) ;//格式化输出
- extern int serialDataAvail (const int fd) ;//返回设备缓存区接收到的数据个数
- extern int serialGetchar (const int fd) ;//从设备ID读取一个字符
print("press the button: "+request.body.read().decode())
serial = pi.serialOpen('/dev/ttyAMA0',9600)
arg = request.body.read().decode()
if(arg=='up'):
pi.serialPuts(serial,"forward")
所以这段代码很简单,首先当我们网页端的按钮按下的时候,就会输出一个值。树莓派第一步先把读到的值printf显示在树莓派终端,然后打开串口获得serial,接下来把值赋给arg。下面就是一连串的判断语句,当判断到arg等于up的时候,就通过串口输出forward这个字符串。如果需要实现其他的功能,其实也就是更改这部分,比如输出个低电平之类的。函数用到的都是wiringpi的函数,只不过在python里面使用必须前面带个pi.。
4.3 串口映射的更改
先要了解为什么更改串口映射,可以看看这篇博客:《浅尝树莓派3之串口配置》。
首先进入树莓派/boot/overlays/里面,没有发现pi3-miniuart-bt-overlay文件,所我们要去下载pi3-miniuart-bt-overlay文件,解压出pi3-miniuart-bt-overlay.dtb文件,并将dtb文件拷贝到/boot/overlays/目录下,这一步在PC端插入U盘进行。
重新登录VNC,我们可以看到文件夹里面已经有这个dtb文件了。在树莓派命令终端中通过命令查看树莓派3当前的串口映射关系.
ls -l /dev
我们可以看到,serial0(GPIO串口)对应的是ttyS0(mini串口),serial1(蓝牙)对应的是ttyAMA0(硬件串口)。
下面我们来编辑config文件
nmno命令详解:《详解linux中nano命令》 在该文件中增加一行代码
然后通过Crl+O保存文件,接着按下回车,就可以成功保存文件,最后按Ctrl+X退出文件。
输入sudo reboot,重启树莓派。
通过VNC Viewer重新进入树莓派界面。再通过ls -l /dev
查看修改后的映射关系,可以看出,两者的映射关系已经发生对调。
禁用串口的控制台功能
通过以下两个命令停止和禁用串口的控制台功能
sudo systemctl stop serial-getty@ttyAMA0.service
sudo systemctl disable serial-getty@ttyAMA0.service
然后编辑cmdline.txt文件
sudo nano /boot/cmdline.txt
文件里面有如下内容dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
把console=serical0,115200删掉,剩下来部分如下所示。
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
用sudo reboot
重启树莓派,完成配置。
4.4 硬件连接
通过USB-TTL模块将树莓派与PC端进行连接,将模块的TXD与树莓派的RXD连接,将模块的RXD与树莓派的TXD连接,将模块与树莓派的GND相互连接。树莓派使用自己的独立电源,否则容易造成电压不稳。
树莓派的引脚图如上图所示,连接如下图所示。
串口助手设置如下图。
网页端如下。
在树莓派界面输入以下命令,运行index.py程序
python index.py
在网页端按下按键,树莓派终端显示信息,并通过串口也对外输出信息。
串口接收到数据。
到了这一步,我就可以利用CC3200串口接收树莓派的信息去完成小车的控制。