回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

基于Flask框架的视频操控小车 简单

头像 gray6666 2021.04.14 2193 0

复刻是传承,超越亦是创新,融合则是传承与创新之间不断碰撞,正是在这种不断碰撞中才衍生出许许多多经典。每个人都不断在各自行业创造创新,创客的身影遍布艺术、音乐、建筑、科学、娱乐等领域。近年越来越多的人意识到跨界融合的重要性,唯有集众家之所长,融合多领域智慧的才能创造更多经典。

project-image

步骤1 一、项目选题

很多年前初次尝试运动小车参考了谢老师的开源机器人教材,主控板是Romeo V1 控制器+MiniQ 机器人底盘,现在迭代到V2版;模块化编程、巡线是当时最火的案例。

新课程标准要求高中信息技术引入Python语言和物联网技术,如何能在讲好语言的基础上,结合开源硬件,物联网络准备案例,成为我们共同的探讨的任务。

本轮挑战项目为《基于Flask 框架的视频操控小车》

新技术+新思想的碰撞必将带来无限可能。

为写这个案例,我翻阅了图书馆的html,css网页设计的教材,学习了flask框架基本教程;

但本人能力有限,不当之处,欢迎各位同仁批评指正、共同完善。

具体实现功能见下图

project-image

步骤2 二、知识储备

1.什么是Flask?(树莓派搭建flask框架服务器)

Flask是由python实现的一个web微框架,让我们可以使用Python语言快速实现一个网站或Web服务。较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。另外,Flask还有很强的定制性,用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。

安装命令 pip install flask

Flask小案例

新建py文件,输入7句样例代码

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

return 'Hello World!'

if __name__ == '__main__':

app.run()

运行代码,登录127.0.0.1:5000就可看到网页显示Hello World!

2.什么是流媒体?(小车视频观看的数据格式)

流媒体(streaming media)是指将一连串的媒体数据压缩后,经过网上分段发送数据,在网上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如果不使用此技术,就必须在使用前下载整个媒体文件。流式传输可传送现场影音或预存于服务器上的影片,当观看者在收看这些影音文件时,影音数据在送达观看者的计算机后立即由特定播放软件播放。

3.如何把视频流输出到浏览器?(获取视频的方法)

opencv通过获取本地实时视频流,利用flask框架构建一个实时视频流服务器,然后其他机器可以通过向这个服务器发送请求来获取这台机器上的实时视频流。常见网络摄像机采用此方法传输视频。

4.HTML(超文本标记语言) (编写前端小车操控界面)

超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。您可以使用 HTML 来建立自己的 WEB 站点,HTML 运行在浏览器上,由浏览器来解析。

5.CSS (层叠样式表)(本部分为提高篇,是优化主页的常用技术)

层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和模型样式编辑的能力。

6.GPIO (树莓派通过GPIO发送命给L298N电机驱动板,控制小车运动)

GPIO(英语:General-purpose input/output),通用型之输入输出的简称 ; 其接脚可以供使用者由程控自由使用,PIN脚依现实考量可作为通用输入(GPI)或通用输出(GPO)或通用输入与输出(GPIO)。

7.L298N驱动模块(驱动2个电机)

L298N,是一款接受高电压的电机驱动器,直流电机和步进电机都可以驱动。一片驱动芯片可同时控制两个直流减速电机做不同动作,在6V到46V的电压范围内,提供2安培的电流,并且具有过热自断和反馈检测功能。实验室标配,价格便宜,资料满天飞。

参考资料

https://blog.miguelgrinberg.com/post/video-streaming-with-flask

英文版 https://flask.palletsprojects.com/en/1.1.x/

中文版 https://flask.net.cn/

步骤3 材料清单

材料清单

  • 树莓派4B X1 链接
  • 摄像头 X1 链接
  • L298N电机驱动模块 X1
  • 金属履带小车一套(含2节18650电池) X1
  • 充电宝1个(树莓派供电) X1
  • 杜邦线(一根母对公,四根母对母) X5
project-image

步骤4 组装小车

组装车架可按照说明,或替换类似款式均可,组装步骤略

project-image

小车连线图

注意:树莓派我用的是充电宝供电,请务必注意

project-image

重点:小车电机,L298N,树莓派及线路连接

1.左右蓝色的两路分别连接电机M1和M2
2.18650电池盒正极连接12V供电,负极接GND,
移动电源通过USB Type-C给树莓派供电
注意,树莓派需要和电池盒共地即树莓派GND针脚要和电池盒负极共地

project-image

3.蓝色连接IN1连接树莓派11针脚

绿色连接IN2连接树莓派13针脚

黄色连接IN1连接树莓派15针脚

红色连接IN1连接树莓派16针脚

注意黑色连线6号针脚;树莓派GND和电池组共地

4.通道A使能和通道B使能可以不接,这样小车可以运动但无法调速。

project-image
project-image

步骤5 小车动起来

小车运动原理

project-image

编程软件为Tonny编辑器,python3.7

代码
#导入GPIO库
import RPi.GPIO as GPIO
import time
#设置GPIO模式
GPIO.setmode(GPIO.BOARD)
#设置in1到in4接口
IN1 = 11
IN2 = 13
IN3 = 15
IN4 = 16
#初始化接口
# def init():
#     GPIO.setup(IN1,GPIO.OUT)
#     GPIO.setup(IN2,GPIO.OUT)
#     GPIO.setup(IN3,GPIO.OUT)
#     GPIO.setup(IN4,GPIO.OUT)
GPIO.setup(IN1,GPIO.OUT)
GPIO.setup(IN2,GPIO.OUT)
GPIO.setup(IN3,GPIO.OUT)
GPIO.setup(IN4,GPIO.OUT)
#小车前进函数函数
def front():
    GPIO.output(IN1,GPIO.HIGH)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.HIGH)
    GPIO.output(IN4,GPIO.LOW)
#小车后退函数
def back():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.HIGH)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.HIGH)
#小车左转函数
def left():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.HIGH)
    GPIO.output(IN4,GPIO.LOW)
#小车右转函数
def right():
    GPIO.output(IN1,GPIO.HIGH)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.LOW)
#停止函数
def stop():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.LOW)
##############小车前,后,左,右,停止测试###############
#小车前进5秒
front()
time.sleep(5)
#小车后退5秒
back()
time.sleep(5)
#小车右转5秒
right()
time.sleep(5)
#左转5秒 
left()
time.sleep(5)
#停止运行,并释放端口
stop()
GPIO.cleanup()

测试视频

步骤6 flask框架搭建服务器,视频控制小车

flask框架结构解析

app_car.py 启动树莓派服务器

static文件夹存放CSS文件

templates文件夹存放index.html文件

其他

camera_pi.py是调用的摄像头库

carcs.py是测试小车的代码

project-image

index.html是启动时程序显示的控制页面,用自带文本编辑器编写,代码没有排版

核心语句如下:

为调用static中的CSS设置页面文件

img src="{{ url_for('video_feed') }}" width="50%">指定视频流并用50%比例显示

网页用了from控件通过flask框架的post方法通信;也可以用ge或其他方法

################代码附后#############################

project-image

CSS格式编辑我不太熟悉,临时抱佛脚,主页显示是红底黄字,颜色搭配欠佳

body{
background: red;
color: yellow;
}

核心代码,app_car.py

project-image
代码
from flask import Flask,request,render_template,Response   # 导入flask框架所需要的模块
import RPi.GPIO as GPIO    #导入RPi.GPIO库
import time                #计时器
from camera_pi import Camera #
#设置GPIO模式
GPIO.setmode(GPIO.BOARD)
#设置in1到in4接口
IN1 = 11
IN2 = 13
IN3 = 15
IN4 = 16
#初始化接口
def init():
    GPIO.setup(IN1,GPIO.OUT)
    GPIO.setup(IN2,GPIO.OUT)
    GPIO.setup(IN3,GPIO.OUT)
    GPIO.setup(IN4,GPIO.OUT)
'''
小车运动函数
'''
#前进
def front1():
    GPIO.output(IN1,GPIO.HIGH)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.HIGH)
    GPIO.output(IN4,GPIO.LOW)
#后退
def back1():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.HIGH)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.HIGH)

#左转
def left1():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.HIGH)
    GPIO.output(IN4,GPIO.LOW)
    #time.sleep(move_time)
    #GPIO.cleanup()

#右转
def right1():
    GPIO.output(IN1,GPIO.HIGH)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.LOW)
    #time.sleep(move_time)
    #GPIO.cleanup()

def stop1():
    GPIO.output(IN1,GPIO.LOW)
    GPIO.output(IN2,GPIO.LOW)
    GPIO.output(IN3,GPIO.LOW)
    GPIO.output(IN4,GPIO.LOW)

############################
# 固定写法
app = Flask(__name__)
############################
#摄像头函数调用了前辈写好的模块,后续再做解释
def gen(camera):
    """Video streaming generator function."""
    while True:
        frame = camera.get_frame()
        yield (b'--frame \r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')


@app.route('/video_feed')
def video_feed():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen(Camera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')
#############################
# 进入的首个网页
@app.route('/',methods=['GET','POST'])
def main():
    return render_template("index.html")   # 返回网页

# 点击打开
@app.route('/front',methods=['POST'])
def front():
    front1()
    return render_template("index.html")  #返回一开始的页面
# 点击关闭
@app.route("/back",methods=['POST'])
def back():
    back1()
    return render_template("index.html")  #返回一开始的页面

@app.route("/left",methods=['POST'])
def left():
    left1()
    time.sleep(0.5)
    stop1()   
    return render_template("index.html")

@app.route("/right",methods=['POST'])
def right():
    right1()
    time.sleep(0.5)
    stop1()
    return render_template("index.html")  #返回主页
@app.route("/stop",methods=['POST'])
def stop():
    stop1()
    time.sleep(0.5)
    return render_template("index.html")  #返回主页
if __name__=="__main__":
    init() #初始化GPIO端口
    app.run(host='0.0.0.0',port=5000)#配置端口和IP
GPIO.clearnup()

VNC登录测试

手机测试

参考资料

https://blog.miguelgrinberg.com/post/video-streaming-with-flask

英文版 https://flask.palletsprojects.com/en/1.1.x/

中文版 https://flask.net.cn/

评论

user-avatar