// 192.168.178.34 #include # include # include #include // must be defined before Blynk #if defined(ESP8266) #include #include #include #include // #include #elif defined(ESP32) // Board Lolin ESP32 C3 #include #include #include #include #include #include #include #define D5 8 #define D6 6 #endif #include #include #include #include #include #include #include #include #include #include #define MQTT #ifdef MQTT #include #endif /* $ echo -ne "~20004642E00200FD37\r" | hexdump -ve '1/1 "%.2X."' 7E.32.30.30.30.34.36.34.32.45.30.30.32.30.30.46.44.33.37.0D. # Get pack #0 telemetry data (CID2 `0x42`) TX -> "~20004642E00200FD37\r" RX <- "~2000460010960001100CD70CE90CF40CD60CEF0CE50CE10CDC0CE90CF00CE80CEF0CEA0CDA0CDE0CD8060BA60BA00B970BA60BA50BA2FD5C14A0344E0A426803134650004603E8149F0000000000000000DC6C\r" # Get system parameters (CID2 `0x47`) TX -> " RX <- ? # Get protocol version (CID2 `0x4F`) TX -> "~2000464F0000FD9A\r" RX <- ? # Get manufacturer info (CID2 `0x51`) TX -> "~200046510000FDAE\r" RX <- "~20004600C040313130312D5350313520020743414E50726F746F636F6C3A536F666172202020F046\r" # Get management info (pylontech only?) TX -> "~200046920000FDA9\r" RX <- ? # Get module serial number (pylontech only?) TX -> "~200046930000FDA8\r" RX <- ? */ String sendString = "~22014A42E00201FD28\r"; String sendString0 = "~22014A42E00201FD28\r"; String sendString1 = "~22014A510000FDA0\r"; String sendString2 = "~22014A47E00201FD23\r"; String sendString3 = "~20004642E00200FD37\r"; String sendString4 = "~200046470000FDA9\r"; String sendString5 = "~200046510000FDAE\r"; String sendString6 = "~200046920000FDA9\r"; String sendString7 = "~200046930000FDA8\r"; String receiveString = "~22014A00E0C600270D14E6100D0D0D0D0D2A0D0E0D0E0D0F0D0E0D0E0D0E0D0E0D100D0F0D110D0D0D100D0B00BE00AA00B40400B400B400AA00AA000000000064013C8C3C880001000000000000000000230000000000000000000000000000000000000000000000D490"; float cell[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // cell 1 to 16 4 characters each float cell2[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 3 tems 4c, num 2c, 4(num) temps, current 4c, char received[384]; float vmin; float vmax; int diff; float sum; float SOC = -1; StaticJsonDocument<128> doc; #define MQTT_SOC "Josma/SOC" #define MQTT_BAT "Josma/BAT" const char* mqttServerName = "raspberrypi.fritz.box"; char mqtt_server[40] = "192.168.178.37"; //MQTT Broker IP // const char* mqttServerName = "raspi-display.fritz.box"; // char mqtt_server[40] = "192.168.178.42"; //MQTT Broker IP // char mqtt_server[40] = "0.0.0.0"; //MQTT Broker IP char mqtt_port[6] = "1883"; //MQTT Broker port char mqtt_user[20] = "mqtt_user"; //MQTT Broker user 'mqtt_user' char mqtt_pass[20] = "mqtt"; //MQTT Broker password bool mqtt = false; // const char* mqttServerName = "raspi-display.fritz.box"; // char mqtt_server[40] = "192.168.178.42"; //MQTT Broker IP // // char mqtt_server[40] = "0.0.0.0"; //MQTT Broker IP // char mqtt_port[6] = "1883"; //MQTT Broker port // char mqtt_user[20] = "mqtt_user"; //MQTT Broker user 'mqtt_user' // char mqtt_pass[20] = "mymqtt"; //MQTT Broker password // bool mqtt = false; // sw(rx,tx) SoftwareSerial sw(D5, D6); SimpleTimer timer; const char* hostname = "Josma"; const char* ssid = MySsid;// WiFi Credential const char* pass = MyPass; // WiFi Password AsyncWebServer server(80); WiFiClient espClient; #ifdef MQTT MqttClient mqttClient(espClient); #endif IPAddress mqttServerIP; String page = ""; String output = "output"; int counter = 0; float toggle = 0.1; int timerTask = 0; int count = 0; char Version[256]; //--------------------------------------------------------------------------------------------- String makePage() { String color[18] = {"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"}; double min = 4; double max = 2; int maxi = 0; int mini = 15; for (int i = 0; i < 16; i++) { if (cell[i] > 3.65) color[i] = "FFA000"; if (cell[i] < 3.0) color[i] = "FFA000"; if (cell[i] > max) { max = cell[i]; maxi = i;} if (cell[i] < min) { min = cell[i]; mini = i;} } color[maxi] = "fff600"; color[mini] = "00e0ff"; if (cell2[8] > 0) color[16] = "7fff00"; if (cell2[8] < 0) color[16] = "FFA600"; if (diff < 100) color[17] = "7fff00"; else color[17] = "FFA600"; String mqtt_addr = mqttServerIP.toString(); page = ""; page += " "; page += ""; page += ""; page += ""; page += ""; page += ""; page += "
"; page += "

SEPLOS_BMS V2.2 { update }

"; page += "

" + String(Version) + "

"; page += "

 

"; page += "

json . Go Back

"; page += ""; page += "

 

"; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; /* page += ""; page += ""; page += ""; */ page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += ""; page += "
" + String(cell[0], 3) + " V" + String(cell[1], 3) + " V" + String(cell[2], 3) + " V" + String(cell[3], 3) + " V
" + String(cell[4], 3) + " V" + String(cell[5], 3) + " V" + String(cell[6], 3) + " V" + String(cell[7], 3) + " V
" + String(cell[8], 3) + " V" + String(cell[9], 3) + " V" + String(cell[10], 3) + " V" + String(cell[11], 3) + " V
" + String(cell[12], 3) + " V" + String(cell[13], 3) + " V" + String(cell[14], 3) + " V" + String(cell[15], 3) + " V
" + String(cell2[0]) + " °C" + String(cell2[1]) + " °C" + String(cell2[2]) + " °C
" + String(cell2[0]) + " °C2 °C3 °C
V min" + String(vmin, 3) + " V
V max" + String(vmax, 3) + " V
V diff" + String(diff) + " mV
voltage" + String(sum) + " V
current" + String(cell2[8]) + " A
power" + String(cell2[8] * sum) + " W
capacity" + String(cell2[13]) + " Ah
max capacity" + String(cell2[12]) + " Ah
SOC" + String(SOC) + " %
loadcycles" + String(cell2[14]) + "
"; page += "

 

"; // page += output; // page += ""; if (mqtt) page += "

mqtt broker is " + String(mqtt_addr) + "

"; page += ""; page += "
"; page += "
"; return page; } //----------------------------------------------------------------------------------------------- void write_Seplos() { if (count > 0) count = 0; if (count == 0) sendString = sendString0; if (count == 1) sendString = sendString1; if (count == 2) sendString = sendString2; if (count == 3) sendString = sendString3; if (count == 4) sendString = sendString4; if (count == 5) sendString = sendString5; if (count == 6) sendString = sendString6; if (count == 7) sendString = sendString7; count++; sw.println(sendString); Serial.println(sendString); } //----------------------------------------------------------------------------------------------- void read_Seplos() { int i = 0; Serial.println("start reading"); while (sw.available()) { char x = sw.read(); if (i > 0) received[i++] = x; if (x == '~') received[i++] = x; // start when x == '~' Serial.print(x); delay(1); } if (i > 0) toggle = 1; else toggle = 0.1; received[i] = 0; Serial.println(); Serial.print("len: "); Serial.println(i); output = String(count); output += sendString; output += " Bytes read: "; output += String(i); output += "\n"; output += String(received); output += "\n"; if (count != 1) return; // int size = 4; if (i > 25 + 2 + 64) { for (int k = 0, j = 25; k < 16; j += size, k++) { char num[5]; for (int i = 0; i < size; i++) { num[i] = received[i + j]; } num[size] = 0; cell[k] = (float)strtol(num, NULL, 16) / 1000; output += String(cell[k]); output += String("\n"); Serial.println(num); Serial.println(cell[k]); } } // output += String(&(received[25 + 2 + 64 + 34])); output += "\n"; for (int k = 0, j = 25 + 64; k < 18; j += size, k++) { char num[5]; size = 4; if (k == 3)size = 2; if (k == 11)size = 2; for (int i = 0; i < size; i++) { num[i] = received[i + j]; } num[size] = 0; float f = 1000; if (k == 0)f = 10; if (k == 1)f = 10; if (k == 2)f = 10; if (k == 3)f = 1; // 2character, num of temp cells (4) if (k == 4)f = 10; if (k == 5)f = 10; if (k == 6)f = 10; if (k == 7)f = 10; if (k == 8)f = 100; // current if (k == 9)f = 10; if (k == 10)f = 10; if (k == 11)f = 10; if (k == 12)f = 100; // max capacity if (k == 13)f = 100; // current capacity if (k == 14)f = 1; // load cycles? if (k == 15)f = 1; cell2[k] = (float)strtol(num, NULL, 16) / f; if (k == 8 && cell2[k] > 327.67) cell2[k] -= 655.36; output += String(cell2[k]) + " " + String(num); output += String("\n"); Serial.println(num); Serial.println(cell2[k]); } vmin = cell[0]; vmax = cell[0]; sum = cell[0]; for (i = 1; i < 16; i++) { if (vmin > cell[i]) vmin = cell[i]; if (vmax < cell[i]) vmax = cell[i]; sum += cell[i]; } diff = round(1000 * (vmax - vmin)); output += String(vmin, 3) + " " + String(vmax, 3); output += String("\n"); #ifdef MQTT if (cell2[12] > 0) { if (SOC != 100 * cell2[13] / cell2[12]) { SOC = 100 * cell2[13] / cell2[12]; update_mqtt(); } } #endif doc["U"] = sum; doc["CAP"] = cell2[13]; doc["SOC"] = SOC; } #ifdef MQTT //--------------------------------------------------------------------------------------------- void update_mqtt() { if (!mqttClient.connected()) mqttClient.connect(mqtt_server, atoi(mqtt_port)); //if not connected to mqtt broker delay(10); if (mqttClient.connected()) { //if connected, publish data mqttClient.beginMessage(MQTT_SOC); mqttClient.print(SOC); mqttClient.endMessage(); mqttClient.beginMessage(MQTT_BAT); mqttClient.print(sum); mqttClient.endMessage(); } else { mqtt = initMqtt(); } } //--------------------------------------------------------------------------------------------- bool initMqtt() { //MQTT init WiFi.hostByName(mqttServerName, mqttServerIP); Serial.println(mqttServerIP); String s = mqttServerIP.toString(); if (s.length() > 10) strcpy(mqtt_server, s.c_str()); Serial.println(mqtt_server); mqttClient.setId(hostname); //set mqtt broker/server id if (*mqtt_user != 0) mqttClient.setUsernamePassword(mqtt_user, mqtt_pass); //set mqtt user/password if (*mqtt_server != 0) if (!mqttClient.connect(mqtt_server, atoi(mqtt_port))) { //connect to mqtt server with mqtt port Serial.print("mqtt failed: "); Serial.println(mqttClient.connectError()); return false; } else { Serial.println("mqtt connected"); if (mqttClient.subscribe(MQTT_SOC)) Serial.print("mqtt subscribed to "); Serial.println(MQTT_SOC); if (mqttClient.subscribe(MQTT_BAT)) Serial.print("mqtt subscribed to "); Serial.println(MQTT_BAT); return true; } return false; } #endif //----------------------------------------------------------------------------------------------- void setup() { sprintf (Version, "Version: %s.%s.", __FILE__, __DATE__); Serial.begin(115200); sw.begin(9600); timer.setInterval(1000 * 60 * 1, write_Seplos); WiFi.mode(WIFI_STA); WiFi.setHostname(hostname); // while(!Serial.available()) delay(100); delay(2000); Serial.println(); // addresses += pzem1.searchAddresses(); WiFi.begin(ssid, pass); int counter = 0; while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(1000); counter++; if (counter > 60) ESP.restart(); } Serial.print("IP Address : "); Serial.println(WiFi.localIP()); server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { makePage(); request->send(200, "text/html", page); if (timerTask == 0) // timerTask = timer.setTimeout(100, write_Seplos); write_Seplos(); }); server.on("/json", HTTP_GET, [](AsyncWebServerRequest * request) { write_Seplos(); String htmlBuffer = " "; htmlBuffer += ""; String jsonBuffer; read_Seplos(); serializeJsonPretty(doc, jsonBuffer); htmlBuffer += jsonBuffer; htmlBuffer += ""; request->send(200, "text/html", jsonBuffer); // request->send(200, "text/html", htmlBuffer); }); server.begin(); AsyncElegantOTA.setID(hostname); AsyncElegantOTA.begin(&server, hostname, hostname); // Start ElegantOTA mqtt = initMqtt(); } //----------------------------------------------------------------------------------------------- void loop() { timer.run(); if (sw.available()) { read_Seplos(); // timerTask = 0; } } /* // welcome message Serial.println("SimpleTimer Example"); Serial.println("One timer is triggered every 15 seconds"); Serial.println("Another timer is set to trigger only once after 10 seconds"); Serial.println("Another timer is set to trigger 10 times"); Serial.println(); // timed actions setup timer.setInterval(15000, RepeatTask); timer.setTimeout(10000, OnceOnlyTask); timer.setInterval(1000, DigitalClockDisplay); timer.setTimer(1200, TenTimesTask, 10); */