mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
Merge branch 'main' into feature/test-mode
This commit is contained in:
commit
8dbf3960c4
17 changed files with 58 additions and 52 deletions
|
@ -2,7 +2,7 @@
|
|||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
//TODO before using
|
||||
//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)
|
||||
// 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)
|
||||
|
||||
|
@ -80,7 +80,7 @@ void update_values_i3_battery() { //This function maps all the values fetched v
|
|||
{
|
||||
max_target_charge_power = 0;
|
||||
} else {
|
||||
max_target_charge_power = 5000; //Hardcoded value for testing. TODO, read real value from battery when discovered
|
||||
max_target_charge_power = 5000; //Hardcoded value for testing. TODO: read real value from battery when discovered
|
||||
}
|
||||
|
||||
if (SOC < 500) //If Soc is under 5%, stop dicharging
|
||||
|
@ -88,16 +88,16 @@ void update_values_i3_battery() { //This function maps all the values fetched v
|
|||
max_target_discharge_power = 0;
|
||||
} else {
|
||||
max_target_discharge_power =
|
||||
5000; //Hardcoded value for testing. TODO, read real value from battery when discovered
|
||||
5000; //Hardcoded value for testing. TODO: read real value from battery when discovered
|
||||
}
|
||||
|
||||
Battery_Power = (Battery_Current * (Battery_Volts / 10));
|
||||
|
||||
stat_batt_power = Battery_Power; //TODO, is mapping OK?
|
||||
stat_batt_power = Battery_Power; //TODO:, is mapping OK?
|
||||
|
||||
temperature_min; //hardcoded to 5*C in startup, TODO, find from battery CAN later
|
||||
temperature_min; //hardcoded to 5*C in startup, TODO:, find from battery CAN later
|
||||
|
||||
temperature_max; //hardcoded to 6*C in startup, TODO, find from battery CAN later
|
||||
temperature_max; //hardcoded to 6*C in startup, TODO:, find from battery CAN later
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
|
|
@ -23,7 +23,7 @@ extern uint16_t stat_batt_power;
|
|||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
extern uint8_t batteryAllowsContactorClosing;
|
||||
extern bool batteryAllowsContactorClosing;
|
||||
// Definitions for BMS status
|
||||
#define STANDBY 0
|
||||
#define INACTIVE 1
|
||||
|
|
|
@ -95,7 +95,7 @@ void update_values_chademo_battery() { //This function maps all the values fetc
|
|||
|
||||
max_target_discharge_power = (MaximumDischargeCurrent * MaximumBatteryVoltage); //In Watts, Convert A to P
|
||||
|
||||
battery_voltage = TargetBatteryVoltage; //Todo, scaling?
|
||||
battery_voltage = TargetBatteryVoltage; //TODO: scaling?
|
||||
|
||||
capacity_Wh = ((RatedBatteryCapacity / 0.11) *
|
||||
1000); //(Added in CHAdeMO v1.0.1), maybe handle hardcoded on lower protocol version?
|
||||
|
|
|
@ -32,8 +32,8 @@ static double voltage2 = 0;
|
|||
static double BMU_Current = 0;
|
||||
static double BMU_PackVoltage = 0;
|
||||
static double BMU_Power = 0;
|
||||
static double cell_voltages[89]; //array with all the cellvoltages //Todo, what is max array size? 80/88 cells?
|
||||
static double cell_temperatures[89]; //array with all the celltemperatures //Todo, what is max array size? 80/88cells?
|
||||
static double cell_voltages[89]; //array with all the cellvoltages //TODO: what is max array size? 80/88 cells?
|
||||
static double cell_temperatures[89]; //array with all the celltemperatures //TODO: what is max array size? 80/88cells?
|
||||
static double max_volt_cel = 3.70;
|
||||
static double min_volt_cel = 3.70;
|
||||
static double max_temp_cel = 20.00;
|
||||
|
@ -65,7 +65,7 @@ void update_values_imiev_battery() { //This function maps all the values fetche
|
|||
max_target_discharge_power = 10000; //Otherwise we can discharge 10kW from the pack!
|
||||
}
|
||||
|
||||
stat_batt_power = BMU_Power; //TODO, Scaling?
|
||||
stat_batt_power = BMU_Power; //TODO: Scaling?
|
||||
|
||||
static int n = sizeof(cell_voltages) / sizeof(cell_voltages[0]);
|
||||
max_volt_cel = cell_voltages[0]; // Initialize max with the first element of the array
|
||||
|
@ -164,7 +164,7 @@ void update_values_imiev_battery() { //This function maps all the values fetche
|
|||
|
||||
void receive_can_imiev_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
|
||||
12; //TODO: move this inside a known message ID to prevent CAN inverter from keeping battery alive detection going
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x374: //BMU message, 10ms - SOC
|
||||
temp_value = ((rx_frame.data.u8[1] - 10) / 2);
|
||||
|
|
|
@ -25,7 +25,7 @@ extern uint16_t temperature_max;
|
|||
extern uint16_t CANerror;
|
||||
extern uint16_t cell_max_voltage;
|
||||
extern uint16_t cell_min_voltage;
|
||||
extern uint8_t batteryAllowsContactorClosing;
|
||||
extern bool batteryAllowsContactorClosing;
|
||||
extern uint8_t LEDcolor;
|
||||
// Definitions for BMS status
|
||||
#define STANDBY 0
|
||||
|
|
|
@ -23,7 +23,7 @@ extern uint16_t stat_batt_power;
|
|||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
extern uint8_t batteryAllowsContactorClosing;
|
||||
extern bool batteryAllowsContactorClosing;
|
||||
// Definitions for BMS status
|
||||
#define STANDBY 0
|
||||
#define INACTIVE 1
|
||||
|
|
|
@ -405,9 +405,9 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
|||
LB_Failsafe_Status = (rx_frame.data.u8[1] & 0x07);
|
||||
LB_MainRelayOn_flag = (byte)((rx_frame.data.u8[3] & 0x20) >> 5);
|
||||
if (LB_MainRelayOn_flag) {
|
||||
batteryAllowsContactorClosing = 1;
|
||||
batteryAllowsContactorClosing = true;
|
||||
} else {
|
||||
batteryAllowsContactorClosing = 0;
|
||||
batteryAllowsContactorClosing = false;
|
||||
}
|
||||
LB_Full_CHARGE_flag = (byte)((rx_frame.data.u8[3] & 0x10) >> 4);
|
||||
LB_Interlock = (byte)((rx_frame.data.u8[3] & 0x08) >> 3);
|
||||
|
|
|
@ -25,8 +25,9 @@ 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 batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint8_t LEDcolor; //Enum, 0-10
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
// Definitions for bms_status
|
||||
#define STANDBY 0
|
||||
#define INACTIVE 1
|
||||
|
|
|
@ -71,7 +71,7 @@ static uint8_t packContactorSetState = 0;
|
|||
static uint8_t packCtrsClosingAllowed = 0;
|
||||
static uint8_t pyroTestInProgress = 0;
|
||||
static uint8_t send221still = 10;
|
||||
static uint8_t LFP_Chemistry = 0;
|
||||
static bool LFP_Chemistry = false;
|
||||
//Fault codes
|
||||
static uint8_t WatchdogReset = 0; //Warns if the processor has experienced a reset due to watchdog reset.
|
||||
static uint8_t PowerLossReset = 0; //Warns if the processor has experienced a reset due to power loss.
|
||||
|
@ -177,7 +177,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
|
||||
battery_voltage = (volts * 10); //One more decimal needed (370 -> 3700)
|
||||
|
||||
battery_current = amps; //TODO, this needs verifying if scaling is right
|
||||
battery_current = (amps * 10); //Increase decimal (13A -> 13.0A)
|
||||
|
||||
capacity_Wh = (nominal_full_pack_energy * 100); //Scale up 75.2kWh -> 75200Wh
|
||||
if (capacity_Wh > 60000) {
|
||||
|
@ -201,7 +201,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
max_target_charge_power = 15000; //Otherwise we can push 15kW into the pack!
|
||||
}
|
||||
|
||||
stat_batt_power = (volts * amps); //TODO, check if scaling is OK
|
||||
stat_batt_power = (volts * amps); //TODO: check if scaling is OK
|
||||
|
||||
min_temp = (min_temp * 10);
|
||||
temperature_min = convert2unsignedInt16(min_temp);
|
||||
|
@ -232,13 +232,13 @@ 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 data 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 = 1;
|
||||
LFP_Chemistry = true;
|
||||
}
|
||||
if (cell_max_v > 3700) {
|
||||
LFP_Chemistry = 0;
|
||||
LFP_Chemistry = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,14 +37,14 @@ void handle_update_data_modbus39500() {
|
|||
system_data[9] =
|
||||
1; //Running status, equiv to register 37762, 0 = Offline, 1 = Standby,2 = Running, 3 = Fault, 4 = sleep mode
|
||||
system_data[10] = battery_voltage; //Battery bus voltage (766.5V = 7665)
|
||||
system_data[11] = 9; //TODO, GOES LOWER WITH LOW SOC
|
||||
system_data[11] = 9; //TODO: GOES LOWER WITH LOW SOC
|
||||
system_data[12] = 0;
|
||||
system_data[13] = 699; //TODO, GOES LOWER WITH LOW SOC
|
||||
system_data[13] = 699; //TODO: GOES LOWER WITH LOW SOC
|
||||
system_data[14] = 1; //Always 1 in logs
|
||||
system_data[15] = 18; //Always 18 in logs
|
||||
system_data[16] = 8066; //TODO, GOES HIGHER WITH LOW SOC (max allowed charge W?)
|
||||
system_data[16] = 8066; //TODO: GOES HIGHER WITH LOW SOC (max allowed charge W?)
|
||||
system_data[17] = 17;
|
||||
system_data[18] = 44027; //TODO, GOES LOWER WITH LOW SOC
|
||||
system_data[18] = 44027; //TODO: GOES LOWER WITH LOW SOC
|
||||
system_data[19] = 0;
|
||||
system_data[20] = 435; //Always 435 in logs
|
||||
system_data[21] = 0;
|
||||
|
|
|
@ -185,7 +185,7 @@ void update_values_can_pylon() { //This function maps all the values fetched fr
|
|||
PYLON_4211.data.u8[0] = (battery_voltage >> 8);
|
||||
PYLON_4211.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
|
||||
//Current (TODO, SIGNED? Or looks like it could be just offset, in that case the below line wont work)
|
||||
//Current (TODO: SIGNED? Or looks like it could be just offset, in that case the below line wont work)
|
||||
PYLON_4210.data.u8[2] = (battery_current >> 8);
|
||||
PYLON_4210.data.u8[3] = (battery_current & 0x00FF);
|
||||
PYLON_4211.data.u8[2] = (battery_current >> 8);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
//TODO, change CAN sending routine once confirmed that 500ms interval is OK for this battery type
|
||||
//TODO: change CAN sending routine once confirmed that 500ms interval is OK for this battery type
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis1s = 0; // will store last time a Xs CAN Message was send
|
||||
|
@ -167,7 +167,7 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
//Voltage (370.0)
|
||||
SMA_4D8.data.u8[0] = (battery_voltage >> 8);
|
||||
SMA_4D8.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
//Current (TODO, signed OK?)
|
||||
//Current (TODO: signed OK?)
|
||||
SMA_4D8.data.u8[2] = (battery_current >> 8);
|
||||
SMA_4D8.data.u8[3] = (battery_current & 0x00FF);
|
||||
//Temperature average
|
||||
|
@ -176,7 +176,7 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
|
||||
//Error bits
|
||||
//SMA_158.data.u8[0] = //bit12 Fault high temperature, bit34Battery cellundervoltage, bit56 Battery cell overvoltage, bit78 batterysystemdefect
|
||||
//TODO, add all error bits
|
||||
//TODO: add all error bits
|
||||
}
|
||||
|
||||
void receive_can_sma(CAN_frame_t rx_frame) {
|
||||
|
|
|
@ -307,7 +307,7 @@ void update_values_can_sofar() { //This function maps all the values fetched fr
|
|||
}
|
||||
|
||||
void receive_can_sofar(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) { //In here we need to respond to the inverter. TODO make logic
|
||||
switch (rx_frame.MsgID) { //In here we need to respond to the inverter. TODO: make logic
|
||||
case 0x605:
|
||||
//frame1_605 = rx_frame.data.u8[1];
|
||||
//frame3_605 = rx_frame.data.u8[3];
|
||||
|
|
|
@ -20,8 +20,9 @@ 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 batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint8_t LEDcolor; //Enum, 0-10
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
extern uint16_t min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
// Definitions for BMS status
|
||||
|
|
|
@ -118,7 +118,7 @@ void CAN_WriteFrame(CAN_frame_t* tx_frame) {
|
|||
void update_values_can_solax() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
// If not receiveing any communication from the inverter, open contactors and return to battery announce state
|
||||
if (millis() - LastFrameTime >= SolaxTimeout) {
|
||||
inverterAllowsContactorClosing = 0;
|
||||
inverterAllowsContactorClosing = false;
|
||||
STATE = BATTERY_ANNOUNCE;
|
||||
}
|
||||
//Calculate the required values
|
||||
|
@ -150,13 +150,13 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
|
||||
//Put the values into the CAN messages
|
||||
//BMS_Limits
|
||||
SOLAX_1872.data.u8[0] = (uint8_t)max_voltage; //Todo, scaling OK?
|
||||
SOLAX_1872.data.u8[0] = (uint8_t)max_voltage; //TODO: scaling OK?
|
||||
SOLAX_1872.data.u8[1] = (max_voltage >> 8);
|
||||
SOLAX_1872.data.u8[2] = (uint8_t)min_voltage; //Todo, scaling OK?
|
||||
SOLAX_1872.data.u8[2] = (uint8_t)min_voltage; //TODO: scaling OK?
|
||||
SOLAX_1872.data.u8[3] = (min_voltage >> 8);
|
||||
SOLAX_1872.data.u8[4] = (uint8_t)(max_charge_rate_amp * 10); //Todo, scaling OK?
|
||||
SOLAX_1872.data.u8[4] = (uint8_t)(max_charge_rate_amp * 10); //TODO: scaling OK?
|
||||
SOLAX_1872.data.u8[5] = ((max_charge_rate_amp * 10) >> 8);
|
||||
SOLAX_1872.data.u8[6] = (uint8_t)(max_discharge_rate_amp * 10); //Todo, scaling OK?
|
||||
SOLAX_1872.data.u8[6] = (uint8_t)(max_discharge_rate_amp * 10); //TODO: scaling OK?
|
||||
SOLAX_1872.data.u8[7] = ((max_discharge_rate_amp * 10) >> 8);
|
||||
|
||||
//BMS_PackData
|
||||
|
@ -166,7 +166,7 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
SOLAX_1873.data.u8[3] = (battery_current >> 8);
|
||||
SOLAX_1873.data.u8[4] = (uint8_t)(SOC / 100); //SOC (100.00%)
|
||||
//SOLAX_1873.data.u8[5] = //Seems like this is not required? Or shall we put SOC decimals here?
|
||||
SOLAX_1873.data.u8[6] = (uint8_t)(remaining_capacity_Wh / 100); //Todo, scaling OK?
|
||||
SOLAX_1873.data.u8[6] = (uint8_t)(remaining_capacity_Wh / 100); //TODO: scaling OK?
|
||||
SOLAX_1873.data.u8[7] = ((remaining_capacity_Wh / 100) >> 8);
|
||||
|
||||
//BMS_CellData
|
||||
|
@ -175,10 +175,10 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
SOLAX_1874.data.u8[2] = (uint8_t)temperature_min;
|
||||
SOLAX_1874.data.u8[3] = (temperature_min >> 8);
|
||||
SOLAX_1874.data.u8[4] =
|
||||
(uint8_t)(cell_max_voltage); //Todo, scaling OK? Supposed to be alarm trigger absolute cell max?
|
||||
(uint8_t)(cell_max_voltage); //TODO: scaling OK? Supposed to be alarm trigger absolute cell max?
|
||||
SOLAX_1874.data.u8[5] = (cell_max_voltage >> 8);
|
||||
SOLAX_1874.data.u8[6] =
|
||||
(uint8_t)(cell_min_voltage); //Todo, scaling OK? Supposed to be alarm trigger absolute cell min?
|
||||
(uint8_t)(cell_min_voltage); //TODO: scaling OK? Supposed to be alarm trigger absolute cell min?
|
||||
SOLAX_1874.data.u8[7] = (cell_min_voltage >> 8);
|
||||
|
||||
//BMS_Status
|
||||
|
@ -188,10 +188,10 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
SOLAX_1875.data.u8[4] = (uint8_t)0; // Contactor Status 0=off, 1=on.
|
||||
|
||||
//BMS_PackTemps (strange name, since it has voltages?)
|
||||
SOLAX_1876.data.u8[2] = (uint8_t)cell_max_voltage; //Todo, scaling OK?
|
||||
SOLAX_1876.data.u8[2] = (uint8_t)cell_max_voltage; //TODO: scaling OK?
|
||||
SOLAX_1876.data.u8[3] = (cell_min_voltage >> 8);
|
||||
|
||||
SOLAX_1876.data.u8[6] = (uint8_t)cell_min_voltage; //Todo, scaling OK?
|
||||
SOLAX_1876.data.u8[6] = (uint8_t)cell_min_voltage; //TODO: scaling OK?
|
||||
SOLAX_1876.data.u8[7] = (cell_min_voltage >> 8);
|
||||
|
||||
//Unknown
|
||||
|
@ -201,10 +201,10 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
(uint8_t)0x02; // The above firmware version applies to:02 = Master BMS, 10 = S1, 20 = S2, 30 = S3, 40 = S4
|
||||
|
||||
//BMS_PackStats
|
||||
SOLAX_1878.data.u8[0] = (uint8_t)(battery_voltage); //TODO, should this be max or current voltage?
|
||||
SOLAX_1878.data.u8[0] = (uint8_t)(battery_voltage); //TODO: should this be max or current voltage?
|
||||
SOLAX_1878.data.u8[1] = ((battery_voltage) >> 8);
|
||||
|
||||
SOLAX_1878.data.u8[4] = (uint8_t)capacity_Wh; //TODO, scaling OK?
|
||||
SOLAX_1878.data.u8[4] = (uint8_t)capacity_Wh; //TODO: scaling OK?
|
||||
SOLAX_1878.data.u8[5] = (capacity_Wh >> 8);
|
||||
|
||||
// BMS_Answer
|
||||
|
@ -220,7 +220,7 @@ void receive_can_solax(CAN_frame_t rx_frame) {
|
|||
switch (STATE) {
|
||||
case (BATTERY_ANNOUNCE):
|
||||
Serial.println("Solax Battery State: Announce");
|
||||
inverterAllowsContactorClosing = 0;
|
||||
inverterAllowsContactorClosing = false;
|
||||
SOLAX_1875.data.u8[4] = (0x00); // Inform Inverter: Contactor 0=off, 1=on.
|
||||
for (int i = 0; i <= number_of_batteries; i++) {
|
||||
CAN_WriteFrame(&SOLAX_1872);
|
||||
|
@ -253,7 +253,7 @@ void receive_can_solax(CAN_frame_t rx_frame) {
|
|||
break;
|
||||
|
||||
case (CONTACTOR_CLOSED):
|
||||
inverterAllowsContactorClosing = 1;
|
||||
inverterAllowsContactorClosing = true;
|
||||
SOLAX_1875.data.u8[4] = (0x01); // Inform Inverter: Contactor 0=off, 1=on.
|
||||
CAN_WriteFrame(&SOLAX_1872);
|
||||
CAN_WriteFrame(&SOLAX_1873);
|
||||
|
|
|
@ -26,7 +26,7 @@ extern uint16_t min_voltage;
|
|||
extern uint16_t max_voltage;
|
||||
extern uint16_t cell_max_voltage;
|
||||
extern uint16_t cell_min_voltage;
|
||||
extern uint8_t inverterAllowsContactorClosing;
|
||||
extern bool inverterAllowsContactorClosing;
|
||||
|
||||
// Timeout in milliseconds
|
||||
#define SolaxTimeout 2000
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue