diff --git a/README.md b/README.md index e18215ba..ff16d934 100644 --- a/README.md +++ b/README.md @@ -33,52 +33,18 @@ At the same time, EV manufacturers have been putting high capacity battery packs For examples showing wiring, see each battery type's own Wiki page. For instance the [Nissan LEAF page](https://github.com/dalathegreat/Battery-Emulator/wiki/Battery:-Nissan-LEAF---e%E2%80%90NV200) -## How to compile the software 💻 +## How to install the software 💻 Start by watching this [quickstart guide](https://www.youtube.com/watch?v=hcl2GdHc0Y0) [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/hcl2GdHc0Y0/0.jpg)](https://www.youtube.com/watch?v=hcl2GdHc0Y0) -1. Download the Arduino IDE: https://www.arduino.cc/en/software -2. Open the Arduino IDE. -3. Click `File` menu -> `Preferences` -> `Additional Development` -> `Additional Board Manager URLs` -> Enter the URL in the input box: `https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json` and click OK. -4. Click `Tools` menu -> `Board: "...."` -> `Boards Manager...`, install the `esp32` package by `Espressif Systems` (not `Arduino ESP32 Boards`), then press `Close`. - -**NOTE: The ESP32 version depends on which release of Battery-Emulator you are running! See the [Release Notes](https://github.com/dalathegreat/Battery-Emulator/releases) for more info on which version to use with the current version (Suggested ESP32 version X.Y.Z)** - -![bild](https://github.com/dalathegreat/Battery-Emulator/assets/26695010/6a2414b1-f2ca-4746-8e8d-9afd78bd9252) - -5. The Arduino board should be set to `ESP32 Dev Module` and `Partition Scheme` to `Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)` (under `Tools` -> `Board` -> `ESP32 Arduino`) with the following settings: - -![ArduinoSettings](https://github.com/user-attachments/assets/74d36b07-cca4-4bf1-9eaf-1e7fa4e1effe) - -6. Select which battery type you will use, along with other optional settings. This is done in the `USER_SETTINGS.h` file. -7. Copy the `USER_SECRETS.TEMPLATE.h` file to `USER_SECRETS.h` and update connectivity settings inside this file. -8. Press `Verify` and `Upload` to send the sketch to the board. -NOTE: In some cases, the LilyGo must be powered through the main power connector instead of USB-C - when performing the initial firmware upload. -NOTE: On Mac, the following USB driver may need to be installed: https://github.com/WCHSoftGroup/ch34xser_macos - -NOTE: If you see garbled messages on the serial console, change the serial console to match the baud rate to the code, currently 115200. - -NOTE: If you see the error `Sketch too big` then check you set the Partition Scheme above correctly. - -This video explains all the above mentioned steps: - - - -### Linux Development Environment Setup -In addition to the steps above, ESP32 requires a dependency for a Python module, pyserial install using the cli.\ -```python3 -m pip install pyserial``` - -If you're using Ubuntu , use apt to manage the dependencies of arduino:\ -pyserial install: ```sudo apt install python3-serial``` - -Arduino AppImage must be set as executable after downloading to run correctly\ -example: ```chmod 775 arduino-ide_2.3.3_Linux_64bit.AppImage``` - -Also you might need to install FUSE to run appimages -```sudo apt install libfuse2``` +1. Open the [webinstaller page](https://dalathegreat.github.io/BE-Web-Installer/) +2. Follow the instructions on that page to install the software +3. After successful installation, connect to the wireless network (Battery-Emulator , password: 123456789) +4. Go to setup page and configure component selection +5. (OPTIONAL, connect the board to your home Wifi) +6. Connect your battery and inverter to the board and you are done! 🔋⚡ ## Dependencies 📖 This code uses the following excellent libraries: @@ -88,7 +54,7 @@ This code uses the following excellent libraries: - [eModbus/eModbus](https://github.com/eModbus/eModbus) MIT-License - [ESP32Async/AsyncTCP](https://github.com/ESP32Async/AsyncTCP) LGPL-3.0 license - [ESP32Async/ESPAsyncWebServer](https://github.com/ESP32Async/ESPAsyncWebServer) LGPL-3.0 license -- [miwagner/ESP32-Arduino-CAN](https://github.com/miwagner/ESP32-Arduino-CAN/) MIT-License +- [pierremolinaro/acan-esp32](https://github.com/pierremolinaro/acan-esp32) MIT-License - [pierremolinaro/acan2515](https://github.com/pierremolinaro/acan2515) MIT-License - [pierremolinaro/acan2517FD](https://github.com/pierremolinaro/acan2517FD) MIT-License diff --git a/Software/src/battery/BATTERIES.cpp b/Software/src/battery/BATTERIES.cpp index a444ed1a..1c954d13 100644 --- a/Software/src/battery/BATTERIES.cpp +++ b/Software/src/battery/BATTERIES.cpp @@ -296,6 +296,8 @@ bool user_selected_tesla_GTW_rightHandDrive = true; uint16_t user_selected_tesla_GTW_mapRegion = 2; uint16_t user_selected_tesla_GTW_chassisType = 2; uint16_t user_selected_tesla_GTW_packEnergy = 1; +/* User-selected EGMP+others settings */ +bool user_selected_use_estimated_SOC = false; // Use 0V for user selected cell/pack voltage defaults (On boot will be replaced with saved values from NVM) uint16_t user_selected_max_pack_voltage_dV = 0; diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index 0324c189..cb24124e 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -62,7 +62,7 @@ extern uint16_t user_selected_max_pack_voltage_dV; extern uint16_t user_selected_min_pack_voltage_dV; extern uint16_t user_selected_max_cell_voltage_mV; extern uint16_t user_selected_min_cell_voltage_mV; - +extern bool user_selected_use_estimated_SOC; extern bool user_selected_LEAF_interlock_mandatory; extern bool user_selected_tesla_digital_HVIL; extern uint16_t user_selected_tesla_GTW_country; diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.cpp b/Software/src/battery/KIA-E-GMP-BATTERY.cpp index 20f3cd8e..664d4867 100644 --- a/Software/src/battery/KIA-E-GMP-BATTERY.cpp +++ b/Software/src/battery/KIA-E-GMP-BATTERY.cpp @@ -114,16 +114,17 @@ uint8_t KiaEGmpBattery::calculateCRC(CAN_frame rx_frame, uint8_t length, uint8_t void KiaEGmpBattery::update_values() { -#ifdef ESTIMATE_SOC_FROM_CELLVOLTAGE - // Use the simplified pack-based SOC estimation with proper compensation - datalayer.battery.status.real_soc = estimateSOC(batteryVoltage, datalayer.battery.info.number_of_cells, batteryAmps); + if (user_selected_use_estimated_SOC) { + // Use the simplified pack-based SOC estimation with proper compensation + datalayer.battery.status.real_soc = + estimateSOC(batteryVoltage, datalayer.battery.info.number_of_cells, batteryAmps); - // For comparison or fallback, we can still calculate from min/max cell voltages - SOC_estimated_lowest = estimateSOCFromCell(CellVoltMin_mV); - SOC_estimated_highest = estimateSOCFromCell(CellVoltMax_mV); -#else - datalayer.battery.status.real_soc = (SOC_Display * 10); //increase SOC range from 0-100.0 -> 100.00 -#endif + // For comparison or fallback, we can still calculate from min/max cell voltages + SOC_estimated_lowest = estimateSOCFromCell(CellVoltMin_mV); + SOC_estimated_highest = estimateSOCFromCell(CellVoltMax_mV); + } else { + datalayer.battery.status.real_soc = (SOC_Display * 10); //increase SOC range from 0-100.0 -> 100.00 + } datalayer.battery.status.soh_pptt = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00% diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.h b/Software/src/battery/KIA-E-GMP-BATTERY.h index dfd0237c..f28b8529 100644 --- a/Software/src/battery/KIA-E-GMP-BATTERY.h +++ b/Software/src/battery/KIA-E-GMP-BATTERY.h @@ -3,7 +3,7 @@ #include "CanBattery.h" #include "KIA-E-GMP-HTML.h" -#define ESTIMATE_SOC_FROM_CELLVOLTAGE +extern bool user_selected_use_estimated_SOC; class KiaEGmpBattery : public CanBattery { public: diff --git a/Software/src/battery/TESLA-BATTERY.cpp b/Software/src/battery/TESLA-BATTERY.cpp index 42226c9f..ff4208be 100644 --- a/Software/src/battery/TESLA-BATTERY.cpp +++ b/Software/src/battery/TESLA-BATTERY.cpp @@ -976,22 +976,22 @@ void TeslaBattery:: if ((datalayer.system.status.inverter_allows_contactor_closing == true) && (datalayer.battery.status.bms_status != FAULT) && (!datalayer.system.settings.equipment_stop_active)) { // Carry on: 0x221 DRIVE state & reset power down timer - vehicleState = 1; - powerDownTimer = 180; //0x221 50ms cyclic, 20 calls/second + vehicleState = CAR_DRIVE; + powerDownSeconds = 9; } else { // Faulted state, or inverter blocks contactor closing // Shut down: 0x221 ACCESSORY state for 3 seconds, followed by GOING_DOWN, then OFF - if (powerDownTimer <= 180 && powerDownTimer > 120) { - vehicleState = 2; //ACCESSORY - powerDownTimer--; + if (powerDownSeconds <= 9 && powerDownSeconds > 6) { + vehicleState = ACCESSORY; + powerDownSeconds--; } - if (powerDownTimer <= 120 && powerDownTimer > 60) { - vehicleState = 3; //GOING_DOWN - powerDownTimer--; + if (powerDownSeconds <= 6 && powerDownSeconds > 3) { + vehicleState = GOING_DOWN; + powerDownSeconds--; } - if (powerDownTimer <= 60 && powerDownTimer > 0) { - vehicleState = 0; //OFF - powerDownTimer--; + if (powerDownSeconds <= 3 && powerDownSeconds > 0) { + vehicleState = CAR_OFF; + powerDownSeconds--; } } @@ -2059,7 +2059,7 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) { previousMillis50 = currentMillis; //0x221 VCFRONT_LVPowerState - if (vehicleState == 1) { // Drive + if (vehicleState == CAR_DRIVE) { switch (muxNumber_TESLA_221) { case 0: generateMuxFrameCounterChecksum(TESLA_221_DRIVE_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); @@ -2077,7 +2077,7 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) { //Generate next new frame frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; } - if (vehicleState == 2) { // Accessory + if (vehicleState == ACCESSORY) { switch (muxNumber_TESLA_221) { case 0: generateMuxFrameCounterChecksum(TESLA_221_ACCESSORY_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); @@ -2095,7 +2095,7 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) { //Generate next new frame frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; } - if (vehicleState == 3) { // Going down + if (vehicleState == GOING_DOWN) { switch (muxNumber_TESLA_221) { case 0: generateMuxFrameCounterChecksum(TESLA_221_GOING_DOWN_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); @@ -2113,7 +2113,7 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) { //Generate next new frame frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; } - if (vehicleState == 0) { // Off + if (vehicleState == CAR_OFF) { switch (muxNumber_TESLA_221) { case 0: generateMuxFrameCounterChecksum(TESLA_221_OFF_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); diff --git a/Software/src/battery/TESLA-BATTERY.h b/Software/src/battery/TESLA-BATTERY.h index 0bf4037f..91311b52 100644 --- a/Software/src/battery/TESLA-BATTERY.h +++ b/Software/src/battery/TESLA-BATTERY.h @@ -78,7 +78,11 @@ class TeslaBattery : public CanBattery { uint8_t muxNumber_TESLA_221 = 0; uint8_t frameCounter_TESLA_221 = 15; // Start at 15 for Mux 0 uint8_t vehicleState = 1; // "OFF": 0, "DRIVE": 1, "ACCESSORY": 2, "GOING_DOWN": 3 - uint16_t powerDownTimer = 180; // Car power down (i.e. contactor open) tracking timer, 3 seconds per sendingState + static const uint8_t CAR_OFF = 0; + static const uint8_t CAR_DRIVE = 1; + static const uint8_t ACCESSORY = 2; + static const uint8_t GOING_DOWN = 3; + uint8_t powerDownSeconds = 9; // Car power down (i.e. contactor open) tracking timer, 3 seconds per sendingState //0x2E1 VCFRONT_status, 6 mux tracker uint8_t muxNumber_TESLA_2E1 = 0; //0x334 UI diff --git a/Software/src/communication/nvm/comm_nvm.cpp b/Software/src/communication/nvm/comm_nvm.cpp index 58eba5c9..315c9fcc 100644 --- a/Software/src/communication/nvm/comm_nvm.cpp +++ b/Software/src/communication/nvm/comm_nvm.cpp @@ -104,6 +104,7 @@ void init_stored_settings() { user_selected_can_addon_crystal_frequency_mhz = settings.getUInt("CANFREQ", 8); user_selected_canfd_addon_crystal_frequency_mhz = settings.getUInt("CANFDFREQ", 40); user_selected_LEAF_interlock_mandatory = settings.getBool("INTERLOCKREQ", false); + user_selected_use_estimated_SOC = settings.getBool("SOCESTIMATED", false); user_selected_tesla_digital_HVIL = settings.getBool("DIGITALHVIL", false); user_selected_tesla_GTW_country = settings.getUInt("GTWCOUNTRY", 0); user_selected_tesla_GTW_rightHandDrive = settings.getBool("GTWRHD", false); diff --git a/Software/src/devboard/webserver/settings_html.cpp b/Software/src/devboard/webserver/settings_html.cpp index 6c91561c..8184bea4 100644 --- a/Software/src/devboard/webserver/settings_html.cpp +++ b/Software/src/devboard/webserver/settings_html.cpp @@ -251,6 +251,10 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti return settings.getBool("DBLBTR") ? "checked" : ""; } + if (var == "SOCESTIMATED") { + return settings.getBool("SOCESTIMATED") ? "checked" : ""; + } + if (var == "CNTCTRL") { return settings.getBool("CNTCTRL") ? "checked" : ""; } @@ -912,6 +916,11 @@ const char* getCANInterfaceName(CAN_Interface interface) { display: contents; } + form .if-socestimated { display: none; } /* Integrations where you can turn on SOC estimation */ + form[data-battery="16"] .if-socestimated { + display: contents; + } + form .if-dblbtr { display: none; } form[data-dblbtr="true"] .if-dblbtr { display: contents; @@ -1022,6 +1031,11 @@ const char* getCANInterfaceName(CAN_Interface interface) { +
+ + +
+