作为一个EE专业的学生,不务正业的搞了FE。但是借这次大三课程设计的契机,也受到了某PM的启发,进行了一次非常简单的IOT(Internet Of Things)开发,回到了最初的起点。
要实现的功能?
通过移动端网页控制步进电机的正转,反转,停止,变速。
需要点亮的技能树?
- MicroPython - 编程语言,python在物联网领域的子集
- nodemcu - 主角,价值20元左右的WIFI物联网开发板,基于esp8266。
- step motor - 步进电机
- mqtt - 基于TCP/IP的pub/sub模型的实时协议,广泛用于物联网领域
- server — 集成mqtt,为前端提供接口,连接machine和前端,编程语言取决于你,我选择node
- 前端 - 用户终端,Andriod/IOS/Web,我选择Web
开发环境
Mac os 10.12.5
开始动手
- 安装驱动
根据自己的平台安装驱动,然后将开发板使用usb连接电脑
https://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx
在mac环境下,查看是否连接端口成功
$ ls /dev/cu.*
# 显示
$ /dev/cu.SLAB_USBtoUART
找到自己的开发板连接的串口,后续用于刷固件和连接开发板
- 刷micropython固件
nodemcu自带的编程环境是lua,我选择了更熟悉的micropython,所以先刷micropython的固件。
根据这个链接刷好固件
- 开始硬件编程
下载ESploer
ESPlorer是开发ESP8266的一个编辑器,使用Java编写,所以需要安装Java环境,使用Java打开
$ java -jar ESPlorer.jar
步进电机的具体控制代码在这里就不展开了,本文重点在于如何实现在用户终端控制机器。
- 上传固件
在这里有一点非常重要。
在micropython的文件系统中,有两个文件比较特殊
- boot.py 在每一次reset或者通电后会自动执行,一般不需要修改,也无法修改
- main.py 在每一次reset或者通电后boot.py执行后会自动执行main.py。所以这就是我们需要的入口文件
使用ESPlorer的save to esp
是不能将电脑上的main.py成功上传到板子中的。踩坑。。。
必须使用ampy。
安装好ampy之后
$ ampy help #可以查看ampy的具体用法,put命令就是我们需要的
$ ampy -b 115200 -p /dev/cu.SLAB_USBtoUART put main.py /main.py
这样main.py就成功上传了
- wifi
在能够让步进电机转动之后,我们要将这看似没什么用处的电机接入互联网,这就带来了无限的想象力。
在接入互联网之前要先连上WIFI。
def doConnect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('SSID', 'PASSWORD')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
- mqtt
连上互联网之后就要连接服务器了
micropython內建库中没有mqtt模块,但是强大的社区提供了 实现
将simple.py下载下来放到工程目录,当然也要上传到板子上。
def mqtt():
SERVER = "192.168.1.19"
CLIENT_ID = "umqtt_client"
PORT = 8173
TOPIC = 'micropython' # 订阅的主题
client = MQTTClient(CLIENT_ID, SERVER, PORT,"0","0")
# Subscribed messages will be delivered to this callback
client.set_callback(sub_cb)
client.connect()
client.subscribe(TOPIC)
print("Connected to %s, subscribed to %s topic" % (SERVER, TOPIC))
try:
while 1:
client.wait_msg()
finally:
client.disconnect()
client.set_callback(sub_cb)
其中的sub_cb回调就是业务逻辑的具体实现了。
def parse(m):
arr = m.split('&')
dic = {}
for item in arr:
temp = item.split('=')
dic[temp[0]] = temp[1]
return dic
def sub_cb(topic, msg):
global state # 1是正转,2是反转
message = msg.decode('utf-8') # 从二进制转为utf-8
dic = parse(message) # 使用querystring解析成字典
type = dic['type'] # 动作
speed = dic['payload'] # 速度
speed = int(speed) # string转为int
if type == "stop":
stop()
elif type == "positive":
state = 1
start(positive,speed) #正转
elif type == "negetive":
state = 2
start(negetive,speed) #反转
elif type == "speed": # 变速
if state == 1:
start(positive,speed)
elif state == 2:
start(negetive,speed)
一个没解决的问题是micropython中的ujson模块没有使用成功,所以使用了querystring来传递信息。
- 服务端实现
硬件部分就差不多大功告成了。
硬件部分使用mqtt向服务器订阅了micropython这个主题,接下来就是服务端发布订阅消息。
服务端使用express集成mosca来实现的。
mosca是mqtt协议的node实现。
根据文档设置好端口,开启一个mqtt服务器,将服务器暴露在global下,但是感觉不是一个很好的方法,node还有待学习。
api接口的简单实现类似于这样
const getMessage = (m) => {
m = querystring.stringify(m)
let message = {
topic: 'micropython', // 订阅主题
payload: m,
qos: 1,
retain: false
}
return message;
}
// 正转接口
router.post('/positive', function(req, res, next) {
mqtt.publish(getMessage({
type: 'positive',
payload: req.body.speed
}), function() {
res.json(template(true,'success'))
})
});
- 前端实现
前端可以选择Andriod/IOS/Web,任选一个来向服务器发送http请求。
中心思想
我打开手机上的网页,点击一个按钮,电机就转动起来了。手中的小小机器貌似有了魔法,可以操纵没有任何实际物理关联的机器。
虽然是一个简单的不能再简单的功能,对于现在已经很先进的智能家居,物联网不值一提的功能,但是却让我切身感受到了互联网真正的力量和无限的想象力。
既然物联网这么好玩,那我还是好好搞前端吧!