简单WiFi控制小车系统(树莓派+python+web控制界面)

简介: 好丑😂 对不对 ,不过反正可以蛇皮走位就行。 蛇皮走位演示视频: 只需要 一个 index.html 和Index.py 就可以实现 简单WiFi 控制小车。你需要准备的有

网络异常,图片无法展示
|

好丑😂 对不对 ,不过反正可以蛇皮走位就行。

蛇皮走位演示视频: 手机QQ视频_20190105152514.mp4_免费高速下载|百度网盘-分享无限制

只需要 一个 index.html  和Index.py 就可以实现 简单WiFi 控制小车。

你需要准备的有

 python 环境

bottle 库

安装bottle命令

pip install bottle

网络异常,图片无法展示
|

树莓派控制界面(web客户端)

index.html源码

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>遥控树莓派</title><linkhref="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"rel="stylesheet"media="screen"><scriptsrc="http://cdn.staticfile.org/jquery/2.2.4/jquery.min.js"></script><styletype="text/css">#front {
margin-left: 55px;
margin-bottom: 3px;
        }
#rear{
margin-top: 3px;
margin-left: 55px;
        }
.btn{
background: #62559f;
            }
</style><script>$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
            });
        });
</script></head><body><divid="container"class="container"><div><buttonid="front"class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"></button></div><div><buttonid='leftFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"></button><buttonid='stop'class="btn btn-lg btn-primary glyphicon glyphicon-stop"></button><buttonid='rightFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"></button></div><div><buttonid='rear'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"></button></div><div><buttonid='leftRear'class="btn btn-lg btn-primary glyphicon">左后转</button><buttonid='rightRear'class="btn btn-lg btn-primary glyphicon">右后转</button></div></div><scriptsrc="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script></body></html>

js脚本解释:

<script>$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
//表示 按钮对应的id值 会被传入树莓派服务器中,就如同 你在树莓派的命令行(cmd)中输入 id 的值            });
        });
</script>

树莓派小车控制程序(web服务端)

index.py 源码

#!/usr/bin/env python3# -*- coding:utf-8 -*-frombottleimportget,post,run,request,templateimportRPi.GPIOasGPIOimporttimeimportsys####  定义Car类classCar(object):
def__init__(self):
self.enab_pin= [5,6,13,19]
####  self.enab_pin是使能端的pinself.inx_pin= [21,22,23,24]
####  self.inx_pin是控制端in的pinself.RightAhead_pin=self.inx_pin[0]
self.RightBack_pin=self.inx_pin[1]
self.LeftAhead_pin=self.inx_pin[2]
self.LeftBack_pin=self.inx_pin[3]
####  分别是右轮前进,右轮退后,左轮前进,左轮退后的pinself.setup()
####  setup函数初始化端口defsetup(self):
print ("begin setup ena enb pin")
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
forpininself.enab_pin: 
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.HIGH)
####  初始化使能端pin,设置成高电平pin=Noneforpininself.inx_pin:
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.LOW)
####  初始化控制端pin,设置成低电平print ("setup ena enb pin over")
####  fornt函数,小车前进deffront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  leftFront函数,小车左拐弯defleftFront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
####  rightFront函数,小车右拐弯defrightFront(self):
self.setup()
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  rear函数,小车后退defrear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  leftRear函数,小车左退defleftRear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
####  rightRear函数,小车右退defrightRear(self):
self.setup()
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  定义main主函数defmain(status):
car=Car()
ifstatus=="front":
car.front()
elifstatus=="leftFront":
car.leftFront()
elifstatus=="rightFront":
car.rightFront()
elifstatus=="rear":
car.rear()
elifstatus=="leftRear":
car.leftRear()
elifstatus=="rightRear":
car.rightRear()
elifstatus=="stop":
car.setup()      
@get("/")
defindex():
returntemplate("index")
@post("/cmd")
defcmd():
adss=request.body.read().decode()
print("按下了按钮:"+adss)
main(adss)
return"OK"run(host="0.0.0.0")

web服务端 实际就这点代码, 主要是 bottle 库的强大,(实际控制的小车的代码 根据自己的需求改就行了)

frombottleimportget,post,run,request,template@get("/")
defindex():
returntemplate("index") 
#### 这个是 客户端请求 服务端就发给一个 index.html 控制界面给客户端@post("/cmd")
defcmd():
adss=request.body.read().decode()#### 接收到 客户端 发过来的数据print("按下了按钮:"+adss)
main(adss)  #### 传值到主函数 实现对应功能return"OK"run(host="0.0.0.0")  #### 开启服务端

运行 index.py 开启服务器:

网络异常,图片无法展示
|

然后打开浏览器(手机浏览器也可以但必须在同一个局域网内) 输入 树莓派的ip

我的是 http://192.168.191.4:8080

有可能 打开比较慢  10分钟内吧 😁(我第一次打开 就用了好久 都以为没有成功)

网络异常,图片无法展示
|

手机端输入ip

网络异常,图片无法展示
|

在后台可以查看到相应的操作日志

网络异常,图片无法展示
|

当然如果你有更为复杂的需求,可以采用 websocket 的方式,下面奉上代码

先运行服务端代码 car.py,然后再 运行 car.html

 car.py 代码

#coding=utf8importstruct, socket, sysimporthashlibimportthreading, randomimporttimefrombase64importb64encode, b64decodeimportRPi.GPIOasGPIOimportsysGPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(17,GPIO.OUT)
p=GPIO.PWM(17,600)
p_pin=35p.start(p_pin)
####  定义Car类classCar(object):
def__init__(self):
self.inx_pin= [19,26,5,6]
####  self.inx_pin是控制端in的pinself.RightAhead_pin=self.inx_pin[0]
self.LeftAhead_pin=self.inx_pin[1]
self.RightBack_pin=self.inx_pin[2]
self.LeftBack_pin=self.inx_pin[3]
####  分别是右轮前进,左轮前进,右轮退后,左轮退后的pinself.RightP_pin=17self.LeftP_pin=27self.setup()
####  setup函数初始化端口defsetup(self):
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
####  初始化使能端pin,设置成高电平pin=Noneforpininself.inx_pin:
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.LOW)
####  初始化控制端pin,设置成低电平print ("setup ena enb pin over")
####  fornt函数,小车前进deffront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  leftFront函数,小车左拐弯defleftFront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
####  rightFront函数,小车右拐弯defrightFront(self):
self.setup()
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  rear函数,小车后退defrear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  leftRear函数,小车左退defleftRear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
####  rightRear函数,小车右退defrightRear(self):
self.setup()
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  定义main主函数defmain(status):
car=Car()
ifstatus=="front":
car.front()
elifstatus=="leftFront":
car.leftFront()
elifstatus=="rightFront":
car.rightFront()
elifstatus=="rear":
car.rear()
elifstatus=="leftRear":
car.leftRear()
elifstatus=="rightRear":
car.rightRear()
elifstatus=="stop":
car.setup()      
#p.stop()elifstatus=="q1":
p.ChangeDutyCycle(35)
elifstatus=="q2":
p.ChangeDutyCycle(50)
elifstatus=="q3":
p.ChangeDutyCycle(75)
elifstatus=="q4":
p.ChangeDutyCycle(90)
elifstatus=="q5":
p.ChangeDutyCycle(100)
##socketconnectionlist= {}
defdecode(data):
ifnotlen(data):
returnFalse# 用数据包的第二个字节,与127作与位运算,拿到前七位。length=data[1] &127# 这七位在数据头部分成为payload,如果payload等于126,就要再扩展2个字节。# 如果等于127,就要再扩展8个字节。# 如果小于等于125,那它就占这一个字节。iflength==126:
extend_payload_len=data[2:4]
mask=data[4:8]
decoded=data[8:]
eliflength==127:
extend_payload_len=data[2:10]
mask=data[10:14]
decoded=data[14:]
else:
extend_payload_len=Nonemask=data[2:6]
decoded=data[6:]
byte_list=bytearray()
print(mask)
print(decoded)
# 当payload确定之后,再往后数4个字节,这4个字节成为masking key,再之后的内容就是接收到的数据部分。# 数据部分的每一字节都要和masking key作异或位运算,得出来的结果就是真实的数据内容。foriinrange(len(decoded)):
chunk=decoded[i] ^mask[i%4]
byte_list.append(chunk)
new_str=str(byte_list, encoding="utf-8")
print(new_str)
returnnew_strdefencode(data):  
data=str.encode(data)
head=b'\x81'iflen(data) <126:
head+=struct.pack('B', len(data))
eliflen(data) <=0xFFFF:
head+=struct.pack('!BH', 126, len(data))
else:
head+=struct.pack('!BQ', 127, len(data))
returnhead+datadefsendMessage(message):
globalconnectionlistforconnectioninconnectionlist.values():
connection.send(encode(message))
defdeleteconnection(item):
globalconnectionlistdelconnectionlist['connection'+item]
classWebSocket(threading.Thread):
GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"def__init__(self,conn,index,name,remote, path="/"):
threading.Thread.__init__(self)
self.conn=connself.index=indexself.name=nameself.remote=remoteself.path=pathself.buffer=""defrun(self):
print('Socket%s Start!'%self.index)
headers= {}
self.handshaken=FalsewhileTrue:
try: 
ifself.handshaken==False:
print ('Socket%s Start Handshaken with %s!'% (self.index,self.remote))
self.buffer+=bytes.decode(self.conn.recv(1024))
ifself.buffer.find('\r\n\r\n') !=-1:
header, data=self.buffer.split('\r\n\r\n', 1)
forlineinheader.split("\r\n")[1:]:
key, value=line.split(": ", 1)
headers[key] =valueheaders["Location"] = ("ws://%s%s"%(headers["Host"], self.path))
key=headers['Sec-WebSocket-Key']
token=b64encode(hashlib.sha1(str.encode(str(key+self.GUID))).digest())
handshake="HTTP/1.1 101 Switching Protocols\r\n"\
"Upgrade: websocket\r\n"\
"Connection: Upgrade\r\n"\
"Sec-WebSocket-Accept: "+bytes.decode(token)+"\r\n"\
"WebSocket-Origin: "+str(headers["Origin"])+"\r\n"\
"WebSocket-Location: "+str(headers["Location"])+"\r\n\r\n"self.conn.send(str.encode(str(handshake)))
self.handshaken=Trueprint('Socket%s Handshaken with %s success!'%(self.index, self.remote))
sendMessage('Welcome, '+self.name+' !')
else:
msg=decode(self.conn.recv(1024))
main(msg)
ifmsg=='quit':
print ('Socket%s Logout!'% (self.index))
nowTime=time.strftime('%H:%M:%S',time.localtime(time.time()))
sendMessage('%s %s say: %s'% (nowTime, self.remote, self.name+' Logout'))                  
deleteconnection(str(self.index))
self.conn.close()
breakelse:
#print('Socket%s Got msg:%s from %s!' % (self.index, msg, self.remote))nowTime=time.strftime('%H:%M:%S',time.localtime(time.time()))
sendMessage('%s %s say: %s'% (nowTime, self.remote, msg))       
self.buffer=""exceptExceptionase:
self.conn.close()
classWebSocketServer(object):
def__init__(self):
self.socket=Nonedefbegin(self):
print( 'WebSocketServer Start!')
self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(("172.19.8.102", 8081))
self.socket.listen(50)
globalconnectionlisti=0whileTrue:
connection, address=self.socket.accept()
username=address[0]     
newSocket=WebSocket(connection,i,username,address)
newSocket.start()
connectionlist['connection'+str(i)]=connectioni=i+1if__name__=="__main__":
server=WebSocketServer()
server.begin()

car.html  代码:

<!DOCTYPE html><htmllang="zh-cn"><head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>遥控树莓派</title><linkhref="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"rel="stylesheet"media="screen"><scriptsrc="http://cdn.staticfile.org/jquery/2.2.4/jquery.min.js"></script><styletype="text/css">#front {
margin-left: 55px;
margin-bottom: 3px;
        }
#rear{
margin-top: 3px;
margin-left: 55px;
        }
.btn{
background: #62559f;
            }
</style><script>varsocket;
functioninit() {
varhost="ws://192.168.1.111:8081/";
try {
socket=newWebSocket(host);
socket.onopen=function () {
                };
socket.onmessage=function () {
                };
socket.onclose=function () {
                };
            }
catch (ex) {
            }
        }
functionsend(msg) {
try {
socket.send(msg);
            } catch (ex) {
            }
        }
window.onbeforeunload=function () {
try {
socket.send('quit');
socket.close();
socket=null;
            }
catch (ex) {
            }
        };
</script></head><bodyonload="init()"><divid="container"class="container"><div><buttonid="front"class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"onclick="send('front')"></button></div><div><buttonid='leftFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"onclick="send('leftFront')"></button><buttonid='stop'class="btn btn-lg btn-primary glyphicon glyphicon-stop"onclick="send('stop')"></button><buttonid='rightFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"onclick="send('rightFront')"></button></div><divstyle="height:50px;"><buttonid='rear'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"onclick="send('rear')"></button></div><divstyle="height:20px;"></div><divstyle="height:50px;"><buttonid='leftRear'class="btn btn-lg btn-primary glyphicon"onclick="send('leftRear')">左后转</button><buttonid='rightRear'class="btn btn-lg btn-primary glyphicon"onclick="send('rightRear')">右后转</button></div><divstyle="height:20px;"></div><divstyle="height:50px;"><buttonid='q1'class="btn btn-lg btn-primary glyphicon"onclick="send('q1')">P1</button><buttonid='q2'class="btn btn-lg btn-primary glyphicon"onclick="send('q2')">P2</button><buttonid='q3'class="btn btn-lg btn-primary glyphicon"onclick="send('q3')">P3</button><divstyle="height:20px;"></div><buttonid='q4'class="btn btn-lg btn-primary glyphicon"onclick="send('q4')">P4</button><buttonid='q5'class="btn btn-lg btn-primary glyphicon"onclick="send('q5')">P5</button></div></div><scriptsrc="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script></body></html>

注意: host 端口号要匹配哦

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
13天前
|
移动开发 开发者 HTML5
构建响应式Web界面:Flexbox与Grid的实战应用
【10月更文挑战第22天】随着互联网的普及,用户对Web界面的要求越来越高,不仅需要美观,还要具备良好的响应性和兼容性。为了满足这些需求,Web开发者需要掌握一些高级的布局技术。Flexbox和Grid是现代Web布局的两大法宝,它们分别由CSS3和HTML5引入,能够帮助开发者构建出更加灵活和易于维护的响应式Web界面。本文将深入探讨Flexbox和Grid的实战应用,并通过具体实例来展示它们在构建响应式Web界面中的强大能力。
30 3
|
9天前
|
移动开发 数据可视化 前端开发
可视化设计web界面的工具
有什么可视化设计web界面的工具
25 0
|
24天前
|
前端开发 开发者 容器
构建响应式Web界面:Flexbox与Grid布局的深度解析
【10月更文挑战第11天】本文深入解析了CSS3中的Flexbox和Grid布局,探讨了它们的特点、应用场景及使用方法。Flexbox适用于一维布局,如导航栏;Grid布局则适用于二维布局,如复杂网格。通过示例代码和核心属性介绍,帮助开发者灵活构建响应式Web界面。
45 5
|
1月前
|
SQL 关系型数据库 数据库
优化Web开发流程:Python ORM的优势与实现细节
【10月更文挑战第4天】在Web开发中,数据库操作至关重要,但直接编写SQL语句既繁琐又易错。对象关系映射(ORM)技术应运而生,让开发者以面向对象的方式操作数据库,显著提升了开发效率和代码可维护性。本文探讨Python ORM的优势及其实现细节,并通过Django ORM的示例展示其应用。ORM提供高级抽象层,简化数据库操作,提高代码可读性,并支持多种数据库后端,防止SQL注入。Django内置强大的ORM系统,通过定义模型、生成数据库表、插入和查询数据等步骤,展示了如何利用ORM简化复杂的数据库操作。
58 6
|
2月前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
95 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
10天前
|
消息中间件 监控 Kafka
Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面
随着大数据技术的发展,Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面,方便管理和监控 Kafka 集群。本文详细介绍了 Kafka Manager 的部署步骤和基本使用方法,包括配置文件的修改、启动命令、API 示例代码等,帮助你快速上手并有效管理 Kafka 集群。
32 0
|
1月前
|
数据可视化 测试技术 Linux
基于Python后端构建多种不同的系统终端界面研究
【10月更文挑战第10天】本研究探讨了利用 Python 后端技术构建多样化系统终端界面的方法,涵盖命令行界面(CLI)、图形用户界面(GUI)及 Web 界面。通过分析各种界面的特点、适用场景及关键技术,展示了如何使用 Python 标准库和第三方库(如 `argparse`、`click`、`Tkinter` 和 `PyQt`)实现高效、灵活的界面设计。旨在提升用户体验并满足不同应用场景的需求。
|
2月前
|
前端开发 搜索推荐 算法
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
中草药管理与推荐系统。本系统使用Python作为主要开发语言,前端使用HTML,CSS,BootStrap等技术和框架搭建前端界面,后端使用Django框架处理应用请求,使用Ajax等技术实现前后端的数据通信。实现了一个综合性的中草药管理与推荐平台。具体功能如下: - 系统分为普通用户和管理员两个角色 - 普通用户可以登录,注册、查看物品信息、收藏物品、发布评论、编辑个人信息、柱状图饼状图可视化物品信息、并依据用户注册时选择的标签进行推荐 和 根据用户对物品的评分 使用协同过滤推荐算法进行推荐 - 管理员可以在后台对用户和物品信息进行管理编辑
76 12
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
|
2月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
104 6
|
2月前
|
SQL 缓存 数据库
构建高效Web应用:掌握Python中的ORM映射技术
在Web开发中,数据库操作至关重要,但直接编写SQL语句会增加代码复杂度并降低效率。对象关系映射(ORM)技术通过将对象模型映射为数据库表,使开发者能以面向对象的方式处理数据,提升开发效率和代码可维护性。本文以Python和SQLAlchemy为例,介绍ORM的基本概念、安装方法及使用技巧,并展示其在提升Web应用性能方面的优势。通过ORM,开发者可以简化数据库操作,专注于业务逻辑实现,提高开发效率和代码质量。
48 1

热门文章

最新文章