MES机联网2:采集网关
目录信息
硬件清单
- ESP8266(Wifi模块)
- 降压模块(24V转3V)
- 按键(无锁,自复位)
采集参数
- 时长:IO变化,上报时长
- 产量:IO变化,上报计数
- 节拍:时间差=合格/不合格按键时间-开始按键时间
- 合格:IO变化,合格数+1
- 不合格:IO变化,不合格数+1
接线示意图

支持功能
- 自动联网(程序启动后,查找本地文件存储的wifi账号和密码,如果文件为空,或者wifi连不上则进入入ap模式,在网页界面上输入账户和密码,保存到本地文件并进行连接,连接成功后重启ESP;超时5分钟未连上wifi则重启ESP)
- 自动同步时间、硬件喂狗、OTA固件升级(上电检测/远程升级)
- IO电平监测
- MQClient订阅和发布
开发工具
- Arduino IDE
代码结构

#include <Ticker.h> #include <ESP8266httpUpdate.h> #include "GlobalVar.h" #include "GpioInput.h" #include "WebConfig.h" #include "Common.h" #include "KeyValueStore.h" #include "MQClient.h" #include "JsonGenerator.h" #include <ArduinoJson.h> // 三色灯 GPIOInput RED(RED_PIN, INPUT_PULLUP, 20, 5);// INPUT GPIOInput YELLOW(YELLOW_PIN, INPUT_PULLUP, 20, 5); GPIOInput GREEN(GREEN_PIN, INPUT_PULLUP, 20, 5); // 计数 GPIOInput COUNT(COUNT_PIN, INPUT_PULLUP, 20, 5); // 按键 GPIOInput START(START_PIN, INPUT_PULLUP, 20, 5); GPIOInput PASS(PASS_PIN, INPUT_PULLUP, 20, 5); GPIOInput NG(NG_PIN, INPUT_PULLUP, 20, 5); MQClient mqttClient; Ticker wdtTicker; String WorkshopId_Value; String LineId_Value; String DeviceId_Value; bool First = true; int MCUTYPE = 1000; void setup() { ESP.wdtEnable(8000); // 8秒看门狗 wdtTicker.attach_ms(5000, hardwareWatchdog); // Serial.begin(9600); // 先初始化串口 Serial.println(""); Serial.printf("MCU RUN,Version:%s\n", Version.c_str()); // 再输出信息 SPIFFS.begin(); WebConfig::initWifi(); if (KeyValueStore::exists(MAC)) { // 初始化时间 Common::initTime(); // 获取完整日期时间 String fullDateTime = Common::getCurrentTime(); Serial.println("当前时间: " + fullDateTime); // 输出示例:2023-10-05T08:59:22Z String mac = KeyValueStore::get(MAC); SubTopic.concat(mac); PubTopic.concat(mac); WorkshopId_Value = KeyValueStore::get(WorkshopId); LineId_Value = KeyValueStore::get(LineId); DeviceId_Value = KeyValueStore::get(DeviceId); Serial.printf("MAC:%s,WorkshopId:%s,LineId:%s,DeviceId:%s\n", MAC.c_str(), WorkshopId_Value.c_str(), LineId_Value.c_str(), DeviceId_Value.c_str()); // MQTT初始化 mqttClient.init(KeyValueStore::get(MQServer), KeyValueStore::getLong(MQPort), KeyValueStore::get(MQUid), KeyValueStore::get(MQPwd), SubTopic, PubTopic, "clientid", subCallBack); } } void loop() { WebConfig::checkWifi(); mqttClient.loop(); // 保持MQTT连接 // OTA发送 if (First && WiFi.status() == WL_CONNECTED && mqttClient.isConnected()) { First = false; String ota = JsonGenerator::generateOTA(DeviceId_Value, Version, MCUTYPE); mqttClient.publish(ota.c_str()); } // 检查IO信号 // 三色灯 int red = RED.read(); int yellow = YELLOW.read(); int green = GREEN.read(); if (red == HIGH || yellow == HIGH || green == HIGH) { // LOW HIGH String startstate = KeyValueStore::get("LightChangeState"); if (startstate.equals("")) startstate = "000"; String starttime = KeyValueStore::get("LightChangeTs"); if (starttime.equals("")) starttime = Common::getCurrentTime(); unsigned long t1 = KeyValueStore::getLong("LightChangeTl"); String currenttime = Common::getCurrentTime(); unsigned long t2 = Common::getCurrentTimestamp(); String currentstate = String(digitalRead(RED_PIN)) + String(digitalRead(YELLOW_PIN)) + String(digitalRead(GREEN_PIN)); Serial.printf("Light Change,oldstate:%s,starttime:%s,currenttime:%s,currentstate:%s\n", startstate.c_str(), starttime.c_str(), currenttime.c_str(), currentstate.c_str()); // 状态改变,进行上报 if (!startstate.equals(currentstate)) { unsigned long periodsec = t2 - t1; // 保存 KeyValueStore::set("LightChangeState", currentstate); KeyValueStore::set("LightChangeTs", currenttime); KeyValueStore::setLong("LightChangeTl", t2); // 上报数据 String colorJson = JsonGenerator::generateColorChange( WorkshopId_Value, LineId_Value, DeviceId_Value, currentstate, startstate, starttime, // 开始时间 currenttime, // 结束时间 periodsec // 持续时间秒数 ); mqttClient.publish(colorJson.c_str()); } } // 计数 int count = COUNT.read(); if (count == HIGH) { // LOW HIGH unsigned long lightcount = KeyValueStore::getLong("LightCount"); lightcount = lightcount + 1; Serial.println("Light Count: " + String(lightcount)); // 保存时间戳 KeyValueStore::setLong("LightCount", lightcount); // 上报数据 String countJson = JsonGenerator::generateCount( WorkshopId_Value, LineId_Value, DeviceId_Value, lightcount ); mqttClient.publish(countJson.c_str()); } // 按键 int start = START.read(); int pass = PASS.read(); int ng = NG.read(); // 开始 if (start == HIGH) { // LOW HIGH unsigned long t1 = Common::getCurrentTimestamp(); Serial.println("Light Start: " + String(t1)); KeyValueStore::setLong("LightStartTs", t1); // 保存时间戳 } // 结束 if (pass == HIGH || ng == HIGH) { // LOW HIGH // 产量 unsigned long lightCount = KeyValueStore::getLong("LightCount"); unsigned long passCount = KeyValueStore::getLong("LightPass"); unsigned long ngCount = KeyValueStore::getLong("LightNg"); // 节拍 unsigned long t1 = KeyValueStore::getLong("LightStartTs"); unsigned long t2 = Common::getCurrentTimestamp(); unsigned long pitchTime = t2 - t1; // 合格+1 if (pass == HIGH) { passCount = passCount + 1; KeyValueStore::setLong("LightPass", passCount); } // 不合格+1 if (ng == HIGH) { ngCount = ngCount + 1; KeyValueStore::setLong("LightNg", ngCount); } Serial.printf("Light End,EndTime:%d,StartTime:%d,lightCount:%d,pitchtime:%d,passCount:%d,ngCount:%d\n",t2, t1, lightCount, pitchTime, passCount, ngCount); // 上报数据 String completeJson = JsonGenerator::generateComplete( WorkshopId_Value, LineId_Value, DeviceId_Value, lightCount, pitchTime, passCount, ngCount ); mqttClient.publish(completeJson.c_str()); } } /** * 硬件喂狗 */ void hardwareWatchdog() { ESP.wdtFeed(); } /** * MQ回调函数 */ void subCallBack(char* topic, byte* payload, unsigned int length) { // 转换payload为字符串 payload[length] = '\0'; String message = String((char*)payload); Serial.print("Received ["); Serial.print(topic); Serial.print("]: "); Serial.println(message); // 解析JSON数据 DynamicJsonDocument doc(256); DeserializationError error = deserializeJson(doc, message); if (error) { Serial.print("JSON解析失败: "); Serial.println(error.c_str()); return; } // 处理指令类型 int command = doc["c"]; switch(command) { case 1: // 固件升级指令 if (doc["m"]["errcode"] == 0) { String url = doc["m"]["url"].as<String>(); if (!url.equals("")) { Serial.println("开始固件升级: " + url); updateBin(url); } } break; case 2: // 重启 Serial.println("远程升级,即将重启"); delay(1000); ESP.restart(); break; case 6: // 重置计数器指令 Serial.println("收到重置指令"); KeyValueStore::setLong("LightCount", 0); KeyValueStore::setLong("LightPass", 0); KeyValueStore::setLong("LightNg", 0); break; default: Serial.println("未知指令类型"); break; } } /** * 固件升级函数 */ void updateBin(String upUrl){ // 增加升级前校验 ESPhttpUpdate.rebootOnUpdate(false); // 禁用自动重启 // 增加升级失败重试机制 for(int i=0; i<3; i++){ WiFiClient UpdateClient; t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient, upUrl); switch(ret) { case HTTP_UPDATE_FAILED: Serial.printf("升级失败原因: %s\n", ESPhttpUpdate.getLastErrorString().c_str()); delay(5000); break; case HTTP_UPDATE_NO_UPDATES: Serial.println("无可用更新"); return; case HTTP_UPDATE_OK: Serial.println("升级成功,即将重启"); delay(1000); ESP.restart(); return; } } }
qq:505645074

浙公网安备 33010602011771号