前言
- 初步功能已经实现
- arduino ide编程效率不高,代码长点就麻烦,所以改用vscode了,配置很简单,在arduino ide正常使用的情况下安装vscode的arduino插件,设置目录即可
- vscode显示串口信息不支持中文,所以print的字符串都改成英文了,反正也都是些小学英语
- 本次更新后已经可以测试使用了,细节问题需要在使用中发现修改,俗称debug
运行逻辑
- esp8266设定距离阈值,发生改变时上传数据给thingsboard,数据包含距离,总时长,单次时长,休息时长
- thingsboard收到报文后判断周末9:30 – 21:30期间,可以使用4小时,单次最长1小时,必须休息10分钟
- thingsboard发反馈报文给esp8266,红灯表示当天不可以使用,蓝灯表示必须休息,绿灯表示可以使用,无人时灯灭
- esp8266接收到反馈报文后执行点灯,并且根据状态统计总时长,单次时长,休息时长
TB规则链
- 判断是否周末
1 2 3 4 5 6 |
var now = new Date(); var day = now.getDay(); var weeks = new Array(7, 1, 2, 3, 4, 5, 6); var week = weeks[day]; return week > 5; |
- 判断时间段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var myDate = new Date(); var h = myDate.getHours(); var m = myDate.getMinutes(); var result = true; if (h > 8 && h < 22){ if (h == 9 && m < 30){ result = false; }else if (h == 21 && m > 30){ result = false; }else{ result = true; } }else{ result = false; } return result; |
已知问题
- 清洗无效数据的逻辑有点绕,代码写得有点狂野,不是很友好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
if (lastDistance > THD && distance < THD) <em>// 检测到人</em> { while (devTime < 5000) <em>// 5秒内数据稳定</em> { delay(500); <em>// 等待200毫秒</em> devTime += 500; ranging(); if (distance > THD) { <em>// 距离数据改变则不上报</em> goto COUNT; } } tbPublish(); <em>// 上报数据 </em> }else if(lastDistance < THD && distance > THD) <em>// 离开</em> { while (devTime < 5000) <em>// 5秒内数据稳定</em> { delay(500); <em>// 等待200毫秒</em> devTime += 500; ranging(); if (distance < THD) { <em>// 距离数据改变则不上报</em> goto COUNT; } } tbPublish(); <em>// 上报数据 </em> } |
- 统计时间的代码if嵌套多了点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
COUNT: <em>// 统计时长</em> if (g_val == 1024){ onceTime = millis() - beginTime + shortTime; if ((onceTime > 3600000) || (playTime+onceTime > 14400000)) { <em>// 单次1或总长4超时</em> playTime += onceTime; <em>// 总时长</em> restTime = 0; <em>// 清空休息时间</em> tbPublish(); <em>// 上报数据</em> } }else if (b_val == 1024) { restTime = millis() - restBegin; if (restTime > 600000){ <em>// 休息10分钟</em> tbPublish(); <em>// 上报数据</em> } } |
ESP8266完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> <em>// 设置wifi信息</em> const char* ssid = "g*****"; const char* password = "******"; const char* mqttServer = "www.weishadian.com"; <em>// 建立wifi和mqtt对象</em> WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); const char* client_ID = "any20211128145527"; <em>// id可以任意</em> const char* mqttUserName = "QidR*******vQMW"; <em>// 设备令牌,token</em> const char* mqttPassword = ""; <em>// 密码为空</em> char dataTemplate[] = "{\"distance\": %.2f, \"onceTime\": %d, \"playTime\": %d, \"restTime\": %d}"; <em>// 简单信息模板</em> char attrData[] = "{\"deviceName\": \"boyPC\"}"; <em>// 简单信息模板</em> char postData[100]; <em>// 报文</em> <em>// 主题</em> char topic[] = "v1/devices/me/telemetry"; <em>// 发布遥测数据的主题</em> char rpcTopic[] = "v1/devices/me/rpc/request/+"; <em>// rpc主题</em> <em>// 超声波引脚</em> #define trigPin D1 #define echoPin D2 <em>// rgb灯引脚</em> #define r D5 #define g D6 #define b D7 <em>// 声明时间和距离的变量</em> float duration; float distance; float lastDistance = 0; <em>// 记录时间</em> int beginTime = 0; <em>// 开始时间</em> int shortTime = 0; <em>// 中途离开时间</em> int restBegin = 0; <em>// 开始休息</em> int playTime = 0; <em>// 总时长</em> int onceTime = 0; <em>// 单次时长</em> int restTime = 9999999; <em>// 休息时长</em> <em>// 状态</em> int r_val = 0; int g_val = 0; int b_val = 0; <em>// 距离阈值</em> unsigned int THD = 60; <em>// 60cm</em> unsigned int devTime; <em>// 误差检测时长</em> DynamicJsonDocument doc(200); <em>// 服务器报文存储</em> void setup(){ pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(r, OUTPUT); pinMode(g, OUTPUT); pinMode(b, OUTPUT); Serial.begin(9600); wifiAndMqtt(); } void loop(){ <em>// 检查MQTT连接状态</em> if (!mqttClient.connected()) { WiFi.disconnect(); <em>// 断开wifi</em> Serial.println("Disconnect,Reconnect after 5 seconds..."); delay(5000); wifiAndMqtt(); Serial.println("Reconnect successfully!"); } <em>// 处理信息以及心跳</em> mqttClient.loop(); ranging(); <em>// 测距</em> devTime = 0; if (lastDistance > THD && distance < THD) <em>// 检测到人</em> { while (devTime < 5000) <em>// 5秒内数据稳定</em> { delay(500); <em>// 等待200毫秒</em> devTime += 500; ranging(); if (distance > THD) { <em>// 距离数据改变则不上报</em> goto COUNT; } } tbPublish(); <em>// 上报数据 </em> }else if(lastDistance < THD && distance > THD) <em>// 离开</em> { while (devTime < 5000) <em>// 5秒内数据稳定</em> { delay(500); <em>// 等待200毫秒</em> devTime += 500; ranging(); if (distance < THD) { <em>// 距离数据改变则不上报</em> goto COUNT; } } tbPublish(); <em>// 上报数据 </em> } COUNT: <em>// 统计时长</em> if (g_val == 1024){ onceTime = millis() - beginTime + shortTime; if ((onceTime > 3600000) || (playTime+onceTime > 14400000)) { <em>// 单次1或总长4超时</em> playTime += onceTime; <em>// 总时长</em> restTime = 0; <em>// 清空休息时间</em> tbPublish(); <em>// 上报数据</em> } }else if (b_val == 1024) { restTime = millis() - restBegin; if (restTime > 600000){ <em>// 休息10分钟</em> tbPublish(); <em>// 上报数据</em> } } delay(1000); } <em>// 超声波测距函数</em> void ranging(){ <em>// 这里不需要返回值,因为使用的都是全局变量</em> <em>// 清除trig的任务,防止trig处于高电平状态</em> digitalWrite(trigPin, LOW); delayMicroseconds(2); <em>// 拉高trig发射一个持续10微秒的超声波</em> digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); <em>// 读取echo的检测HIGH脉冲信号,返回持续时间,单位是微秒</em> duration = pulseIn(echoPin, HIGH); <em>// 计算距离,设置声速为0.034262 cm/s</em> distance= duration*0.034262/2.0; Serial.println(distance); } <em>// 收到信息后的回调函数</em> void receiveCallback(char* topic, byte* payload, unsigned int length) { Serial.print("Topic: ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(""); Serial.print("Top Size(Bytes) "); Serial.println(length); <em>// 反序列化报文</em> deserializeJson(doc, payload); r_val = doc["params"]["D5"].as<int>(); g_val = doc["params"]["D6"].as<int>(); b_val = doc["params"]["D7"].as<int>(); if (g_val == 1024){ <em>// 开始使用</em> beginTime = millis(); <em>// 开始计时</em> restBegin = 0; <em>// 清空开始休息计时</em> }else if (b_val == 1024 && restTime == 0) { restBegin = millis(); <em>// 开始休息计时</em> onceTime = 0; <em>// 清空单次时长</em> }else if((r_val + g_val + b_val) == 0 && onceTime > 0){ <em>// 离开停止计时</em> shortTime += millis() - beginTime; } analogWrite(r, r_val); analogWrite(g, g_val); analogWrite(b, b_val); } <em>// wifi和mqtt连接</em> void wifiAndMqtt(){ <em>//设置为无线终端模式</em> WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); <em>// 连接WiFi</em> <em>//等待WiFi连接,成功连接后输出成功信息</em> while (WiFi.status() != WL_CONNECTED) { delay(1000); } <em>// 设置MQTT服务器和端口号</em> mqttClient.setServer(mqttServer, 1883); <em>// 明文模式</em> mqttClient.setCallback(receiveCallback); <em>// 收到报文的回调函数</em> mqttClient.connect(client_ID, mqttUserName, mqttPassword); <em>// 连接mqtt服务器</em> while (!mqttClient.connected()){ delay(1000); } <em>// mqttClient.subscribe(attrResponse, 0); // 订阅主题</em> mqttClient.subscribe(rpcTopic, 0); <em>// 订阅主题</em> } <em>// 发送报文</em> void tbPublish(){ lastDistance = distance; snprintf(postData, 100, dataTemplate, distance, onceTime, playTime, restTime); <em>// 格式化报文</em> Serial.print("Up Data:"); Serial.println(postData); Serial.println(distance); mqttClient.publish(topic, (uint8_t *)postData, strlen(postData)); Serial.println("-------------"); } |
近期评论