作者 | Haor.L

责编 | 王晓曼

出品 | CSDN博客

笔者最近参加了校内的一场物联网开发竞赛,从零开始,踩坑无数,感觉很多时候事情都不像预料的一样发展,离开了美好的IDE,太多事情要在板子上一步步摸索。运行失败还好,运行成功但BUG了,简直不知道从何查起

但认识了M5Stack简单的线上系统,学习了MQTT,HTTP等数据传输方式,入门Arduino和MIrcopython等开发语言,接触ESP32的板子,感受最深的一点就是,物联网的准入门槛并没有那么高,成本也没有那么高,但这还是一片混沌未开的区域,进场者真的可以大有所为,起码方便自己的日常生活是绰绰有余的。

总的来说,这次物联网入坑,值得!

阅读本文后你将收获:

  • 了解M5STACK这款新兴的片上系统

  • 了解这款板子的开发环境如何配置

  • 掌握ONENET数据传输

  • 掌握HTTP的GET方法

  • 会搭建笔者前几天做的项目雏形:健康码追踪系统

开发准备

本博客作为学习物联网开发的笔记,也简单的将自己的片上系统作为例程写出来。

  • ESP-IDF工具链配置:乐鑫文档

  • UIflow在线IDE

  • M5STACK的官方开发文档( 很全,如果你也打算使用M5STACK系列的开发板,强烈建议从此入门)

  • 本博客项目的代码仓库(欢迎赏星):https://github.com/haoruilee/M5Stack_Healthy_code_tracer

M5STACK简介

M5STACK是一款对初学者非常友好的ESP32开发板,可以用Micropython和C编程,也可以用很简单的拖拽式编程,拥有庞大的官方文档,只是国内只在最近开始流行,油管和B站上都有官方的教学视频,也在常常更新,很有创造力的一个产品。

结构上主要分为Core和Unit,Core作为核心控件,Unit作为传感器采集数据。

下图图就是笔者自己做的产品雏形,中间的小屏幕是Core,作为主控,周围有GPS和RFID,摄像头等单元用来采集数据。

设计雏形:

由于所有的M5产品都预设了乐高块,所有你可以把他们拼在乐高模组上,油管上还有不少人用它做乐高机器人,确实是很有创意的一款产品,颜值也不错,所以笔者选择它用来开发。

环境配置

UIFlow环境

在线编程地址:UIFlow

前几天GIthub发布了远程编译器Codespace,可以看出远程编译确实是大势所趋。

这里不得不说UIFlow把物联网的门槛大大降低了,笔者配置ESP-IDF用了将近一天,而使用UIFlow可以免去一切环境配置的痛苦。

支持拖拽编程,可视化UI设计,自带例程,确实是良心产品。

ESP-IDF环境

方法一

笔者配置ESP-IDF工具链时,一开始是使用Windows系统的工具安装器。

ESP-IDF 工具安装器可在“开始”菜单中,创建一个打开ESP-IDF 命令提示符窗口的快捷方式。本快捷方式可以打开 Windows 命令提示符(即 cmd.exe),并运行 export.bat 脚本以设置各环境变量(比如 PATH,IDF_PATH 等)。

(不得不说,这个安装器的健壮性非常差!!)

安装心得:上网技巧+把系统的PATH重新检查一遍,有些卸载残余的PATH会导致玄学问题!

方法二(更推荐)

宇宙第一VS code中有插件 ESPRESSIF

可以更清楚每时每刻在干什么,也更清楚出了BUG去哪里修补。


感知模块

M5开发了很多环境传感器,包括温湿度,人体感应,RFID,摄像头等等,在官方开发文档上也都给出了相关例程和GIthub的源码链接。

笔者自己的项目使用的是RFID、GPS和Camera模块,其中除了Camera只能用ESP-IDF编程,其他单元都支持在UIFlow上在线编程,再加上,Micropython确实比C++舒服太多。


网络连接

Wi-Fi链接

M5Stack已经自己预置了Wi-Fi链接,开机就是,不过在Mircopython里写起来也很简单,下面是一个范例:

import network
SSID="YOUR-WIFI-NAME"
PASSWORD="YOUR-WIFI-PASSWORD"
wlan=None
s=Nonedef connectWifi(ssid,passwd):'''连接指定wifi'''global wlanwlan=network.WLAN(network.STA_IF)wlan.active(True)wlan.disconnect()wlan.connect(ssid,passwd)while(wlan.ifconfig()[0]=='0.0.0.0'):time.sleep(1)return True

使用Mircoython的Wi-Fi模块,connect(ssid,password),就可以进入可爱的Wi-Fi连接界面了,M5GO的封装还是不错的。

NB-IOT
IOT模组需要额外配一张NB卡,某宝20就可以拿下一年500M流量,不过笔者没有继续尝试,已经有可爱的M5GO和稳定的Wi-Fi,就没探索用3G进行通讯。


HTTP通讯

接下来介绍物联网的精髓,“联网”,采集到了数据,那数据上报和传输是重中之重。

笔者觉得HTTP是最好理解,好入门的通讯协议,这里也先介绍这种方法。

建议参考视频:B站:接入中国移动ONENET平台

笔者尝试过诸如阿里云和一些外国的平台,最后发现都不如中国移动专门为物联网开发的ONENET,一来稳定,不用担心服务商跑路,而来阿里云显得太过臃肿,对入门者很不友好,最终选择了ONENET,他的HTTP封装好了很好看的数据流模板,如:

  • 位置信息可视化:

  • 自动折线图

POST上传数据

创建流模板

首先需要创建一个数据流模板,用于接收传过来的数据:

发送请求

请求方式:POST

URL:http://api.heclouds.com/devices/device_id/datapoints

其中,device_id:需要替换为设备ID

注意:ONENET默认post的数据叫Datastreams,参数配置见表:

请求实例:

{"datastreams": [{"id": "temperature","datapoints": [{"at": "2013-04-22T00:35:43","value": "bacd"},{"at": "2013-04-22T00:55:43","value": 84}]},{"id": "key","datapoints": [{"at": "2013-04-22T00:35:43","value": {"x": 123,"y": 123.994}},{"at": "2013-04-22T00:35:43","value": 23.001}]}]
}

使用ONENET的模拟API调用可以快速熟悉数据的模式:

其中,URL的device_id,和下面的API_key换成自己设备的,可以在设备列表找到,就可以往自己设备的数据流模板传一个值为3的value。

Micropython用HTTP

UIFlow里自带了HTTP模块,但是很玄学,很难用!

这里笔者用Micropython自己写了一份HTTP的传输:

def http_put_data(data):#post data into oneneturl='http://api.heclouds.com/devices/'+DEVICE_ID+'/datapoints'values={'datastreams':[{"id":"temperature","datapoints":[{"value":data}]}]}jdata = json.dumps(values)                 r=urequests.post(url,data=jdata,headers={"api-key":API_KEY})return r

亲测还是很好用的,可能是UIFlow自己的json封装比较奇怪?

使用模组交互的数据传输

既然M5STACK可以同时使用多个模组,那么自然也就可以使用模组来控制数据传输:

如:使用RFID卡,控制POST:

rfid0 = unit.get(unit.RFID, unit.PORTA)while(True):if rfid0.isCardOn():rsp = http_put_data(12)emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,1,1,1,1,1,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], 0xff0000)else:#wlan.disconnect()#wlan.active(False)emoji0.show_map([[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0],[0,0,0,1,0,0,0]], 0xff0000)wait(1)

第一行的rfid0 = unit.get(unit.RFID, unit.PORTA)是指定从PORTA读取RFID的射频信息


使用HTTP的GET获取b站信息

有POST就要有GET,这里介绍一个B站大佬“正负加减”的例程,获取自己的粉丝数,里面讲解也很细致,大佬也是老Geek了,关注不亏!

UIFlow的GET结构:

核心思想是知道哪个key是follow,可以在F5审查源代码找到:

此处的URL是

http://api.bilibili.com/x/relation/stat?vmid=99566555

UP和DOWN是控制RGB等的函数。


我的片上系统设计全过程

设计初衷

在疫情管控最严格的的时候,经常能看到触目惊心的“寻找x月x日乘坐xxxx的乘客”,如果能追寻乘坐公共交通者的足迹,会给疫情管控带来很大便利。

设计方法

笔者希望结合GPS,RFID和摄像头功能,做个车载的识别信息-上报信息的小系统。

具体涉及到二维码识别,RFID识别,GPS获取和HTTP上报。

然而,这个设计一开始就遇到了难题。网上购买的测温枪,他的蓝牙数据我无法解包,好像是和腾讯连连有自己的相关配置。

腾讯连连界面:

既然腾讯连连已经写到那么好了,那就不抢他的饭碗了。

既然没办法解析内容,那下面笔者将用ENV单元采集的环境温度代替乘客温度进行收发。

分模块实现

RFID控制块

首先声明RFID模块的串口:

rfid0 = unit.get(unit.RFID, unit.PORTA)

该段指从A口串入RFID模组

【注:M5STACK使用颜色标明了A,B,C三个Grove口,见下图】

上图中RFID的串口是红色,就对应到M5GO左侧的红色接口:

GRIVE HUB

由于笔者同时还需要使用红色串口的ENV单元,因此额外购买了GROVE HUB

这样就有两个A口了。

访问设置时不需要加以区分,都从PORTA引入:

rfid0 = unit.get(unit.RFID, unit.PORTA)
env0 = unit.get(unit.ENV, unit.PORTA)

使用Emoji模块做可视化:

笔者使用循环判断是否有卡片接近,无则显示待机Emoji,有则显示✅

 #循环判断是否有卡片接近while(True):#熄灭RGB灯rgb.setBrightness(0)#清空Emoji显示emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], 0x000000)#判断是否有卡片接近if rfid0.isCardOn():#有卡片接近显示对号emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,1],[0,0,0,0,0,1,1],[1,0,0,0,1,1,0],[0,1,1,1,1,0,0],[0,0,1,1,0,0,0]], 0x33ff33)#发送RFID读取到的卡片IDrsp_RFID = http_put_RFID((str(rfid0.readUid())))#完成后指示灯变绿rgb.setColorAll(0x33ff33)rgb.setBrightness(10)else:#可选是否断开wifi#wlan.disconnect()#wlan.active(False)#等待卡片接近时,Emoji展示"。。。"emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,1,0,1,0,1,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], 0x000000)wait(1)

这里的Emoji模块是先在UIFlow里敲好,再进Micropython里查看的。

HTTP传输块

HTTP传输在上文已经讲了不少,这里优先介绍GPS的传输:

GPS的命令也是要加“value:”的,形如value:{“lon”:lon,“lat”:lat},这个地方一开始把笔者坑的不轻

def http_put_location(lon,lat):'''传输地理位置数据点至ONENET平台的location数据流lon:longitude,经度lat: latitude,纬度url:http的post地址values:请参考https://open.iot.10086.cn/doc/multiprotocol/  文档中的"HTTP协议上传数据点模块,配置json格式信息"API_KEY:设备发送HTTP请求的证书,请参考https://open.iot.10086.cn/doc/multiprotocol/book/develop/http/api/api-usage.html  文档中的"鉴权说明"'''url='http://api.heclouds.com/devices/YOUR-DEVICE-ID/datapoints'values={'datastreams':[{"id":"location","datapoints":[{"value":{"lon":lon,"lat":lat}}]}]}jdata = json.dumps(values)                 r=urequests.post(url,data=jdata,headers={"api-key":API_KEY})return r

这里请把YOUR-DEVICE-ID替换为自己的数据流中设备编号,参考ONENET手册。

Wi-Fi连接块

UIflow里封装了很好的Wi-Fi-connect:

wifiCfg.doConnect(SSID, PASSWORD)

如果你的Micropython里没有一键Wi-Fi连接,笔者自己也实现了一个:

  def connectWifi(ssid,passwd):'''如果您的Micropython不携带WifiCfg.doconnect,请参考本函数函数作用:连接至名称为SSID,密码为passwd的wifi'''global wlanwlan=network.WLAN(network.STA_IF)wlan.active(True)wlan.disconnect()wlan.connect(ssid,passwd)while(wlan.ifconfig()[0]=='0.0.0.0'):time.sleep(1)return True

二维码识别块

  • 本部分使用ESP-IDF编程

  • 使用的摄像头是M5CAMERA

  • 属性是OV2640

参考官方例程

  //拍摄
camera_fb_t* esp_camera_fb_get()
{if (s_state == NULL) {return NULL;}if(!I2S0.conf.rx_start) {if(s_state->config.fb_count > 1) {ESP_LOGD(TAG, "i2s_run");}if (i2s_run() != 0) {return NULL;}}if(s_state->config.fb_count == 1) {xSemaphoreTake(s_state->frame_ready, portMAX_DELAY);}if(s_state->config.fb_count == 1) {return (camera_fb_t*)s_state->fb;}camera_fb_int_t * fb = NULL;if(s_state->fb_out) {xQueueReceive(s_state->fb_out, &fb, portMAX_DELAY);}return (camera_fb_t*)fb;
}//二维码识别
void qr_recoginze(void *pdata) {camera_fb_t *camera_config = pdata;if(pdata==NULL){ESP_LOGI(TAG,"Camera Size err");return;}struct quirc *q;struct quirc_data qd;uint8_t *image;q = quirc_new();if (!q) {printf("can't create quirc object\r\n");vTaskDelete(NULL) ;}//printf("begin to quirc_resize\r\n");if (quirc_resize(q, camera_config->width, camera_config->height)< 0){printf("quirc_resize err\r\n");quirc_destroy(q);vTaskDelete(NULL) ;}image = quirc_begin(q, NULL, NULL);memcpy(image, camera_config->buf, camera_config->len);quirc_end(q);int id_count = quirc_count(q);if (id_count == 0) {quirc_destroy(q);return;}struct quirc_code code;quirc_extract(q, 0, &code);quirc_decode(&code, &qd);dump_info(q);quirc_destroy(q);
}

这里依赖了太多官方库…建议去代码仓库翻一翻。

K210的二维码识别

上文是ESP32类型的开发板识别代码,可以看到非常繁琐,改起来简直要了老命

使用Micropython的话,代码就变的可爱多了~

【此部分使用Maxipy编程】

 import sensor
import image
import lcd
import timeclock = time.clock()
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)
sensor.run(1)
sensor.skip_frames(30)
while True:clock.tick()img = sensor.snapshot()res = img.find_qrcodes()fps =clock.fps()if len(res) > 0:img.draw_string(2,2, res[0].payload(), color=(0,128,0), scale=2)print(res[0].payload())lcd.display(img)

这里Maxipy的官方文档还给出了修正图像的方法:

如果使用了镜头,画面会有扭曲,需要矫正画面使用 lens_corr 函数来矫正,比如 2.8mm, img.lens_corr(1.8)

(没事翻一翻这个Maxipy的文档还是很有启发的,大概两小时就能通读一遍)

GPS传输块

室内经常没有信号(实测室外也很少有…)因此在传递GPS的时候笔者额外设计了防止无信号的代码。

GPS的http传输函数已经在上文讲了,此处和RFID卡片控制进行结合:

 if rfid0.isCardOn():#有卡片接近显示对号emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,1],[0,0,0,0,0,1,1],[1,0,0,0,1,1,0],[0,1,1,1,1,0,0],[0,0,1,1,0,0,0]], 0x33ff33)#发送RFID读取到的卡片IDrsp_RFID = http_put_RFID((str(rfid0.readUid())))#防止测试时无信号if str(gps0.pos_quality) != "1" and str(gps0.pos_quality) != "6":lon=116.39137751349433lat=39.8969585128568else:#默认北京lon=gps0.longitudelat=gps0.latitudetry:rsp_LOCATION=http_put_location(float(lon),float(lat))except:emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,1],[0,0,0,0,0,1,1],[1,0,0,0,1,1,0],[0,1,1,1,1,0,0],[0,0,1,1,0,0,0]], 0xff0000)#传输温度rsp = http_put_data(env0.temperature)#完成后指示灯变绿rgb.setColorAll(0x33ff33)rgb.setBrightness(10)else:#可选是否断开wifi#wlan.disconnect()#wlan.active(False)#等待卡片接近时,Emoji展示"。。。"emoji0.show_map([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,1,0,1,0,1,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]], 0x000000)wait(1)



后记

参赛时间仓促,没能完全搞明白每个引脚的用途,没有好好触摸一遍C和开发板,没有用NB-IOT通讯。没有做蓝牙通讯解包…还是有很多遗憾的,还好设备还在,可以继续探索物联网的神奇。
成果效果:

版权声明:本文为CSDN博主「Haor.L」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_46233323/article/details/106054434」

更多精彩推荐
☞程序员在家办公没显示屏,我被领导鄙视了
☞Get!读懂数据科学和机器学习,看这文就够了
☞深度剖析数据库国产化迁移之路
☞Go远超Python,机器学习人才极度稀缺,全球16,655位程序员告诉你这些真相
☞我佛了!用KNN实现验证码识别,又 Get 到一招
☞超级账本Hyperledger Fabric中的Protobuf到底是什么?
你点的每个“在看”,我都认真当成了喜欢

零基础物联网开发,踩坑无数,得到这份宝典 | 原力计划相关推荐

  1. 【Flutter混合开发踩坑日记之‘applicationVariants‘ for extension ‘android‘】

    Flutter混合开发踩坑日记之'applicationVariants' for extension 'android' 正文 坑一:Could not get unknown property ' ...

  2. mybatis mapper.xml dtd_全栈开发踩坑之路4-用MyBatis实现服务

    1.前言 上一篇文章介绍了如何设计后端的Mysql数据库:Alex Wang:全栈开发踩坑之路3-MySql数据库设计,本文介绍如何用MyBatis实现后端服务. 本后端项目的Github地址(撰写中 ...

  3. 2021爱智先行者—(2)零基础APP开发实例

    [本文正在参与"2021爱智先行者-征文大赛"活动],活动链接:https://bbs.csdn.net/topics/602601454 欢迎关注 『Python小白的项目实战』 ...

  4. 让垃圾分类开发“极快致简”的好物件,零基础的开发小白也能轻松驾驭它!

    摘要:2019年7月1日,史称"最严格的垃圾分类法"<上海市生活垃圾管理条例>正式开始施行,一时之间上海人最常用的见面语从"侬好"变成了" ...

  5. 零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)—项目概述篇(一)

    零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)-项目概述篇(一) 一.项目开发总体框架 二.项目开发流程 三.项目技术选型

  6. android usb没有读写节点,2019踩坑无数含泪写下最新教程系列(三)树莓派挂载android(树莓派通过usb读取手机里面档案)...

    2019踩坑无数含泪写下最新教程系列(三)树莓派挂载android(树莓派通过usb读取手机里面档案) STEP1: Install packages Install support for MTP: ...

  7. 微信vue路由跳转兼容_Vue微信公众号开发踩坑记录

    需求 微信授权登录(基于公众号的登录方案) 接入JS-SDK实现图片上传,分享等功能 现状及难点 采用的Vue框架,前后端分离模式(vue工程仅作为客户端),用户通过域名访问的是客户端,但是微信授权中 ...

  8. 微信开发踩坑之旅 之 开发准备及服务器配置

    在工作和兴趣的机缘巧合之下,我开始接触微信开发.在这里简单记述自己的微信开发踩坑之旅. 首先,由于本人标准的理工科生,记述的语言有所不足,我尽量说明准确和详细点. 本文记述主线 ·申请公众号 ·公众号 ...

  9. 乐视体感摄像头开发踩坑记录

    乐视三合一体感相机开发踩坑记录 第一次用Cmake,以下如有错误请大佬指正 开发环境: Linux ARM(树莓派4) AstraSDK-v2.1.3 Arm/Arm64(https://orbbec ...

最新文章

  1. 【多标签文本分类】Large Scale Multi-label Text Classification with Semantic Word Vectors
  2. 金融科技创业公司Revolut增加对BCH和XRP支持
  3. Spring Boot Admin 2.2.0发布,支持最新Spring Boot/Cloud之外,新增中文展示!
  4. 昇腾 OSError: [Errno 22] Invalid argument: ‘protocol‘
  5. MVC学习(四)几种分页的实现(3)
  6. android studio 中的编码问题
  7. 符号化Symbol(符号)体系(转载)
  8. 棱镜刘大澎:云时代的手游SDK接入
  9. 验证二叉搜索树Python解法
  10. USB接口定义(Z)
  11. 谷歌浏览器调用本地exe_无需修改前端和后端代码本地跨域开发设置
  12. Python开发第一步的环境搭建
  13. 日常计算机使用的需求和解决方案(一)
  14. 8000401a 因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码
  15. 多元相关性分析_SPSS分析问卷数据的流程------一篇带你学会SPSS
  16. Dell笔记本降低Bios版本简单而可靠的方法(1.15亦成功降级)
  17. 解决fortify扫描出的Path Manipulation问题(java语言)
  18. 初识JavaScript,体验JS的美好
  19. UVA12304 2D Geometry 110 in 1!
  20. java springboot pdf插入图片 定点插图

热门文章

  1. MySQl数据库常用的DOS命令
  2. Team Foundation Server
  3. 图解CSS3----3-目标伪类选择器
  4. 软件工程第一周预备作业
  5. Activity去Title的几种方式
  6. [LibTorch] Tensor 与 Mat 相互转换
  7. [论文翻译] Medical Matting: A New Perspective on Medical Segmentation with Uncertainty
  8. php神盾 var 1.54,神盾加密解密教程(一)PHP变量可用字符
  9. mysql 计算时区差_在MySQL中计算时区的偏移量
  10. Linux Shell编程笔记6 sed流编辑器