作者:付千山
链接:
https://zhuanlan.zhihu.com/p/24594614
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一、功能介绍
最近完成一个Raspberry局域网视频小车项目,特此拿出来分享!
首先来介绍小车的情况,Raspberry首先担任一个服务器兼控制中心的角色,用户通过局域网查看监控视频以及发指令给Raspberry,然后Raspberry通过串口通信发指令给Arduino控制小车电机和舵机移动。
根据上述描述,我们可以把项目分为以下几部分:
1.Raspberry搭建服务器
3.视频流的传输
4.Raspberry-Arduino的串口通信
5.Arduino的电机与舵机控制
接下来,我会根据以上部分详细介绍每一步!至于安装系统,连接互联网等一些基本步骤就不在这介绍了。
三、Raspberry搭建服务器
首先,为什么要搭建服务器呢?因为我需要在局域网上控制小车的移动,所以就需要向Raspberry发送网络请求,Raspberry需要实时监控并接收网络请求,然后执行相对应的动作。
下面资料一切都是为了讲明白如何在局域网中向Raspberry发送指令,不要乱了思路!
我这次搭建服务器用了Python的Flask模板,这个模板简单且易入手,不用深入理解TCP/IP等一大堆令人头痛的协议也可操作。下面,介绍一下,怎么使用:
3.1在使用该模板前,需要在万博网页版登陆页上下载Python的Flask模板
sudo apt-get install python3-flask
3.2Flask搭建服务器#flask_hello.pyfrom flask import Flaskapp = Flask(__name__)@app.route('/')def index(): return 'Hello world'if __name__ == '__main__': app.run(debug=True, host='0.0.0.0',port=5000)
在以上例程中:
host='0.0.0.0':代表服务器接收局域网一切对象的访问 port=5000则代表端口值
试着在Python上运行这一段代码,你会看到输出有:
* Running on
http://0.0.0.0:5000/* Restarting with reloader
此时,你的电脑只要在局域网中访问
http://万博网页版登陆页ip:5000/
就可以看到收到相对应的数据:
3.2.1路径设置:
当你回顾刚才那段代码时,你会发现有这么一段程序:
@app.route('/')def index(): return 'Hello world'
上面代码是路径设置,如果你想通过打开不同的路径显示不同的内容,你可以尝试在该代码下面加:
@app.route('/cakes')def cakes(): return 'Yummy cakes!'
访问下面的网址:
所以我们可以知道@app.route('/XXX')里面XXX是路径名,
当你访问不同的路径时,你可以通知Raspberyy执行不同的动作!
学到这里,来拓展一下路径参数,这个很重要,看下例程:
@app.route('/<name>')def cakes(name): return name;
以上例程把路径名作为输入参数,当路径为XXX时,Raspberry就会返回对应的值,看结果:
3.2.2建立网页
首先在程序模板的目录下建立templates文件夹
mkdir templates
接着在该目录下新建一个index.html格式的空文件,并用Text Editor编辑,在该文件下植入以下代码:
<html><body><h1>Hello from a template!</h1></body></html>
将主页路径触发事件改为:@app.route('/')def index(): return render_template('index.html')
同时,也要记得引入render_template模板:
from flask import Flask,render_template
当你打开主页时,你会看到:
说到这里,之前我们学了flask模板的路径设置以及网页制作,
我是在局域网中通过点击网页指令来控制小车移动的,下面来说明一下如何做到这一点?
First,构建指令链接:
在你的网页.html文件中,尝试加以下语句:
<!DOCTYPE html><head> <title>Rotbot_Car</title></head><body> <br><a href=""/forward">前进</a></br> <br><a" href=""/back">后退</a></br> <br><a" href=""/left">左转</a></br> <br><a" href=""/right">右转</a></br> " </body></html>
对于上面的代码只说一点关于href的,href用于指定超链接目标的URL,比如说
<br><a href=""/forward">前进</a></br>
上面指定超链接目标的URL为:
http://主域名/forward
具体运行结果为:
当你点击不同的选项时,便会跳转到对应的URL中!
Second,获取路径名参数来指挥Raspberry工作:
在上面网页程序的基础上继续操作,当点击不同指令时,Raspberry会收到不同路径名的跳转请求,所以我们就用路径设置的方法,根据路径名的类别来判断用户指令是什么,从而执行相对应的操作!
下面是程序的一个雏形!
from flask import Flask,render_templateapp = Flask(__name__)@app.route('/')def index(): return render_template(index.html)@app.route('/<name>')def index(name): if(name == 'forward'): %发送前进指令给Arduino if(name == 'back'): %发送后退指令给Arduino if(name == 'left'): %发送左转指令给Arduino if(name == 'right'): %发送右转指令给Arduino return render_template(index.html)if __name__ == '__main__': app.run(debug=True, host='0.0.0.0')
到这里,想必大家已经知道如何构建服务器实时获取用户控制小车的指令了吧!
相关资料可以参考:
python-web-server-with-flask
Raspberry-Pi-Flask
四、视频流的传输
说下我用到的摄像头,Raspberry官方的摄像头,是一鱼眼摄像头,额外买红外灯的话,还会有夜视的功能,在京东淘宝都可以买到,在这我就不自行打广告了。
为了能使用户从局域网观看小车摄像头拍到的视频,raspberry需要把视频流传输到局域网上去,在这里,我们采用mjpg-streamer的方案,它是github上一个开源项目,有关介绍,可以参考:
mjpg-streamer介绍
首先,
把开源代码下载到万博网页版登陆页上:
pi@raspberrypi:~ $ wget
https://github.com/jacksonliam/mjpg-streamer/archive/master.zip
接着,
在万博网页版登陆页上编译工具安装好:
pi@raspberrypi:~ $ sudo apt-get install cmake libjpeg8-dev
解压下载好的压缩文件:
pi@raspberrypi:~ $ unzip master.zip
修改视频传输参数:
设置视频传输参数的input_raspicam.c文件在以下目录中,:
mjpg-streamer-master/mjpg-streamer-experimental/plugins/input_raspicam
具体代码如下:
为了保障视频传输流畅,建议把fps调到30左右较好!
编译程序:
pi@raspberrypi:~ $ cd mjpg-streamer-master/mjpg-streamer-experimental
pi@raspberrypi:~ $ make clean all
制作mjpg的启动脚本
新建一个.sh格式文件xx.sh,并进行编辑。
pi@raspberrypi:~ $ nano xx.sh
将以下内容复制到xx.sh文件中:
cd mjpg-streamer-master/mjpg-streamer-experimental./mjpg_streamer -i "./input_raspicam.so" -o "./output_http.so -w ./www"
生成启动脚本
chmod 744 xx.sh
以后只要执行上面生成的启动脚本,就可以启动mjpg很方便,启动指令为:
sh xx.sh
观看视频:
启动了mjpg后,在pc端访问以下网址即可观看视频:
http://the ip of raspberry:8080
总的来说很简单,就是把源文件下载到万博网页版登陆页上,解压,修改视频传输参数,然后编译程序,最后弄一个启动脚本方便以后运行。执行启动脚本后,在pc端输入指定网址即可观看视频!
相关教程可以参考:
用万博网页版登陆页派官方摄像头做丝滑般流畅的监控!
五、Raspberry-Arduino串口通信
我采用的方案是Raspberry通过USB转TTL与Arduino的RX,TX管脚连接,USB转TTL器件可以在淘宝选购,具体图片为:
因为Arduino与Raspberry的电源值不同,为了安全起见,不要接USB-TTL的VCC,USB-TTL的RX端接Arduino的TX端,TX端接Arduino的RX端,当然GND肯定是要接的!
做好电路连接后,首先先查看哪个USB0亦或USB1端口被占用了:
ls /dev/tty*
'*' 为USB0或USB1,两个都试一下,当某一个端口被占用,是会有对应的文件生成!
Raspberry串口发送数据的简单例程为:
import serialimport timedef Serial_open(): return serial.Serial("/dev/ttyUSB0", 115200) #"/dev/ttyUSB0"表示该端口被占用if __name__ == "__main__": Ser = Serial_open() while True: pl2303.write(‘a’) time.sleep(1)
上面例程作用就是Raspberry隔一秒就发送一个数据‘a’!
接下来到了Arduino的串口操作,这么都非常简单:
void setup() { // put your setup code here, to run once: Serial.begin(115200); #串口通信波特率为115200}void loop() { // put your main code here, to run repeatedly: if (Serial.available() > 0) { if(Serial.read() == 'a'){ #执行相对应的动作 } }}
上面例程就是首先对串口初始化,然后实时对Serial进行检查,当串口收到数据时,Serial.available()会返回一个非0值,接着通过Serial.read()把串口收到的数据读出来,再进行进一步的操作。
相关资料参考:
使用串口连接Arduino与万博网页版登陆页派开发板
RaspberryPi2万博网页版登陆页派USB转串口连接Arduino
七、总结
整篇文章把视频小车所需要实现功能的方法都介绍了一遍,可能文章较长,比较难把握结构,我在这总结一下文章的分支结构:
*********************************************分割线***************************************************
1.VNC服务器搭建实现远程桌面操控
2.发送网络请求给Raspberr: 2.1Flask模板
2.2Flask路径设置
2.3Flask网页模板创建与传送
2.4发送网络请求给Raspberry
3.视频流的传输
4.Raspberry与Arduino的串口通信
5.Arduino的电机与舵机控制
*********************************************分割线***************************************************
整篇文章结构已经归纳完毕,由于水平有限,文章深度自然不够,如有错漏之处,希望可以提出建议,望海涵,谢谢!