5145| 2
|
[2019参赛作品] 【脑洞大赛】IoT标签 |
本帖最后由 安卓机器人 于 2019-8-21 00:57 编辑 IoT 标 签 源 起: 在我们小区门口,有一家不大的店~叫“福美家超市”。主打是卖菜,兼有副食品和小百货等。奇怪的是,旁边有几家类似功能的店,其他家多是冷冷清清,这一家却总是得排队付款。就算附近农村卖小菜的农民在附近围了一圈儿又一圈儿,似乎也没能冲淡这家店的生意! 今天,照例来到这家店里准备买菜,大家伙儿自觉地站了两排,向前推进得似火比平常慢了点。正在选菜中,老板娘不知对谁发了个话,“哎,大妈,您稍等会儿啊,今天缺两人没来吶”。今天小两口子一同协作:一个称重贴标签,另一个扫码收款(向多数老年人),年轻人常常是手机付款。时不时也有不想多等的年轻人离开店铺。 我的感觉是排队买菜的现象已经有几年了。有一次为关于他儿子学编程事聊了一会儿。他们每天3~4点就得起床,要赶往蔬菜集散中心采购,回到店里,还要不停地整理菜品,全家齐上阵,吃饭不定点,直到晚上23点接近24点才能睡觉。几乎天天如此,年年如此。所以老板的问题似乎也是我的问题,忽然自动激发了是不是可以利用最近学习人工智能技术,其中之一是机器学习,可以对各种菜品进行训练学习,达到一定次数后不难识别常见超市蔬菜瓜果等。由此制作一种能自动识别称重贴标的AI菜篮子。 这家店年轻的老板及老板娘怎么也不会想到,一位顾客会为他们店更高效地卖菜而想办法。哈哈,这就是创客吧。 当然,小白的我对人工智能才刚刚接触,这个AI菜篮子当前仅存脑海里备档哟。 但是结合电子墨水屏制作未来超市的商品IoT标签并不难。 IoT标签: 一种在超市、便利店、药房、甚至员工胸牌等场景显示信息的电子类标签。随着人工智能时代的来临,将越来越多地替代传统纸质标签;每一个电子价签通过无线网络与商场计算机数据库或上云互连,实时、准确地显示不同区域商品最新的基本信息。 IoT标签 VS 纸质标签:
目前制作IoT标签的最佳选择是电子墨水屏。 什么是电子墨水屏?(参考:电子发烧友网~"传感器技术") 电子墨水屏(E-link): 电子墨水屏技术最早可以追溯到 1996 年,它基于美国麻省理工学院媒体实验室(MIT Media Lab)的一项研究,利用电泳技术(EPD)实现显示,这类屏幕的显示效果十分接近传统纸张,因此也被成为“电子纸”。1997 年,麻省理工学院的教授 Joseph Jacobson 创立 E_Ink 公司,开始推动电子纸技术走向商业化,电子墨水技术成为电子纸的主流。 电子墨水与印刷使用的墨水很相似,都是用颜料所制,这也是为什么我们看到电子墨水屏和传统纸张显示效果相似的原因。电子墨水通常会制成薄膜,由大量微胶囊﹙microcapsules﹚组成,这些微胶囊只有人类头发的直径大小。微胶囊中的黑白小球是带不同电荷的色素颗粒,初始状态下,色素颗粒悬浮在微胶囊中,当施加一定方向的电场后,相应的色素颗粒被推到顶部,微胶囊就会显示不同的颜色,而不同颜色的微胶囊组成了各种文字和图案。电子纸显示屏是靠反射环境光来显示图案的,不需要背光,即使是在阳光底下,电子纸显示屏依然清晰可视,可视角度几乎达到了 180°。因此,电子纸显示屏非常适合阅读。 电子墨水屏基本结构如下图所示: ⒈上层;⒉透明电极层;⒊透明微胶囊;⒋带正电荷的白色颜料;⒌带负电荷的黑色颜料;⒍透明液体(油);⒎电极像素层;⒏基板;⒐光线;⒑白色;⒒黑色。 电子墨水屏是由许多电子墨水组成,它是融合化学,物理和电子学的整体产生的一种新材料。电子墨水可以看成一个个胶囊的样子(如上图所示)。每一个胶囊(位置6)里面有液体电荷,其中正电荷染白色,负电荷染黑色。当在一侧(位置8)给予正负电压,带有电荷的液体就会被分别吸引和排斥。这样,每一个像素点就可以显示白色或者黑色了。因为电子墨水的刷新是不连续的,每一次刷新完成就可以保持现在的图形,即使拔掉电池也依旧保存,因为电子墨水具有双稳态效应(磁滞效应)。 电子墨水屏的优点: 1、省电(可用于低功耗场景) 2、护眼(未来很可能替代纸质阅读) 电子墨水屏当前的缺点: 1、目前主要只有黑白产品,彩色有三色(黑白红)/(黑白黄)/4096色。 2、不能快速响应一些动画类需求。 3、彩色屏刷新过程中会闪屏。 4、成本高。 微雪的柔性墨水屏祼屏(黑白): 尺寸: 2.13 inch 工作电压:3.3V/5V 通信接口:SPI 点距:0.229* 0.228 分辨率:212*104 显示颜色:黑、白 灰度等级:2 局部刷新 :0.3s 全局刷新 :2s 注意事项(摘自微雪): 1. 支持局刷的屏幕,注意使用的时候不能一直用局刷对屏幕进行刷新,需要在做几次局刷之后,对屏幕进行一次全刷清屏。否则会造成屏幕显示效果异常,无法修复。 2. 三色的墨水屏,建议将屏幕刷白朝上存放,使用前,先上电做几次刷白操作。 3. 注意屏幕不能长时间上电,在屏幕不刷新的时候,要将屏幕设置成睡眠模式,或者进行断电处理。否则屏幕长时间保持高电压状态,会损坏膜片,无法修复。 4. 使用墨水屏的时候,建议刷新时间间隔至少是 180s, 并且至少每 24 小时做一次刷新,如果长期不使用墨水屏的话,要将墨水屏刷白存放。 5. 屏幕进入睡眠模式之后,会忽略发送的图片数据,只有重新初始化才能正常刷新。 6. 屏幕的 FPC 排线比较脆弱,注意使用的时候沿屏幕水平方向弯曲排线,不可以沿屏幕垂直方向弯曲排线。 7. 墨水屏屏幕较为脆弱,注意尽量避免跌落,碰撞,用力按压。 DF~FireBeetle 三色电子墨水屏(黑白红): 工作电压:3.3V 数据总线:SPI 颜色:黑白红三色 屏幕尺寸:2.13 inch 像素:212×104 刷新时间:12~15s 背面(下角白色方块与微控制器上一致,是防呆防反插标志哟^_^): DF~FireBeetle 低功耗系列之一萤火虫 ESP32微控制器 (支持WiFi&Bluetooth): 可以较方便地控制FireBeetle电子墨水屏。 DF为FireBeetle(三色)电子墨水屏提供的API列表: #include "DFRobot_IL0376F_SPI.h" DFRobot_IL0376F_SPI eink; //创建一个ePaper对象 函数功能:设定字库和墨水屏片选引脚并初始化。 void begin(const char cs_W21, const char cs_GT30, const char dc, busy); 函数功能:清除屏幕为指定颜色。 InkScreen_Error clear(uint8_t color); 函数功能:显示图片(212*104),可以是红色、黑白、红白黑三色图片。 void drawPicture(const unsigned char *pic_bw, const unsigned char *pic_red); 函数功能:刷新屏幕显示。 void flush(void); 函数功能:显示字符串。 void disString(uint8_t x, uint8_t y, char *ch, uint8_t color); 函数功能:画点。 InkScreen_Error drawPoint(const unsigned char x, const unsigned char y, const unsigned char color); 函数功能:画线。 InkScreen_Error drawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color); 函数功能:画矩形框。 InkScreen_Error drawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) 函数功能:画圆形边框或者填充圆形。 InkScreen_Error drawFillRect(uint16_t x1, uint16_t y1, uint16_t width, uint16_t length, uint8_t color); 参数1 (xc,yc): 圆心坐标 (xc∈(0,211),yc∈(0,103)。 InkScreen_Error drawCircle(uint16_t xc, uint16_t yc, uint16_t r, uint16_t fill, uint8_t color); 结合例程及上API对电子墨水屏~IoT货架标签进行界面布局: 主要是在程序中对各种元素进行坐标定位、字号选择、颜色确定、图形绘制等。 测试电子墨水屏程序(Arduino): [mw_shl_code=cpp,true]/*! * 08/19/2019测试电子墨水屏程序 * from file FigureDemo.ino * 分辨率:212*104 */ #include "Arduino.h" #include "DFRobot_IL0376F_SPI.h" #define STOCK_PIN A2 // 这里可以利用环境光线传感器收集数据模拟商品“美福记”库存状态变化 DFRobot_IL0376F_SPI epaper; #define EPAPER_CS D3 #define Font_CS D6 #define EPAPER_DC D8 #define EPAPER_BUSY D7 char foodName[]=""; float price = 0.0; int stock_per = 100; void setup(void) { Serial.begin(115200); //Select the corresponding pins epaper.begin(EPAPER_CS, Font_CS, EPAPER_DC, EPAPER_BUSY); } void loop(void) { epaper.fillScreen(WHITE); //Displays a string, black font epaper.disString(1,5, 2,"食",BLACK); epaper.disString(1,45, 2,"品",BLACK); epaper.disString(0,83, 1,"FOOD",BLACK); //Let me draw 2 red dotLines for(uint8_t x=33,y=0; y<103; y+=2) { epaper.drawPixel(x,y,RED); epaper.drawPixel(x+1,y,RED); } epaper.disString(35,1, 1,"品名:",BLACK); epaper.disString(35,18, 1,"Name",BLACK); epaper.disString(35,35, 1,"价格:",BLACK); epaper.disString(35,52, 1,"Price",BLACK); epaper.disString(35,69, 1,"库存:",BLACK); epaper.disString(35,86, 1,"Stock",BLACK); epaper.disString(78,1, 1,"美福记",RED); epaper.disString(78,30, 2,"29.8",RED); epaper.disString(140,45, 1,"¥/Kg",RED); epaper.disString(185,1, 1,"20%",RED); // Draw a down arrow epaper.fillRect(191,18, 12,40,RED); epaper.fillTriangle(184,50, 210,50, 197,70,RED); //Draw a black rectangle(x,y,l,r,c) epaper.drawRoundRect(75,75, 135,23,8,BLACK); epaper.drawRoundRect(76,76, 133,21,8,WHITE); epaper.drawRoundRect(77,77, 131,19,8,WHITE); stock_per =map(analogRead(A2),0,1023,0,100); epaper.fillRoundRect(78,78, 129*stock_per/100,17,7,RED); epaper.disString(185,1, 1,"20%",RED); //Refresh screen display epaper.flush(); delay(10000); }[/mw_shl_code] 测试IoT程序(ARDUINO):[mw_shl_code=cpp,true]#include <WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> #include "DFRobot_Aliyun.h" #include "DFRobot_DHT11.h" #define DHT11_PIN D2 //定义传感器引脚,用于收集数据模拟库存数据 /*配置WIFI名和密码*/ const char * WIFI_SSID = "your ssid"; const char * WIFI_PASSWORD = "your password"; /*配置设备证书信息*/ String ProductKey = "xxxxxxxxxx"; String ClientId = "12345"; String DeviceName = "STOCK"; String DeviceSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxx"; /*配置域名和端口号*/ String ALIYUN_SERVER = "iot-as-mqtt.cn-shanghai.aliyuncs.com"; uint16_t PORT = 1883; /*需要操作的产品标识符(温度和湿度两个标识符)*/ String TempIdentifier = "xxxxxxx"; String HumiIdentifier = "xxxxxxxx"; /*需要上报和订阅的两个TOPIC*/ const char * subTopic = "xxxxxxxxxxxxxxxxxxxxxxxxx/property/set";//****set const char * pubTopic = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/property/post";//******post DFRobot_Aliyun myAliyun; WiFiClient espClient; PubSubClient client(espClient); DFRobot_DHT11 DHT; void connectWiFi(){ Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID,WIFI_PASSWORD); while(WiFi.status() != WL_CONNECTED){ delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.print("IP Adderss: "); Serial.println(WiFi.localIP()); } void callback(char * topic, byte * payload, unsigned int len){ Serial.print("Recevice ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < len; i++){ Serial.print((char)payload); } Serial.println(); } void ConnectAliyun(){ while(!client.connected()){ Serial.print("Attempting MQTT connection..."); /*根据自动计算的用户名和密码连接到Alinyun的设备,不需要更改*/ if(client.connect(myAliyun.client_id,myAliyun.username,myAliyun.password)){ Serial.println("connected"); client.subscribe(subTopic); }else{ Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void setup(){ Serial.begin(115200); /*连接WIFI*/ connectWiFi(); /*初始化Alinyun的配置,可自动计算用户名和密码*/ myAliyun.init(ALIYUN_SERVER,ProductKey,ClientId,DeviceName,DeviceSecret); client.setServer(myAliyun.mqtt_server,PORT); /*设置回调函数,当收到订阅信息时会执行回调函数*/ client.setCallback(callback); /*连接到Aliyun*/ ConnectAliyun(); } uint8_t tempTime = 0; void loop(){ if(!client.connected()){ ConnectAliyun(); } /*一分钟上报两次温湿度(模拟福美记和福美佳两种商品的库存状态数据)信息*/ if(tempTime > 60){ tempTime = 0; DHT.read(DHT11_PIN); Serial.print("DHT.temperature="); Serial.println(DHT.temperature); Serial.print("DHT.humidity="); Serial.println(DHT.humidity); client.publish(pubTopic,("{\"id\":"+ClientId+",\"params\":{\""+TempIdentifier+"\":"+DHT.temperature+",\""+HumiIdentifier+"\":"+DHT.humidity+"},\"method\":\"thing.event.property.post\"}").c_str()); }else{ tempTime++; delay(500); } client.loop(); }[/mw_shl_code] 利用阿里云生成安卓APP: 本应用采取 DHT11 温湿度传感器获取环境温度和湿度模拟商品库存状态,并将数据传输给手机 App 显示,从而实现远程实时监控库存的功能。 应用目标:通过手机 App 实时监测超市商品库存情况。 所需元件: DHT11 温湿度传感器 x1 FireBettle Board-ESP32 x1 FireBettle Gravity 扩展板 x1 DHT11x1 智能手机 x1 硬件连接: 把 FireBettle Gravity 扩展板直插在 FireBettle Board-ESP32 主板上,再把 DHT11 温湿 度模块接在扩展板的 D2 数字引脚上,确保电源引脚、接地引脚和信号引脚都连接正确。 按以下我亲自成功的步骤进行即可:(或者参考官方教程) 1.打开浏览器,输入网址 https://iot.aliyun.com,登录并进入物联网平台. 2.创建一个名为“库存监测”的产品,如下图所示,若产品创建成功,会自动出现在产品列表中; 3. 为库存监测产品定义功能名分别为“美福记”和“美福佳”的属性,自定义产品标识符,美福记取值范围为0~100,美福佳为 0~100,如下图所示。功能添加完毕后,会自动出现在自定义功能栏下。 4.为库存监测产品添加一个名为 STOCK 的设备,如下图所示,设备添加完毕后,会自动出现在设备列表中。 5.将库存监测产品导入“我的智能云家庭管理”项目中,如下图所示: 6.创建移动应用开发APP: 选中左侧导航栏的移动应用开发在右侧单击打开“新增可视化应用”,如下图所示: 7.点击自定义页面后的+号,编辑,将“自定义新增页 1”改为库存监测,用鼠标将可视化组建下的实时曲线控件拖动到中间的页面上,如下图所示: 8.选中其中一个实时曲线,点击数据->配置数据,在弹出的选项框里选择相应的选项,并点击确定。 9.修改样式,常常保存。 10.配置首页模块。这一步是为了设置一个导航栏,链接到上面设计的“库存监测”。选中[功能]首页模块->列表,如下图所示,选中新增页面入口,在弹出的“页面入口 1”下,完成相应信息的选择,将其链接到刚才设计的“库存监测“页面,如下图所示,点击确定完成配置后,别忘了点击保存。 11.安装包生成。在编辑页面,点击构建,选择 Andriod 构建或 iOS 发构建,如下图所示: 12.手机扫码,APP到手了! 13.我定义的APP~“IoT标签”界面: 以上测试程序合并为最终程序(ARDUINO):[mw_shl_code=cpp,true]#include "Arduino.h" #include <WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> #include "DFRobot_Aliyun.h" #include "DFRobot_DHT11.h" #include "DFRobot_IL0376F_SPI.h" ///////////////////////////////////////////// DFRobot_IL0376F_SPI epaper; #define DHT11_PIN D2 //定义传感器引脚,用于收集数据模拟库存数据 #define EPAPER_CS D3 //定义电子墨水屏相关 #define Font_CS D6 #define EPAPER_DC D8 #define EPAPER_BUSY D7 ////////////////////////////////////////////// /*配置WIFI名和密码*/ const char * WIFI_SSID = "XXXXXXX"; const char * WIFI_PASSWORD = "XXXXXXXXXX"; /*配置设备证书信息*/ String ProductKey = "XXXXXXXXXXX"; String ClientId = "12345"; String DeviceName = "STOCK"; String DeviceSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; /*配置域名和端口号*/ String ALIYUN_SERVER = "iot-as-mqtt.cn-shanghai.aliyuncs.com"; uint16_t PORT = 1883; /*需要操作的产品标识符(温度和湿度两个标识符)*/ String TempIdentifier = "meifuji"; String HumiIdentifier = "meifujia"; /*需要上报和订阅的两个TOPIC*/ const char * subTopic = "/sys/XXXXXXXXXXX/STOCK/thing/service/property/set";//****set const char * pubTopic = "/sys/XXXXXXXXXXX/STOCK/thing/event/property/post";//******post DFRobot_Aliyun myAliyun; WiFiClient espClient; PubSubClient client(espClient); DFRobot_DHT11 DHT; /////////////////////////////////////////////// void connectWiFi(){ Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID,WIFI_PASSWORD); while(WiFi.status() != WL_CONNECTED){ delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.print("IP Adderss: "); Serial.println(WiFi.localIP()); } /////////////////////////////////////////////// void callback(char * topic, byte * payload, unsigned int len){ Serial.print("Recevice ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < len; i++){ Serial.print((char)payload); } Serial.println(); } /////////////////////////////////////////////// void ConnectAliyun(){ while(!client.connected()){ Serial.print("Attempting MQTT connection..."); /*根据自动计算的用户名和密码连接到Alinyun的设备,不需要更改*/ if(client.connect(myAliyun.client_id,myAliyun.username,myAliyun.password)){ Serial.println("connected"); client.subscribe(subTopic); }else{ Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } /////////////////////////////////////////////////// void setup(){ Serial.begin(115200); //Select the corresponding pins epaper.begin(EPAPER_CS, Font_CS, EPAPER_DC, EPAPER_BUSY); /*连接WIFI*/ connectWiFi(); /*初始化Alinyun的配置,可自动计算用户名和密码*/ myAliyun.init(ALIYUN_SERVER,ProductKey,ClientId,DeviceName,DeviceSecret); client.setServer(myAliyun.mqtt_server,PORT); /*设置回调函数,当收到订阅信息时会执行回调函数*/ client.setCallback(callback); /*连接到Aliyun*/ ConnectAliyun(); } ////////////////////////////////////////////////// uint8_t tempTime = 0; uint8_t stock_per = 100; void loop(){ if(!client.connected()){ ConnectAliyun(); } /*上报温湿度(模拟福美记和福美佳两种商品的库存状态数据)信息*/ DHT.read(DHT11_PIN); Serial.print("DHT.temperature= "); Serial.println(DHT.temperature); Serial.print("DHT.humidity= "); Serial.println(DHT.humidity); client.publish(pubTopic,("{\"id\":"+ClientId+",\"params\":{\""+TempIdentifier+"\":"+DHT.temperature+",\""+HumiIdentifier+"\":"+DHT.humidity+"},\"method\":\"thing.event.property.post\"}").c_str()); client.loop(); /*借用DH11传感器的温度数据显示福美记商品的库存状态信息*/ stock_per = DHT.temperature; epaper.fillScreen(WHITE); //Displays a string, black font epaper.disString(1,5, 2,"食",BLACK); epaper.disString(1,45, 2,"品",BLACK); epaper.disString(0,83, 1,"FOOD",BLACK); //Let me draw 2 red dotLines for(uint8_t x=33,y=0; y<103; y+=2) { epaper.drawPixel(x,y,RED); epaper.drawPixel(x+1,y,RED); } epaper.disString(35,1, 1,"品名:",BLACK); epaper.disString(35,18, 1,"Name",BLACK); epaper.disString(35,35, 1,"价格:",BLACK); epaper.disString(35,52, 1,"Price",BLACK); epaper.disString(35,69, 1,"库存:",BLACK); epaper.disString(35,86, 1,"Stock",BLACK); epaper.disString(78,1, 1,"美福记",RED); epaper.disString(78,30, 2,"29.8",RED); epaper.disString(140,45, 1,"¥/Kg",RED); epaper.disString(185,1, 1,"20%",RED); // Draw a down arrow epaper.fillRect(191,18, 12,40,RED); epaper.fillTriangle(184,50, 210,50, 197,70,RED); //Draw a black rectangle(x,y,l,r,c) epaper.drawRoundRect(75,75, 135,23,8,BLACK); epaper.drawRoundRect(76,76, 133,21,8,WHITE); epaper.drawRoundRect(77,77, 131,19,8,WHITE); epaper.fillRoundRect(78,78, 129*stock_per/100,17,7,RED); epaper.disString(185,1, 1,"20%",RED); //Refresh screen display epaper.flush(); delay(12000); }[/mw_shl_code] 运行代码串口显示温度(库存)28: 再看电子墨水屏显示库存(指红色部分约28%): |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed