diff --git a/Software/Software.ino b/Software/Software.ino index 0a139cba..bea32ea4 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -490,6 +490,7 @@ void handle_LED_state() { // BMS in fault state overrides everything if (bms_status == FAULT) { + LEDcolor = RED; pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red LED full brightness } diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index 3573aee2..be806778 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -9,9 +9,9 @@ unsigned long ota_progress_millis = 0; const char index_html[] PROGMEM = R"rawliteral( - Battery Emulator Web Server + Battery Emulator - + -

Battery Emulator Web Server

+

Battery Emulator

%PLACEHOLDER% @@ -93,7 +93,7 @@ void init_WiFi_STA(const char* ssid, const char* password) { } if (WiFi.status() == WL_CONNECTED) { // WL_CONNECTED is assigned when connected to a WiFi network wifi_connected = true; - wifi_state = "connected"; + wifi_state = "Connected"; // Print local IP address and start web server Serial.println(""); Serial.print("Connected to WiFi network: "); @@ -102,7 +102,7 @@ void init_WiFi_STA(const char* ssid, const char* password) { Serial.println(WiFi.localIP()); } else { wifi_connected = false; - wifi_state = "not connected"; + wifi_state = "Not connected"; Serial.print("Not connected to WiFi network: "); Serial.println(ssid); Serial.println("Please check WiFi network name and password, and if WiFi network is available."); @@ -120,6 +120,14 @@ void init_ElegantOTA() { String processor(const String& var) { if (var == "PLACEHOLDER") { String content = ""; + //Page format + content += ""; + + // Start a new block with a specific background color + content += "
"; + // Display LED color content += "

LED color: "; switch (LEDcolor) { @@ -136,17 +144,165 @@ String processor(const String& var) { content += "RED

"; break; case TEST_ALL_COLORS: - content += "RAINBOW"; + content += "RGB Testing loop"; break; default: break; } // Display ssid of network connected to and, if connected to the WiFi, its own IP content += "

SSID: " + String(ssid) + "

"; - content += "

status: " + wifi_state + "

"; + content += "

Wifi status: " + wifi_state + "

"; if (wifi_connected == true) { content += "

IP: " + WiFi.localIP().toString() + "

"; } + // Close the block + content += "
"; + + // Start a new block with a specific background color + content += "
"; + + // Display which components are used + content += "

Inverter protocol: "; +#ifdef BYD_CAN + content += "BYD Battery-Box Premium HVS over CAN Bus"; +#endif +#ifdef BYD_MODBUS + content += "BYD 11kWh HVM battery over Modbus RTU"; +#endif +#ifdef LUNA2000_MODBUS + content += "Luna2000 battery over Modbus RTU"; +#endif +#ifdef PYLON_CAN + content += "Pylontech battery over CAN bus"; +#endif +#ifdef SMA_CAN + content += "BYD Battery-Box H 8.9kWh, 7 mod over CAN bus"; +#endif +#ifdef SOFAR_CAN + content += "Sofar Energy Storage Inverter High Voltage BMS General Protocol (Extended Frame) over CAN bus"; +#endif +#ifdef SOLAX_CAN + content += "SolaX Triple Power LFP over CAN bus"; +#endif + content += "

"; + + content += "

Battery protocol: "; +#ifdef BMW_I3_BATTERY + content += "BMW i3"; +#endif +#ifdef CHADEMO_BATTERY + content += "Chademo V2X mode"; +#endif +#ifdef IMIEV_CZERO_ION_BATTERY + content += "I-Miev / C-Zero / Ion Triplet"; +#endif +#ifdef KIA_HYUNDAI_64_BATTERY + content += "Kia/Hyundai 64kWh"; +#endif +#ifdef NISSAN_LEAF_BATTERY + content += "Nissan LEAF"; +#endif +#ifdef RENAULT_ZOE_BATTERY + content += "Renault Zoe / Kangoo"; +#endif +#ifdef TESLA_MODEL_3_BATTERY + content += "Tesla Model S/3/X/Y"; +#endif +#ifdef TEST_FAKE_BATTERY + content += "Fake battery for testing purposes"; +#endif + content += "

"; + // Close the block + content += "
"; + + // Start a new block with a specific background color. Color changes depending on BMS status + switch (LEDcolor) { + case GREEN: + content += "
"; + break; + case YELLOW: + content += "
"; + break; + case BLUE: + content += "
"; + break; + case RED: + content += "
"; + break; + case TEST_ALL_COLORS: //Blue in test mode + content += "
"; + break; + default: //Some new color, make background green + content += "
"; + break; + } + + // Display battery statistics within this block + float socFloat = static_cast(SOC) / 100.0; // Convert to float and divide by 100 + float sohFloat = static_cast(StateOfHealth) / 100.0; // Convert to float and divide by 100 + float voltageFloat = static_cast(battery_voltage) / 10.0; // Convert to float and divide by 10 + float currentFloat = 0; + if (battery_current > 32767) { //Handle negative values on this unsigned value + currentFloat = static_cast(-(65535 - battery_current)) / 10.0; // Convert to float and divide by 10 + } else { + currentFloat = static_cast(battery_current) / 10.0; // Convert to float and divide by 10 + } + float powerFloat = 0; + if (stat_batt_power > 32767) { //Handle negative values on this unsigned value + powerFloat = static_cast(-(65535 - stat_batt_power)); + } else { + powerFloat = static_cast(stat_batt_power); + } + float tempMaxFloat = 0; + float tempMinFloat = 0; + if (temperature_max > 32767) { //Handle negative values on this unsigned value + tempMaxFloat = static_cast(-(65535 - temperature_max)) / 10.0; // Convert to float and divide by 10 + } else { + tempMaxFloat = static_cast(temperature_max) / 10.0; // Convert to float and divide by 10 + } + if (temperature_min > 32767) { //Handle negative values on this unsigned value + tempMinFloat = static_cast(-(65535 - temperature_min)) / 10.0; // Convert to float and divide by 10 + } else { + tempMinFloat = static_cast(temperature_min) / 10.0; // Convert to float and divide by 10 + } + content += "

SOC: " + String(socFloat, 2) + "

"; + content += "

SOH: " + String(sohFloat, 2) + "

"; + content += "

Voltage: " + String(voltageFloat, 1) + " V

"; + content += "

Current: " + String(currentFloat, 1) + " A

"; + content += "

Power: " + String(powerFloat, 0) + " W

"; + content += "

Total capacity: " + String(capacity_Wh) + " Wh

"; + content += "

Remaining capacity: " + String(remaining_capacity_Wh) + " Wh

"; + content += "

Max discharge power: " + String(max_target_discharge_power) + " W

"; + content += "

Max charge power: " + String(max_target_charge_power) + " W

"; + content += "

Cell max: " + String(cell_max_voltage) + " mV

"; + content += "

Cell min: " + String(cell_min_voltage) + " mV

"; + content += "

Temperature max: " + String(tempMaxFloat, 1) + " C

"; + content += "

Temperature min: " + String(tempMinFloat, 1) + " C

"; + if (bms_status == 3) { + content += "

BMS Status: OK

"; + } else { + content += "

BMS Status: FAULT

"; + } + if (bms_char_dis_status == 2) { + content += "

Battery charging!

"; + } else if (bms_char_dis_status == 1) { + content += "

Battery discharging!

"; + } else { //0 idle + content += "

Battery idle

"; + } + // Close the block + content += "
"; + + content += ""; + content += ""; + + //Script for refreshing page + content += ""; + return content; } return String(); diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index f599cea9..e5e736d4 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -9,7 +9,25 @@ #include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h" #include "../config.h" // Needed for LED defines -extern uint8_t LEDcolor; // Enum, 0-10 +extern uint16_t SOC; //SOC%, 0-100.00 (0-10000) +extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000) +extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000) +extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485) +extern uint16_t capacity_Wh; //Wh, 0-60000 +extern uint16_t remaining_capacity_Wh; //Wh, 0-60000 +extern uint16_t max_target_discharge_power; //W, 0-60000 +extern uint16_t max_target_charge_power; //W, 0-60000 +extern uint16_t bms_status; //Enum, 0-5 +extern uint16_t bms_char_dis_status; //Enum, 0-2 +extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530) +extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) +extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385) +extern uint16_t cell_max_voltage; //mV, 0-4350 +extern uint16_t cell_min_voltage; //mV, 0-4350 +extern uint8_t LEDcolor; //Enum, 0-10 +extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false +extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false + extern const char* ssid; extern const char* password; extern const char* ssidAP;