基于IoT的多功能智能跑操系统
项目目标
- 通过ESP32作为主控芯片实现打卡系统的基本逻辑功能
- 利用RFID Unit 实现IC卡的信息识别、读取功能
- 基于MQTT信息传输技术实现跑操信息的”线下-云平台“交互功能
- 使用M5 StickV实现二维码识别技术
项目原理
- MQTT
设置MQTT服务器有三个步骤:
-
设置MQTT服务器设置
MQTT服务器的三大要素是:服务器ID,用户名和密码。其他要素,比如端口号是1883,一般都是用这个的,还有服务器是该平台的网址。
-
发布数据
发布数据的两个要点是主题和数据格式。主题的格式不同的平台会有不同的要求,建议参考平台的API参数。第二是数据格式,一般都是用JSON格式。
-
订阅数据
订阅数据和发布数据基本相同,也是设置主题和数据。但发布和订阅的主题不同。因为MQTT是比较简单的通讯协议,所以安全性要由中间人来提供。订阅数据会返回Mid, Result两个值,可以透过这两个值检查数据有没有错误和有没 有上传成功,具体语句可以看PahoMQTT库。
我们用的是Ubidots这个IoT平台,详情可以参考这个网站。
Ubidots Docs
-
M5StickV
设置M5StickV识别二维码的步骤:
- 使用micropython自带的sensor和image库,分别设置摄影镜头和图像的参数。而LCD库为控制屏幕显示的参数。我们我镜头参数设定如下图像色彩格式:选择是RGB565色彩图。设置图像像素大小,sensor.QQVGA: 160x120。把img设为获取摄影机的图像。
- 使用img库的find_qrcode是检测图上是否有qrcode,如果有则会返回一系列的qrcode的参数,如解析的数据,规格等。
- 因为我们主要用的是解碼的代码,所以单独取译码结果来作下一步使用。
-
RFID
RFID卡的结构有UID和BLOCKS。UID是每张卡的唯一标识符,只可读不可写。BLOCKS是可读可写的,因此我们把学生的数据放在BLOCKS里。值得注意的时要加入延时,否则如果进行可累加的操作,会因为射频处理识别的频率高而多次识别。
-
UART
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,通常称作UART) 是一种串行异步收发协议,应用十分广泛。UART工作原理是将数据的二进制位一位一位的进行传输。在UART通讯协议中信号线上的状态位高电平代表’1’低电平代表’0’。当然两个设备使用UART串口通讯时,必须先约定好传输速率和一些数据位。在进行传输前必须要对硬件进行连接,连接方式如图所示:
TX:发送数据端,要接对面设备的RX
RX:接收数据端,要接对面设备的TX
GND:保证两设备共地,有统一的参考平面
我们先分析我们使用到的器件的接口,可以从硬件设计图中找到我们使用到的器件,M5Go Lite的TX和RX接口为GPIO17和GPIO16,而M5StickV的TX和RX为GPIO35和GPIO34。
使用方法为调用Micropython带有的uart库,设置好相应平台。
概念图
代码
M5GO LITE的代码
from m5stack import *
from m5ui import *
from uiflow import *
import wifiCfg
from m5mqtt import M5mqtt
import json
import time
import unit
import machine
from numbers import Number
def Wifi_reconnect():
while (wifiCfg.wlan_sta.isconnected()) != 1:
wifiCfg.reconnect()
label0.setText('Wifi connected')
data = None
#setScreenColor(0xe4a797)
rfid0 = unit.get(unit.RFID, unit.PORTA)
uart = None
t1 = None
t2 = None
student_checkag=[]
m5mqtt = M5mqtt('random', 'industrial.api.ubidots.com', 1883, 'BBFF-HXOoqxfhftjZSub2lDqbK019M3KHFg', '', 300)
setScreenColor(0x000000)
label0 = M5TextBox(69, 33, "Running System", lcd.FONT_Comic,0x89eee1, rotate=0)
label1 = M5TextBox(40, 86, "Name :", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label2 = M5TextBox(76, 124, "ID :", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label3 = M5TextBox(40, 165, "Count :", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label4 = M5TextBox(135, 86, "", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label5 = M5TextBox(135, 124, "", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label6 = M5TextBox(135, 165, "", lcd.FONT_DejaVu18,0xff66d2, rotate=0)
label7 = M5TextBox(30, 188, "", lcd.FONT_DejaVu18,0xffd400, rotate=0)
title0 = M5Title(title="Title", x=3 , fgcolor=0xFFFFFF, bgcolor=0x3e4329)
label10 = M5TextBox(20, 35, "123", lcd.FONT_Default,0xFFFFFF, rotate=0)
label10.hide()
title10 = M5Title(title="Today runner list:", x=3 , fgcolor=0xFFFFFF, bgcolor=0x0000FF)
title10.hide()
wifistatus = None
Name = None
count = None
uid = None
A = None
uartmsg=None
A_J = None
m5mqtt.start()
def showlist():
title0.show()
label10.show()
def hidelist():
title0.hide()
label10.hide()
def showmainui():
label0.show()
label1.show()
label2.show()
label3.show()
label4.show()
label5.show()
label6.show()
label7.show()
label8.show()
label9.show()
def hidemainui():
label0.hide()
label1.hide()
label2.hide()
label3.hide()
label4.hide()
label5.hide()
label6.hide()
label7.hide()
label8.hide()
label9.hide()
def buttonA_wasPressed():
title0.show()
label10.show()
global list_run
list_run = ''
student_checkag.sort()
for i in range(len(student_checkag)):
if(i==0):
list_run=str(i+1)+'. '+student_checkag[i]+' '
elif(i%4==0):
list_run=str(i+1)+'. '+student_checkag[i]+' '+'\n'
else:
list_run=str(i+1)+'. '+student_checkag[i]+' '
label10.setText(str(list_run))
hidemainui()
pass
btnA.wasPressed(buttonA_wasPressed)
def mainproamg():
while True:
while wifistatus == 0:
wifiCfg.auto_connect()
Wifi_reconnect()
try :
if rfid0.isCardOn():
rgb.setColorAll(0xff0000)
#rfid0.writeBlock(1,'213173444')
#rfid0.writeBlock(2,'yangmi')
uid = rfid0.readBlockStr(1)
if(str(uid) not in student_checkag):
Name = rfid0.readBlockStr(2)
count = int((rfid0.readBlockStr(4)))
count = count + 1
rfid0.writeBlock(4,str(count))
A = {"Student":{"value":count, "context":{"CardID":uid, "name" :Name }}}
A_J = json.dumps(A)
label5.setText(str(uid))
label4.setText(str(Name))
label6.setText(str(count))
m5mqtt.publish(str('/v1.6/devices/esp32'),str(A_J))
student_checkag.append(str(uid))
speaker.sing(392, 1)
speaker.sing(349, 1)
speaker.sing(330, 1)
speaker.sing(294, 1)
wait_ms(1000)
label7.setText(str(""))
else:
label7.setText(str("Please do not scan again!"))
wait_ms(2000)
label7.setText(str(""))
elif(uart.any()):
uartmsg = uart.readline()
m5mqtt.publish(str(''),str(uartmsg))
wait_ms(2)
pass
except:
wait(1)
wait_ms(2)
def buttonB_wasPressed():
hidelist()
showmainui()
mainproamg()
pass
btnB.wasPressed(buttonB_wasPressed)
mainproamg()
M5STICKV的代码
import sensor, image ,time #forcam
import lcd #for lcd屏
from machine import I2C,UART
from fpioa_manager import fm #导入maipy的fm(fpioa manager)这个内置的对象,用于后续注册工作。
student_0={'student_number':'test1234567','student_0_name':'鍾思捷'}
#uart initial
fm.register(35, fm.fpioa.UART2_TX, force=True)
fm.register(34, fm.fpioa.UART2_RX, force=True)
uart_Port = UART(UART.UART2, 115200,8,0,0, timeout=1000, read_buf_len= 4096)
clock = time.clock()
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # can be QVGA on M7...
sensor.set_vflip(1)
sensor.set_hmirror(1)
sensor.skip_frames(20)
sensor.run(1) #在OPENMV中會自動運行 miropython中不知道要不要加
sensor.set_auto_gain(False) #自动增益off
while(True):
img = sensor.snapshot()
#img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
check =img.find_qrcodes()
#print(check)
if(len(check)>0):
data=check[0].payload()
print(data)
uart_Port.write(data)
time.sleep(2)