mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Merge branch 'main' into bugfix/char-dis-status
This commit is contained in:
commit
ecce5a61ac
32 changed files with 821 additions and 326 deletions
|
@ -54,8 +54,8 @@ ModbusServerRTU MBserver(Serial2, 2000);
|
|||
#endif
|
||||
|
||||
// Common inverter parameters. Batteries map their values to these variables
|
||||
uint16_t max_voltage = ABSOLUTE_MAX_VOLTAGE; // If higher charging is not possible (goes into forced discharge)
|
||||
uint16_t min_voltage = ABSOLUTE_MIN_VOLTAGE; // If lower disables discharging battery
|
||||
uint16_t max_voltage = 5000; //V+1, 0-500.0 (0-5000)
|
||||
uint16_t min_voltage = 2500; //V+1, 0-500.0 (0-5000)
|
||||
uint16_t battery_voltage = 3700; //V+1, 0-500.0 (0-5000)
|
||||
uint16_t battery_current = 0;
|
||||
uint16_t SOC = 5000; //SOC%, 0-100.00 (0-10000)
|
||||
|
@ -144,11 +144,7 @@ void setup() {
|
|||
|
||||
inform_user_on_inverter();
|
||||
|
||||
inform_user_on_battery();
|
||||
|
||||
#ifdef BATTERY_HAS_INIT
|
||||
init_battery();
|
||||
#endif
|
||||
|
||||
// BOOT button at runtime is used as an input for various things
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
|
@ -344,6 +340,9 @@ void inform_user_on_inverter() {
|
|||
#ifdef SMA_CAN
|
||||
Serial.println("SMA CAN protocol selected");
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
Serial.println("SMA Tripower CAN protocol selected");
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
Serial.println("SOFAR CAN protocol selected");
|
||||
#endif
|
||||
|
@ -354,42 +353,13 @@ void inform_user_on_inverter() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void inform_user_on_battery() {
|
||||
// Inform user what battery is used
|
||||
#ifdef BMW_I3_BATTERY
|
||||
Serial.println("BMW i3 battery selected");
|
||||
#endif
|
||||
#ifdef CHADEMO_BATTERY
|
||||
Serial.println("Chademo battery selected");
|
||||
#endif
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
Serial.println("Mitsubishi i-MiEV / Citroen C-Zero / Peugeot Ion battery selected");
|
||||
#endif
|
||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||
Serial.println("Kia Niro / Hyundai Kona 64kWh battery selected");
|
||||
#endif
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
Serial.println("Nissan LEAF battery selected");
|
||||
#endif
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
Serial.println("Renault Kangoo battery selected");
|
||||
#endif
|
||||
#ifdef SANTA_FE_PHEV_BATTERY
|
||||
Serial.println("Hyundai Santa Fe PHEV battery selected");
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
Serial.println("Renault Zoe battery selected");
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
Serial.println("Tesla Model 3 battery selected");
|
||||
#endif
|
||||
#ifdef TEST_FAKE_BATTERY
|
||||
Serial.println("Test mode with fake battery selected");
|
||||
#endif
|
||||
void init_battery() {
|
||||
// Inform user what battery is used and perform setup
|
||||
setup_battery();
|
||||
#ifdef SERIAL_LINK_RECEIVER
|
||||
Serial.println("SERIAL_DATA_LINK_RECEIVER selected");
|
||||
#endif
|
||||
#if !defined(ABSOLUTE_MAX_VOLTAGE)
|
||||
#ifndef BATTERY_SELECTED
|
||||
#error No battery selected! Choose one from the USER_SETTINGS.h file
|
||||
#endif
|
||||
}
|
||||
|
@ -402,42 +372,16 @@ void receive_can() { // This section checks if we have a complete CAN message i
|
|||
if (rx_frame.FIR.B.FF == CAN_frame_std) {
|
||||
//printf("New standard frame");
|
||||
// Battery
|
||||
#ifdef BMW_I3_BATTERY
|
||||
receive_can_i3_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef CHADEMO_BATTERY
|
||||
receive_can_chademo_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
receive_can_imiev_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||
receive_can_kiaHyundai_64_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
receive_can_leaf_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
receive_can_kangoo_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef SANTA_FE_PHEV_BATTERY
|
||||
receive_can_santafe_phev_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
receive_can_zoe_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
receive_can_tesla_model_3_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef TEST_FAKE_BATTERY
|
||||
receive_can_test_battery(rx_frame);
|
||||
#endif
|
||||
receive_can_battery(rx_frame);
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
receive_can_byd(rx_frame);
|
||||
#endif
|
||||
#ifdef SMA_CAN
|
||||
receive_can_sma(rx_frame);
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
receive_can_sma_tripower(rx_frame);
|
||||
#endif
|
||||
// Charger
|
||||
#ifdef CHEVYVOLT_CHARGER
|
||||
|
@ -470,40 +414,14 @@ void send_can() {
|
|||
#ifdef SMA_CAN
|
||||
send_can_sma();
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
send_can_sma_tripower();
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
send_can_sofar();
|
||||
#endif
|
||||
// Battery
|
||||
#ifdef BMW_I3_BATTERY
|
||||
send_can_i3_battery();
|
||||
#endif
|
||||
#ifdef CHADEMO_BATTERY
|
||||
send_can_chademo_battery();
|
||||
#endif
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
send_can_imiev_battery();
|
||||
#endif
|
||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||
send_can_kiaHyundai_64_battery();
|
||||
#endif
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
send_can_leaf_battery();
|
||||
#endif
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
send_can_kangoo_battery();
|
||||
#endif
|
||||
#ifdef SANTA_FE_PHEV_BATTERY
|
||||
send_can_santafe_phev_battery();
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
send_can_zoe_battery();
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
send_can_tesla_model_3_battery();
|
||||
#endif
|
||||
#ifdef TEST_FAKE_BATTERY
|
||||
send_can_test_battery();
|
||||
#endif
|
||||
send_can_battery();
|
||||
#ifdef CHEVYVOLT_CHARGER
|
||||
send_can_chevyvolt_charger();
|
||||
#endif
|
||||
|
@ -683,36 +601,7 @@ void handle_contactors() {
|
|||
|
||||
void update_values() {
|
||||
// Battery
|
||||
#ifdef BMW_I3_BATTERY
|
||||
update_values_i3_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef CHADEMO_BATTERY
|
||||
update_values_chademo_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
update_values_imiev_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||
update_values_kiaHyundai_64_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
update_values_leaf_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
update_values_kangoo_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef SANTA_FE_PHEV_BATTERY
|
||||
update_values_santafe_phev_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
update_values_zoe_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
update_values_tesla_model_3_battery(); // Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef TEST_FAKE_BATTERY
|
||||
update_values_test_battery(); // Map the fake values to the correct registers
|
||||
#endif
|
||||
update_values_battery(); // Map the fake values to the correct registers
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
update_values_can_byd();
|
||||
|
@ -729,6 +618,9 @@ void update_values() {
|
|||
#ifdef SMA_CAN
|
||||
update_values_can_sma();
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
update_values_can_sma_tripower();
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
update_values_can_sofar();
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
//#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 SMA_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" over CAN bus
|
||||
//#define SMA_TRIPOWER_CAN //Enable this line to emulate a "SMA Home Storage battery" over CAN bus
|
||||
//#define SOFAR_CAN //Enable this line to emulate a "Sofar Energy Storage Inverter High Voltage BMS General Protocol (Extended Frame)" over CAN bus
|
||||
//#define SOLAX_CAN //Enable this line to emulate a "SolaX Triple Power LFP" over CAN bus
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
#include "NISSAN-LEAF-BATTERY.h" //See this file for more LEAF battery settings
|
||||
#define BATTERY_HAS_INIT
|
||||
#endif
|
||||
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
|
@ -48,4 +47,11 @@
|
|||
#include "SERIAL-LINK-RECEIVER-FROM-BATTERY.h" //See this file for more Serial-battery settings
|
||||
#endif
|
||||
|
||||
#ifndef SERIAL_LINK_RECEIVER // The serial thing does its thing
|
||||
void update_values_battery();
|
||||
void receive_can_battery(CAN_frame_t rx_frame);
|
||||
void send_can_battery();
|
||||
void setup_battery(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#include "BMW-I3-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "BMW-I3-BATTERY.h"
|
||||
|
||||
//TODO: before using
|
||||
// Map the final values in update_values_i3_battery, set some to static values if not available (current, discharge max , charge max)
|
||||
// Map the final values in update_values_battery, set some to static values if not available (current, discharge max , charge max)
|
||||
// Check if I3 battery stays alive with only 10B and 512. If not, add 12F. If that doesn't help, add more from CAN log (ask Dala)
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
|
@ -54,7 +56,7 @@ static uint16_t Battery_Status = 0;
|
|||
static uint16_t DC_link = 0;
|
||||
static int16_t Battery_Power = 0;
|
||||
|
||||
void update_values_i3_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
//Calculate the SOC% value to send to inverter
|
||||
Calculated_SOC = (Display_SOC * 10); //Increase decimal amount
|
||||
Calculated_SOC =
|
||||
|
@ -122,7 +124,7 @@ void update_values_i3_battery() { //This function maps all the values fetched v
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_i3_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
CANstillAlive = 12;
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x431: //Battery capacity [200ms]
|
||||
|
@ -168,7 +170,7 @@ void receive_can_i3_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_i3_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 600ms CAN Message
|
||||
if (currentMillis - previousMillis600 >= interval600) {
|
||||
|
@ -190,3 +192,12 @@ void send_can_i3_battery() {
|
|||
ESP32Can.CANWriteFrame(&BMW_10B);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("BMW i3 battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,28 +5,28 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t SOC;
|
||||
extern uint16_t StateOfHealth;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t capacity_Wh;
|
||||
extern uint16_t remaining_capacity_Wh;
|
||||
extern uint16_t max_target_discharge_power;
|
||||
extern uint16_t max_target_charge_power;
|
||||
extern uint16_t stat_batt_power;
|
||||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485)
|
||||
extern uint16_t capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t remaining_capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t max_target_discharge_power; //W, 0-60000
|
||||
extern uint16_t max_target_charge_power; //W, 0-60000
|
||||
extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530)
|
||||
extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint16_t cellvoltages[120]; //mV 0-4350 per cell
|
||||
extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by each battery.
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_i3_battery();
|
||||
void receive_can_i3_battery(CAN_frame_t rx_frame);
|
||||
void send_can_i3_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "CHADEMO-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef CHADEMO_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "CHADEMO-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send
|
||||
|
@ -89,7 +91,7 @@ uint8_t DynamicControlStatus = 0;
|
|||
uint8_t HighCurrentControlStatus = 0;
|
||||
uint8_t HighVoltageControlStatus = 0;
|
||||
|
||||
void update_values_chademo_battery() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
||||
|
||||
SOC = ChargingRate;
|
||||
|
||||
|
@ -133,7 +135,7 @@ void update_values_chademo_battery() { //This function maps all the values fetc
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_chademo_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
CANstillAlive == 12; //We are getting CAN messages from the vehicle, inform the watchdog
|
||||
|
||||
switch (rx_frame.MsgID) {
|
||||
|
@ -189,7 +191,7 @@ void receive_can_chademo_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_chademo_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
|
@ -205,3 +207,11 @@ void send_can_chademo_battery() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Chademo battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 2000; // 200.0V under this, discharging further is disabled
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,29 +5,28 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped
|
||||
extern uint16_t SOC;
|
||||
extern uint16_t StateOfHealth;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t capacity_Wh;
|
||||
extern uint16_t remaining_capacity_Wh;
|
||||
extern uint16_t max_target_discharge_power;
|
||||
extern uint16_t max_target_charge_power;
|
||||
extern uint8_t bms_status;
|
||||
extern uint16_t stat_batt_power;
|
||||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485)
|
||||
extern uint16_t capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t remaining_capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t max_target_discharge_power; //W, 0-60000
|
||||
extern uint16_t max_target_charge_power; //W, 0-60000
|
||||
extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530)
|
||||
extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint16_t cellvoltages[120]; //mV 0-4350 per cell
|
||||
extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by each battery.
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_chademo_battery();
|
||||
void receive_can_chademo_battery(CAN_frame_t rx_frame);
|
||||
void send_can_chademo_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||
|
||||
//Code still work in progress, TODO:
|
||||
//Figure out if CAN messages need to be sent to keep the system happy?
|
||||
|
@ -40,7 +42,7 @@ static double min_volt_cel = 3.70;
|
|||
static double max_temp_cel = 20.00;
|
||||
static double min_temp_cel = 19.00;
|
||||
|
||||
void update_values_imiev_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
SOC = (uint16_t)(BMU_SOC * 100); //increase BMU_SOC range from 0-100 -> 100.00
|
||||
|
||||
battery_voltage = (uint16_t)(BMU_PackVoltage * 10); // Multiply by 10 and cast to uint16_t
|
||||
|
@ -161,7 +163,7 @@ void update_values_imiev_battery() { //This function maps all the values fetche
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_imiev_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
CANstillAlive =
|
||||
12; //TODO: move this inside a known message ID to prevent CAN inverter from keeping battery alive detection going
|
||||
switch (rx_frame.MsgID) {
|
||||
|
@ -217,10 +219,19 @@ void receive_can_imiev_battery(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_imiev_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
previousMillis100 = currentMillis;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Mitsubishi i-MiEV / Citroen C-Zero / Peugeot Ion battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,30 +5,29 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
extern uint16_t SOC;
|
||||
extern uint16_t StateOfHealth;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t capacity_Wh;
|
||||
extern uint16_t remaining_capacity_Wh;
|
||||
extern uint16_t max_target_discharge_power;
|
||||
extern uint16_t max_target_charge_power;
|
||||
extern uint16_t stat_batt_power;
|
||||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
extern uint16_t cell_max_voltage;
|
||||
extern uint16_t cell_min_voltage;
|
||||
// These parameters need to be mapped for the Inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485)
|
||||
extern uint16_t capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t remaining_capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t max_target_discharge_power; //W, 0-60000
|
||||
extern uint16_t max_target_charge_power; //W, 0-60000
|
||||
extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530)
|
||||
extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint16_t cellvoltages[120]; //mV 0-4350 per cell
|
||||
extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by each battery.
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_imiev_battery();
|
||||
void receive_can_imiev_battery(CAN_frame_t rx_frame);
|
||||
void send_can_imiev_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "KIA-HYUNDAI-64-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "KIA-HYUNDAI-64-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send
|
||||
|
@ -146,7 +148,7 @@ CAN_frame_t KIA64_7E4_ack = {
|
|||
.MsgID = 0x7E4,
|
||||
.data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; //Ack frame, correct PID is returned
|
||||
|
||||
void update_values_kiaHyundai_64_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
|
||||
//Calculate the SOC% value to send to inverter
|
||||
soc_calculated = SOC_Display;
|
||||
|
@ -293,7 +295,7 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x4DE:
|
||||
break;
|
||||
|
@ -523,7 +525,7 @@ void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_kiaHyundai_64_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
//Send 100ms message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
|
@ -596,3 +598,12 @@ uint16_t convertToUnsignedInt16(int16_t signed_value) {
|
|||
return (uint16_t)signed_value;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Kia Niro / Hyundai Kona 64kWh battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define MAXCHARGEPOWERALLOWED 10000
|
||||
#define MAXDISCHARGEPOWERALLOWED 10000
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -30,9 +31,7 @@ extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by eac
|
|||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_kiaHyundai_64_battery();
|
||||
void receive_can_kiaHyundai_64_battery(CAN_frame_t rx_frame);
|
||||
void send_can_kiaHyundai_64_battery();
|
||||
uint16_t convertToUnsignedInt16(int16_t signed_value);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "BATTERIES.h"
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
#include "NISSAN-LEAF-BATTERY.h"
|
||||
#ifdef MQTT
|
||||
#include "../devboard/mqtt/mqtt.h"
|
||||
|
@ -165,7 +167,7 @@ void print_with_units(char* header, int value, char* units) {
|
|||
Serial.print(units);
|
||||
}
|
||||
|
||||
void update_values_leaf_battery() { /* This function maps all the values fetched via CAN to the correct parameters used for modbus */
|
||||
void update_values_battery() { /* This function maps all the values fetched via CAN to the correct parameters used for modbus */
|
||||
/* Start with mapping all values */
|
||||
|
||||
StateOfHealth = (LB_StateOfHealth * 100); //Increase range from 99% -> 99.00%
|
||||
|
@ -255,8 +257,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
}
|
||||
|
||||
//Check if SOC% is plausible
|
||||
if (battery_voltage >
|
||||
(ABSOLUTE_MAX_VOLTAGE - 100)) { // When pack voltage is close to max, and SOC% is still low, raise FAULT
|
||||
if (battery_voltage > (max_voltage - 100)) { // When pack voltage is close to max, and SOC% is still low, raise FAULT
|
||||
if (LB_SOC < 650) {
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, LB_SOC / 10); // Set event with the SOC as data
|
||||
} else {
|
||||
|
@ -412,7 +413,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x1DB:
|
||||
if (is_message_corrupt(rx_frame)) {
|
||||
|
@ -676,7 +677,7 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_leaf_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
|
@ -907,6 +908,12 @@ uint16_t Temp_fromRAW_to_F(uint16_t temperature) { //This function feels horrib
|
|||
return static_cast<uint16_t>(1094 + (309 - temperature) * 2.5714285714285715);
|
||||
}
|
||||
|
||||
void init_battery(void) {
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Nissan LEAF battery selected");
|
||||
|
||||
nof_cellvoltages = 96;
|
||||
max_voltage = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 2450; // 245.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -27,13 +27,9 @@ extern uint16_t cellvoltages[120]; //mV 0-4350 per cell
|
|||
extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by each battery.
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_leaf_battery();
|
||||
void receive_can_leaf_battery(CAN_frame_t rx_frame);
|
||||
void send_can_leaf_battery();
|
||||
uint16_t convert2unsignedint16(int16_t signed_value);
|
||||
uint16_t Temp_fromRAW_to_F(uint16_t temperature);
|
||||
bool is_message_corrupt(CAN_frame_t rx_frame);
|
||||
|
||||
void init_battery(void);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "RENAULT-KANGOO-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef RENAULT_KANGOO_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "RENAULT-KANGOO-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
#define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Fronius
|
||||
|
@ -57,7 +59,7 @@ static const int interval10 = 10; // interval (ms) at which send CAN Messag
|
|||
static const int interval100 = 100; // interval (ms) at which send CAN Messages
|
||||
static const int interval1000 = 1000; // interval (ms) at which send CAN Messages
|
||||
|
||||
void update_values_kangoo_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
StateOfHealth = (LB_SOH * 100); //Increase range from 99% -> 99.00%
|
||||
|
||||
//Calculate the SOC% value to send to Fronius
|
||||
|
@ -175,7 +177,7 @@ void update_values_kangoo_battery() { //This function maps all the values fetch
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_kangoo_battery(CAN_frame_t rx_frame) //GKOE reworked
|
||||
void receive_can_battery(CAN_frame_t rx_frame) //GKOE reworked
|
||||
{
|
||||
|
||||
switch (rx_frame.MsgID) {
|
||||
|
@ -237,7 +239,7 @@ void receive_can_kangoo_battery(CAN_frame_t rx_frame) //GKOE reworked
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_kangoo_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message (for 2.4s, then pause 10s)
|
||||
if ((currentMillis - previousMillis100) >= (interval100 + GVL_pause)) {
|
||||
|
@ -267,3 +269,12 @@ uint16_t convert2uint16(int16_t signed_value) {
|
|||
return (uint16_t)signed_value;
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Renault Kangoo battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,16 +5,17 @@
|
|||
#include "../devboard/config.h" // Needed for defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define ABSOLUTE_CELL_MAX_VOLTAGE \
|
||||
4100 // Max Cell Voltage mV! if voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_CELL_MIN_VOLTAGE \
|
||||
3000 // Min Cell Voltage mV! if voltage goes under this, discharging further is disabled
|
||||
#define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -32,9 +33,7 @@ extern uint16_t CANerror;
|
|||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_kangoo_battery();
|
||||
void receive_can_kangoo_battery(CAN_frame_t rx_frame);
|
||||
void send_can_kangoo_battery();
|
||||
uint16_t convert2uint16(int16_t signed_value);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "RENAULT-ZOE-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "RENAULT-ZOE-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
#define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Fronius
|
||||
|
@ -42,7 +44,7 @@ static const int interval10 = 10; // interval (ms) at which send CAN Messag
|
|||
static const int interval100 = 100; // interval (ms) at which send CAN Messages
|
||||
static const int interval1000 = 1000; // interval (ms) at which send CAN Messages
|
||||
|
||||
void update_values_zoe_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
StateOfHealth = (LB_SOH * 100); //Increase range from 99% -> 99.00%
|
||||
|
||||
//Calculate the SOC% value to send to Fronius
|
||||
|
@ -136,7 +138,7 @@ void update_values_zoe_battery() { //This function maps all the values fetched
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_zoe_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x42E: //HV SOC & Battery Temp & Charging Power
|
||||
|
@ -150,7 +152,7 @@ void receive_can_zoe_battery(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_zoe_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
|
@ -163,3 +165,12 @@ void send_can_zoe_battery() {
|
|||
//ESP32Can.CANWriteFrame(&ZOE_423);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Renault Zoe battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,16 +5,17 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define ABSOLUTE_CELL_MAX_VOLTAGE \
|
||||
4100 // Max Cell Voltage mV! if voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_CELL_MIN_VOLTAGE \
|
||||
3000 // Min Cell Voltage mV! if voltage goes under this, discharging further is disabled
|
||||
#define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -32,8 +33,6 @@ extern uint16_t CANerror;
|
|||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_zoe_battery();
|
||||
void receive_can_zoe_battery(CAN_frame_t rx_frame);
|
||||
void send_can_zoe_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "SANTA-FE-PHEV-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef SANTA_FE_PHEV_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "SANTA-FE-PHEV-BATTERY.h"
|
||||
|
||||
/* Credits go to maciek16c for these findings!
|
||||
https://github.com/maciek16c/hyundai-santa-fe-phev-battery
|
||||
|
@ -57,7 +59,7 @@ CAN_frame_t SANTAFE_523 = {.FIR = {.B =
|
|||
.MsgID = 0x523,
|
||||
.data = {0x60, 0x00, 0x60, 0, 0, 0, 0, 0}};
|
||||
|
||||
void update_values_santafe_phev_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
|
||||
SOC;
|
||||
|
||||
|
@ -92,7 +94,7 @@ void update_values_santafe_phev_battery() { //This function maps all the values
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_santafe_phev_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
CANstillAlive = 12;
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x200:
|
||||
|
@ -127,7 +129,7 @@ void receive_can_santafe_phev_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_santafe_phev_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
//Send 10ms message
|
||||
if (currentMillis - previousMillis10 >= interval10) {
|
||||
|
@ -174,3 +176,12 @@ uint8_t CalculateCRC8(CAN_frame_t rx_frame) {
|
|||
}
|
||||
return (uint8_t)crc;
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Hyundai Santa Fe PHEV battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,29 +5,28 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4030 // 403.0V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
extern uint16_t SOC;
|
||||
extern uint16_t StateOfHealth;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t capacity_Wh;
|
||||
extern uint16_t remaining_capacity_Wh;
|
||||
extern uint16_t max_target_discharge_power;
|
||||
extern uint16_t max_target_charge_power;
|
||||
extern uint16_t stat_batt_power;
|
||||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485)
|
||||
extern uint16_t capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t remaining_capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t max_target_discharge_power; //W, 0-60000
|
||||
extern uint16_t max_target_charge_power; //W, 0-60000
|
||||
extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530)
|
||||
extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint16_t cellvoltages[120]; //mV 0-4350 per cell
|
||||
extern uint8_t nof_cellvoltages; // Total number of cell voltages, set by each battery.
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_santafe_phev_battery();
|
||||
void receive_can_santafe_phev_battery(CAN_frame_t rx_frame);
|
||||
void send_can_santafe_phev_battery();
|
||||
uint8_t CalculateCRC8(CAN_frame_t rx_frame);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
|
||||
// https://github.com/mackelec/SerialDataLink
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "TESLA-MODEL-3-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "TESLA-MODEL-3-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
/* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */
|
||||
|
@ -48,10 +50,10 @@ static uint16_t regenerative_limit = 0;
|
|||
static uint16_t discharge_limit = 0;
|
||||
static uint16_t max_heat_park = 0;
|
||||
static uint16_t hvac_max_power = 0;
|
||||
static uint16_t min_voltage = 0;
|
||||
static uint16_t max_discharge_current = 0;
|
||||
static uint16_t max_charge_current = 0;
|
||||
static uint16_t max_voltage = 0;
|
||||
static uint16_t bms_max_voltage = 0;
|
||||
static uint16_t bms_min_voltage = 0;
|
||||
static uint16_t high_voltage = 0;
|
||||
static uint16_t low_voltage = 0;
|
||||
static uint16_t output_current = 0;
|
||||
|
@ -163,7 +165,7 @@ static const char* hvilStatusState[] = {"NOT OK",
|
|||
|
||||
#define REASONABLE_ENERGYAMOUNT 20 //When the BMS stops making sense on some values, they are always <20
|
||||
|
||||
void update_values_tesla_model_3_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
//After values are mapped, we perform some safety checks, and do some serial printouts
|
||||
//Calculate the SOH% to send to inverter
|
||||
if (bat_beginning_of_life != 0) { //div/0 safeguard
|
||||
|
@ -242,7 +244,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
|
||||
cell_deviation_mV = (cell_max_v - cell_min_v);
|
||||
|
||||
//Determine which chemistry battery pack is using (crude method, TODO: replace with real CAN data later)
|
||||
//Determine which chemistry battery pack is using (crude method, TODO: replace with real CAN identifier later)
|
||||
if (soc_vi > 900) { //When SOC% is over 90.0%, we can use max cell voltage to estimate what chemistry is used
|
||||
if (cell_max_v < 3450) {
|
||||
LFP_Chemistry = true;
|
||||
|
@ -251,10 +253,22 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
LFP_Chemistry = false;
|
||||
}
|
||||
}
|
||||
// An even better way is to check how many cells are in the pack. NCM/A batteries have 96s, LFP has 102-106s
|
||||
if (nof_cellvoltages > 101) {
|
||||
LFP_Chemistry = true;
|
||||
}
|
||||
|
||||
//Once cell chemistry is determined, set maximum and minimum total pack voltage safety limits
|
||||
if (LFP_Chemistry) {
|
||||
max_voltage = 3640;
|
||||
min_voltage = 2450;
|
||||
} else { // NCM/A chemistry
|
||||
max_voltage = 4030;
|
||||
min_voltage = 3100;
|
||||
}
|
||||
|
||||
//Check if SOC% is plausible
|
||||
if (battery_voltage >
|
||||
(ABSOLUTE_MAX_VOLTAGE - 100)) { // When pack voltage is close to max, and SOC% is still low, raise FAULT
|
||||
if (battery_voltage > (max_voltage - 100)) { // When pack voltage is close to max, and SOC% is still low, raise FAULT
|
||||
if (SOC < 6500) { //When SOC is less than 65.00% when approaching max voltage
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, SOC / 100);
|
||||
}
|
||||
|
@ -335,6 +349,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
if (LFP_Chemistry) {
|
||||
Serial.print("LFP chemistry detected!");
|
||||
}
|
||||
Serial.print(nof_cellvoltages);
|
||||
Serial.println("");
|
||||
Serial.print("Cellstats, Max: ");
|
||||
Serial.print(cell_max_v);
|
||||
|
@ -368,7 +383,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
static int mux = 0;
|
||||
static int temp = 0;
|
||||
|
||||
|
@ -481,8 +496,10 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
case 0x2d2:
|
||||
//Min / max limits
|
||||
min_voltage = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.01 * 2; //Example 24148mv * 0.01 = 241.48 V
|
||||
max_voltage = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]) * 0.01 * 2; //Example 40282mv * 0.01 = 402.82 V
|
||||
bms_min_voltage =
|
||||
((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.01 * 2; //Example 24148mv * 0.01 = 241.48 V
|
||||
bms_max_voltage =
|
||||
((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]) * 0.01 * 2; //Example 40282mv * 0.01 = 402.82 V
|
||||
max_charge_current =
|
||||
(((rx_frame.data.u8[5] & 0x3F) << 8) | rx_frame.data.u8[4]) * 0.1; //Example 1301? * 0.1 = 130.1?
|
||||
max_discharge_current =
|
||||
|
@ -558,7 +575,7 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_tesla_model_3_battery() {
|
||||
void send_can_battery() {
|
||||
/*From bielec: My fist 221 message, to close the contactors is 0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96 and then,
|
||||
to cause "hv_up_for_drive" I send an additional 221 message 0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA so
|
||||
two 221 messages are being continuously transmitted. When I want to shut down, I stop the second message and only send
|
||||
|
@ -683,3 +700,12 @@ void printDebugIfActive(uint8_t symbol, const char* message) {
|
|||
Serial.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Tesla Model 3 battery selected");
|
||||
|
||||
max_voltage = 4030; // 403.0V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4030 // 403.0V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 2450 // 245.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
#define MAXCHARGEPOWERALLOWED 15000 // 15000W we use a define since the value supplied by Tesla is always 0
|
||||
#define MAXDISCHARGEPOWERALLOWED \
|
||||
60000 // 60000W we need to cap this value to max 60kW, most inverters overflow otherwise
|
||||
|
||||
// These parameters need to be mapped for the Inverter
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -32,13 +33,11 @@ extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
|||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool LFP_Chemistry;
|
||||
|
||||
void update_values_tesla_model_3_battery();
|
||||
void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame);
|
||||
void send_can_tesla_model_3_battery();
|
||||
void printFaultCodesIfActive();
|
||||
void printDebugIfActive(uint8_t symbol, const char* message);
|
||||
void print_int_with_units(char* header, int value, char* units);
|
||||
void print_SOC(char* header, int SOC);
|
||||
uint16_t convert2unsignedInt16(int16_t signed_value);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "TEST-FAKE-BATTERY.h"
|
||||
#include "BATTERIES.h"
|
||||
#ifdef TEST_FAKE_BATTERY
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "TEST-FAKE-BATTERY.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was send
|
||||
|
@ -16,7 +18,7 @@ void print_units(char* header, int value, char* units) {
|
|||
Serial.print(units);
|
||||
}
|
||||
|
||||
void update_values_test_battery() { /* This function puts fake values onto the parameters sent towards the inverter */
|
||||
void update_values_battery() { /* This function puts fake values onto the parameters sent towards the inverter */
|
||||
SOC = 5000; // 50.00%
|
||||
|
||||
StateOfHealth = 9900; // 99.00%
|
||||
|
@ -63,7 +65,7 @@ void update_values_test_battery() { /* This function puts fake values onto the p
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_test_battery(CAN_frame_t rx_frame) {
|
||||
void receive_can_battery(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0xABC:
|
||||
break;
|
||||
|
@ -71,7 +73,7 @@ void receive_can_test_battery(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
void send_can_test_battery() {
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100) {
|
||||
|
@ -79,3 +81,12 @@ void send_can_test_battery() {
|
|||
// Put fake messages here incase you want to test sending CAN
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
Serial.println("Test mode with fake battery selected");
|
||||
|
||||
max_voltage = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
min_voltage = 2450; // 245.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define ABSOLUTE_MAX_VOLTAGE \
|
||||
4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint16_t max_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t min_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
|
@ -28,8 +28,6 @@ extern uint16_t cellvoltages[120]; //mV 0-5000 per cell
|
|||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_test_battery();
|
||||
void receive_can_test_battery(CAN_frame_t rx_frame);
|
||||
void send_can_test_battery();
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -142,6 +142,7 @@ void init_events(void) {
|
|||
events.entries[EVENT_CELL_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
|
||||
events.entries[EVENT_UNKNOWN_EVENT_SET].level = EVENT_LEVEL_ERROR;
|
||||
events.entries[EVENT_OTA_UPDATE].level = EVENT_LEVEL_UPDATE;
|
||||
events.entries[EVENT_OTA_UPDATE_TIMEOUT].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_DUMMY_INFO].level = EVENT_LEVEL_INFO;
|
||||
events.entries[EVENT_DUMMY_DEBUG].level = EVENT_LEVEL_DEBUG;
|
||||
events.entries[EVENT_DUMMY_WARNING].level = EVENT_LEVEL_WARNING;
|
||||
|
@ -235,6 +236,8 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
|
|||
return "Error in serial function: Some ERROR level fault in transmitter, received by receiver";
|
||||
case EVENT_OTA_UPDATE:
|
||||
return "OTA update started!";
|
||||
case EVENT_OTA_UPDATE_TIMEOUT:
|
||||
return "OTA update timed out!";
|
||||
case EVENT_EEPROM_WRITE:
|
||||
return "Info: The EEPROM was written";
|
||||
default:
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
XX(EVENT_CELL_DEVIATION_HIGH) \
|
||||
XX(EVENT_UNKNOWN_EVENT_SET) \
|
||||
XX(EVENT_OTA_UPDATE) \
|
||||
XX(EVENT_OTA_UPDATE_TIMEOUT) \
|
||||
XX(EVENT_DUMMY_INFO) \
|
||||
XX(EVENT_DUMMY_DEBUG) \
|
||||
XX(EVENT_DUMMY_WARNING) \
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "webserver.h"
|
||||
#include <Preferences.h>
|
||||
#include "../utils/events.h"
|
||||
#include "../utils/timer.h"
|
||||
|
||||
// Create AsyncWebServer object on port 80
|
||||
AsyncWebServer server(80);
|
||||
|
@ -21,6 +22,9 @@ enum WifiState {
|
|||
|
||||
WifiState wifi_state = INIT;
|
||||
|
||||
MyTimer ota_timeout_timer = MyTimer(5000);
|
||||
bool ota_active = false;
|
||||
|
||||
unsigned const long WIFI_MONITOR_INTERVAL_TIME = 15000;
|
||||
unsigned const long INIT_WIFI_CONNECT_TIMEOUT = 8000; // Timeout for initial WiFi connect in milliseconds
|
||||
unsigned const long DEFAULT_WIFI_RECONNECT_INTERVAL = 1000; // Default WiFi reconnect interval in ms
|
||||
|
@ -299,6 +303,14 @@ void wifi_monitor() {
|
|||
Serial.println(" Hostname: " + String(WiFi.getHostname()));
|
||||
}
|
||||
}
|
||||
|
||||
if (ota_active && ota_timeout_timer.elapsed()) {
|
||||
// OTA timeout, try to restore can and clear the update event
|
||||
ESP32Can.CANInit();
|
||||
clear_event(EVENT_OTA_UPDATE);
|
||||
set_event(EVENT_OTA_UPDATE_TIMEOUT, 0);
|
||||
ota_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void init_WiFi_STA(const char* ssid, const char* password, const uint8_t wifi_channel) {
|
||||
|
@ -635,6 +647,11 @@ void onOTAStart() {
|
|||
// Log when OTA has started
|
||||
ESP32Can.CANStop();
|
||||
set_event(EVENT_OTA_UPDATE, 0);
|
||||
|
||||
// If already set, make a new attempt
|
||||
clear_event(EVENT_OTA_UPDATE_TIMEOUT);
|
||||
ota_active = true;
|
||||
ota_timeout_timer.reset();
|
||||
}
|
||||
|
||||
void onOTAProgress(size_t current, size_t final) {
|
||||
|
@ -642,6 +659,9 @@ void onOTAProgress(size_t current, size_t final) {
|
|||
if (millis() - ota_progress_millis > 1000) {
|
||||
ota_progress_millis = millis();
|
||||
Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
|
||||
|
||||
// Reset the "watchdog"
|
||||
ota_timeout_timer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,7 +671,11 @@ void onOTAEnd(bool success) {
|
|||
Serial.println("OTA update finished successfully!");
|
||||
} else {
|
||||
Serial.println("There was an error during OTA update!");
|
||||
|
||||
// If we fail without a timeout, try to restore CAN
|
||||
ESP32Can.CANInit();
|
||||
}
|
||||
ota_active = false;
|
||||
clear_event(EVENT_OTA_UPDATE);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
#include "SMA-CAN.h"
|
||||
#endif
|
||||
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
#include "SMA-TRIPOWER-CAN.h"
|
||||
#endif
|
||||
|
||||
#ifdef SOFAR_CAN
|
||||
#include "SOFAR-CAN.h"
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
/* TODO: Map error bits in 0x158 */
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis100ms = 0; // will store last time a 100ms CAN Message was send
|
||||
static const int interval100ms = 100; // interval (ms) at which send CAN Messages
|
||||
|
@ -94,10 +96,12 @@ CAN_frame_t SMA_158 = {.FIR = {.B =
|
|||
.MsgID = 0x158,
|
||||
.data = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0xAA, 0xAA}};
|
||||
|
||||
static int discharge_current = 0;
|
||||
static int charge_current = 0;
|
||||
static int temperature_average = 0;
|
||||
static int ampere_hours_remaining = 0;
|
||||
static int16_t discharge_current = 0;
|
||||
static int16_t charge_current = 0;
|
||||
static int16_t temperature_average = 0;
|
||||
static int16_t temp_min = 0;
|
||||
static int16_t temp_max = 0;
|
||||
static uint16_t ampere_hours_remaining = 0;
|
||||
|
||||
void update_values_can_sma() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
//Calculate values
|
||||
|
@ -111,7 +115,9 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
//The above calculation results in (30 000*10)/3700=81A
|
||||
discharge_current = (discharge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A)
|
||||
|
||||
temperature_average = ((temperature_max + temperature_min) / 2);
|
||||
temp_min = temperature_min; //Convert from unsigned to signed
|
||||
temp_max = temperature_max;
|
||||
temperature_average = ((temp_max + temp_min) / 2);
|
||||
|
||||
ampere_hours_remaining =
|
||||
((remaining_capacity_Wh / battery_voltage) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
|
@ -149,10 +155,63 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
//Temperature average
|
||||
SMA_4D8.data.u8[4] = (temperature_average >> 8);
|
||||
SMA_4D8.data.u8[5] = (temperature_average & 0x00FF);
|
||||
//Battery ready
|
||||
if (bms_status == ACTIVE) {
|
||||
SMA_4D8.data.u8[6] = READY_STATE;
|
||||
} else {
|
||||
SMA_4D8.data.u8[6] = STOP_STATE;
|
||||
}
|
||||
|
||||
//Error bits
|
||||
/*
|
||||
//SMA_158.data.u8[0] = //bit12 Fault high temperature, bit34Battery cellundervoltage, bit56 Battery cell overvoltage, bit78 batterysystemdefect
|
||||
//TODO: add all error bits. Sending message with all 0xAA until that.
|
||||
|
||||
0x158 can be used to send error messages or warnings.
|
||||
|
||||
Each message is defined of two bits:
|
||||
01=message triggered
|
||||
10=no message triggered
|
||||
0xA9=10101001, triggers first message
|
||||
0xA6=10100110, triggers second message
|
||||
0x9A=10011010, triggers third message
|
||||
0x6A=01101010, triggers forth message
|
||||
bX defines the byte
|
||||
|
||||
b0 A9 Battery system defect
|
||||
b0 A6 Battery cell overvoltage fault
|
||||
b0 9A Battery cell undervoltage fault
|
||||
b0 6A Battery high temperature fault
|
||||
b1 A9 Battery low temperature fault
|
||||
b1 A6 Battery high temperature fault
|
||||
b1 9A Battery low temperature fault
|
||||
b1 6A Overload (reboot required)
|
||||
b2 A9 Overload (reboot required)
|
||||
b2 A6 Incorrect switch position for the battery disconnection point
|
||||
b2 9A Battery system short circuit
|
||||
b2 6A Internal battery hardware fault
|
||||
b3 A9 Battery imbalancing fault
|
||||
b3 A6 Battery service life expiry
|
||||
b3 9A Battery system thermal management defective
|
||||
b3 6A Internal battery hardware fault
|
||||
b4 A9 Battery system defect (warning)
|
||||
b4 A6 Battery cell overvoltage fault (warning)
|
||||
b4 9A Battery cell undervoltage fault (warning)
|
||||
b4 6A Battery high temperature fault (warning)
|
||||
b5 A9 Battery low temperature fault (warning)
|
||||
b5 A6 Battery high temperature fault (warning)
|
||||
b5 9A Battery low temperature fault (warning)
|
||||
b5 6A Self-diagnosis (warning)
|
||||
b6 A9 Self-diagnosis (warning)
|
||||
b6 A6 Incorrect switch position for the battery disconnection point (warning)
|
||||
b6 9A Battery system short circuit (warning)
|
||||
b6 6A Internal battery hardware fault (warning)
|
||||
b7 A9 Battery imbalancing fault (warning)
|
||||
b7 A6 Battery service life expiry (warning)
|
||||
b7 9A Battery system thermal management defective (warning)
|
||||
b7 6A Internal battery hardware fault (warning)
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
void receive_can_sma(CAN_frame_t rx_frame) {
|
||||
|
@ -164,11 +223,11 @@ void receive_can_sma(CAN_frame_t rx_frame) {
|
|||
case 0x420: //Message originating from SMA inverter - Timestamp
|
||||
//Frame0-3 Timestamp
|
||||
break;
|
||||
case 0x660: //Message originating from SMA inverter
|
||||
case 0x3E0: //Message originating from SMA inverter - ?
|
||||
break;
|
||||
case 0x5E0: //Message originating from SMA inverter
|
||||
case 0x5E0: //Message originating from SMA inverter - String
|
||||
break;
|
||||
case 0x560: //Message originating from SMA inverter
|
||||
case 0x560: //Message originating from SMA inverter - Init
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -185,9 +244,9 @@ void send_can_sma() {
|
|||
ESP32Can.CANWriteFrame(&SMA_558);
|
||||
ESP32Can.CANWriteFrame(&SMA_598);
|
||||
ESP32Can.CANWriteFrame(&SMA_5D8);
|
||||
ESP32Can.CANWriteFrame(&SMA_618_1);
|
||||
ESP32Can.CANWriteFrame(&SMA_618_2);
|
||||
ESP32Can.CANWriteFrame(&SMA_618_3);
|
||||
ESP32Can.CANWriteFrame(&SMA_618_1); // TODO, should these 3x
|
||||
ESP32Can.CANWriteFrame(&SMA_618_2); // be sent as batch?
|
||||
ESP32Can.CANWriteFrame(&SMA_618_3); // or alternate on each send?
|
||||
ESP32Can.CANWriteFrame(&SMA_358);
|
||||
ESP32Can.CANWriteFrame(&SMA_3D8);
|
||||
ESP32Can.CANWriteFrame(&SMA_458);
|
||||
|
|
|
@ -18,11 +18,15 @@ extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 funct
|
|||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint8_t bms_status;
|
||||
extern uint16_t min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
#define READY_STATE 0x03
|
||||
#define STOP_STATE 0x02
|
||||
|
||||
void update_values_can_sma();
|
||||
void send_can_sma();
|
||||
void receive_can_sma(CAN_frame_t rx_frame);
|
||||
|
|
364
Software/src/inverter/SMA-TRIPOWER-CAN.cpp
Normal file
364
Software/src/inverter/SMA-TRIPOWER-CAN.cpp
Normal file
|
@ -0,0 +1,364 @@
|
|||
#include "SMA-TRIPOWER-CAN.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
/* TODO:
|
||||
- Figure out the manufacturer info needed in send_tripower_init() CAN messages
|
||||
- CAN logs from real system might be needed
|
||||
- Figure out how cellvoltages need to be displayed
|
||||
- Figure out if sending send_tripower_init() like we do now is OK
|
||||
- Figure out how to send the non-cyclic messages when needed
|
||||
*/
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis500ms = 0; // will store last time a 100ms CAN Message was send
|
||||
static const int interval500ms = 100; // interval (ms) at which send CAN Messages
|
||||
|
||||
//Actual content messages
|
||||
static CAN_frame_t SMA_00D = { // Battery Limits
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x00D,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_00F = { // Battery State
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x00F,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_011 = { // Battery Energy
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x011,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_013 = { // Battery Measurements
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x013,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_014 = { // Battery Tempeartures and Cellvoltages
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x014,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_005 = { // Battery Alarms 1
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x005,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_007 = { // Battery Alarms 2
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x007,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_006 = { // Battery Error Codes
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x006,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_008 = { // Battery Events
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x008,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_015 = { // Battery Data 1
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x015,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_016 = { // Battery Data 2
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x016,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_017 = { // Battery Manufacturer
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x017,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
static CAN_frame_t SMA_018 = { // Battery Name
|
||||
.FIR = {.B =
|
||||
{
|
||||
.DLC = 8,
|
||||
.FF = CAN_frame_std,
|
||||
}},
|
||||
.MsgID = 0x018,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
static int discharge_current = 0;
|
||||
static int charge_current = 0;
|
||||
static int temperature_average = 0;
|
||||
static int ampere_hours_remaining = 0;
|
||||
static int ampere_hours_max = 0;
|
||||
static bool batteryAlarm = false;
|
||||
static bool BMSevent = false;
|
||||
|
||||
enum BatteryState { NA, INIT, BAT_STANDBY, OPERATE, WARNING, FAULTED, UPDATE, BAT_UPDATE };
|
||||
BatteryState batteryState = OPERATE;
|
||||
enum InverterControlFlags {
|
||||
EMG_CHARGE_REQUEST,
|
||||
EMG_DISCHARGE_REQUEST,
|
||||
NOT_ENOUGH_ENERGY_FOR_START,
|
||||
INVERTER_STAY_ON,
|
||||
FORCED_BATTERY_SHUTDOWN,
|
||||
RESERVED,
|
||||
BATTERY_UPDATE_AVAILABLE,
|
||||
NO_BATTERY_UPDATED_BY_INV
|
||||
};
|
||||
InverterControlFlags inverterControlFlags = BATTERY_UPDATE_AVAILABLE;
|
||||
enum Events0 {
|
||||
START_SOC_CALIBRATE,
|
||||
STOP_SOC_CALIBRATE,
|
||||
START_POWERLIMIT,
|
||||
STOP_POWERLIMIT,
|
||||
PREVENTATIVE_BAT_SHUTDOWN,
|
||||
THERMAL_MANAGEMENT,
|
||||
START_BALANCING,
|
||||
STOP_BALANCING
|
||||
};
|
||||
Events0 events0 = START_BALANCING;
|
||||
enum Events1 { START_BATTERY_SELFTEST, STOP_BATTERY_SELFTEST };
|
||||
Events1 events1 = START_BATTERY_SELFTEST;
|
||||
enum Command2Battery { IDLE, RUN, NOT_USED1, NOT_USED2, SHUTDOWN, FIRMWARE_UPDATE, BATSELFUPDATE, NOT_USED3 };
|
||||
Command2Battery command2Battery = RUN;
|
||||
enum InvInitState { SYSTEM_FREQUENCY, XPHASE_SYSTEM, BLACKSTART_OPERATION };
|
||||
InvInitState invInitState = SYSTEM_FREQUENCY;
|
||||
|
||||
void update_values_can_sma_tripower() { //This function maps all the values fetched from battery CAN to the inverter CAN
|
||||
//Calculate values
|
||||
charge_current =
|
||||
((max_target_charge_power * 10) / max_voltage); //Charge power in W , max volt in V+1decimal (P=UI, solve for I)
|
||||
//The above calculation results in (30 000*10)/3700=81A
|
||||
charge_current = (charge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A)
|
||||
|
||||
discharge_current = ((max_target_discharge_power * 10) /
|
||||
max_voltage); //Charge power in W , max volt in V+1decimal (P=UI, solve for I)
|
||||
//The above calculation results in (30 000*10)/3700=81A
|
||||
discharge_current = (discharge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A)
|
||||
|
||||
temperature_average = ((temperature_max + temperature_min) / 2);
|
||||
|
||||
ampere_hours_remaining =
|
||||
((remaining_capacity_Wh / battery_voltage) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
ampere_hours_max = ((capacity_Wh / battery_voltage) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
|
||||
batteryState = OPERATE;
|
||||
inverterControlFlags = INVERTER_STAY_ON;
|
||||
|
||||
//Map values to CAN messages
|
||||
// Battery Limits
|
||||
//Battery Max Charge Voltage (eg 400.0V = 4000 , 16bits long)
|
||||
SMA_00D.data.u8[0] = (max_voltage >> 8);
|
||||
SMA_00D.data.u8[1] = (max_voltage & 0x00FF);
|
||||
//Battery Min Discharge Voltage (eg 300.0V = 3000 , 16bits long)
|
||||
SMA_00D.data.u8[2] = (min_voltage >> 8);
|
||||
SMA_00D.data.u8[3] = (min_voltage & 0x00FF);
|
||||
//Discharge limited current, 500 = 50A, (0.1, A)
|
||||
SMA_00D.data.u8[4] = (discharge_current >> 8);
|
||||
SMA_00D.data.u8[5] = (discharge_current & 0x00FF);
|
||||
//Charge limited current, 125 =12.5A (0.1, A)
|
||||
SMA_00D.data.u8[6] = (charge_current >> 8);
|
||||
SMA_00D.data.u8[7] = (charge_current & 0x00FF);
|
||||
|
||||
// Battery State
|
||||
//SOC (100.00%)
|
||||
SMA_00F.data.u8[0] = (SOC >> 8);
|
||||
SMA_00F.data.u8[1] = (SOC & 0x00FF);
|
||||
//StateOfHealth (100.00%)
|
||||
SMA_00F.data.u8[2] = (StateOfHealth >> 8);
|
||||
SMA_00F.data.u8[3] = (StateOfHealth & 0x00FF);
|
||||
//State of charge (AH, 0.1)
|
||||
SMA_00F.data.u8[4] = (ampere_hours_remaining >> 8);
|
||||
SMA_00F.data.u8[5] = (ampere_hours_remaining & 0x00FF);
|
||||
//Fully charged (AH, 0.1)
|
||||
SMA_00F.data.u8[6] = (ampere_hours_max >> 8);
|
||||
SMA_00F.data.u8[7] = (ampere_hours_max & 0x00FF);
|
||||
|
||||
// Battery Energy
|
||||
//Charged Energy Counter TODO: are these needed?
|
||||
//SMA_011.data.u8[0] = (X >> 8);
|
||||
//SMA_011.data.u8[1] = (X & 0x00FF);
|
||||
//SMA_011.data.u8[2] = (X >> 8);
|
||||
//SMA_011.data.u8[3] = (X & 0x00FF);
|
||||
//Discharged Energy Counter TODO: are these needed?
|
||||
//SMA_011.data.u8[4] = (X >> 8);
|
||||
//SMA_011.data.u8[5] = (X & 0x00FF);
|
||||
//SMA_011.data.u8[6] = (X >> 8);
|
||||
//SMA_011.data.u8[7] = (X & 0x00FF);
|
||||
|
||||
// Battery Measurements
|
||||
//Voltage (370.0)
|
||||
SMA_013.data.u8[0] = (battery_voltage >> 8);
|
||||
SMA_013.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
//Current (TODO: signed OK?)
|
||||
SMA_013.data.u8[2] = (battery_current >> 8);
|
||||
SMA_013.data.u8[3] = (battery_current & 0x00FF);
|
||||
//Temperature average
|
||||
SMA_013.data.u8[4] = (temperature_average >> 8);
|
||||
SMA_013.data.u8[5] = (temperature_average & 0x00FF);
|
||||
//Battery state
|
||||
SMA_013.data.u8[6] = batteryState;
|
||||
SMA_013.data.u8[6] = inverterControlFlags;
|
||||
|
||||
// Battery Temperature and Cellvoltages
|
||||
// Battery max temperature
|
||||
SMA_014.data.u8[0] = (temperature_max >> 8);
|
||||
SMA_014.data.u8[1] = (temperature_max & 0x00FF);
|
||||
// Battery min temperature
|
||||
SMA_014.data.u8[2] = (temperature_min >> 8);
|
||||
SMA_014.data.u8[3] = (temperature_min & 0x00FF);
|
||||
// Battery Cell Voltage (sum)
|
||||
//SMA_014.data.u8[4] = (??? >> 8); //TODO scaling?
|
||||
//SMA_014.data.u8[5] = (??? & 0x00FF); //TODO scaling?
|
||||
// Cell voltage min
|
||||
//SMA_014.data.u8[6] = (??? >> 8); //TODO scaling? 0-255
|
||||
// Cell voltage max
|
||||
//SMA_014.data.u8[7] = (??? >> 8); //TODO scaling? 0-255
|
||||
|
||||
//SMA_006.data.u8[0] = (ErrorCode >> 8);
|
||||
//SMA_006.data.u8[1] = (ErrorCode & 0x00FF);
|
||||
//SMA_006.data.u8[2] = ModuleNumber;
|
||||
//SMA_006.data.u8[3] = ErrorLevel;
|
||||
//SMA_008.data.u8[0] = Events0;
|
||||
//SMA_008.data.u8[1] = Events1;
|
||||
|
||||
//SMA_005.data.u8[0] = BMSalarms0;
|
||||
//SMA_005.data.u8[1] = BMSalarms1;
|
||||
//SMA_005.data.u8[2] = BMSalarms2;
|
||||
//SMA_005.data.u8[3] = BMSalarms3;
|
||||
//SMA_005.data.u8[4] = BMSalarms4;
|
||||
//SMA_005.data.u8[5] = BMSalarms5;
|
||||
//SMA_005.data.u8[6] = BMSalarms6;
|
||||
//SMA_005.data.u8[7] = BMSalarms7;
|
||||
|
||||
//SMA_007.data.u8[0] = DCDCalarms0;
|
||||
//SMA_007.data.u8[1] = DCDCalarms1;
|
||||
//SMA_007.data.u8[2] = DCDCalarms2;
|
||||
//SMA_007.data.u8[3] = DCDCalarms3;
|
||||
//SMA_007.data.u8[4] = DCDCwarnings0;
|
||||
//SMA_007.data.u8[5] = DCDCwarnings1;
|
||||
//SMA_007.data.u8[6] = DCDCwarnings2;
|
||||
//SMA_007.data.u8[7] = DCDCwarnings3;
|
||||
|
||||
//SMA_015.data.u8[0] = BatterySystemVersion;
|
||||
//SMA_015.data.u8[1] = BatterySystemVersion;
|
||||
//SMA_015.data.u8[2] = BatterySystemVersion;
|
||||
//SMA_015.data.u8[3] = BatterySystemVersion;
|
||||
//SMA_015.data.u8[4] = BatteryCapacity;
|
||||
//SMA_015.data.u8[5] = BatteryCapacity;
|
||||
//SMA_015.data.u8[6] = NumberOfModules;
|
||||
//SMA_015.data.u8[7] = BatteryManufacturerID;
|
||||
|
||||
//SMA_016.data.u8[0] = SerialNumber;
|
||||
//SMA_016.data.u8[1] = SerialNumber;
|
||||
//SMA_016.data.u8[2] = SerialNumber;
|
||||
//SMA_016.data.u8[3] = SerialNumber;
|
||||
//SMA_016.data.u8[4] = ManufacturingDate;
|
||||
//SMA_016.data.u8[5] = ManufacturingDate;
|
||||
//SMA_016.data.u8[6] = ManufacturingDate;
|
||||
//SMA_016.data.u8[7] = ManufacturingDate;
|
||||
|
||||
//SMA_017.data.u8[0] = Multiplex;
|
||||
//SMA_017.data.u8[1] = ManufacturerName;
|
||||
//SMA_017.data.u8[2] = ManufacturerName;
|
||||
//SMA_017.data.u8[3] = ManufacturerName;
|
||||
//SMA_017.data.u8[4] = ManufacturerName;
|
||||
//SMA_017.data.u8[5] = ManufacturerName;
|
||||
//SMA_017.data.u8[6] = ManufacturerName;
|
||||
//SMA_017.data.u8[7] = ManufacturerName;
|
||||
|
||||
//SMA_018.data.u8[0] = Multiplex;
|
||||
//SMA_018.data.u8[1] = BatteryName;
|
||||
//SMA_018.data.u8[2] = BatteryName;
|
||||
//SMA_018.data.u8[3] = BatteryName;
|
||||
//SMA_018.data.u8[4] = BatteryName;
|
||||
//SMA_018.data.u8[5] = BatteryName;
|
||||
//SMA_018.data.u8[6] = BatteryName;
|
||||
//SMA_018.data.u8[7] = BatteryName;
|
||||
}
|
||||
|
||||
void receive_can_sma_tripower(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x00D: //Inverter Measurements
|
||||
break;
|
||||
case 0x00F: //Inverter Feedback
|
||||
break;
|
||||
case 0x010: //Time from inverter
|
||||
break;
|
||||
case 0x015: //Initialization message from inverter
|
||||
send_tripower_init();
|
||||
break;
|
||||
case 0x017: //Initialization message from inverter 2
|
||||
//send_tripower_init();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_sma_tripower() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// Send CAN Message every 500ms
|
||||
if (currentMillis - previousMillis500ms >= interval500ms) {
|
||||
previousMillis500ms = currentMillis;
|
||||
|
||||
ESP32Can.CANWriteFrame(&SMA_00D); //Battery limits
|
||||
ESP32Can.CANWriteFrame(&SMA_00F); // Battery state
|
||||
ESP32Can.CANWriteFrame(&SMA_011); // Battery Energy
|
||||
ESP32Can.CANWriteFrame(&SMA_013); // Battery Measurements
|
||||
ESP32Can.CANWriteFrame(&SMA_014); // Battery Temperatures and cellvoltages
|
||||
}
|
||||
|
||||
if (batteryAlarm) { //Non-cyclic
|
||||
ESP32Can.CANWriteFrame(&SMA_005); // Battery Alarms 1
|
||||
ESP32Can.CANWriteFrame(&SMA_007); // Battery Alarms 2
|
||||
}
|
||||
|
||||
if (BMSevent) { //Non-cyclic
|
||||
ESP32Can.CANWriteFrame(&SMA_006); // Battery Errorcode
|
||||
ESP32Can.CANWriteFrame(&SMA_008); // Battery Events
|
||||
}
|
||||
}
|
||||
|
||||
void send_tripower_init() {
|
||||
ESP32Can.CANWriteFrame(&SMA_015); // Battery Data 1
|
||||
ESP32Can.CANWriteFrame(&SMA_016); // Battery Data 2
|
||||
ESP32Can.CANWriteFrame(&SMA_017); // Battery Manufacturer
|
||||
ESP32Can.CANWriteFrame(&SMA_018); // Battery Name
|
||||
}
|
32
Software/src/inverter/SMA-TRIPOWER-CAN.h
Normal file
32
Software/src/inverter/SMA-TRIPOWER-CAN.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef SMA_CAN_TRIPOWER_H
|
||||
#define SMA_CAN_TRIPOWER_H
|
||||
#include <Arduino.h>
|
||||
#include "../../USER_SETTINGS.h"
|
||||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
extern uint16_t SOC; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t StateOfHealth; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t battery_current; //A+1, Goes thru convert2unsignedint16 function (5.0A = 50, -5.0A = 65485)
|
||||
extern uint16_t capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t remaining_capacity_Wh; //Wh, 0-60000
|
||||
extern uint16_t max_target_discharge_power; //W, 0-60000
|
||||
extern uint16_t max_target_charge_power; //W, 0-60000
|
||||
extern uint8_t bms_char_dis_status; //Enum, 0-2
|
||||
extern uint16_t stat_batt_power; //W, Goes thru convert2unsignedint16 function (5W = 5, -5W = 65530)
|
||||
extern uint16_t temperature_min; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t temperature_max; //C+1, Goes thru convert2unsignedint16 function (15.0C = 150, -15.0C = 65385)
|
||||
extern uint16_t cell_max_voltage; //mV, 0-4350
|
||||
extern uint16_t cell_min_voltage; //mV, 0-4350
|
||||
extern uint16_t min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void update_values_can_sma_tripower();
|
||||
void send_can_sma_tripower();
|
||||
void receive_can_sma_tripower(CAN_frame_t rx_frame);
|
||||
void send_tripower_init();
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue