1. 简介
本项目的硬件是基于BeagleBone® Black板卡和一个USB的WIFI蓝牙模块(主要用于联网),软件部分是通过python实现的功能代码,使用了python的http.server、Adafruit_BBIO和threading包。
2. 硬件介绍
BeagleBone Black 是一款面向开发人员和业余爱好者的低成本、高扩展、社区支持的开发平台。
板卡处理器采用了 TI 公司 AM3358 芯片,ARM Cortex™ A8 内核,主频为1GHz 。AM3358还支持SGX 3D图形引擎、NEON浮点加速、可编程实时单元等外设。
BBB 板载了512MB DDR3L内存以及4GB eMMC闪存,另外还有电源管理、以太网、一个USB主机、一个USB客户端、三个按钮、4个用户LED、HDMI D型接口、LCD接口、2个46P扩展接口。
BBB的扩展性非常高,很适合demo验证,DIY等场景。
下面是BBB的布局图:
关键器件布局:
连接器、LED和按键布局:
3.项目设计实现思路
本项目通过python的simplehttp包搭建webserver作为前端交互服务,后端通过实现ledserver来提供led的控制服务。
前后端交互通过event来同步,即前端发布event,后端接收event后执行相应的控制。
led服务通过BBIO库进行io的初始化及逻辑控制,从而实现led的状态控制。
功能框图放在下面的软件介绍中,可以从软件框图中看到服务及服务间的事件同步关系。
4. 软件介绍
软件主要分两部分,一部分是web服务器,另一部分是led服务,led服务控制的LED是USR1和USR2,可以根据需要增加和减少LED的个数。
功能框图:
4.1 web服务
web服务是通过http.server软件包来实现的,下面通过代码来介绍一下这部分的实现:
通过继承SimpleHTTPRequestHandler实现了一个控制led的web服务类,即MyWebLed
class MyWebLed(SimpleHTTPRequestHandler):
def do_HEAD(self):
# 省略实现
def _redirect(self, path):
# 省略实现
def _get_html_body(self):
# 省略实现
def do_GET(self):
# 省略实现
def do_POST(self):
# 省略实现
其中关键的方法有:do_GET、do_POST,下面详细展开说明:
首先是do_GET方法,主要功能是当浏览器发送GET请求时,返回对应的html数据,这里将数据分为http头和http数据主体两部分。
def do_GET(self):
self.do_HEAD()
html_body = self._get_html_body()
self.wfile.write(html_body.format(myleds.CurState()).encode('utf-8'))
然后时do_POST的实现,这里包含了主要的控制逻辑,包括LED的状态及模式控制,最后返回最新的http数据,包含了LED最新的状态:
def do_POST(self):
content_len = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_len).decode('utf-8')
post_data = post_data.split('=')[1]
if post_data == 'On':
print('on')
myleds.LedsOn()
elif post_data == 'Off':
print('off')
myleds.LedsOff()
else :
print('Blinky')
myleds.LedsBlinky()
self._redirect('/')
html_body = self._get_html_body()
self.wfile.write(html_body.format(myleds.CurState()).encode('utf-8'))
最后补充一下html的源码,即 _get_html_body内的实现
def _get_html_body(self):
return '''
<html>
<body style="width:960px;margin:20px auto;">
<h1>Hello, MyLedServer!</h1>
<p>Current state is :{}</p>
<form action="/" method="POST">
Turn LED:
<input type="submit" name="submit" value="On">
<input type="submit" name="submit" value="Off">
<input type="submit" name="submit" value="Blinky">
</form>
</body>
</html>
'''
4.2 led服务
led服务通过threading包来实现主要功能,下面是源码的说明:
首先介绍类实现及实例化:
class MyLedsServer():
def _led_init(self):
# 省略实现
def _led_toggle(self):
# 省略实现
def _led_on(self):
# 省略实现
def _led_off(self):
# 省略实现
def _led_entry(self, *args):
# 省略实现
def __init__(self, leds):
# 省略实现
def CurState(self):
# 省略实现
def LedsOn(self):
# 省略实现
def LedsOff(self):
# 省略实现
def LedsBlinky(self):
# 省略实现
LEDS_TABLE = ['USR1','USR2']
myleds = MyLedsServer(LEDS_TABLE)
其中主要的代码是_led_entry、LedsOn/LedsOff/LedsBlinky,下面展开说明一下:
def _led_entry(self, *args):
if len(args) == 0:
return None
event = args[0]
count = self.default_count
cur_sta = self.cur_sta
while True:
if event.wait(0.1): # 100ms
cur_sta = self.cur_sta
event.clear()
print('new event:{}'.format(cur_sta))
count = self.default_count
if cur_sta == 'ON':
self._led_on()
elif cur_sta == 'OFF':
self._led_off()
else:
if count == 0:
count = self.default_count
self._led_toggle()
else:
count = count - 1
def LedsOn(self):
self.cur_sta = 'ON'
self.event.set()
def LedsOff(self):
self.cur_sta = 'OFF'
self.event.set()
def LedsBlinky(self):
self.cur_sta = 'BLINKY'
self.event.set()
_led_entry通过等待event来更新led工作的状态,然后主循环是根据led工作状态来执行对应的动作。
LedsOn/LedsOff/LedsBlinky则是通过event通知_led_entry需要执行什么样的工作状态,web服务中就是通过调用这几个接口来实现对应的功能。
5. 展示
然后是html页面的展示:
通过On、Off、Blinky三个按钮选择LED控制不同的工作模式,下面是OFF状态下的照片
然后是ON的照片,BLINKY的话照片无法展示出来效果,所以就不提供了。
实物照片如下:
6. 总结
到此本项目的软硬件介绍已经完成了,通过本次任务了解了python的web服务搭建以及如何通过python控制硬件模块。由于之前没有接触过这一块的知识,所以感觉还是收益颇多的。