Loading... 这里操作的是太阳能mppt控制板 型号是:太阳宣言 支持Rs485对设备数据进行读取以及设置   ## 注意事项 其他设备连接esp8266时,其他设备转出来的rx和tx需要对接到esp8266上的D1和D2接口 不能对接到esp8266的tx和rx,否则烧录失败 ## 实现功能 读取到数据之后,通过连接wifi对局域网接口发送数据,无需有线连接设备读取,后面将继续实现对接ai,全权掌控所有设备数据,整理和监控 ## 实现代码 ```c #include <Arduino.h> #include <ModbusMaster.h> #include <SoftwareSerial.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> // ---------- WiFi 配置 ---------- const char* WIFI_SSID = "*****";// 账号 const char* WIFI_PASS = "******";// 密码 const char* SERVER_URL = "http://192.168.66.21:5000/data"; // ---------- RS485 软件串口和 DE/RE 控制 ---------- #define RS485_RX_PIN 4 // D2 #define RS485_TX_PIN 5 // D1 #define RS485_DE_RE 2 // D4,DE/RE控制 SoftwareSerial rs485Serial(RS485_RX_PIN, RS485_TX_PIN); // RX, TX ModbusMaster node; void preTransmission() { digitalWrite(RS485_DE_RE, HIGH); } // 发送 void postTransmission() { digitalWrite(RS485_DE_RE, LOW); } // 接收 // ---------- 通用解析函数 ---------- int parseControllerTemp(uint16_t regValue) { uint8_t high_byte = (regValue >> 8) & 0xFF; int sign = (high_byte & 0x80) ? -1 : 1; return sign * (high_byte & 0x7F); } // ---------- 读取寄存器封装 ---------- uint16_t readRegister16(uint16_t addr) { if (node.readHoldingRegisters(addr, 1) == node.ku8MBSuccess) { return node.getResponseBuffer(0); } return 0xFFFF; // 错误返回 } // ---------- Arduino setup ---------- void setup() { pinMode(RS485_DE_RE, OUTPUT); digitalWrite(RS485_DE_RE, LOW); // 默认接收 Serial.begin(115200); rs485Serial.begin(9600); node.begin(1, rs485Serial); // 从机ID 1 node.preTransmission(preTransmission); node.postTransmission(postTransmission); Serial.println("BM控制器开始读取..."); // WiFi 连接 WiFi.begin(WIFI_SSID, WIFI_PASS); Serial.print("正在连接WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi 已连接!"); Serial.print("IP 地址: "); Serial.println(WiFi.localIP()); } // ---------- Arduino loop ---------- void loop() { // ---------- 基本信息 ---------- uint16_t soc = readRegister16(0x0100); uint16_t voltage = readRegister16(0x0101); uint16_t charge_current = readRegister16(0x0102); uint16_t discharge_raw = readRegister16(0x0103); int controller_temp = 0, battery_temp = 0; float discharge_current = 0; if (discharge_raw != 0xFFFF) { uint8_t high_byte = (discharge_raw >> 8) & 0xFF; uint8_t low_byte = discharge_raw & 0xFF; controller_temp = (high_byte & 0x80 ? -1 : 1) * (high_byte & 0x7F); battery_temp = low_byte; discharge_current = discharge_raw / 100.0; } uint16_t pv_v = readRegister16(0x0107); uint16_t pv_a = readRegister16(0x0108); uint16_t pv_w = readRegister16(0x0109); uint16_t load_v = readRegister16(0x0104); uint16_t load_a = readRegister16(0x0105); uint16_t load_w = readRegister16(0x0106); // 打印到串口 Serial.printf("SOC: %d %%, 电池电压: %.1f V, 充电电流: %.2f A\n", soc & 0xFF, voltage/10.0, charge_current/100.0); Serial.printf("放电电流: %.2f A, 控制器温度: %d ℃, 电池温度: %d ℃\n", discharge_current, controller_temp, battery_temp); Serial.printf("光伏: %.1f V, %.2f A, %d W | 负载: %.1f V, %.2f A, %d W\n", pv_v/10.0, pv_a/100.0, pv_w, load_v/10.0, load_a/100.0, load_w); // ---------- 上传数据 ---------- if (WiFi.status() == WL_CONNECTED) { WiFiClient client; // ESP8266 需要单独定义 HTTPClient http; http.begin(client, SERVER_URL); // 这里传入 client http.addHeader("Content-Type", "application/json"); String json = "{"; json += "\"soc\":" + String(soc & 0xFF); json += ",\"voltage\":" + String(voltage/10.0); json += ",\"charge_current\":" + String(charge_current/100.0); json += ",\"discharge_current\":" + String(discharge_current); json += ",\"controller_temp\":" + String(controller_temp); json += ",\"battery_temp\":" + String(battery_temp); json += ",\"pv_voltage\":" + String(pv_v/10.0); json += ",\"pv_current\":" + String(pv_a/100.0); json += ",\"pv_power\":" + String(pv_w); json += ",\"load_voltage\":" + String(load_v/10.0); json += ",\"load_current\":" + String(load_a/100.0); json += ",\"load_power\":" + String(load_w); json += "}"; int httpResponseCode = http.POST(json); if (httpResponseCode > 0) { Serial.printf("数据已发送,返回码: %d\n", httpResponseCode); } else { Serial.printf("发送失败,错误: %s\n", http.errorToString(httpResponseCode).c_str()); } http.end(); } else { Serial.println("WiFi 未连接,无法上传"); } Serial.println("-----------------------------"); delay(5000); // 5秒上传一次 } ``` ## 打印结果 ```sh ----------------------------- SOC: 0 %, 电池电压: 12.8 V, 充电电流: 0.00 A 放电电流: 80.84 A, 控制器温度: 31 ℃, 电池温度: 148 ℃ 光伏: 2.8 V, 0.00 A, 0 W | 负载: 12.7 V, 0.00 A, 0 W 发送失败,错误: connection failed ----------------------------- ``` ## 后端接口代码 ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/data", methods=["POST"]) def receive_data(): try: data = request.get_json() # 接收 JSON 数据 print("收到的数据:", data) # 这里可以做数据存储,比如写文件、存数据库 with open("received_data.log", "a", encoding="utf-8") as f: f.write(str(data) + "\n") return jsonify({"status": "ok", "message": "数据已接收"}), 200 except Exception as e: return jsonify({"status": "error", "message": str(e)}), 400 if __name__ == "__main__": # 0.0.0.0 表示允许局域网访问,端口随意,比如 5000\ # 使用的时候用电脑的局域网ip或者服务器的公网ip app.run(host="0.0.0.0", port=5000, debug=True) ``` 最后修改:2025 年 09 月 09 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏