简单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 端口号要匹配哦

目录
相关文章
|
6月前
|
安全 数据安全/隐私保护 Windows
如何在Windows 10系统中查看已连接WiFi密码-亲测可用-优雅草卓伊凡
如何在Windows 10系统中查看已连接WiFi密码-亲测可用-优雅草卓伊凡
288 15
如何在Windows 10系统中查看已连接WiFi密码-亲测可用-优雅草卓伊凡
|
4月前
|
IDE 开发工具 Python
魔搭notebook在web IDE下,使用jupyter notebook,python扩展包无法更新升级
魔搭notebook在web IDE下,使用jupyter notebook,python扩展包无法更新升级,不升级无法使用,安装python扩展包的时候一直停留在installing
108 4
|
11月前
|
移动开发 开发者 HTML5
构建响应式Web界面:Flexbox与Grid的实战应用
【10月更文挑战第22天】随着互联网的普及,用户对Web界面的要求越来越高,不仅需要美观,还要具备良好的响应性和兼容性。为了满足这些需求,Web开发者需要掌握一些高级的布局技术。Flexbox和Grid是现代Web布局的两大法宝,它们分别由CSS3和HTML5引入,能够帮助开发者构建出更加灵活和易于维护的响应式Web界面。本文将深入探讨Flexbox和Grid的实战应用,并通过具体实例来展示它们在构建响应式Web界面中的强大能力。
173 3
|
8月前
|
数据采集 Web App开发 存储
打造高效的Web Scraper:Python与Selenium的完美结合
本文介绍如何使用Python结合Selenium,通过代理IP、设置Cookie和User-Agent抓取BOSS直聘的招聘信息,包括公司名称、岗位、要求和薪资。这些数据可用于行业趋势、人才需求、企业动态及区域经济分析,为求职者、企业和分析师提供宝贵信息。文中详细说明了环境准备、代理配置、登录操作及数据抓取步骤,并提醒注意反爬虫机制和验证码处理等问题。
186 1
打造高效的Web Scraper:Python与Selenium的完美结合
|
7月前
|
运维 网络安全 文件存储
找不到类似 Docker Desktop 的 Web 管理界面?试试这些开源方案
Docker Desktop 是本地容器化开发的利器,但存在无法通过 Web 远程管理、跨平台体验不一致等问题。为此,推荐几款轻量级、可 Web 化管理的 Docker 工具:Portainer 功能全面,适合企业级运维;CasaOS 集成应用商店和 NAS 功能,适合家庭/个人开发环境;Websoft9 提供预集成环境,新手友好。这些工具能有效提升容器管理效率,满足不同场景需求。
366 3
|
7月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
8月前
|
存储 JSON JavaScript
WEB CAD插件通过上下文对象MxPluginContext修改UI界面的方法
本文介绍了如何使用MxPluginContext动态控制MxCAD项目的UI界面。通过该上下文对象,开发者可以灵活设置UI配置,如控制操作栏显隐、编辑按钮、添加侧边栏等。具体方法包括调用`getUiConfig()`获取并修改`mxUiConfig.json`中的属性,实现界面的定制化。此外,还提供了控制命令行聚焦的功能,解决输入框焦点锁定问题。详细代码示例和效果对比图展示了具体实现步骤,帮助开发者更好地适配项目需求。
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
473 7
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
前端开发 搜索推荐 算法
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
中草药管理与推荐系统。本系统使用Python作为主要开发语言,前端使用HTML,CSS,BootStrap等技术和框架搭建前端界面,后端使用Django框架处理应用请求,使用Ajax等技术实现前后端的数据通信。实现了一个综合性的中草药管理与推荐平台。具体功能如下: - 系统分为普通用户和管理员两个角色 - 普通用户可以登录,注册、查看物品信息、收藏物品、发布评论、编辑个人信息、柱状图饼状图可视化物品信息、并依据用户注册时选择的标签进行推荐 和 根据用户对物品的评分 使用协同过滤推荐算法进行推荐 - 管理员可以在后台对用户和物品信息进行管理编辑
432 12
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
|
12月前
|
前端开发 开发者 容器
构建响应式Web界面:Flexbox与Grid布局的深度解析
【10月更文挑战第11天】本文深入解析了CSS3中的Flexbox和Grid布局,探讨了它们的特点、应用场景及使用方法。Flexbox适用于一维布局,如导航栏;Grid布局则适用于二维布局,如复杂网格。通过示例代码和核心属性介绍,帮助开发者灵活构建响应式Web界面。
282 5

热门文章

最新文章

推荐镜像

更多
下一篇
oss教程