Merge branch 'main' into feature/test-mode

This commit is contained in:
Daniel Öster 2023-11-15 17:23:03 +02:00 committed by GitHub
commit 8dbf3960c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 58 additions and 52 deletions

View file

@ -82,6 +82,7 @@ const uint8_t maxBrightness = 100;
uint8_t LEDcolor = GREEN;
// Contactor parameters
#ifdef CONTACTOR_CONTROL
enum State { DISCONNECTED, PRECHARGE, NEGATIVE, POSITIVE, PRECHARGE_OFF, COMPLETED, SHUTDOWN_REQUESTED };
State contactorStatus = DISCONNECTED;
@ -89,16 +90,19 @@ State contactorStatus = DISCONNECTED;
#define PRECHARGE_TIME_MS 160
#define NEGATIVE_CONTACTOR_TIME_MS 1000
#define POSITIVE_CONTACTOR_TIME_MS 2000
#ifdef PWM_CONTACTOR_CONTROL
#define PWM_Freq 20000 // 20 kHz frequency, beyond audible range
#define PWM_Res 10 // 10 Bit resolution 0 to 1023, maps 'nicely' to 0% 100%
#define PWM_Hold_Duty 250
#define POSITIVE_PWM_Ch 0
#define NEGATIVE_PWM_Ch 1
#endif
unsigned long prechargeStartTime = 0;
unsigned long negativeStartTime = 0;
unsigned long timeSpentInFaultedMode = 0;
uint8_t batteryAllowsContactorClosing = 0;
uint8_t inverterAllowsContactorClosing = 1;
#endif
bool batteryAllowsContactorClosing = false;
bool inverterAllowsContactorClosing = true;
// Initialization
void setup() {
@ -252,7 +256,7 @@ void inform_user_on_inverter() {
Serial.println("SOFAR CAN protocol selected");
#endif
#ifdef SOLAX_CAN
inverterAllowsContactorClosing = 0; // The inverter needs to allow first on this protocol
inverterAllowsContactorClosing = false; // The inverter needs to allow first on this protocol
intervalUpdateValues = 800; // This protocol also requires the values to be updated faster
Serial.println("SOLAX CAN protocol selected");
#endif

View file

@ -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) {

View file

@ -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

View file

@ -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?

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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];

View file

@ -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

View file

@ -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);

View file

@ -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