Halfway to the finish line

This commit is contained in:
Cabooman 2024-02-11 13:13:47 +01:00
parent d9f3dbc3d0
commit 5e0893d3ca
3 changed files with 40 additions and 141 deletions

View file

@ -12,7 +12,7 @@
//#define CHADEMO_BATTERY //#define CHADEMO_BATTERY
//#define IMIEV_CZERO_ION_BATTERY //#define IMIEV_CZERO_ION_BATTERY
//#define KIA_HYUNDAI_64_BATTERY //#define KIA_HYUNDAI_64_BATTERY
//#define NISSAN_LEAF_BATTERY #define NISSAN_LEAF_BATTERY
//#define RENAULT_KANGOO_BATTERY //#define RENAULT_KANGOO_BATTERY
//#define RENAULT_ZOE_BATTERY //#define RENAULT_ZOE_BATTERY
//#define SANTA_FE_PHEV_BATTERY //#define SANTA_FE_PHEV_BATTERY
@ -21,7 +21,7 @@
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */ /* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
//#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus //#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
//#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU #define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
//#define LUNA2000_MODBUS //Enable this line to emulate a "Luna2000 battery" over Modbus RTU //#define LUNA2000_MODBUS //Enable this line to emulate a "Luna2000 battery" over Modbus RTU
//#define PYLON_CAN //Enable this line to emulate a "Pylontech battery" over CAN bus //#define PYLON_CAN //Enable this line to emulate a "Pylontech battery" over CAN bus
//#define SMA_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" over CAN bus //#define SMA_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" over CAN bus
@ -40,7 +40,7 @@
//#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot //#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot
/* MQTT options */ /* MQTT options */
//#define MQTT // Enable this line to enable MQTT #define MQTT // Enable this line to enable MQTT
#define MQTT_SUBSCRIPTIONS \ #define MQTT_SUBSCRIPTIONS \
{ "my/topic/abc", "my/other/topic" } { "my/topic/abc", "my/other/topic" }
#define MQTT_SERVER "192.168.xxx.yyy" #define MQTT_SERVER "192.168.xxx.yyy"

View file

@ -4,25 +4,9 @@
#include "../config.h" #include "../config.h"
#include "timer.h" #include "timer.h"
typedef enum {
EVENT_STATE_INIT = 0,
EVENT_STATE_INACTIVE,
EVENT_STATE_ACTIVE,
EVENT_STATE_ACTIVE_LATCHED
} EVENT_STATE_TYPE;
typedef struct {
uint32_t timestamp; // Time in seconds since startup when the event occurred
uint8_t data; // Custom data passed when setting the event, for example cell number for under voltage
uint8_t occurences; // Number of occurrences since startup
uint8_t led_color; // LED indication
EVENT_STATE_TYPE state; // Event state
} EVENTS_STRUCT_TYPE;
typedef struct { typedef struct {
EVENTS_STRUCT_TYPE entries[EVENT_NOF_EVENTS]; EVENTS_STRUCT_TYPE entries[EVENT_NOF_EVENTS];
uint32_t time_seconds; uint32_t time_seconds;
char message[256];
MyTimer second_timer; MyTimer second_timer;
uint8_t nof_yellow_events; uint8_t nof_yellow_events;
uint8_t nof_blue_events; uint8_t nof_blue_events;
@ -31,6 +15,8 @@ typedef struct {
/* Local variables */ /* Local variables */
static EVENT_TYPE events; static EVENT_TYPE events;
static const char* EVENTS_ENUM_TYPE_STRING[] = {EVENTS_ENUM_TYPE(GENERATE_STRING)};
static const char* EVENTS_LEVEL_TYPE_STRING[] = {EVENTS_LEVEL_TYPE(GENERATE_STRING)};
/* Local function prototypes */ /* Local function prototypes */
static void update_event_time(void); static void update_event_time(void);
@ -125,15 +111,14 @@ static void set_event(EVENTS_ENUM_TYPE event, uint8_t data, bool latched) {
} }
// If the event is already set, no reason to continue // If the event is already set, no reason to continue
if ((events.entries[event].state == EVENT_STATE_ACTIVE) || if ((events.entries[event].state != EVENT_STATE_ACTIVE) &&
(events.entries[event].state == EVENT_STATE_ACTIVE_LATCHED)) { (events.entries[event].state != EVENT_STATE_ACTIVE_LATCHED)) {
return; events.entries[event].occurences++;
} }
// We should set the event, update event info // We should set the event, update event info
events.entries[event].timestamp = events.time_seconds; events.entries[event].timestamp = events.time_seconds;
events.entries[event].data = data; events.entries[event].data = data;
events.entries[event].occurences++;
// Check if the event is latching // Check if the event is latching
events.entries[event].state = latched ? EVENT_STATE_ACTIVE_LATCHED : EVENT_STATE_ACTIVE; events.entries[event].state = latched ? EVENT_STATE_ACTIVE_LATCHED : EVENT_STATE_ACTIVE;
@ -141,10 +126,8 @@ static void set_event(EVENTS_ENUM_TYPE event, uint8_t data, bool latched) {
update_led_color(); update_led_color();
update_bms_status(); update_bms_status();
// Set the associated event message, even if debug is disabled
set_message(event);
#ifdef DEBUG_VIA_USB #ifdef DEBUG_VIA_USB
Serial.println(events.message); Serial.println(get_event_message(event));
#endif #endif
} }
@ -205,83 +188,6 @@ static void update_led_color(void) {
// events.total_led_color = max(events.total_led_color, events.entries[event].led_color); // events.total_led_color = max(events.total_led_color, events.entries[event].led_color);
} }
static void set_message(EVENTS_ENUM_TYPE event) {
switch (event) {
case EVENT_CAN_FAILURE:
snprintf(events.message, sizeof(events.message),
"No CAN communication detected for 60s. Shutting down battery control.");
break;
case EVENT_CAN_WARNING:
snprintf(events.message, sizeof(events.message),
"ERROR: High amount of corrupted CAN messages detected. Check CAN wire shielding!");
break;
case EVENT_WATER_INGRESS:
snprintf(events.message, sizeof(events.message),
"Water leakage inside battery detected. Operation halted. Inspect battery!");
break;
case EVENT_12V_LOW:
snprintf(events.message, sizeof(events.message),
"12V battery source below required voltage to safely close contactors. Inspect the supply/battery!");
break;
case EVENT_SOC_PLAUSIBILITY_ERROR:
snprintf(events.message, sizeof(events.message),
"ERROR: SOC reported by battery not plausible. Restart battery!");
break;
case EVENT_KWH_PLAUSIBILITY_ERROR:
snprintf(events.message, sizeof(events.message),
"Warning: kWh remaining reported by battery not plausible. Battery needs cycling.");
break;
case EVENT_BATTERY_CHG_STOP_REQ:
snprintf(events.message, sizeof(events.message),
"ERROR: Battery raised caution indicator AND requested charge stop. Inspect battery status!");
break;
case EVENT_BATTERY_DISCHG_STOP_REQ:
snprintf(events.message, sizeof(events.message),
"ERROR: Battery raised caution indicator AND requested discharge stop. Inspect battery status!");
break;
case EVENT_BATTERY_CHG_DISCHG_STOP_REQ:
snprintf(events.message, sizeof(events.message),
"ERROR: Battery raised caution indicator AND requested charge/discharge stop. Inspect battery status!");
break;
case EVENT_LOW_SOH:
snprintf(
events.message, sizeof(events.message),
"ERROR: State of health critically low. Battery internal resistance too high to continue. Recycle battery.");
break;
case EVENT_HVIL_FAILURE:
snprintf(events.message, sizeof(events.message),
"ERROR: Battery interlock loop broken. Check that high voltage connectors are seated. Battery will be "
"disabled!");
break;
case EVENT_INTERNAL_OPEN_FAULT:
snprintf(events.message, sizeof(events.message),
"ERROR: High voltage cable removed while battery running. Opening contactors!");
break;
case EVENT_CELL_UNDER_VOLTAGE:
snprintf(events.message, sizeof(events.message),
"ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
break;
case EVENT_CELL_OVER_VOLTAGE:
snprintf(events.message, sizeof(events.message),
"ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
break;
case EVENT_CELL_DEVIATION_HIGH:
snprintf(events.message, sizeof(events.message), "ERROR: HIGH CELL DEVIATION!!! Inspect battery!");
break;
case EVENT_UNKNOWN_EVENT_SET:
snprintf(events.message, sizeof(events.message), "An unknown event was set! Review your code!");
break;
case EVENT_OTA_UPDATE:
snprintf(events.message, sizeof(events.message), "OTA update started!");
break;
case EVENT_DUMMY:
snprintf(events.message, sizeof(events.message), "The dummy event was set!"); // Don't change this event message!
break;
default:
return "UNKNOWN";
}
}
const char* get_event_message(EVENTS_ENUM_TYPE event) { const char* get_event_message(EVENTS_ENUM_TYPE event) {
switch (event) { switch (event) {
case EVENT_CAN_FAILURE: case EVENT_CAN_FAILURE:
@ -326,14 +232,7 @@ const char* get_event_message(EVENTS_ENUM_TYPE event) {
} }
const char* get_event_enum_string(EVENTS_ENUM_TYPE event) { const char* get_event_enum_string(EVENTS_ENUM_TYPE event) {
const char* fullString = EVENTS_ENUM_TYPE_STRING[event]; return EVENTS_ENUM_TYPE_STRING[event] + 6; // Return the event name but skip "EVENT_" that should always be first
if (strncmp(fullString, "EVENT_", 6) == 0) {
return fullString + 6; // Skip the first 6 characters
}
return fullString;
} }
static void set_event_message(EVENTS_ENUM_TYPE event) { const char* get_event_type(EVENTS_ENUM_TYPE event) {}
const char* message = get_event_message(event);
snprintf(event_message, sizeof(event_message), "%s", message);
}

View file

@ -4,10 +4,27 @@
#ifndef UNIT_TEST #ifndef UNIT_TEST
#include <Arduino.h> #include <Arduino.h>
extern unsigned long previous_millis;
extern uint32_t time_seconds;
#endif #endif
typedef enum {
EVENT_STATE_INIT = 0,
EVENT_STATE_INACTIVE,
EVENT_STATE_ACTIVE,
EVENT_STATE_ACTIVE_LATCHED
} EVENTS_STATE_TYPE;
typedef struct {
uint32_t timestamp; // Time in seconds since startup when the event occurred
uint8_t data; // Custom data passed when setting the event, for example cell number for under voltage
uint8_t occurences; // Number of occurrences since startup
uint8_t led_color; // LED indication
EVENTS_STATE_TYPE state; // Event state
} EVENTS_STRUCT_TYPE;
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
/* Event enumeration */
#define EVENTS_ENUM_TYPE(XX) \ #define EVENTS_ENUM_TYPE(XX) \
XX(EVENT_CAN_FAILURE) \ XX(EVENT_CAN_FAILURE) \
XX(EVENT_CAN_WARNING) \ XX(EVENT_CAN_WARNING) \
@ -25,42 +42,25 @@ extern uint32_t time_seconds;
XX(EVENT_CELL_OVER_VOLTAGE) \ XX(EVENT_CELL_OVER_VOLTAGE) \
XX(EVENT_CELL_DEVIATION_HIGH) \ XX(EVENT_CELL_DEVIATION_HIGH) \
XX(EVENT_UNKNOWN_EVENT_SET) \ XX(EVENT_UNKNOWN_EVENT_SET) \
XX(EVENT_OTA_UPDATE) \
XX(EVENT_DUMMY) \ XX(EVENT_DUMMY) \
XX(EVENT_NOF_EVENTS) XX(EVENT_NOF_EVENTS)
typedef enum {
EVENT_CAN_FAILURE = 0u, // RED event
EVENT_CAN_WARNING, // YELLOW event
EVENT_WATER_INGRESS, // RED event
EVENT_12V_LOW, // YELLOW event
EVENT_SOC_PLAUSIBILITY_ERROR, // RED event
EVENT_KWH_PLAUSIBILITY_ERROR, // YELLOW event
EVENT_BATTERY_CHG_STOP_REQ, // RED event
EVENT_BATTERY_DISCHG_STOP_REQ, // RED event
EVENT_BATTERY_CHG_DISCHG_STOP_REQ, // RED event
EVENT_LOW_SOH, // RED event
EVENT_HVIL_FAILURE, // RED event
EVENT_INTERNAL_OPEN_FAULT, // RED event
EVENT_CELL_UNDER_VOLTAGE, // RED event
EVENT_CELL_OVER_VOLTAGE, // RED event
EVENT_CELL_DEVIATION_HIGH, // YELLOW event
EVENT_UNKNOWN_EVENT_SET, // RED event
EVENT_OTA_UPDATE, // BLUE event
EVENT_DUMMY, // RED event
EVENT_NOF_EVENTS // RED event
} EVENTS_ENUM_TYPE;
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
typedef enum { EVENTS_ENUM_TYPE(GENERATE_ENUM) } EVENTS_ENUM_TYPE; typedef enum { EVENTS_ENUM_TYPE(GENERATE_ENUM) } EVENTS_ENUM_TYPE;
static const char* EVENTS_ENUM_TYPE_STRING[] = {EVENTS_ENUM_TYPE(GENERATE_STRING)}; /* Event type enumeration */
#define EVENTS_LEVEL_TYPE(XX) \
XX(EVENT_LEVEL_ERROR) \
XX(EVENT_LEVEL_WARNING) \
XX(EVENT_LEVEL_INFO) \
XX(EVENT_LEVEL_DEBUG)
typedef enum { EVENTS_LEVEL_TYPE(GENERATE_ENUM) } EVENTS_LEVEL_TYPE;
const char* get_event_enum_string(EVENTS_ENUM_TYPE event); const char* get_event_enum_string(EVENTS_ENUM_TYPE event);
const char* get_event_message(EVENTS_ENUM_TYPE event); const char* get_event_message(EVENTS_ENUM_TYPE event);
const char* get_led_color_display_text(u_int8_t led_color); const char* get_led_color_display_text(u_int8_t led_color);
const char* get_event_type(EVENTS_ENUM_TYPE event);
void init_events(void); void init_events(void);
void set_event_latched(EVENTS_ENUM_TYPE event, uint8_t data); void set_event_latched(EVENTS_ENUM_TYPE event, uint8_t data);