mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Merge branch 'main' into feature/lilygo_t_2can
This commit is contained in:
commit
c3caad4da7
50 changed files with 363 additions and 858 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -4,6 +4,15 @@
|
|||
# Ignore any files in any build folder
|
||||
*build/
|
||||
|
||||
# Ignore any generated test files from running locally
|
||||
test/CMakeCache.txt
|
||||
test/CMakeFiles/
|
||||
test/CTestTestfile.cmake
|
||||
test/Makefile
|
||||
test/cmake_install.cmake
|
||||
test/gtest/
|
||||
test/tests[1]_include.cmake
|
||||
|
||||
# Ignore .exe (unit tests)
|
||||
*.exe
|
||||
**/.DS_Store
|
||||
|
|
|
@ -38,3 +38,15 @@ Or force it to check all files with
|
|||
```
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
## Local Unit test run
|
||||
The Unit tests run gtest. Here is how to install this on Debian/Ubuntu and run it locally
|
||||
```
|
||||
sudo apt-get install libgtest-dev
|
||||
sudo apt-get install cmake
|
||||
```
|
||||
Navigate to Battery-Emulator/test folder
|
||||
```
|
||||
sudo cmake CMakeLists.txt
|
||||
sudo make
|
||||
```
|
||||
|
|
|
@ -64,7 +64,7 @@ void setup() {
|
|||
|
||||
init_serial();
|
||||
|
||||
// We print this after setting up serial, such that is also printed to serial with DEBUG_VIA_USB set.
|
||||
// We print this after setting up serial, so that is also printed if configured to do so
|
||||
logging.printf("Battery emulator %s build " __DATE__ " " __TIME__ "\n", version_number);
|
||||
|
||||
init_events();
|
||||
|
@ -80,10 +80,10 @@ void setup() {
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(LOG_CAN_TO_SD) || defined(LOG_TO_SD)
|
||||
if (datalayer.system.info.CAN_SD_logging_active || datalayer.system.info.SD_logging_active) {
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
||||
&logging_loop_task, esp32hal->WIFICORE());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!init_contactors()) {
|
||||
return;
|
||||
|
@ -167,22 +167,21 @@ void setup() {
|
|||
// Loop empty, all functionality runs in tasks
|
||||
void loop() {}
|
||||
|
||||
#if defined(LOG_CAN_TO_SD) || defined(LOG_TO_SD)
|
||||
void logging_loop(void*) {
|
||||
|
||||
init_logging_buffers();
|
||||
init_sdcard();
|
||||
|
||||
while (true) {
|
||||
#ifdef LOG_TO_SD
|
||||
if (datalayer.system.info.SD_logging_active) {
|
||||
write_log_to_sdcard();
|
||||
#endif
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
}
|
||||
|
||||
if (datalayer.system.info.CAN_SD_logging_active) {
|
||||
write_can_frame_to_sdcard();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void connectivity_loop(void*) {
|
||||
esp_task_wdt_add(NULL); // Register this task with WDT
|
||||
|
@ -352,9 +351,6 @@ void init_serial() {
|
|||
// Init Serial monitor
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {}
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("__ OK __");
|
||||
#endif // DEBUG_VIA_USB
|
||||
}
|
||||
|
||||
void check_interconnect_available() {
|
||||
|
|
|
@ -108,12 +108,6 @@
|
|||
//#define EQUIPMENT_STOP_BUTTON // Enable this to allow an equipment stop button connected to the Battery-Emulator to disengage the battery
|
||||
//#define LFP_CHEMISTRY //Tesla specific setting, enable this line to startup in LFP mode
|
||||
//#define INTERLOCK_REQUIRED //Nissan LEAF specific setting, if enabled requires both high voltage conenctors to be seated before starting
|
||||
//#define LOG_TO_SD //Enable this line to log diagnostic data to SD card (WARNING, raises CPU load, do not use for production)
|
||||
//#define LOG_CAN_TO_SD //Enable this line to log incoming/outgoing CAN & CAN-FD messages to SD card (WARNING, raises CPU load, do not use for production)
|
||||
//#define DEBUG_VIA_USB //Enable this line to have the USB port output serial diagnostic data while program runs (WARNING, raises CPU load, do not use for production)
|
||||
//#define DEBUG_VIA_WEB //Enable this line to log diagnostic data while program runs, which can be viewed via webpage (WARNING, slightly raises CPU load, do not use for production)
|
||||
//#define DEBUG_CAN_DATA //Enable this line to print incoming/outgoing CAN & CAN-FD messages to USB serial (WARNING, raises CPU load, do not use for production)
|
||||
|
||||
/* CAN options */
|
||||
//#define CAN_ADDON //Enable this line to activate an isolated secondary CAN Bus using add-on MCP2515 chip (Needed for some inverters / double battery)
|
||||
#define CRYSTAL_FREQUENCY_MHZ 8 //CAN_ADDON option, what is your MCP2515 add-on boards crystal frequency?
|
||||
|
@ -179,14 +173,6 @@
|
|||
//#define MAX_CUSTOM_CELL_VOLTAGE_MV 4250 // 4250 = 4.250V , Maximum cell voltage in millivolts (4250 = 4.250V)
|
||||
//#define MIN_CUSTOM_CELL_VOLTAGE_MV 2650 // 2650 = 2.650V , Minimum cell voltage in millivolts (2650 = 2.650V)
|
||||
|
||||
/* LED settings. Optional customization for how the blinking pattern on the LED should behave.
|
||||
* CLASSIC - Slow up/down ramp. If CLASSIC, then a ramp up and ramp down will finish in LED_PERIOD_MS milliseconds
|
||||
* FLOW - Ramp up/down depending on flow of energy
|
||||
* HEARTBEAT - Heartbeat-like LED pattern that reacts to the system state with color and BPM
|
||||
*/
|
||||
#define LED_MODE CLASSIC
|
||||
#define LED_PERIOD_MS 3000
|
||||
|
||||
/* Do not change any code below this line */
|
||||
/* Only change battery specific settings above and in "USER_SETTINGS.cpp" */
|
||||
typedef struct {
|
||||
|
@ -226,10 +212,6 @@ extern IPAddress gateway;
|
|||
extern IPAddress subnet;
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_VIA_USB) || defined(DEBUG_VIA_WEB) || defined(LOG_TO_SD)
|
||||
#define DEBUG_LOG
|
||||
#endif
|
||||
|
||||
#if defined(MEB_BATTERY)
|
||||
#define PRECHARGE_CONTROL
|
||||
#endif
|
||||
|
|
|
@ -307,9 +307,7 @@ void BmwIXBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
|
||||
if ((rx_frame.data.u8[6] << 8 | rx_frame.data.u8[7]) == 10000 ||
|
||||
(rx_frame.data.u8[8] << 8 | rx_frame.data.u8[9]) == 10000) { //Qualifier Invalid Mode - Request Reboot
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell MinMax Qualifier Invalid - Requesting BMS Reset");
|
||||
#endif // DEBUG_LOG
|
||||
//set_event(EVENT_BATTERY_VALUE_UNAVAILABLE, (millis())); //Eventually need new Info level event type
|
||||
transmit_can_frame(&BMWiX_6F4_REQUEST_HARD_RESET);
|
||||
} else { //Only ingest values if they are not the 10V Error state
|
||||
|
@ -378,15 +376,11 @@ void BmwIXBattery::transmit_can(unsigned long currentMillis) {
|
|||
// Detect edge
|
||||
if (ContactorCloseRequest.previous == false && ContactorCloseRequest.present == true) {
|
||||
// Rising edge detected
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Rising edge detected. Resetting 10ms counter.");
|
||||
#endif // DEBUG_LOG
|
||||
counter_10ms = 0; // reset counter
|
||||
} else if (ContactorCloseRequest.previous == true && ContactorCloseRequest.present == false) {
|
||||
// Dropping edge detected
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Dropping edge detected. Resetting 10ms counter.");
|
||||
#endif // DEBUG_LOG
|
||||
counter_10ms = 0; // reset counter
|
||||
}
|
||||
ContactorCloseRequest.previous = ContactorCloseRequest.present;
|
||||
|
@ -465,12 +459,10 @@ void BmwIXBattery::setup(void) { // Performs one time setup at startup
|
|||
|
||||
void BmwIXBattery::HandleIncomingUserRequest(void) {
|
||||
// Debug user request to open or close the contactors
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("User request: contactor close: ");
|
||||
logging.print(userRequestContactorClose);
|
||||
logging.print(" User request: contactor open: ");
|
||||
logging.println(userRequestContactorOpen);
|
||||
#endif // DEBUG_LOG
|
||||
if ((userRequestContactorClose == false) && (userRequestContactorOpen == false)) {
|
||||
// do nothing
|
||||
} else if ((userRequestContactorClose == true) && (userRequestContactorOpen == false)) {
|
||||
|
@ -488,10 +480,8 @@ void BmwIXBattery::HandleIncomingUserRequest(void) {
|
|||
userRequestContactorClose = false;
|
||||
userRequestContactorOpen = false;
|
||||
// print error, as both these flags shall not be true at the same time
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println(
|
||||
"Error: user requested contactors to close and open at the same time. Contactors have been opened.");
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,15 +490,11 @@ void BmwIXBattery::HandleIncomingInverterRequest(void) {
|
|||
// Detect edge
|
||||
if (InverterContactorCloseRequest.previous == false && InverterContactorCloseRequest.present == true) {
|
||||
// Rising edge detected
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter requests to close contactors");
|
||||
#endif // DEBUG_LOG
|
||||
BmwIxCloseContactors();
|
||||
} else if (InverterContactorCloseRequest.previous == true && InverterContactorCloseRequest.present == false) {
|
||||
// Falling edge detected
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter requests to open contactors");
|
||||
#endif // DEBUG_LOG
|
||||
BmwIxOpenContactors();
|
||||
} // else: do nothing
|
||||
|
||||
|
@ -517,16 +503,12 @@ void BmwIXBattery::HandleIncomingInverterRequest(void) {
|
|||
}
|
||||
|
||||
void BmwIXBattery::BmwIxCloseContactors(void) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Closing contactors");
|
||||
#endif // DEBUG_LOG
|
||||
contactorCloseReq = true;
|
||||
}
|
||||
|
||||
void BmwIXBattery::BmwIxOpenContactors(void) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Opening contactors");
|
||||
#endif // DEBUG_LOG
|
||||
contactorCloseReq = false;
|
||||
counter_100ms = 0; // reset counter, such that keep contactors closed message sequence starts from the beginning
|
||||
}
|
||||
|
@ -552,46 +534,34 @@ void BmwIXBattery::HandleBmwIxCloseContactorsRequest(uint16_t counter_10ms) {
|
|||
if (counter_10ms == 0) {
|
||||
// @0 ms
|
||||
transmit_can_frame(&BMWiX_510);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x510 - 1/6");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_10ms == 5) {
|
||||
// @50 ms
|
||||
transmit_can_frame(&BMWiX_276);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x276 - 2/6");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_10ms == 10) {
|
||||
// @100 ms
|
||||
BMWiX_510.data.u8[2] = 0x04; // TODO: check if needed
|
||||
transmit_can_frame(&BMWiX_510);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x510 - 3/6");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_10ms == 20) {
|
||||
// @200 ms
|
||||
BMWiX_510.data.u8[2] = 0x10; // TODO: check if needed
|
||||
BMWiX_510.data.u8[5] = 0x80; // needed to close contactors
|
||||
transmit_can_frame(&BMWiX_510);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x510 - 4/6");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_10ms == 30) {
|
||||
// @300 ms
|
||||
BMWiX_16E.data.u8[0] = 0x6A;
|
||||
BMWiX_16E.data.u8[1] = 0xAD;
|
||||
transmit_can_frame(&BMWiX_16E);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x16E - 5/6");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_10ms == 50) {
|
||||
// @500 ms
|
||||
BMWiX_16E.data.u8[0] = 0x03;
|
||||
BMWiX_16E.data.u8[1] = 0xA9;
|
||||
transmit_can_frame(&BMWiX_16E);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Transmitted 0x16E - 6/6");
|
||||
#endif // DEBUG_LOG
|
||||
ContactorState.closed = true;
|
||||
ContactorState.open = false;
|
||||
}
|
||||
|
@ -613,9 +583,7 @@ void BmwIXBattery::BmwIxKeepContactorsClosed(uint8_t counter_100ms) {
|
|||
0xC9, 0x3A, 0xF7}; // Explicit declaration, to prevent modification by other functions
|
||||
|
||||
if (counter_100ms == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Sending keep contactors closed messages started");
|
||||
#endif // DEBUG_LOG
|
||||
// @0 ms
|
||||
transmit_can_frame(&BMWiX_510);
|
||||
} else if (counter_100ms == 7) {
|
||||
|
@ -631,9 +599,7 @@ void BmwIXBattery::BmwIxKeepContactorsClosed(uint8_t counter_100ms) {
|
|||
BMWiX_16E.data.u8[0] = 0x02;
|
||||
BMWiX_16E.data.u8[1] = 0xA7;
|
||||
transmit_can_frame(&BMWiX_16E);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Sending keep contactors closed messages finished");
|
||||
#endif // DEBUG_LOG
|
||||
} else if (counter_100ms == 140) {
|
||||
// @14000 ms
|
||||
// reset counter (outside of this function)
|
||||
|
|
|
@ -122,9 +122,7 @@ bool BmwPhevBattery::storeUDSPayload(const uint8_t* payload, uint8_t length) {
|
|||
if (gUDSContext.UDS_bytesReceived + length > sizeof(gUDSContext.UDS_buffer)) {
|
||||
// Overflow => abort
|
||||
gUDSContext.UDS_inProgress = false;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("UDS Payload Overflow");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
memcpy(&gUDSContext.UDS_buffer[gUDSContext.UDS_bytesReceived], payload, length);
|
||||
|
@ -134,9 +132,7 @@ bool BmwPhevBattery::storeUDSPayload(const uint8_t* payload, uint8_t length) {
|
|||
// If we’ve reached or exceeded the expected length, mark complete
|
||||
if (gUDSContext.UDS_bytesReceived >= gUDSContext.UDS_expectedLength) {
|
||||
gUDSContext.UDS_inProgress = false;
|
||||
// #ifdef DEBUG_LOG
|
||||
// logging.println("Recived all expected UDS bytes");
|
||||
// #endif // DEBUG_LOG
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -196,9 +192,7 @@ void BmwPhevBattery::wake_battery_via_canbus() {
|
|||
|
||||
change_can_speed(original_speed);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Sent magic wakeup packet to SME at 100kbps...");
|
||||
#endif
|
||||
}
|
||||
|
||||
void BmwPhevBattery::update_values() { //This function maps all the values fetched via CAN to the battery datalayer
|
||||
|
@ -246,9 +240,7 @@ void BmwPhevBattery::update_values() { //This function maps all the values fetc
|
|||
datalayer.battery.status.cell_min_voltage_mV = 9999; //Stale values force stop
|
||||
datalayer.battery.status.cell_max_voltage_mV = 9999; //Stale values force stop
|
||||
set_event(EVENT_STALE_VALUE, 0);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Stale Min/Max voltage values detected during charge/discharge sending - 9999mV...");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
|
||||
datalayer.battery.status.cell_min_voltage_mV = min_cell_voltage; //Value is alive
|
||||
|
@ -398,11 +390,7 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
rx_frame.data.u8[4] ==
|
||||
0xAD) { //Balancing Status 01 Active 03 Not Active 7DLC F1 05 71 03 AD 6B 01
|
||||
balancing_status = (rx_frame.data.u8[6]);
|
||||
// #ifdef DEBUG_LOG
|
||||
|
||||
//logging.println("Balancing Status received");
|
||||
|
||||
// #endif // DEBUG_LOG
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -525,7 +513,6 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
battery_current = ((int32_t)((gUDSContext.UDS_buffer[3] << 24) | (gUDSContext.UDS_buffer[4] << 16) |
|
||||
(gUDSContext.UDS_buffer[5] << 8) | gUDSContext.UDS_buffer[6])) *
|
||||
0.1;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Received current/amps measurement data: ");
|
||||
logging.print(battery_current);
|
||||
logging.print(" - ");
|
||||
|
@ -538,7 +525,6 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
logging.print(" ");
|
||||
}
|
||||
logging.println(); // new line at the end
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
|
||||
//Cell Min/Max
|
||||
|
@ -553,7 +539,6 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
min_cell_voltage = (gUDSContext.UDS_buffer[9] << 8 | gUDSContext.UDS_buffer[10]) / 10;
|
||||
max_cell_voltage = (gUDSContext.UDS_buffer[11] << 8 | gUDSContext.UDS_buffer[12]) / 10;
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell Min Max Invalid 65535 or 0...");
|
||||
logging.print("Received data: ");
|
||||
for (uint16_t i = 0; i < gUDSContext.UDS_bytesReceived; i++) {
|
||||
|
@ -565,7 +550,6 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
logging.print(" ");
|
||||
}
|
||||
logging.println(); // new line at the end
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,16 +602,12 @@ void BmwPhevBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
if (rx_frame.data.u8[6] > 0 && rx_frame.data.u8[6] < 255) {
|
||||
battery_temperature_min = (rx_frame.data.u8[6] - 50);
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Pre parsed Cell Temp Min is Invalid ");
|
||||
#endif
|
||||
}
|
||||
if (rx_frame.data.u8[7] > 0 && rx_frame.data.u8[7] < 255) {
|
||||
battery_temperature_max = (rx_frame.data.u8[7] - 50);
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Pre parsed Cell Temp Max is Invalid ");
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <Arduino.h>
|
||||
#include "../communication/can/comm_can.h"
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "../devboard/utils/logging.h"
|
||||
|
||||
uint8_t reverse_bits(uint8_t byte) {
|
||||
uint8_t reversed = 0;
|
||||
|
@ -122,9 +123,7 @@ void BmwSbox::transmit_can(unsigned long currentMillis) {
|
|||
SBOX_100.data.u8[0] = 0x86; // Precharge relay only
|
||||
prechargeStartTime = currentMillis;
|
||||
contactorStatus = NEGATIVE;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("S-BOX Precharge relay engaged");
|
||||
#endif
|
||||
logging.println("S-BOX Precharge relay engaged");
|
||||
break;
|
||||
case NEGATIVE:
|
||||
if (currentMillis - prechargeStartTime >= CONTACTOR_CONTROL_T1) {
|
||||
|
@ -132,9 +131,7 @@ void BmwSbox::transmit_can(unsigned long currentMillis) {
|
|||
negativeStartTime = currentMillis;
|
||||
contactorStatus = POSITIVE;
|
||||
datalayer.shunt.precharging = true;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("S-BOX Negative relay engaged");
|
||||
#endif
|
||||
logging.println("S-BOX Negative relay engaged");
|
||||
}
|
||||
break;
|
||||
case POSITIVE:
|
||||
|
@ -145,18 +142,14 @@ void BmwSbox::transmit_can(unsigned long currentMillis) {
|
|||
positiveStartTime = currentMillis;
|
||||
contactorStatus = PRECHARGE_OFF;
|
||||
datalayer.shunt.precharging = false;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("S-BOX Positive relay engaged");
|
||||
#endif
|
||||
logging.println("S-BOX Positive relay engaged");
|
||||
}
|
||||
break;
|
||||
case PRECHARGE_OFF:
|
||||
if (currentMillis - positiveStartTime >= CONTACTOR_CONTROL_T3) {
|
||||
SBOX_100.data.u8[0] = 0x6A; // Negative + Positive
|
||||
contactorStatus = COMPLETED;
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("S-BOX Precharge relay released");
|
||||
#endif
|
||||
logging.println("S-BOX Precharge relay released");
|
||||
datalayer.shunt.contactors_engaged = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -116,7 +116,6 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
x102_chg_session.ChargingCurrentRequest = newChargingCurrentRequest;
|
||||
x102_chg_session.TargetBatteryVoltage = newTargetBatteryVoltage;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
//Note on p131
|
||||
uint8_t chargingrate = 0;
|
||||
if (x100_chg_lim.ConstantOfChargingRateIndication > 0) {
|
||||
|
@ -124,7 +123,6 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
logging.print("Charge Rate (kW): ");
|
||||
logging.println(chargingrate);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Table A.26—Charge control termination command patterns -- should echo x108 handling
|
||||
|
||||
|
@ -136,41 +134,31 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
*/
|
||||
if ((CHADEMO_Status == CHADEMO_INIT && vehicle_permission) ||
|
||||
(x102_chg_session.s.status.StatusVehicleChargingEnabled && !vehicle_permission)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inconsistent charge/discharge state.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_FAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryOverVoltage) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery over voltage.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryUnderVoltage) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery under voltage.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryCurrentDeviation) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery current deviation. Possible EVSE issue?");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x102_chg_session.f.fault.FaultBatteryVoltageDeviation) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle indicates fault, battery voltage deviation. Possible EVSE issue?");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
@ -183,18 +171,14 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
|
||||
//FIXME condition nesting or more stanzas needed here for clear determination of cessation reason
|
||||
if (CHADEMO_Status == CHADEMO_POWERFLOW && EVSE_mode == CHADEMO_CHARGE && !vehicle_permission) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("State of charge ceiling reached or charging interrupted, stop charging");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vehicle_permission && CHADEMO_Status == CHADEMO_NEGOTIATE) {
|
||||
CHADEMO_Status = CHADEMO_EV_ALLOWED;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("STATE shift to CHADEMO_EV_ALLOWED in process_vehicle_charging_session()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -203,23 +187,17 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
|||
// consider relocating
|
||||
if (vehicle_permission && CHADEMO_Status == CHADEMO_EVSE_PREPARE && priorTargetBatteryVoltage == 0 &&
|
||||
newTargetBatteryVoltage > 0 && x102_chg_session.s.status.StatusVehicleChargingEnabled) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("STATE SHIFT to EVSE_START reached in process_vehicle_charging_session()");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_EVSE_START;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vehicle_permission && evse_permission && CHADEMO_Status == CHADEMO_POWERFLOW) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("updating vehicle request in process_vehicle_charging_session()");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("UNHANDLED CHADEMO STATE, try unplugging chademo cable, reboot emulator, and retry!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -231,7 +209,6 @@ void ChademoBattery::process_vehicle_charging_limits(CAN_frame rx_frame) {
|
|||
x200_discharge_limits.MinimumBatteryDischargeLevel = rx_frame.data.u8[6];
|
||||
x200_discharge_limits.MaxRemainingCapacityForCharging = rx_frame.data.u8[7];
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
/* unsigned long currentMillis = millis();
|
||||
if (currentMillis - previousMillis5000 >= INTERVAL_5_S) {
|
||||
previousMillis5000 = currentMillis;
|
||||
|
@ -240,16 +217,13 @@ void ChademoBattery::process_vehicle_charging_limits(CAN_frame rx_frame) {
|
|||
logging.println(0xFF - x200_discharge_limits.MaxRemainingCapacityForCharging);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (get_measured_voltage() <= x200_discharge_limits.MinimumDischargeVoltage && CHADEMO_Status > CHADEMO_NEGOTIATE) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
logging.print("Measured: ");
|
||||
logging.print(get_measured_voltage());
|
||||
logging.print("Minimum voltage: ");
|
||||
logging.print(x200_discharge_limits.MinimumDischargeVoltage);
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +238,6 @@ void ChademoBattery::process_vehicle_discharge_estimate(CAN_frame rx_frame) {
|
|||
x201_discharge_estimate.ApproxDischargeCompletionTime = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]);
|
||||
x201_discharge_estimate.AvailableVehicleEnergy = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[3]);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (currentMillis - previousMillis5000 >= INTERVAL_5_S) {
|
||||
previousMillis5000 = currentMillis;
|
||||
logging.print("x201 availabile vehicle energy, completion time: ");
|
||||
|
@ -272,7 +245,6 @@ void ChademoBattery::process_vehicle_discharge_estimate(CAN_frame rx_frame) {
|
|||
logging.print("x201 approx vehicle completion time: ");
|
||||
logging.println(x201_discharge_estimate.ApproxDischargeCompletionTime);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChademoBattery::process_vehicle_dynamic_control(CAN_frame rx_frame) {
|
||||
|
@ -615,10 +587,8 @@ void ChademoBattery::transmit_can(unsigned long currentMillis) {
|
|||
// TODO need an update_evse_dynamic_control(..) function above before we send 118
|
||||
// 110.0.0
|
||||
if (x102_chg_session.ControlProtocolNumberEV >= 0x03) { //Only send the following on Chademo 2.0 vehicles?
|
||||
#ifdef DEBUG_LOG
|
||||
//FIXME REMOVE
|
||||
logging.println("REMOVE: proto 2.0");
|
||||
#endif
|
||||
transmit_can_frame(&CHADEMO_118);
|
||||
}
|
||||
}
|
||||
|
@ -656,16 +626,12 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
/* ------------------- State override conditions checks ------------------- */
|
||||
/* ------------------------------------------------------------------------------ */
|
||||
if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && x102_chg_session.s.status.StatusVehicleShifterPosition) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle is not parked, abort.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
||||
if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && !vehicle_permission) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Vehicle charge/discharge permission ended, stop.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
||||
|
@ -678,25 +644,19 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
plug_inserted = digitalRead(pin7);
|
||||
|
||||
if (!plug_inserted) {
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
// logging.println("CHADEMO plug is not inserted.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
CHADEMO_Status = CHADEMO_CONNECTED;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CHADEMO plug is inserted. Provide EVSE power to vehicle to trigger initialization.");
|
||||
#endif
|
||||
|
||||
break;
|
||||
case CHADEMO_CONNECTED:
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
//logging.println("CHADEMO_CONNECTED State");
|
||||
#endif
|
||||
/* plug_inserted is .. essentially a volatile of sorts, so verify */
|
||||
if (plug_inserted) {
|
||||
/* If connection is detectable, jumpstart handshake by
|
||||
|
@ -729,17 +689,13 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
/* Vehicle and EVSE dance */
|
||||
//TODO if pin 4 / j goes high,
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
// logging.println("CHADEMO_NEGOTIATE State");
|
||||
#endif
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
break;
|
||||
case CHADEMO_EV_ALLOWED:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_EV_ALLOWED State");
|
||||
#endif
|
||||
// If we are in this state, vehicle_permission was already set to true...but re-verify
|
||||
// that pin 4 (j) reads high
|
||||
if (vehicle_permission) {
|
||||
|
@ -754,10 +710,8 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
}
|
||||
break;
|
||||
case CHADEMO_EVSE_PREPARE:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_EVSE_PREPARE State");
|
||||
#endif
|
||||
/* TODO voltage check of output < 20v
|
||||
* insulation test hypothetically happens here before triggering PIN 10 high
|
||||
* see Table A.28—Requirements for the insulation test for output DC circuit
|
||||
|
@ -790,19 +744,15 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
//state changes to CHADEMO_EVSE_START only upon receipt of charging session request
|
||||
break;
|
||||
case CHADEMO_EVSE_START:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_EVSE_START State");
|
||||
#endif
|
||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
x109_evse_state.s.status.EVSE_status = 0;
|
||||
|
||||
CHADEMO_Status = CHADEMO_EVSE_CONTACTORS_ENABLED;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Initiating contactors");
|
||||
#endif
|
||||
|
||||
/* break rather than fall through because contactors are not instantaneous;
|
||||
* worth giving it a cycle to finish
|
||||
|
@ -810,18 +760,14 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
case CHADEMO_EVSE_CONTACTORS_ENABLED:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_EVSE_CONTACTORS State");
|
||||
#endif
|
||||
|
||||
/* check whether contactors ready, because externally dependent upon inverter allow during discharge */
|
||||
if (contactors_ready) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Contactors ready");
|
||||
logging.print("Voltage: ");
|
||||
logging.println(get_measured_voltage());
|
||||
#endif
|
||||
/* transition to POWERFLOW state if discharge compatible on both sides */
|
||||
if (x109_evse_state.discharge_compatible && x102_chg_session.s.status.StatusVehicleDischargeCompatible &&
|
||||
(EVSE_mode == CHADEMO_DISCHARGE || EVSE_mode == CHADEMO_BIDIRECTIONAL)) {
|
||||
|
@ -840,10 +786,8 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
/* break or fall through ? TODO */
|
||||
break;
|
||||
case CHADEMO_POWERFLOW:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_POWERFLOW State");
|
||||
#endif
|
||||
/* POWERFLOW for charging, discharging, and bidirectional */
|
||||
/* Interpretation */
|
||||
if (x102_chg_session.s.status.StatusVehicleShifterPosition) {
|
||||
|
@ -860,9 +804,7 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
}
|
||||
|
||||
if (get_measured_voltage() <= x200_discharge_limits.MinimumDischargeVoltage) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("x200 minimum discharge voltage met or exceeded, stopping.");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_STOP;
|
||||
}
|
||||
|
||||
|
@ -871,10 +813,8 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
x109_evse_state.s.status.EVSE_status = 1;
|
||||
break;
|
||||
case CHADEMO_STOP:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_STOP State");
|
||||
#endif
|
||||
/* back to CHADEMO_IDLE after teardown */
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
x109_evse_state.s.status.EVSE_status = 0;
|
||||
|
@ -899,17 +839,13 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
case CHADEMO_FAULT:
|
||||
#ifdef DEBUG_LOG
|
||||
// Commented unless needed for debug
|
||||
logging.println("CHADEMO_FAULT State");
|
||||
#endif
|
||||
/* Once faulted, never departs CHADEMO_FAULT state unless device is power cycled as a safety measure */
|
||||
x109_evse_state.s.status.EVSE_error = 1;
|
||||
x109_evse_state.s.status.ChgDischError = 1;
|
||||
x109_evse_state.s.status.ChgDischStopControl = 1;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CHADEMO fault encountered, tearing down to make safe");
|
||||
#endif
|
||||
digitalWrite(pin10, LOW);
|
||||
digitalWrite(pin2, LOW);
|
||||
evse_permission = false;
|
||||
|
@ -919,9 +855,7 @@ void ChademoBattery::handle_chademo_sequence() {
|
|||
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("UNHANDLED CHADEMO_STATE, setting FAULT");
|
||||
#endif
|
||||
CHADEMO_Status = CHADEMO_FAULT;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -108,18 +108,16 @@ uint32_t decode_uint32be(uint8_t data[8], uint8_t offset) {
|
|||
((uint32_t)data[offset + 3]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
void dump_buff(const char* msg, uint8_t* buff, uint8_t len) {
|
||||
Serial.print("[DALY-BMS] ");
|
||||
Serial.print(msg);
|
||||
logging.print("[DALY-BMS] ");
|
||||
logging.print(msg);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Serial.print(buff[i] >> 4, HEX);
|
||||
Serial.print(buff[i] & 0xf, HEX);
|
||||
Serial.print(" ");
|
||||
logging.print(buff[i] >> 4, HEX);
|
||||
logging.print(buff[i] & 0xf, HEX);
|
||||
logging.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
logging.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
void decode_packet(uint8_t command, uint8_t data[8]) {
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -180,9 +178,7 @@ void DalyBms::transmit_rs485(unsigned long currentMillis) {
|
|||
tx_buff[2] = nextCommand;
|
||||
tx_buff[3] = 8;
|
||||
tx_buff[12] = calculate_checksum(tx_buff);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
dump_buff("transmitting: ", tx_buff, 13);
|
||||
#endif
|
||||
Serial2.write(tx_buff, 13);
|
||||
nextCommand++;
|
||||
if (nextCommand > 0x98)
|
||||
|
@ -202,17 +198,12 @@ void DalyBms::receive() {
|
|||
if (recv_len > 0 && recv_buff[0] != 0xA5 || recv_len > 1 && recv_buff[1] != 0x01 ||
|
||||
recv_len > 2 && (recv_buff[2] < 0x90 || recv_buff[2] > 0x98) || recv_len > 3 && recv_buff[3] != 8 ||
|
||||
recv_len > 12 && recv_buff[12] != calculate_checksum(recv_buff)) {
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
dump_buff("dropping partial rx: ", recv_buff, recv_len);
|
||||
#endif
|
||||
recv_len = 0;
|
||||
}
|
||||
|
||||
if (recv_len > 12) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
dump_buff("decoding successfull rx: ", recv_buff, recv_len);
|
||||
#endif
|
||||
decode_packet(recv_buff[2], &recv_buff[4]);
|
||||
recv_len = 0;
|
||||
lastPacket = millis();
|
||||
|
|
|
@ -75,12 +75,9 @@ void ImievCZeroIonBattery::
|
|||
}
|
||||
|
||||
if (!BMU_Detected) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BMU not detected, check wiring!");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Battery Values");
|
||||
logging.print("BMU SOC: ");
|
||||
logging.print(BMU_SOC);
|
||||
|
@ -90,15 +87,6 @@ void ImievCZeroIonBattery::
|
|||
logging.print(BMU_PackVoltage);
|
||||
logging.print(" BMU_Power: ");
|
||||
logging.print(BMU_Power);
|
||||
logging.print(" Cell max voltage: ");
|
||||
logging.print(max_volt_cel);
|
||||
logging.print(" Cell min voltage: ");
|
||||
logging.print(min_volt_cel);
|
||||
logging.print(" Cell max temp: ");
|
||||
logging.print(max_temp_cel);
|
||||
logging.print(" Cell min temp: ");
|
||||
logging.println(min_temp_cel);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImievCZeroIonBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
|
|
@ -102,21 +102,6 @@ void JaguarIpaceBattery::update_values() {
|
|||
} else {
|
||||
clear_event(EVENT_BATTERY_ISOLATION);
|
||||
}
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Values going to inverter");
|
||||
print_units("SOH%: ", (datalayer.battery.status.soh_pptt * 0.01), "% ");
|
||||
print_units(", SOC%: ", (datalayer.battery.status.reported_soc * 0.01), "% ");
|
||||
print_units(", Voltage: ", (datalayer.battery.status.voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", datalayer.battery.status.max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power: ", datalayer.battery.status.max_charge_power_W, "W ");
|
||||
print_units(", Max temp: ", (datalayer.battery.status.temperature_max_dC * 0.1), "°C ");
|
||||
print_units(", Min temp: ", (datalayer.battery.status.temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", datalayer.battery.status.cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage: ", datalayer.battery.status.cell_min_voltage_mV, "mV ");
|
||||
logging.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
void JaguarIpaceBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
|
|
@ -55,7 +55,6 @@ uint16_t KiaEGmpBattery::estimateSOC(uint16_t packVoltage, uint16_t cellCount, i
|
|||
// Calculate average cell voltage in millivolts
|
||||
uint16_t avgCellVoltage = compensatedPackVoltageMv / cellCount;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Pack: ");
|
||||
logging.print(packVoltage / 10.0);
|
||||
logging.print("V, Current: ");
|
||||
|
@ -67,7 +66,6 @@ uint16_t KiaEGmpBattery::estimateSOC(uint16_t packVoltage, uint16_t cellCount, i
|
|||
logging.print("V, Avg Cell: ");
|
||||
logging.print(avgCellVoltage);
|
||||
logging.println("mV");
|
||||
#endif
|
||||
|
||||
// Use the cell voltage lookup table to estimate SOC
|
||||
return estimateSOCFromCell(avgCellVoltage);
|
||||
|
@ -187,7 +185,6 @@ void KiaEGmpBattery::update_values() {
|
|||
|
||||
/* Safeties verified. Perform USB serial printout if configured to do so */
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println(); //sepatator
|
||||
logging.println("Values from battery: ");
|
||||
logging.print("SOC BMS: ");
|
||||
|
@ -244,7 +241,6 @@ void KiaEGmpBattery::update_values() {
|
|||
logging.print(" | Inverter ");
|
||||
logging.print(inverterVoltage);
|
||||
logging.println(" Volts");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Getter implementations for HTML renderer
|
||||
|
|
|
@ -171,9 +171,7 @@ uint8_t vw_crc_calc(uint8_t* inputBytes, uint8_t length, uint32_t address) {
|
|||
magicByte = MB16A954A6[counter];
|
||||
break;
|
||||
default: // this won't lead to correct CRC checksums
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Checksum request unknown");
|
||||
#endif
|
||||
magicByte = 0x00;
|
||||
break;
|
||||
}
|
||||
|
@ -310,9 +308,7 @@ void MebBattery::
|
|||
void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
last_can_msg_timestamp = millis();
|
||||
if (first_can_msg == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("MEB: First CAN msg received\n");
|
||||
#endif
|
||||
first_can_msg = last_can_msg_timestamp;
|
||||
}
|
||||
|
||||
|
@ -326,9 +322,7 @@ void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
if (rx_frame.data.u8[0] !=
|
||||
vw_crc_calc(rx_frame.data.u8, rx_frame.DLC, rx_frame.ID)) { //If CRC does not match calc
|
||||
datalayer.battery.status.CAN_error_counter++;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("MEB: Msg 0x%04X CRC error\n", rx_frame.ID);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
@ -700,29 +694,23 @@ void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
case 3: // EXTERN CHARGING
|
||||
case 4: // AC_CHARGING
|
||||
case 6: // DC_CHARGING
|
||||
#ifdef DEBUG_LOG
|
||||
if (!datalayer.system.status.battery_allows_contactor_closing)
|
||||
logging.printf("MEB: Contactors closed\n");
|
||||
#endif
|
||||
if (datalayer.battery.status.real_bms_status != BMS_FAULT)
|
||||
datalayer.battery.status.real_bms_status = BMS_ACTIVE;
|
||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||
hv_requested = false;
|
||||
break;
|
||||
case 5: // Error
|
||||
#ifdef DEBUG_LOG
|
||||
if (datalayer.system.status.battery_allows_contactor_closing)
|
||||
logging.printf("MEB: Contactors opened\n");
|
||||
#endif
|
||||
datalayer.battery.status.real_bms_status = BMS_FAULT;
|
||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
||||
hv_requested = false;
|
||||
break;
|
||||
case 7: // Init
|
||||
#ifdef DEBUG_LOG
|
||||
if (datalayer.system.status.battery_allows_contactor_closing)
|
||||
logging.printf("MEB: Contactors opened\n");
|
||||
#endif
|
||||
if (datalayer.battery.status.real_bms_status != BMS_FAULT)
|
||||
datalayer.battery.status.real_bms_status = BMS_STANDBY;
|
||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
||||
|
@ -730,10 +718,8 @@ void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
break;
|
||||
case 2: // BALANCING
|
||||
default:
|
||||
#ifdef DEBUG_LOG
|
||||
if (datalayer.system.status.battery_allows_contactor_closing)
|
||||
logging.printf("MEB: Contactors opened\n");
|
||||
#endif
|
||||
if (datalayer.battery.status.real_bms_status != BMS_FAULT)
|
||||
datalayer.battery.status.real_bms_status = BMS_STANDBY;
|
||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
||||
|
@ -1276,10 +1262,8 @@ void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
handle_obd_frame(rx_frame);
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Unknown CAN frame received:\n");
|
||||
dump_can_frame(rx_frame, MSG_RX);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -1292,10 +1276,8 @@ void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
void MebBattery::transmit_can(unsigned long currentMillis) {
|
||||
|
||||
if (currentMillis - last_can_msg_timestamp > 500) {
|
||||
#ifdef DEBUG_LOG
|
||||
if (first_can_msg)
|
||||
logging.printf("MEB: No CAN msg received for 500ms\n");
|
||||
#endif
|
||||
can_msg_received = RX_DEFAULT;
|
||||
first_can_msg = 0;
|
||||
if (datalayer.battery.status.real_bms_status != BMS_FAULT) {
|
||||
|
@ -1373,7 +1355,6 @@ void MebBattery::transmit_can(unsigned long currentMillis) {
|
|||
((int32_t)datalayer_extended.meb.BMS_voltage_intermediate_dV)) < 200))))) {
|
||||
hv_requested = true;
|
||||
datalayer.system.settings.start_precharging = false;
|
||||
#ifdef DEBUG_LOG
|
||||
if (MEB_503.data.u8[3] == BMS_TARGET_HV_OFF) {
|
||||
logging.printf("MEB: Requesting HV\n");
|
||||
}
|
||||
|
@ -1385,7 +1366,6 @@ void MebBattery::transmit_can(unsigned long currentMillis) {
|
|||
logging.printf("MEB: Precharge bit set to inactive\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
MEB_503.data.u8[1] =
|
||||
0x30 | (datalayer.system.status.precharge_status == AUTO_PRECHARGE_PRECHARGING ? 0x80 : 0x00);
|
||||
MEB_503.data.u8[3] = BMS_TARGET_AC_CHARGING;
|
||||
|
@ -1399,7 +1379,6 @@ void MebBattery::transmit_can(unsigned long currentMillis) {
|
|||
datalayer.system.settings.start_precharging = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (MEB_503.data.u8[3] != BMS_TARGET_HV_OFF) {
|
||||
logging.printf("MEB: Requesting HV_OFF\n");
|
||||
}
|
||||
|
@ -1411,7 +1390,6 @@ void MebBattery::transmit_can(unsigned long currentMillis) {
|
|||
logging.printf("MEB: Precharge bit set to inactive\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
MEB_503.data.u8[1] =
|
||||
0x10 | (datalayer.system.status.precharge_status == AUTO_PRECHARGE_PRECHARGING ? 0x80 : 0x00);
|
||||
MEB_503.data.u8[3] = BMS_TARGET_HV_OFF;
|
||||
|
|
|
@ -147,11 +147,9 @@ void MgHsPHEVBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
// 15 = isolation fault
|
||||
// 0/8 = checking
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
if (rx_frame.data.u8[1] != previousState) {
|
||||
logging.printf("MG_HS_PHEV: Battery status changed to %d (%d)\n", rx_frame.data.u8[1], rx_frame.data.u8[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rx_frame.data.u8[1] == 0xf && previousState != 0xf) {
|
||||
// Isolation fault, set event
|
||||
|
@ -168,18 +166,14 @@ void MgHsPHEVBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
// A weird 'stuck' state where the battery won't reconnect
|
||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
||||
if (!datalayer.system.status.BMS_startup_in_progress) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("MG_HS_PHEV: Stuck, resetting.\n");
|
||||
#endif
|
||||
start_bms_reset();
|
||||
}
|
||||
} else if (rx_frame.data.u8[1] == 0xf) {
|
||||
// A fault state (likely isolation failure)
|
||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
||||
if (!datalayer.system.status.BMS_startup_in_progress) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("MG_HS_PHEV: Fault, resetting.\n");
|
||||
#endif
|
||||
start_bms_reset();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -51,39 +51,6 @@ void RenaultKangooBattery::
|
|||
datalayer.battery.status.cell_min_voltage_mV = LB_Cell_Min_Voltage;
|
||||
|
||||
datalayer.battery.status.cell_max_voltage_mV = LB_Cell_Max_Voltage;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Values going to inverter:");
|
||||
logging.print("SOH%: ");
|
||||
logging.print(datalayer.battery.status.soh_pptt);
|
||||
logging.print(", SOC% scaled: ");
|
||||
logging.print(datalayer.battery.status.reported_soc);
|
||||
logging.print(", Voltage: ");
|
||||
logging.print(datalayer.battery.status.voltage_dV);
|
||||
logging.print(", Max discharge power: ");
|
||||
logging.print(datalayer.battery.status.max_discharge_power_W);
|
||||
logging.print(", Max charge power: ");
|
||||
logging.print(datalayer.battery.status.max_charge_power_W);
|
||||
logging.print(", Max temp: ");
|
||||
logging.print(datalayer.battery.status.temperature_max_dC);
|
||||
logging.print(", Min temp: ");
|
||||
logging.print(datalayer.battery.status.temperature_min_dC);
|
||||
logging.print(", BMS Status (3=OK): ");
|
||||
logging.print(datalayer.battery.status.bms_status);
|
||||
|
||||
logging.println("Battery values: ");
|
||||
logging.print("Real SOC: ");
|
||||
logging.print(LB_SOC);
|
||||
logging.print(", Current: ");
|
||||
logging.print(LB_Current);
|
||||
logging.print(", kWh remain: ");
|
||||
logging.print(LB_kWh_Remaining);
|
||||
logging.print(", max mV: ");
|
||||
logging.print(LB_Cell_Max_Voltage);
|
||||
logging.print(", min mV: ");
|
||||
logging.print(LB_Cell_Min_Voltage);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void RenaultKangooBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
|
|
@ -720,13 +720,9 @@ void TeslaBattery::
|
|||
//Start the BMS ECU reset statemachine, only if contactors are OPEN and BMS ECU allows it
|
||||
stateMachineBMSReset = 0;
|
||||
datalayer.battery.settings.user_requests_tesla_bms_reset = false;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BMS reset requested");
|
||||
#endif //DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it");
|
||||
#endif //DEBUG_LOG
|
||||
stateMachineBMSReset = 0xFF;
|
||||
datalayer.battery.settings.user_requests_tesla_bms_reset = false;
|
||||
}
|
||||
|
@ -736,13 +732,9 @@ void TeslaBattery::
|
|||
//Start the SOC reset statemachine, only if SOC < 15% or > 90%
|
||||
stateMachineSOCReset = 0;
|
||||
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SOC reset requested");
|
||||
#endif //DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("ERROR: SOC reset failed due to SOC not being less than 15 or greater than 90");
|
||||
#endif //DEBUG_LOG
|
||||
stateMachineSOCReset = 0xFF;
|
||||
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
|
||||
}
|
||||
|
@ -1002,8 +994,6 @@ void TeslaBattery::
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
|
||||
printFaultCodesIfActive();
|
||||
logging.print("BMS Contactors State: ");
|
||||
logging.print(getBMSContactorState(battery_contactor)); // Display what state the BMS thinks the contactors are in
|
||||
|
@ -1061,7 +1051,6 @@ void TeslaBattery::
|
|||
logging.printf("PCS_ambientTemp: %.2f°C, DCDC_Temp: %.2f°C, ChgPhA: %.2f°C, ChgPhB: %.2f°C, ChgPhC: %.2f°C.\n",
|
||||
PCS_ambientTemp * 0.1 + 40, PCS_dcdcTemp * 0.1 + 40, PCS_chgPhATemp * 0.1 + 40,
|
||||
PCS_chgPhBTemp * 0.1 + 40, PCS_chgPhCTemp * 0.1 + 40);
|
||||
#endif //DEBUG_LOG
|
||||
}
|
||||
|
||||
void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
@ -1911,9 +1900,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF) {
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x50\x03\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
//Received initial response, proceed to actual query
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Received BMS query initial handshake reply");
|
||||
#endif //DEBUG_LOG
|
||||
stateMachineBMSQuery = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -1922,9 +1909,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
battery_partNumber[0] = rx_frame.data.u8[5];
|
||||
battery_partNumber[1] = rx_frame.data.u8[6];
|
||||
battery_partNumber[2] = rx_frame.data.u8[7];
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Received BMS query data frame");
|
||||
#endif //DEBUG_LOG
|
||||
stateMachineBMSQuery = 2;
|
||||
break;
|
||||
}
|
||||
|
@ -1937,32 +1922,25 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
battery_partNumber[7] = rx_frame.data.u8[5];
|
||||
battery_partNumber[8] = rx_frame.data.u8[6];
|
||||
battery_partNumber[9] = rx_frame.data.u8[7];
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Received BMS query second data frame");
|
||||
#endif //DEBUG_LOG
|
||||
break;
|
||||
}
|
||||
if (memcmp(&rx_frame.data.u8[0], "\x22", 1) == 0) {
|
||||
//Final part of part number
|
||||
battery_partNumber[10] = rx_frame.data.u8[1];
|
||||
battery_partNumber[11] = rx_frame.data.u8[2];
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Received BMS query final data frame");
|
||||
#endif //DEBUG_LOG
|
||||
break;
|
||||
}
|
||||
if (memcmp(rx_frame.data.u8, "\x23\x00\x00\x00\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
//Received final frame
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Received BMS query termination frame");
|
||||
#endif //DEBUG_LOG
|
||||
parsed_battery_partNumber = true;
|
||||
stateMachineBMSQuery = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//BMS Reset
|
||||
#ifdef DEBUG_LOG
|
||||
if (stateMachineBMSQuery == 0xFF) { // Make sure this is reset request not query
|
||||
if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) {
|
||||
logging.println("CAN UDS: ECU unlocked");
|
||||
|
@ -1972,7 +1950,6 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
logging.println("CAN UDS: ECU reset positive response, 1 second downtime");
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_LOG
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2375,25 +2352,19 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) {
|
|||
switch (stateMachineBMSQuery) {
|
||||
case 0:
|
||||
//Initial request
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Sending BMS query initial handshake");
|
||||
#endif //DEBUG_LOG
|
||||
TESLA_602.data = {0x02, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can_frame(&TESLA_602);
|
||||
break;
|
||||
case 1:
|
||||
//Send query
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Sending BMS query for pack part number");
|
||||
#endif //DEBUG_LOG
|
||||
TESLA_602.data = {0x03, 0x22, 0xF0, 0x14, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can_frame(&TESLA_602);
|
||||
break;
|
||||
case 2:
|
||||
//Flow control
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN UDS: Sending BMS query flow control");
|
||||
#endif //DEBUG_LOG
|
||||
TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
transmit_can_frame(&TESLA_602);
|
||||
break;
|
||||
|
|
|
@ -42,21 +42,6 @@ void TestFakeBattery::
|
|||
|
||||
//Fake that we get CAN messages
|
||||
datalayer_battery->status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("FAKE Values going to inverter");
|
||||
print_units("SOH%: ", (datalayer_battery->status.soh_pptt * 0.01), "% ");
|
||||
print_units(", SOC%: ", (datalayer_battery->status.reported_soc * 0.01), "% ");
|
||||
print_units(", Voltage: ", (datalayer_battery->status.voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", datalayer_battery->status.max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power: ", datalayer_battery->status.max_charge_power_W, "W ");
|
||||
print_units(", Max temp: ", (datalayer_battery->status.temperature_max_dC * 0.1), "°C ");
|
||||
print_units(", Min temp: ", (datalayer_battery->status.temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", datalayer_battery->status.cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage: ", datalayer_battery->status.cell_min_voltage_mV, "mV ");
|
||||
logging.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
void TestFakeBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
|
|
@ -85,51 +85,6 @@ void VolvoSpaBattery::
|
|||
datalayer.battery.info.total_capacity_Wh = 69511;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
uint8_t cnt = 0;
|
||||
logging.print("BMS reported SOC%: ");
|
||||
logging.println(SOC_BMS);
|
||||
logging.print("Calculated SOC%: ");
|
||||
logging.println(SOC_CALC);
|
||||
logging.print("Rescaled SOC%: ");
|
||||
logging.println(datalayer.battery.status.reported_soc / 100);
|
||||
logging.print("Battery current: ");
|
||||
logging.println(BATT_I);
|
||||
logging.print("Battery voltage: ");
|
||||
logging.println(BATT_U);
|
||||
logging.print("Battery maximum voltage limit: ");
|
||||
logging.println(MAX_U);
|
||||
logging.print("Battery minimum voltage limit: ");
|
||||
logging.println(MIN_U);
|
||||
logging.print("Discharge limit: ");
|
||||
logging.println(HvBattPwrLimDchaSoft);
|
||||
logging.print("Battery Error Indication: ");
|
||||
logging.println(BATT_ERR_INDICATION);
|
||||
logging.print("Maximum battery temperature: ");
|
||||
logging.println(BATT_T_MAX / 10);
|
||||
logging.print("Minimum battery temperature: ");
|
||||
logging.println(BATT_T_MIN / 10);
|
||||
logging.print("Average battery temperature: ");
|
||||
logging.println(BATT_T_AVG / 10);
|
||||
logging.print("BMS Highest cell voltage: ");
|
||||
logging.println(CELL_U_MAX * 10);
|
||||
logging.print("BMS Lowest cell voltage: ");
|
||||
logging.println(CELL_U_MIN * 10);
|
||||
logging.print("BMS Highest cell nr: ");
|
||||
logging.println(CELL_ID_U_MAX);
|
||||
logging.print("Highest cell voltage: ");
|
||||
logging.println(min_max_voltage[1]);
|
||||
logging.print("Lowest cell voltage: ");
|
||||
logging.println(min_max_voltage[0]);
|
||||
logging.print("Cell voltage,");
|
||||
while (cnt < 108) {
|
||||
logging.print(cell_voltages[cnt++]);
|
||||
logging.print(",");
|
||||
}
|
||||
cnt = 0;
|
||||
logging.println(";");
|
||||
#endif
|
||||
}
|
||||
|
||||
void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
@ -140,9 +95,7 @@ void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_I = (0 - ((((rx_frame.data.u8[6] & 0x7F) * 256.0 + rx_frame.data.u8[7]) * 0.1) - 1638));
|
||||
else {
|
||||
BATT_I = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_I not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[2] & 0x08) == 0x08)
|
||||
|
@ -195,9 +148,7 @@ void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_ERR_INDICATION = ((rx_frame.data.u8[0] & 0x40) >> 6);
|
||||
else {
|
||||
BATT_ERR_INDICATION = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_ERR_INDICATION not valid");
|
||||
#endif
|
||||
}
|
||||
if ((rx_frame.data.u8[0] & 0x20) == 0x20) {
|
||||
BATT_T_MAX = ((rx_frame.data.u8[2] & 0x1F) * 256.0 + rx_frame.data.u8[3]);
|
||||
|
@ -207,9 +158,7 @@ void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_T_MAX = 0;
|
||||
BATT_T_MIN = 0;
|
||||
BATT_T_AVG = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_T not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x369:
|
||||
|
@ -217,9 +166,7 @@ void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
HvBattPwrLimDchaSoft = (((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[6]) >> 2);
|
||||
} else {
|
||||
HvBattPwrLimDchaSoft = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("HvBattPwrLimDchaSoft not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x175:
|
||||
|
@ -246,9 +193,7 @@ void VolvoSpaBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
SOC_BMS = ((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[7]);
|
||||
} else {
|
||||
SOC_BMS = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SOC_BMS not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x04) == 0x04) {
|
||||
|
|
|
@ -70,51 +70,6 @@ void VolvoSpaHybridBattery::
|
|||
for (int i = 0; i < 102; ++i) {
|
||||
datalayer.battery.status.cell_voltages_mV[i] = cell_voltages[i];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("BMS reported SOC%: ");
|
||||
logging.println(SOC_BMS);
|
||||
logging.print("Calculated SOC%: ");
|
||||
logging.println(SOC_CALC);
|
||||
logging.print("Rescaled SOC%: ");
|
||||
logging.println(datalayer.battery.status.reported_soc / 100);
|
||||
logging.print("Battery current: ");
|
||||
logging.println(BATT_I);
|
||||
logging.print("Battery voltage: ");
|
||||
logging.println(BATT_U);
|
||||
logging.print("Battery maximum voltage limit: ");
|
||||
logging.println(MAX_U);
|
||||
logging.print("Battery minimum voltage limit: ");
|
||||
logging.println(MIN_U);
|
||||
logging.print("Remaining Energy: ");
|
||||
logging.println(remaining_capacity);
|
||||
logging.print("Discharge limit: ");
|
||||
logging.println(HvBattPwrLimDchaSoft);
|
||||
logging.print("Battery Error Indication: ");
|
||||
logging.println(BATT_ERR_INDICATION);
|
||||
logging.print("Maximum battery temperature: ");
|
||||
logging.println(BATT_T_MAX / 10);
|
||||
logging.print("Minimum battery temperature: ");
|
||||
logging.println(BATT_T_MIN / 10);
|
||||
logging.print("Average battery temperature: ");
|
||||
logging.println(BATT_T_AVG / 10);
|
||||
logging.print("BMS Highest cell voltage: ");
|
||||
logging.println(CELL_U_MAX);
|
||||
logging.print("BMS Lowest cell voltage: ");
|
||||
logging.println(CELL_U_MIN);
|
||||
logging.print("BMS Highest cell nr: ");
|
||||
logging.println(CELL_ID_U_MAX);
|
||||
logging.print("Highest cell voltage: ");
|
||||
logging.println(min_max_voltage[1]);
|
||||
logging.print("Lowest cell voltage: ");
|
||||
logging.println(min_max_voltage[0]);
|
||||
logging.print("Cell voltage,");
|
||||
while (cnt < 102) {
|
||||
logging.print(cell_voltages[cnt++]);
|
||||
logging.print(",");
|
||||
}
|
||||
logging.println(";");
|
||||
#endif
|
||||
}
|
||||
|
||||
void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
|
@ -125,9 +80,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_I = (0 - ((((rx_frame.data.u8[6] & 0x7F) * 256.0 + rx_frame.data.u8[7]) * 0.1) - 1638));
|
||||
else {
|
||||
BATT_I = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_I not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[2] & 0x08) == 0x08)
|
||||
|
@ -148,9 +101,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_U = (((rx_frame.data.u8[0] & 0x07) * 256.0 + rx_frame.data.u8[1]) * 0.25);
|
||||
else {
|
||||
BATT_U = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_U not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x40) == 0x40)
|
||||
|
@ -185,9 +136,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_ERR_INDICATION = ((rx_frame.data.u8[0] & 0x40) >> 6);
|
||||
else {
|
||||
BATT_ERR_INDICATION = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_ERR_INDICATION not valid");
|
||||
#endif
|
||||
}
|
||||
if ((rx_frame.data.u8[0] & 0x20) == 0x20) {
|
||||
BATT_T_MAX = ((rx_frame.data.u8[2] & 0x1F) * 256.0 + rx_frame.data.u8[3]);
|
||||
|
@ -197,9 +146,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
BATT_T_MAX = 0;
|
||||
BATT_T_MIN = 0;
|
||||
BATT_T_AVG = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("BATT_T not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x369:
|
||||
|
@ -207,9 +154,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
HvBattPwrLimDchaSoft = (((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[6]) >> 2);
|
||||
} else {
|
||||
HvBattPwrLimDchaSoft = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("HvBattPwrLimDchaSoft not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x175:
|
||||
|
@ -240,9 +185,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
SOC_BMS = ((rx_frame.data.u8[6] & 0x03) * 256 + rx_frame.data.u8[7]);
|
||||
} else {
|
||||
SOC_BMS = 0;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SOC_BMS not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x04) == 0x04)
|
||||
|
@ -251,9 +194,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
else {
|
||||
//CELL_U_MAX = 0;
|
||||
;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_U_MAX not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x02) == 0x02)
|
||||
|
@ -262,9 +203,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
else {
|
||||
//CELL_U_MIN = 0;
|
||||
;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_U_MIN not valid");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rx_frame.data.u8[0] & 0x08) == 0x08)
|
||||
|
@ -273,9 +212,7 @@ void VolvoSpaHybridBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
|
|||
else {
|
||||
//CELL_ID_U_MAX = 0;
|
||||
;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CELL_ID_U_MAX not valid");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 0x635: // Diag request response
|
||||
|
@ -545,9 +482,7 @@ void VolvoSpaHybridBattery::transmit_can(unsigned long currentMillis) {
|
|||
previousMillis60s = currentMillis;
|
||||
if (true) {
|
||||
readCellVoltages();
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Requesting cell voltages");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,9 +71,6 @@ void ChevyVoltCharger::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
datalayer.charger.CAN_charger_still_alive = CAN_STILL_ALIVE; // Let system know charger is sending CAN
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("CAN Rcv unknown frame MsgID=%x\n", rx_frame.ID);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +143,6 @@ void ChevyVoltCharger::transmit_can(unsigned long currentMillis) {
|
|||
transmit_can_frame(&charger_set_targets);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
/* Serial echo every 5s of charger stats */
|
||||
if (currentMillis - previousMillis5000ms >= INTERVAL_5_S) {
|
||||
previousMillis5000ms = currentMillis;
|
||||
|
@ -156,5 +152,4 @@ void ChevyVoltCharger::transmit_can(unsigned long currentMillis) {
|
|||
logging.printf("Charger mode=%s\n", (charger_mode > MODE_DISABLED) ? "Enabled" : "Disabled");
|
||||
logging.printf("Charger HVset=%uV,%uA finishCurrent=%uA\n", setpoint_HV_VDC, setpoint_HV_IDC, setpoint_HV_IDC_END);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -135,9 +135,7 @@ bool init_CAN() {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Dual CAN Bus (ESP32+MCP2515) selected");
|
||||
#endif // DEBUG_LOG
|
||||
gBuffer.initWithSize(25);
|
||||
|
||||
if (rst_pin != GPIO_NUM_NC) {
|
||||
|
@ -161,14 +159,10 @@ bool init_CAN() {
|
|||
settings2515->mRequestedMode = ACAN2515Settings::NormalMode;
|
||||
const uint16_t errorCode2515 = can2515->begin(*settings2515, [] { can2515->isr(); });
|
||||
if (errorCode2515 == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MCP2515 Can ok");
|
||||
#endif // DEBUG_LOG
|
||||
logging.println("Can ok");
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Error MCP2515 Can: 0x");
|
||||
logging.print("Error Can: 0x");
|
||||
logging.println(errorCode2515, HEX);
|
||||
#endif // DEBUG_LOG
|
||||
set_event(EVENT_CANMCP2515_INIT_FAILURE, (uint8_t)errorCode2515);
|
||||
return false;
|
||||
}
|
||||
|
@ -193,9 +187,7 @@ bool init_CAN() {
|
|||
|
||||
canfd = new ACAN2517FD(cs_pin, SPI2517, int_pin);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("CAN FD add-on (ESP32+MCP2517) selected");
|
||||
#endif // DEBUG_LOG
|
||||
SPI2517.begin(sck_pin, sdo_pin, sdi_pin);
|
||||
auto bitRate = (int)speed * 1000UL;
|
||||
settings2517 = new ACAN2517FDSettings(
|
||||
|
@ -208,7 +200,6 @@ bool init_CAN() {
|
|||
const uint32_t errorCode2517 = canfd->begin(*settings2517, [] { canfd->isr(); });
|
||||
canfd->poll();
|
||||
if (errorCode2517 == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Bit Rate prescaler: ");
|
||||
logging.println(settings2517->mBitRatePrescaler);
|
||||
logging.print("Arbitration Phase segment 1: ");
|
||||
|
@ -225,12 +216,9 @@ bool init_CAN() {
|
|||
logging.print("Arbitration Sample point: ");
|
||||
logging.print(settings2517->arbitrationSamplePointFromBitStart());
|
||||
logging.println("%");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("CAN-FD Configuration error 0x");
|
||||
logging.println(errorCode2517, HEX);
|
||||
#endif // DEBUG_LOG
|
||||
set_event(EVENT_CANMCP2517FD_INIT_FAILURE, (uint8_t)errorCode2517);
|
||||
return false;
|
||||
}
|
||||
|
@ -379,7 +367,8 @@ void receive_frame_canfd_addon() { // This section checks if we have a complete
|
|||
|
||||
// Support functions
|
||||
void print_can_frame(CAN_frame frame, frameDirection msgDir) {
|
||||
#ifdef DEBUG_CAN_DATA // If enabled in user settings, print out the CAN messages via USB
|
||||
|
||||
if (datalayer.system.info.CAN_usb_logging_active) {
|
||||
uint8_t i = 0;
|
||||
Serial.print("(");
|
||||
Serial.print(millis() / 1000.0);
|
||||
|
@ -395,7 +384,7 @@ void print_can_frame(CAN_frame frame, frameDirection msgDir) {
|
|||
Serial.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
#endif // DEBUG_CAN_DATA
|
||||
}
|
||||
|
||||
if (datalayer.system.info.can_logging_active) { // If user clicked on CAN Logging page in webserver, start recording
|
||||
dump_can_frame(frame, msgDir);
|
||||
|
|
|
@ -24,7 +24,6 @@ void show_dtc(uint8_t byte0, uint8_t byte1) {
|
|||
}
|
||||
|
||||
void handle_obd_frame(CAN_frame& rx_frame) {
|
||||
#ifdef DEBUG_LOG
|
||||
if (rx_frame.data.u8[1] == 0x7F) {
|
||||
const char* error_str = "?";
|
||||
switch (rx_frame.data.u8[3]) { // See https://automotive.wiki/index.php/ISO_14229
|
||||
|
@ -107,7 +106,6 @@ void handle_obd_frame(CAN_frame& rx_frame) {
|
|||
}
|
||||
}
|
||||
dump_can_frame(rx_frame, MSG_RX);
|
||||
#endif
|
||||
}
|
||||
|
||||
void transmit_obd_can_frame(unsigned int address, int interface, bool canFD) {
|
||||
|
|
|
@ -147,12 +147,10 @@ bool init_contactors() {
|
|||
}
|
||||
|
||||
static void dbg_contactors(const char* state) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("[");
|
||||
logging.print(millis());
|
||||
logging.print(" ms] contactors control: ");
|
||||
logging.println(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Main functions of the handle_contactors include checking if inverter allows for closing, checking battery 2, checking BMS power output, and actual contactor closing/precharge via GPIO
|
||||
|
|
|
@ -144,6 +144,13 @@ void init_stored_settings() {
|
|||
remote_bms_reset = settings.getBool("REMBMSRESET", false);
|
||||
use_canfd_as_can = settings.getBool("CANFDASCAN", false);
|
||||
|
||||
datalayer.system.info.CAN_usb_logging_active = settings.getBool("CANLOGUSB", false);
|
||||
datalayer.system.info.usb_logging_active = settings.getBool("USBENABLED", false);
|
||||
datalayer.system.info.web_logging_active = settings.getBool("WEBENABLED", false);
|
||||
datalayer.system.info.CAN_SD_logging_active = settings.getBool("CANLOGSD", false);
|
||||
datalayer.system.info.SD_logging_active = settings.getBool("SDLOGENABLED", false);
|
||||
datalayer.battery.status.led_mode = (led_mode_enum)settings.getUInt("LEDMODE", false);
|
||||
|
||||
// WIFI AP is enabled by default unless disabled in the settings
|
||||
wifiap_enabled = settings.getBool("WIFIAPENABLED", true);
|
||||
passwordAP = settings.getString("APPASSWORD", "123456789").c_str();
|
||||
|
|
|
@ -40,9 +40,7 @@ bool init_precharge_control() {
|
|||
}
|
||||
|
||||
// Setup PWM Channel Frequency and Resolution
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge control initialised\n");
|
||||
#endif
|
||||
|
||||
auto hia4v1_pin = esp32hal->HIA4V1_PIN();
|
||||
auto inverter_disconnect_contactor_pin = esp32hal->INVERTER_DISCONNECT_CONTACTOR_PIN();
|
||||
|
@ -87,9 +85,7 @@ void handle_precharge_control(unsigned long currentMillis) {
|
|||
ledcWriteTone(hia4v1_pin, freq); // Set frequency and set dutycycle to 50%
|
||||
prechargeStartTime = currentMillis;
|
||||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_PRECHARGING;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: Starting sequence\n");
|
||||
#endif
|
||||
digitalWrite(inverter_disconnect_contactor_pin, OFF);
|
||||
break;
|
||||
|
||||
|
@ -114,10 +110,8 @@ void handle_precharge_control(unsigned long currentMillis) {
|
|||
freq = Precharge_max_PWM_Freq;
|
||||
if (freq < Precharge_min_PWM_Freq)
|
||||
freq = Precharge_min_PWM_Freq;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: Target: %d V Extern: %d V Frequency: %u\n", target_voltage / 10,
|
||||
external_voltage / 10, freq);
|
||||
#endif
|
||||
ledcWriteTone(hia4v1_pin, freq);
|
||||
}
|
||||
|
||||
|
@ -128,40 +122,31 @@ void handle_precharge_control(unsigned long currentMillis) {
|
|||
digitalWrite(hia4v1_pin, LOW);
|
||||
digitalWrite(inverter_disconnect_contactor_pin, ON);
|
||||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_IDLE;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: Disabling Precharge bms not standby/active or equipment stop\n");
|
||||
#endif
|
||||
} else if (currentMillis - prechargeStartTime >= MAX_PRECHARGE_TIME_MS ||
|
||||
datalayer.battery.status.real_bms_status == BMS_FAULT) {
|
||||
pinMode(hia4v1_pin, OUTPUT);
|
||||
digitalWrite(hia4v1_pin, LOW);
|
||||
digitalWrite(inverter_disconnect_contactor_pin, ON);
|
||||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_FAILURE;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: CRITICAL FAILURE (timeout/BMS fault) -> REQUIRES REBOOT\n");
|
||||
#endif
|
||||
set_event(EVENT_AUTOMATIC_PRECHARGE_FAILURE, 0);
|
||||
// Force stop any further precharge attempts
|
||||
datalayer.system.settings.start_precharging = false;
|
||||
|
||||
// Add event
|
||||
} else if (datalayer.system.status.battery_allows_contactor_closing) {
|
||||
pinMode(hia4v1_pin, OUTPUT);
|
||||
digitalWrite(hia4v1_pin, LOW);
|
||||
digitalWrite(inverter_disconnect_contactor_pin, ON);
|
||||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_COMPLETED;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: Disabled (contacts closed) -> COMPLETED\n");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case AUTO_PRECHARGE_COMPLETED:
|
||||
if (datalayer.system.settings.equipment_stop_active || datalayer.battery.status.bms_status != ACTIVE) {
|
||||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_IDLE;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: equipment stop activated -> IDLE\n");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -172,9 +157,7 @@ void handle_precharge_control(unsigned long currentMillis) {
|
|||
datalayer.system.status.precharge_status = AUTO_PRECHARGE_IDLE;
|
||||
pinMode(hia4v1_pin, OUTPUT);
|
||||
digitalWrite(hia4v1_pin, LOW);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Precharge: equipment stop activated -> IDLE\n");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ struct DATALAYER_BATTERY_STATUS_TYPE {
|
|||
real_bms_status_enum real_bms_status = BMS_DISCONNECTED;
|
||||
|
||||
/** LED mode, customizable by user */
|
||||
led_mode_enum led_mode = LED_MODE;
|
||||
led_mode_enum led_mode = CLASSIC;
|
||||
};
|
||||
|
||||
struct DATALAYER_BATTERY_SETTINGS_TYPE {
|
||||
|
@ -241,6 +241,16 @@ struct DATALAYER_SYSTEM_INFO_TYPE {
|
|||
size_t logged_can_messages_offset = 0;
|
||||
/** bool, determines if CAN messages should be logged for webserver */
|
||||
bool can_logging_active = false;
|
||||
/** bool, determines if USB serial logging should occur */
|
||||
bool CAN_usb_logging_active = false;
|
||||
/** bool, determines if USB serial logging should occur */
|
||||
bool CAN_SD_logging_active = false;
|
||||
/** bool, determines if USB serial logging should occur */
|
||||
bool usb_logging_active = false;
|
||||
/** bool, determines if general logging should be active for webserver */
|
||||
bool web_logging_active = false;
|
||||
/** bool, determines if general logging to SD card should be active */
|
||||
bool SD_logging_active = false;
|
||||
/** uint8_t, enumeration which CAN interface should be used for log playback */
|
||||
uint8_t can_replay_interface = CAN_NATIVE;
|
||||
/** bool, determines if CAN replay should loop or not */
|
||||
|
|
|
@ -319,9 +319,7 @@ static bool publish_common_info(void) {
|
|||
|
||||
serializeJson(doc, mqtt_msg);
|
||||
if (mqtt_publish(state_topic.c_str(), mqtt_msg, false) == false) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
doc.clear();
|
||||
|
@ -392,9 +390,7 @@ static bool publish_cell_voltages(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
doc.clear();
|
||||
|
@ -413,9 +409,7 @@ static bool publish_cell_voltages(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic_2.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell voltage MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
doc.clear();
|
||||
|
@ -440,9 +434,7 @@ static bool publish_cell_balancing(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell balancing MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
doc.clear();
|
||||
|
@ -460,9 +452,7 @@ static bool publish_cell_balancing(void) {
|
|||
serializeJson(doc, mqtt_msg, sizeof(mqtt_msg));
|
||||
|
||||
if (!mqtt_publish(state_topic_2.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Cell balancing MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
doc.clear();
|
||||
|
@ -523,9 +513,7 @@ bool publish_events() {
|
|||
|
||||
serializeJson(doc, mqtt_msg);
|
||||
if (!mqtt_publish(state_topic.c_str(), mqtt_msg, false)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Common info MQTT msg could not be sent");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
} else {
|
||||
set_event_MQTTpublished(event_handle);
|
||||
|
@ -541,9 +529,7 @@ bool publish_events() {
|
|||
static bool publish_buttons_discovery(void) {
|
||||
if (ha_autodiscovery_enabled) {
|
||||
if (ha_buttons_published == false) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Publishing buttons discovery");
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
static JsonDocument doc;
|
||||
for (int i = 0; i < sizeof(buttonConfigs) / sizeof(buttonConfigs[0]); i++) {
|
||||
|
@ -573,16 +559,12 @@ void mqtt_message_received(char* topic_raw, int topic_len, char* data, int data_
|
|||
|
||||
char* topic = strndup(topic_raw, topic_len);
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("MQTT message arrived: [%.*s]\n", topic_len, topic);
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
#ifdef REMOTE_BMS_RESET
|
||||
const char* bmsreset_topic = generateButtonTopic("BMSRESET").c_str();
|
||||
if (strcmp(topic, bmsreset_topic) == 0) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Triggering BMS reset");
|
||||
#endif // DEBUG_LOG
|
||||
start_bms_reset();
|
||||
}
|
||||
#endif // REMOTE_BMS_RESET
|
||||
|
@ -616,21 +598,16 @@ static void mqtt_event_handler(void* handler_args, esp_event_base_t base, int32_
|
|||
|
||||
publish_buttons_discovery();
|
||||
subscribe();
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MQTT connected");
|
||||
#endif // DEBUG_LOG
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
set_event(EVENT_MQTT_DISCONNECT, 0);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MQTT disconnected!");
|
||||
#endif // DEBUG_LOG
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
mqtt_message_received(event->topic, event->topic_len, event->data, event->data_len);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MQTT_ERROR");
|
||||
logging.print("reported from esp-tls");
|
||||
logging.println(event->error_handle->esp_tls_last_esp_err);
|
||||
|
@ -638,7 +615,6 @@ static void mqtt_event_handler(void* handler_args, esp_event_base_t base, int32_
|
|||
logging.println(event->error_handle->esp_tls_stack_err);
|
||||
logging.print("captured as transport's socket errno");
|
||||
logging.println(strerror(event->error_handle->esp_transport_sock_errno));
|
||||
#endif // DEBUG_LOG
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -723,9 +699,7 @@ void mqtt_loop(void) {
|
|||
if (client_started == false) {
|
||||
esp_mqtt_client_start(client);
|
||||
client_started = true;
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("MQTT initialized");
|
||||
#endif // DEBUG_LOG
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,9 +63,7 @@ void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir) {
|
|||
currentTime / 1000, currentTime % 1000, (msgDir == MSG_RX ? "RX0" : "TX1"), frame.ID, frame.DLC);
|
||||
|
||||
if (xRingbufferSend(can_bufferHandle, &messagestr_buffer, size, pdMS_TO_TICKS(2)) != pdTRUE) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Failed to send message to can ring buffer!");
|
||||
#endif // DEBUG_VIA_USB
|
||||
logging.println("Failed to send message to can ring buffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -77,9 +75,7 @@ void add_can_frame_to_buffer(CAN_frame frame, frameDirection msgDir) {
|
|||
size = snprintf(messagestr_buffer, sizeof(messagestr_buffer), "%02X\n", frame.data.u8[i]);
|
||||
|
||||
if (xRingbufferSend(can_bufferHandle, &messagestr_buffer, size, pdMS_TO_TICKS(2)) != pdTRUE) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Failed to send message to can ring buffer!");
|
||||
#endif // DEBUG_VIA_USB
|
||||
logging.println("Failed to send message to can ring buffer!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -127,9 +123,7 @@ void add_log_to_buffer(const uint8_t* buffer, size_t size) {
|
|||
return;
|
||||
|
||||
if (xRingbufferSend(log_bufferHandle, buffer, size, pdMS_TO_TICKS(1)) != pdTRUE) {
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Failed to send message to log ring buffer!");
|
||||
#endif // DEBUG_VIA_USB
|
||||
logging.println("Failed to send message to log ring buffer!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -161,25 +155,22 @@ void write_log_to_sdcard() {
|
|||
}
|
||||
|
||||
void init_logging_buffers() {
|
||||
#if defined(LOG_CAN_TO_SD)
|
||||
|
||||
if (datalayer.system.info.CAN_SD_logging_active) {
|
||||
can_bufferHandle = xRingbufferCreate(32 * 1024, RINGBUF_TYPE_BYTEBUF);
|
||||
if (can_bufferHandle == NULL) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Failed to create CAN ring buffer!");
|
||||
#endif // DEBUG_LOG
|
||||
return;
|
||||
}
|
||||
#endif // defined(LOG_CAN_TO_SD)
|
||||
}
|
||||
|
||||
#if defined(LOG_TO_SD)
|
||||
if (datalayer.system.info.SD_logging_active) {
|
||||
log_bufferHandle = xRingbufferCreate(1024, RINGBUF_TYPE_BYTEBUF);
|
||||
if (log_bufferHandle == NULL) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Failed to create log ring buffer!");
|
||||
#endif // DEBUG_LOG
|
||||
return;
|
||||
}
|
||||
#endif // defined(LOG_TO_SD)
|
||||
}
|
||||
}
|
||||
|
||||
bool init_sdcard() {
|
||||
|
@ -196,22 +187,16 @@ bool init_sdcard() {
|
|||
SD_MMC.setPins(sclk_pin, mosi_pin, miso_pin);
|
||||
if (!SD_MMC.begin("/root", true, true, SDMMC_FREQ_HIGHSPEED)) {
|
||||
set_event_latched(EVENT_SD_INIT_FAILED, 0);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SD Card initialization failed!");
|
||||
#endif // DEBUG_LOG
|
||||
return false;
|
||||
}
|
||||
|
||||
clear_event(EVENT_SD_INIT_FAILED);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("SD Card initialization successful.");
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
sd_card_active = true;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
log_sdcard_details();
|
||||
#endif // DEBUG_LOG
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -159,9 +159,6 @@ void reset_all_events() {
|
|||
}
|
||||
events.level = EVENT_LEVEL_INFO;
|
||||
update_bms_status();
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("All events have been cleared.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_event_MQTTpublished(EVENTS_ENUM_TYPE event) {
|
||||
|
|
|
@ -25,6 +25,7 @@ class LED {
|
|||
void heartbeat_run(void);
|
||||
|
||||
uint8_t up_down(float middle_point_f);
|
||||
int LED_PERIOD_MS = 3000;
|
||||
};
|
||||
|
||||
bool led_init(void);
|
||||
|
|
|
@ -3,19 +3,17 @@
|
|||
#include "../../datalayer/datalayer.h"
|
||||
#include "../sdcard/sdcard.h"
|
||||
|
||||
#if defined(LOG_CAN_TO_SD) || defined(LOG_TO_SD)
|
||||
#if !defined(HW_LILYGO)
|
||||
#error The SD card logging feature is only available on LilyGo hardware
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_LINE_LENGTH_PRINTF 128
|
||||
#define MAX_LENGTH_TIME_STR 14
|
||||
|
||||
bool previous_message_was_newline = true;
|
||||
|
||||
void Logging::add_timestamp(size_t size) {
|
||||
#ifdef DEBUG_LOG
|
||||
// Check if any logging is enabled at runtime
|
||||
if (!datalayer.system.info.web_logging_active && !datalayer.system.info.usb_logging_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* message_string = datalayer.system.info.logged_can_messages;
|
||||
int offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
size_t message_string_size = sizeof(datalayer.system.info.logged_can_messages);
|
||||
|
@ -23,7 +21,7 @@ void Logging::add_timestamp(size_t size) {
|
|||
char* timestr;
|
||||
static char timestr_buffer[MAX_LENGTH_TIME_STR];
|
||||
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (datalayer.system.info.web_logging_active) {
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
/* If web debug is active and can logging is inactive,
|
||||
* we use the debug logging memory directly for writing the timestring */
|
||||
|
@ -34,32 +32,33 @@ void Logging::add_timestamp(size_t size) {
|
|||
} else {
|
||||
timestr = timestr_buffer;
|
||||
}
|
||||
#else
|
||||
} else {
|
||||
timestr = timestr_buffer;
|
||||
#endif // DEBUG_VIA_WEB
|
||||
}
|
||||
|
||||
offset += min(MAX_LENGTH_TIME_STR - 1,
|
||||
snprintf(timestr, MAX_LENGTH_TIME_STR, "%8lu.%03lu ", currentTime / 1000, currentTime % 1000));
|
||||
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
if (datalayer.system.info.web_logging_active && !datalayer.system.info.can_logging_active) {
|
||||
datalayer.system.info.logged_can_messages_offset = offset; // Update offset in buffer
|
||||
}
|
||||
#endif // DEBUG_VIA_WEB
|
||||
|
||||
// LOG_TO_SD remains as compile-time option for now
|
||||
#ifdef LOG_TO_SD
|
||||
add_log_to_buffer((uint8_t*)timestr, MAX_LENGTH_TIME_STR);
|
||||
#endif // LOG_TO_SD
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
if (datalayer.system.info.usb_logging_active) {
|
||||
Serial.write(timestr);
|
||||
#endif // DEBUG_VIA_USB
|
||||
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
}
|
||||
|
||||
size_t Logging::write(const uint8_t* buffer, size_t size) {
|
||||
#ifdef DEBUG_LOG
|
||||
// Check if any logging is enabled at runtime
|
||||
if (!datalayer.system.info.web_logging_active && !datalayer.system.info.usb_logging_active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (previous_message_was_newline) {
|
||||
add_timestamp(size);
|
||||
}
|
||||
|
@ -67,11 +66,12 @@ size_t Logging::write(const uint8_t* buffer, size_t size) {
|
|||
#ifdef LOG_TO_SD
|
||||
add_log_to_buffer(buffer, size);
|
||||
#endif
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
||||
if (datalayer.system.info.usb_logging_active) {
|
||||
Serial.write(buffer, size);
|
||||
#endif
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
}
|
||||
|
||||
if (datalayer.system.info.web_logging_active && !datalayer.system.info.can_logging_active) {
|
||||
char* message_string = datalayer.system.info.logged_can_messages;
|
||||
int offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
size_t message_string_size = sizeof(datalayer.system.info.logged_can_messages);
|
||||
|
@ -82,16 +82,17 @@ size_t Logging::write(const uint8_t* buffer, size_t size) {
|
|||
memcpy(message_string + offset, buffer, size);
|
||||
datalayer.system.info.logged_can_messages_offset = offset + size; // Update offset in buffer
|
||||
}
|
||||
#endif // DEBUG_VIA_WEB
|
||||
|
||||
previous_message_was_newline = buffer[size - 1] == '\n';
|
||||
return size;
|
||||
#endif // DEBUG_LOG
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Logging::printf(const char* fmt, ...) {
|
||||
#ifdef DEBUG_LOG
|
||||
// Check if any logging is enabled at runtime
|
||||
if (!datalayer.system.info.web_logging_active && !datalayer.system.info.usb_logging_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (previous_message_was_newline) {
|
||||
add_timestamp(MAX_LINE_LENGTH_PRINTF);
|
||||
}
|
||||
|
@ -101,7 +102,8 @@ void Logging::printf(const char* fmt, ...) {
|
|||
int offset = datalayer.system.info.logged_can_messages_offset; // Keeps track of the current position in the buffer
|
||||
static char buffer[MAX_LINE_LENGTH_PRINTF];
|
||||
char* message_buffer;
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
|
||||
if (datalayer.system.info.web_logging_active) {
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
/* If web debug is active and can logging is inactive,
|
||||
* we use the debug logging memory directly for writing the output */
|
||||
|
@ -113,9 +115,9 @@ void Logging::printf(const char* fmt, ...) {
|
|||
} else {
|
||||
message_buffer = buffer;
|
||||
}
|
||||
#else
|
||||
} else {
|
||||
message_buffer = buffer;
|
||||
#endif // DEBUG_VIA_WEB
|
||||
}
|
||||
|
||||
va_list(args);
|
||||
va_start(args, fmt);
|
||||
|
@ -126,18 +128,15 @@ void Logging::printf(const char* fmt, ...) {
|
|||
add_log_to_buffer((uint8_t*)message_buffer, size);
|
||||
#endif // LOG_TO_SD
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
if (datalayer.system.info.usb_logging_active) {
|
||||
Serial.write(message_buffer, size);
|
||||
#endif // DEBUG_VIA_USB
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (!datalayer.system.info.can_logging_active) {
|
||||
if (datalayer.system.info.web_logging_active && !datalayer.system.info.can_logging_active) {
|
||||
// Data was already added to buffer, just move offset
|
||||
datalayer.system.info.logged_can_messages_offset =
|
||||
offset + size; // Keeps track of the current position in the buffer
|
||||
}
|
||||
#endif // DEBUG_VIA_WEB
|
||||
|
||||
previous_message_was_newline = message_buffer[size - 1] == '\n';
|
||||
#endif // DEBUG_LOG
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#ifndef __LOGGING_H__
|
||||
#define __LOGGING_H__
|
||||
|
||||
#include <Print.h>
|
||||
#include <inttypes.h>
|
||||
#include "../../../USER_SETTINGS.h"
|
||||
#include "../../datalayer/datalayer.h"
|
||||
#include "types.h"
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
// Real implementation for production
|
||||
#include <Print.h>
|
||||
|
||||
class Logging : public Print {
|
||||
void add_timestamp(size_t size);
|
||||
|
||||
|
@ -13,18 +17,51 @@ class Logging : public Print {
|
|||
virtual size_t write(const uint8_t* buffer, size_t size);
|
||||
virtual size_t write(uint8_t) { return 0; }
|
||||
void printf(const char* fmt, ...);
|
||||
void log_bms_status(real_bms_status_enum bms_status);
|
||||
Logging() {}
|
||||
};
|
||||
|
||||
extern Logging logging;
|
||||
// Production macros
|
||||
#define DEBUG_PRINTF(fmt, ...) \
|
||||
do { \
|
||||
if (datalayer.system.info.web_logging_active || datalayer.system.info.usb_logging_active) { \
|
||||
logging.printf(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_PRINTLN(str) \
|
||||
do { \
|
||||
if (datalayer.system.info.web_logging_active || datalayer.system.info.usb_logging_active) { \
|
||||
logging.println(str); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
#define DEBUG_PRINTF(fmt, ...) logging.printf(fmt, ##__VA_ARGS__)
|
||||
#define DEBUG_PRINTLN(str) logging.println(str)
|
||||
#else
|
||||
// Mock implementation for tests
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
class Logging {
|
||||
public:
|
||||
// Mock methods that do nothing
|
||||
size_t write(const uint8_t* buffer, size_t size) { return size; }
|
||||
size_t write(uint8_t) { return 0; }
|
||||
|
||||
static void printf(const char* fmt, ...) {
|
||||
// Empty implementation - silence unused parameter warnings
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
static void println(const char* str) { (void)str; }
|
||||
|
||||
Logging() {}
|
||||
};
|
||||
|
||||
// Test macros - empty implementations
|
||||
#define DEBUG_PRINTF(fmt, ...) ((void)0)
|
||||
#define DEBUG_PRINTLN(str) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
extern Logging logging;
|
||||
|
||||
#endif // __LOGGING_H__
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "../../datalayer/datalayer.h"
|
||||
#include "index_html.h"
|
||||
|
||||
#if defined(DEBUG_VIA_WEB) || defined(LOG_TO_SD)
|
||||
char* strnchr(const char* s, int c, size_t n) {
|
||||
// Like strchr, but only searches the first 'n' bytes of the string.
|
||||
|
||||
|
@ -54,13 +53,13 @@ String debug_logger_processor(void) {
|
|||
".can-message { background-color: #404E57; margin-bottom: 5px; padding: 10px; border-radius: 5px; font-family: "
|
||||
"monospace; }";
|
||||
content += "</style>";
|
||||
#ifdef DEBUG_VIA_WEB
|
||||
if (datalayer.system.info.web_logging_active) {
|
||||
content += "<button onclick='refreshPage()'>Refresh data</button> ";
|
||||
#endif
|
||||
}
|
||||
content += "<button onclick='exportLog()'>Export to .txt</button> ";
|
||||
#ifdef LOG_TO_SD
|
||||
if (datalayer.system.info.SD_logging_active) {
|
||||
content += "<button onclick='deleteLog()'>Delete log file</button> ";
|
||||
#endif
|
||||
}
|
||||
content += "<button onclick='goToMainPage()'>Back to main page</button>";
|
||||
|
||||
// Start a new block for the debug log messages
|
||||
|
@ -99,12 +98,11 @@ String debug_logger_processor(void) {
|
|||
content += "<script>";
|
||||
content += "function refreshPage(){ location.reload(true); }";
|
||||
content += "function exportLog() { window.location.href = '/export_log'; }";
|
||||
#ifdef LOG_TO_SD
|
||||
if (datalayer.system.info.SD_logging_active) {
|
||||
content += "function deleteLog() { window.location.href = '/delete_log'; }";
|
||||
#endif
|
||||
}
|
||||
content += "function goToMainPage() { window.location.href = '/'; }";
|
||||
content += "</script>";
|
||||
content += index_html_footer;
|
||||
return content;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -46,12 +46,6 @@ String events_processor(const String& var) {
|
|||
EVENTS_ENUM_TYPE event_handle = event.event_handle;
|
||||
event_pointer = event.event_pointer;
|
||||
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Showing Event: " + String(get_event_enum_string(event_handle)) +
|
||||
" count: " + String(event_pointer->occurences) + " seconds: " + String(event_pointer->timestamp) +
|
||||
" data: " + String(event_pointer->data) +
|
||||
" level: " + String(get_event_level_string(event_handle)));
|
||||
#endif
|
||||
content.concat("<div class='event'>");
|
||||
content.concat("<div>" + String(get_event_enum_string(event_handle)) + "</div>");
|
||||
content.concat("<div>" + String(get_event_level_string(event_handle)) + "</div>");
|
||||
|
|
|
@ -93,6 +93,8 @@ String options_from_map(int selected, const TMap& value_name_map) {
|
|||
return options;
|
||||
}
|
||||
|
||||
static const std::map<int, String> led_modes = {{0, "Classic"}, {1, "Energy Flow"}, {2, "Heartbeat"}};
|
||||
|
||||
static const std::map<int, String> tesla_countries = {
|
||||
{21843, "US (USA)"}, {17217, "CA (Canada)"}, {18242, "GB (UK & N Ireland)"},
|
||||
{17483, "DK (Denmark)"}, {17477, "DE (Germany)"}, {16725, "AU (Australia)"}};
|
||||
|
@ -281,6 +283,26 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti
|
|||
return settings.getBool("WIFIAPENABLED", wifiap_enabled) ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "CANLOGUSB") {
|
||||
return settings.getBool("CANLOGUSB") ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "USBENABLED") {
|
||||
return settings.getBool("USBENABLED") ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "WEBENABLED") {
|
||||
return settings.getBool("WEBENABLED") ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "CANLOGSD") {
|
||||
return settings.getBool("CANLOGSD") ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "SDLOGENABLED") {
|
||||
return settings.getBool("SDLOGENABLED") ? "checked" : "";
|
||||
}
|
||||
|
||||
if (var == "MQTTENABLED") {
|
||||
return settings.getBool("MQTTENABLED") ? "checked" : "";
|
||||
}
|
||||
|
@ -555,6 +577,10 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti
|
|||
return options_from_map(settings.getUInt("GTWPACK", 0), tesla_pack);
|
||||
}
|
||||
|
||||
if (var == "LEDMODE") {
|
||||
return options_from_map(settings.getUInt("LEDMODE", 0), led_modes);
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
|
@ -944,6 +970,25 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
|||
<label>Custom hostname: </label>
|
||||
<input type='text' name='HOSTNAME' value="%HOSTNAME%" />
|
||||
|
||||
<label>Enable CAN logging via USB serial: </label>
|
||||
<input type='checkbox' name='CANLOGUSB' value='on' style='margin-left: 0;' %CANLOGUSB% />
|
||||
|
||||
<label>Enable logging via USB serial: </label>
|
||||
<input type='checkbox' name='USBENABLED' value='on' style='margin-left: 0;' %USBENABLED% />
|
||||
|
||||
<label>Enable logging via Webserver: </label>
|
||||
<input type='checkbox' name='WEBENABLED' value='on' style='margin-left: 0;' %WEBENABLED% />
|
||||
|
||||
<label>Enable CAN logging via SD card: </label>
|
||||
<input type='checkbox' name='CANLOGSD' value='on' style='margin-left: 0;' %CANLOGSD% />
|
||||
|
||||
<label>Enable logging via SD card: </label>
|
||||
<input type='checkbox' name='SDLOGENABLED' value='on' style='margin-left: 0;' %SDLOGENABLED% />
|
||||
|
||||
<label for='LEDMODE'>Status LED pattern: </label><select name='LEDMODE' id='LEDMODE'>
|
||||
%LEDMODE%
|
||||
</select>
|
||||
|
||||
<label>Enable MQTT: </label>
|
||||
<input type='checkbox' name='MQTTENABLED' value='on' style='margin-left: 0;' %MQTTENABLED% />
|
||||
|
||||
|
|
|
@ -267,13 +267,13 @@ void init_webserver() {
|
|||
}
|
||||
});
|
||||
|
||||
#if defined(DEBUG_VIA_WEB) || defined(LOG_TO_SD)
|
||||
if (datalayer.system.info.web_logging_active || datalayer.system.info.SD_logging_active) {
|
||||
// Route for going to debug logging web page
|
||||
server.on("/log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
AsyncWebServerResponse* response = request->beginResponse(200, "text/html", debug_logger_processor());
|
||||
request->send(response);
|
||||
});
|
||||
#endif // DEBUG_VIA_WEB
|
||||
}
|
||||
|
||||
// Define the handler to stop can logging
|
||||
server.on("/stop_can_logging", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
|
@ -289,7 +289,20 @@ void init_webserver() {
|
|||
},
|
||||
handleFileUpload);
|
||||
|
||||
#ifndef LOG_CAN_TO_SD
|
||||
if (datalayer.system.info.CAN_SD_logging_active) {
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
pause_can_writing();
|
||||
request->send(SD_MMC, CAN_LOG_FILE, String(), true);
|
||||
resume_can_writing();
|
||||
});
|
||||
|
||||
// Define the handler to delete can log
|
||||
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
delete_can_log();
|
||||
request->send(200, "text/plain", "Log file deleted");
|
||||
});
|
||||
} else {
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String logs = String(datalayer.system.info.logged_can_messages);
|
||||
|
@ -316,24 +329,9 @@ void init_webserver() {
|
|||
response->addHeader("Content-Disposition", String("attachment; filename=\"") + String(filename) + "\"");
|
||||
request->send(response);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LOG_CAN_TO_SD
|
||||
// Define the handler to export can log
|
||||
server.on("/export_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
pause_can_writing();
|
||||
request->send(SD_MMC, CAN_LOG_FILE, String(), true);
|
||||
resume_can_writing();
|
||||
});
|
||||
|
||||
// Define the handler to delete can log
|
||||
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
delete_can_log();
|
||||
request->send(200, "text/plain", "Log file deleted");
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef LOG_TO_SD
|
||||
if (datalayer.system.info.SD_logging_active) {
|
||||
// Define the handler to delete log file
|
||||
server.on("/delete_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
delete_log();
|
||||
|
@ -346,9 +344,7 @@ void init_webserver() {
|
|||
request->send(SD_MMC, LOG_FILE, String(), true);
|
||||
resume_log_writing();
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifndef LOG_TO_SD
|
||||
} else {
|
||||
// Define the handler to export debug log
|
||||
server.on("/export_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
String logs = String(datalayer.system.info.logged_can_messages);
|
||||
|
@ -375,7 +371,7 @@ void init_webserver() {
|
|||
response->addHeader("Content-Disposition", String("attachment; filename=\"") + String(filename) + "\"");
|
||||
request->send(response);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
// Route for going to cellmonitor web page
|
||||
def_route_with_auth("/cellmonitor", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||
|
@ -413,8 +409,9 @@ void init_webserver() {
|
|||
};
|
||||
|
||||
const char* boolSettingNames[] = {
|
||||
"DBLBTR", "CNTCTRL", "CNTCTRLDBL", "PWMCNTCTRL", "PERBMSRESET", "REMBMSRESET", "CANFDASCAN",
|
||||
"WIFIAPENABLED", "MQTTENABLED", "HADISC", "MQTTTOPICS", "INVICNT", "GTWRHD", "DIGITALHVIL",
|
||||
"DBLBTR", "CNTCTRL", "CNTCTRLDBL", "PWMCNTCTRL", "PERBMSRESET", "SDLOGENABLED", "REMBMSRESET",
|
||||
"USBENABLED", "CANLOGUSB", "WEBENABLED", "CANFDASCAN", "CANLOGSD", "WIFIAPENABLED", "MQTTENABLED",
|
||||
"HADISC", "MQTTTOPICS", "INVICNT", "GTWRHD", "DIGITALHVIL",
|
||||
};
|
||||
|
||||
// Handles the form POST from UI to save settings of the common image
|
||||
|
@ -530,6 +527,9 @@ void init_webserver() {
|
|||
} else if (p->name() == "GTWPACK") {
|
||||
auto type = atoi(p->value().c_str());
|
||||
settings.saveUInt("GTWPACK", type);
|
||||
} else if (p->name() == "LEDMODE") {
|
||||
auto type = atoi(p->value().c_str());
|
||||
settings.saveUInt("LEDMODE", type);
|
||||
}
|
||||
|
||||
for (auto& boolSetting : boolSettings) {
|
||||
|
@ -1406,9 +1406,9 @@ String processor(const String& var) {
|
|||
content += "<button onclick='Advanced()'>More Battery Info</button> ";
|
||||
content += "<button onclick='CANlog()'>CAN logger</button> ";
|
||||
content += "<button onclick='CANreplay()'>CAN replay</button> ";
|
||||
#if defined(DEBUG_VIA_WEB) || defined(LOG_TO_SD)
|
||||
if (datalayer.system.info.web_logging_active || datalayer.system.info.SD_logging_active) {
|
||||
content += "<button onclick='Log()'>Log</button> ";
|
||||
#endif // DEBUG_VIA_WEB
|
||||
}
|
||||
content += "<button onclick='Cellmon()'>Cellmonitor</button> ";
|
||||
content += "<button onclick='Events()'>Events</button> ";
|
||||
content += "<button onclick='askReboot()'>Reboot Emulator</button>";
|
||||
|
@ -1488,9 +1488,7 @@ void onOTAProgress(size_t current, size_t final) {
|
|||
// Log every 1 second
|
||||
if (millis() - ota_progress_millis > 1000) {
|
||||
ota_progress_millis = millis();
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
|
||||
#endif // DEBUG_LOG
|
||||
// Reset the "watchdog"
|
||||
ota_timeout_timer.reset();
|
||||
}
|
||||
|
@ -1507,13 +1505,9 @@ void onOTAEnd(bool success) {
|
|||
// Max Charge/Discharge = 0; CAN = stop; contactors = open
|
||||
setBatteryPause(true, true, true, false);
|
||||
// a reboot will be done by the OTA library. no need to do anything here
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("OTA update finished successfully!");
|
||||
#endif // DEBUG_LOG
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("There was an error during OTA update!");
|
||||
#endif // DEBUG_LOG
|
||||
//try to Resume the battery pause and CAN communication
|
||||
setBatteryPause(false, false);
|
||||
}
|
||||
|
|
|
@ -130,33 +130,22 @@ void wifi_monitor() {
|
|||
// Try WiFi.reconnect() if it was successfully connected at least once
|
||||
if (hasConnectedBefore) {
|
||||
lastReconnectAttempt = currentMillis; // Reset reconnection attempt timer
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt...");
|
||||
#endif
|
||||
if (WiFi.reconnect()) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt sucess...");
|
||||
#endif
|
||||
reconnectAttempts = 0; // Reset the attempt counter on successful reconnect
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi reconnect attempt error...");
|
||||
#endif
|
||||
reconnectAttempts++;
|
||||
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Failed to reconnect multiple times, forcing a full connection attempt...");
|
||||
#endif
|
||||
FullReconnectToWiFi();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no previous connection, force a full connection attempt
|
||||
if (currentMillis - lastReconnectAttempt > current_full_reconnect_interval) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("No previous OK connection, force a full connection attempt...");
|
||||
#endif
|
||||
|
||||
wifiap_enabled = true;
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
init_WiFi_AP();
|
||||
|
@ -188,17 +177,13 @@ void connectToWiFi() {
|
|||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Connecting to Wi-Fi...");
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTF("Connecting to Wi-Fi SSID: %s, password: %s, Channel: %d\n", ssid.c_str(), password.c_str(),
|
||||
wifi_channel);
|
||||
WiFi.begin(ssid.c_str(), password.c_str(), wifi_channel);
|
||||
} else {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi already connected.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,11 +205,9 @@ void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||
void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
//clear disconnects events if we got a IP
|
||||
clear_event(EVENT_WIFI_DISCONNECT);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.print("Wi-Fi Got IP. ");
|
||||
logging.print("IP address: ");
|
||||
logging.println(WiFi.localIP().toString());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Event handler for Wi-Fi disconnection
|
||||
|
@ -233,9 +216,7 @@ void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||
if (connected_once) {
|
||||
set_event(EVENT_WIFI_DISCONNECT, 0);
|
||||
}
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Wi-Fi disconnected.");
|
||||
#endif
|
||||
//we dont do anything here, the reconnect will be handled by the monitor
|
||||
//too many events received when the connection is lost
|
||||
//normal reconnect retry start at first 2 seconds
|
||||
|
@ -254,9 +235,7 @@ void init_mDNS() {
|
|||
|
||||
// Initialize mDNS .local resolution
|
||||
if (!MDNS.begin(mdnsHost)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Error setting up MDNS responder!");
|
||||
#endif
|
||||
} else {
|
||||
// Advertise via bonjour the service so we can auto discover these battery emulators on the local network.
|
||||
MDNS.addService(mdnsHost, "tcp", 80);
|
||||
|
|
|
@ -525,38 +525,21 @@ void FoxessCanInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
if (rx_frame.data.u8[0] == 0x03) { //0x1871 [0x03, 0x06, 0x17, 0x05, 0x09, 0x09, 0x28, 0x22]
|
||||
//This message is sent by the inverter every '6' seconds (0.5s after the pack serial numbers)
|
||||
//and contains a timestamp in bytes 2-7 i.e. <YY>,<MM>,<DD>,<HH>,<mm>,<ss>
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter sends current time and date");
|
||||
#endif
|
||||
} else if (rx_frame.data.u8[0] == 0x01) {
|
||||
if (rx_frame.data.u8[4] == 0x00) {
|
||||
// Inverter wants to know bms info (every 1s)
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter requests 1s BMS info, we reply");
|
||||
#endif
|
||||
send_bms_info = true;
|
||||
} else if (rx_frame.data.u8[4] == 0x01) { // b4 0x01 , 0x1871 [0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00]
|
||||
//Inverter wants to know all individual cellvoltages (occurs 6 seconds after valid BMS reply)
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter requests individual battery pack status, we reply");
|
||||
#endif
|
||||
send_individual_pack_status = true;
|
||||
} else if (rx_frame.data.u8[4] == 0x04) { // b4 0x01 , 0x1871 [0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00]
|
||||
//Inverter wants to know all individual cellvoltages (occurs 6 seconds after valid BMS reply)
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter requests cellvoltages and temps, we reply");
|
||||
#endif
|
||||
send_cellvoltages = true;
|
||||
}
|
||||
} else if (rx_frame.data.u8[0] == 0x02) { //0x1871 [0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00]
|
||||
// Ack message
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter acks, no reply needed");
|
||||
#endif
|
||||
} else if (rx_frame.data.u8[0] == 0x05) { //0x1871 [0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Inverter wants to know serial numbers, we reply");
|
||||
#endif
|
||||
// Inverter wants to know serial numbers, we reply
|
||||
send_serial_numbers = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,13 @@ void KostalInverterProtocol::float2frame(uint8_t* arr, float value, uint8_t fram
|
|||
}
|
||||
|
||||
static void dbg_timestamp(void) {
|
||||
#ifdef DEBUG_KOSTAL_RS485_DATA
|
||||
logging.print("[");
|
||||
logging.print(millis());
|
||||
logging.print(" ms] ");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dbg_frame(uint8_t* frame, int len, const char* prefix) {
|
||||
dbg_timestamp();
|
||||
#ifdef DEBUG_KOSTAL_RS485_DATA
|
||||
logging.print(prefix);
|
||||
logging.print(": ");
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
|
@ -34,26 +31,11 @@ static void dbg_frame(uint8_t* frame, int len, const char* prefix) {
|
|||
logging.print(" ");
|
||||
}
|
||||
logging.println("");
|
||||
#endif
|
||||
#ifdef DEBUG_KOSTAL_RS485_DATA_USB
|
||||
Serial.print(prefix);
|
||||
Serial.print(": ");
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
if (frame[i] < 0x10) {
|
||||
Serial.print("0");
|
||||
}
|
||||
Serial.print(frame[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dbg_message(const char* msg) {
|
||||
dbg_timestamp();
|
||||
#ifdef DEBUG_KOSTAL_RS485_DATA
|
||||
logging.println(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing#Encoding_examples */
|
||||
|
|
|
@ -8,13 +8,6 @@
|
|||
#define SELECTED_INVERTER_CLASS KostalInverterProtocol
|
||||
#endif
|
||||
|
||||
//#define DEBUG_KOSTAL_RS485_DATA // Enable this line to get TX / RX printed out via logging
|
||||
//#define DEBUG_KOSTAL_RS485_DATA_USB // Enable this line to get TX / RX printed out via USB
|
||||
|
||||
#if defined(DEBUG_KOSTAL_RS485_DATA) && !defined(DEBUG_LOG)
|
||||
#error "enable LOG_TO_SD, DEBUG_VIA_USB or DEBUG_VIA_WEB in order to use DEBUG_KOSTAL_RS485_DATA"
|
||||
#endif
|
||||
|
||||
class KostalInverterProtocol : public Rs485InverterProtocol {
|
||||
public:
|
||||
const char* name() override { return Name; }
|
||||
|
|
|
@ -35,9 +35,7 @@ ModbusMessage ModbusInverterProtocol::FC03(ModbusMessage request) {
|
|||
if ((addr + words) > MBPV_MAX) {
|
||||
// Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC03 error: illegal request addr=%d words=%d\n", addr, words);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -48,10 +46,6 @@ ModbusMessage ModbusInverterProtocol::FC03(ModbusMessage request) {
|
|||
response.add((uint16_t)(mbPV[addr + i]));
|
||||
}
|
||||
|
||||
// #ifdef DEBUG_LOG
|
||||
// logging.printf("Modbus FC03 response: %d %d\n", addr, mbPV[addr]);
|
||||
// #endif
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -67,9 +61,7 @@ ModbusMessage ModbusInverterProtocol::FC06(ModbusMessage request) {
|
|||
if ((addr) > MBPV_MAX) {
|
||||
// Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC06 error: illegal request addr=%d val=%d\n", addr, val);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -97,18 +89,14 @@ ModbusMessage ModbusInverterProtocol::FC16(ModbusMessage request) {
|
|||
|| (words > 123)) // can't support more than this in request packet
|
||||
{ // Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC16 error: bad registers addr=%d words=%d bytes=%d\n", addr, words, bytes);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
// Address overflow?
|
||||
if ((addr + words) > MBPV_MAX) {
|
||||
// Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC16 error: overflow addr=%d words=%d\n", addr, words);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -145,20 +133,16 @@ ModbusMessage ModbusInverterProtocol::FC23(ModbusMessage request) {
|
|||
|| (read_words > 125)) // can't fit more than this in the response packet
|
||||
{ // Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_VALUE);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC23 error: bad registers write_addr=%d write_words=%d write_bytes=%d read_words=%d\n",
|
||||
write_addr, write_words, write_bytes, read_words);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
// Address overflow?
|
||||
if (((write_addr + write_words) > MBPV_MAX) ||
|
||||
((read_addr + read_words) > MBPV_MAX)) { // Yes - send respective error response
|
||||
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.printf("Modbus FC23 error: overflow write_addr=%d write_words=%d read_addr=%d read_words=%d\n", write_addr,
|
||||
write_words, read_addr, read_words);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,34 +107,11 @@ void PylonLvInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
void dump_frame(CAN_frame* frame) {
|
||||
Serial.print("[PYLON-LV] sending CAN frame ");
|
||||
Serial.print(frame->ID, HEX);
|
||||
Serial.print(": ");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print(frame->data.u8[i] >> 4, HEX);
|
||||
Serial.print(frame->data.u8[i] & 0xf, HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
void PylonLvInverter::transmit_can(unsigned long currentMillis) {
|
||||
|
||||
if (currentMillis - previousMillis1000ms >= 1000) {
|
||||
previousMillis1000ms = currentMillis;
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
dump_frame(&PYLON_351);
|
||||
dump_frame(&PYLON_355);
|
||||
dump_frame(&PYLON_356);
|
||||
dump_frame(&PYLON_359);
|
||||
dump_frame(&PYLON_35C);
|
||||
dump_frame(&PYLON_35E);
|
||||
#endif
|
||||
|
||||
transmit_can_frame(&PYLON_351);
|
||||
transmit_can_frame(&PYLON_355);
|
||||
transmit_can_frame(&PYLON_356);
|
||||
|
|
|
@ -227,9 +227,7 @@ void SmaBydHInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
break;
|
||||
case 0x5E7: //Message originating from SMA inverter - Pairing request
|
||||
case 0x660: //Message originating from SMA inverter - Pairing request
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Received SMA pairing request");
|
||||
#endif // DEBUG_LOG
|
||||
pairing_events++;
|
||||
set_event(EVENT_SMA_PAIRING, pairing_events);
|
||||
datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE;
|
||||
|
|
|
@ -218,9 +218,7 @@ void SmaBydHvsInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
break;
|
||||
case 0x5E7: //Message originating from SMA inverter - Pairing request
|
||||
case 0x660: //Message originating from SMA inverter - Pairing request
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Received SMA pairing request");
|
||||
#endif // DEBUG_LOG
|
||||
pairing_events++;
|
||||
set_event(EVENT_SMA_PAIRING, pairing_events);
|
||||
datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE;
|
||||
|
|
|
@ -126,9 +126,7 @@ void SmaTripowerInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
break;
|
||||
case 0x5E7: //Message originating from SMA inverter - Pairing request
|
||||
case 0x660: //Message originating from SMA inverter - Pairing request
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Received SMA pairing request");
|
||||
#endif // DEBUG_LOG
|
||||
pairing_events++;
|
||||
set_event(EVENT_SMA_PAIRING, pairing_events);
|
||||
datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE;
|
||||
|
|
|
@ -147,9 +147,7 @@ void SolaxInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
|
||||
switch (STATE) {
|
||||
case (BATTERY_ANNOUNCE):
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Solax Battery State: Announce");
|
||||
#endif
|
||||
datalayer.system.status.inverter_allows_contactor_closing = false;
|
||||
SOLAX_1875.data.u8[4] = (0x00); // Inform Inverter: Contactor 0=off, 1=on.
|
||||
for (uint8_t i = 0; i < number_of_batteries; i++) {
|
||||
|
@ -183,9 +181,7 @@ void SolaxInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
transmit_can_frame(&SOLAX_1878);
|
||||
transmit_can_frame(&SOLAX_1801); // Announce that the battery will be connected
|
||||
STATE = CONTACTOR_CLOSED; // Jump to Contactor Closed State
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("Solax Battery State: Contactor Closed");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case (CONTACTOR_CLOSED):
|
||||
|
@ -213,14 +209,10 @@ void SolaxInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
|||
if (rx_frame.ID == 0x1871 && rx_frame.data.u64 == __builtin_bswap64(0x0500010000000000)) {
|
||||
transmit_can_frame(&SOLAX_1881);
|
||||
transmit_can_frame(&SOLAX_1882);
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("1871 05-frame received from inverter");
|
||||
#endif
|
||||
}
|
||||
if (rx_frame.ID == 0x1871 && rx_frame.data.u8[0] == (0x03)) {
|
||||
#ifdef DEBUG_LOG
|
||||
logging.println("1871 03-frame received from inverter");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ ExternalProject_Get_Property(gtest source_dir binary_dir)
|
|||
# Create a libgtest target to be used as a dependency by test programs
|
||||
add_library(libgtest IMPORTED STATIC GLOBAL)
|
||||
add_dependencies(libgtest gtest)
|
||||
add_definitions(-DUNIT_TEST)
|
||||
|
||||
# Set libgtest properties
|
||||
if(WIN32)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "Logging.h"
|
||||
#include "Print.h"
|
||||
|
||||
#include "esp-hal-gpio.h"
|
||||
|
|
4
test/emul/Logging.cpp
Normal file
4
test/emul/Logging.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include "../../src/devboard/utils/logging.h"
|
||||
|
||||
// This creates the global instance that links against the real implementation
|
||||
Logging logging;
|
4
test/emul/Logging.h
Normal file
4
test/emul/Logging.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
// Include the real logging header which will provide the mock implementation
|
||||
#include "../../Software/src/devboard/utils/logging.h"
|
Loading…
Add table
Add a link
Reference in a new issue