mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
Refactoring variable names
This commit is contained in:
parent
032a0d75ee
commit
1730dc20dd
37 changed files with 934 additions and 971 deletions
|
@ -16,9 +16,6 @@ static const int interval20 = 20; // interval (ms) at which send CAN
|
|||
static const int interval600 = 600; // interval (ms) at which send CAN Messages
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
|
||||
#define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter
|
||||
#define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter
|
||||
|
||||
CAN_frame_t BMW_10B = {.FIR = {.B =
|
||||
{
|
||||
.DLC = 3,
|
||||
|
@ -58,47 +55,38 @@ static int16_t Battery_Power = 0;
|
|||
|
||||
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 =
|
||||
LB_MIN_SOC + (LB_MAX_SOC - LB_MIN_SOC) * (Calculated_SOC - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE);
|
||||
if (Calculated_SOC < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to inverter as 0%
|
||||
Calculated_SOC = 0;
|
||||
}
|
||||
if (Calculated_SOC > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to inverter as 100%
|
||||
Calculated_SOC = 1000;
|
||||
}
|
||||
SOC = (Calculated_SOC * 10); //increase LB_SOC range from 0-100.0 -> 100.00
|
||||
system_real_SOC_pptt = (Display_SOC * 100); //increase Display_SOC range from 0-100 -> 100.00
|
||||
|
||||
battery_voltage = Battery_Volts; //Unit V+1 (5000 = 500.0V)
|
||||
system_battery_voltage_dV = Battery_Volts; //Unit V+1 (5000 = 500.0V)
|
||||
|
||||
battery_current = Battery_Current;
|
||||
system_battery_current_dA = Battery_Current;
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX;
|
||||
system_capacity_Wh = BATTERY_WH_MAX;
|
||||
|
||||
remaining_capacity_Wh = (Battery_Capacity_kWh * 1000);
|
||||
system_remaining_capacity_Wh = (Battery_Capacity_kWh * 1000);
|
||||
|
||||
if (SOC > 9900) //If Soc is over 99%, stop charging
|
||||
if (system_scaled_SOC_pptt > 9900) //If Soc is over 99%, stop charging
|
||||
{
|
||||
max_target_charge_power = 0;
|
||||
system_max_charge_power_W = 0;
|
||||
} else {
|
||||
max_target_charge_power = 5000; //Hardcoded value for testing. TODO: read real value from battery when discovered
|
||||
system_max_charge_power_W = 5000; //Hardcoded value for testing. TODO: read real value from battery when discovered
|
||||
}
|
||||
|
||||
if (SOC < 500) //If Soc is under 5%, stop dicharging
|
||||
if (system_scaled_SOC_pptt < 500) //If Soc is under 5%, stop dicharging
|
||||
{
|
||||
max_target_discharge_power = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
} else {
|
||||
max_target_discharge_power =
|
||||
system_max_discharge_power_W =
|
||||
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?
|
||||
system_active_power_W = Battery_Power; //TODO:, is mapping OK?
|
||||
|
||||
temperature_min; //hardcoded to 5*C in startup, TODO:, find from battery CAN later
|
||||
system_temperature_min_dC; //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
|
||||
system_temperature_max_dC; //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) {
|
||||
|
@ -112,15 +100,15 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
Serial.print("SOC% battery: ");
|
||||
Serial.print(Display_SOC);
|
||||
Serial.print(" SOC% sent to inverter: ");
|
||||
Serial.print(SOC);
|
||||
Serial.print(system_scaled_SOC_pptt);
|
||||
Serial.print(" Battery voltage: ");
|
||||
Serial.print(battery_voltage);
|
||||
Serial.print(system_battery_voltage_dV);
|
||||
Serial.print(" Remaining Wh: ");
|
||||
Serial.print(remaining_capacity_Wh);
|
||||
Serial.print(system_remaining_capacity_Wh);
|
||||
Serial.print(" Max charge power: ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(" Max discharge power: ");
|
||||
Serial.print(max_target_discharge_power);
|
||||
Serial.print(system_max_discharge_power_W);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -196,8 +184,8 @@ void send_can_battery() {
|
|||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,24 +8,26 @@
|
|||
#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)
|
||||
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 uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void setup_battery(void);
|
||||
|
||||
|
|
|
@ -93,16 +93,16 @@ uint8_t HighVoltageControlStatus = 0;
|
|||
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for the inverter
|
||||
|
||||
SOC = ChargingRate;
|
||||
system_real_SOC_pptt = ChargingRate;
|
||||
|
||||
max_target_discharge_power = (MaximumDischargeCurrent * MaximumBatteryVoltage); //In Watts, Convert A to P
|
||||
system_max_discharge_power_W = (MaximumDischargeCurrent * MaximumBatteryVoltage); //In Watts, Convert A to P
|
||||
|
||||
battery_voltage = TargetBatteryVoltage; //TODO: scaling?
|
||||
system_battery_voltage_dV = TargetBatteryVoltage; //TODO: scaling?
|
||||
|
||||
capacity_Wh = ((RatedBatteryCapacity / 0.11) *
|
||||
system_capacity_Wh = ((RatedBatteryCapacity / 0.11) *
|
||||
1000); //(Added in CHAdeMO v1.0.1), maybe handle hardcoded on lower protocol version?
|
||||
|
||||
remaining_capacity_Wh = (SOC / 100) * capacity_Wh;
|
||||
system_remaining_capacity_Wh = (SOC / 100) * capacity_Wh;
|
||||
|
||||
/* Check if the Vehicle is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
@ -119,19 +119,19 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
Serial.println(errorCode);
|
||||
}
|
||||
Serial.print("BMS Status (3=OK): ");
|
||||
Serial.println(bms_status);
|
||||
Serial.println(system_bms_status);
|
||||
Serial.print("Max discharge power: ");
|
||||
Serial.println(max_target_discharge_power);
|
||||
Serial.println(system_max_discharge_power_W);
|
||||
Serial.print("Max charge power: ");
|
||||
Serial.println(max_target_charge_power);
|
||||
Serial.println(system_max_charge_power_W);
|
||||
Serial.print("SOH%: ");
|
||||
Serial.println(StateOfHealth);
|
||||
Serial.println(system_SOH_pptt);
|
||||
Serial.print("SOC% to Inverter: ");
|
||||
Serial.println(SOC);
|
||||
Serial.println(system_scaled_SOC_pptt);
|
||||
Serial.print("Temperature Min: ");
|
||||
Serial.println(temperature_min);
|
||||
Serial.println(system_temperature_min_dC);
|
||||
Serial.print("Temperature Max: ");
|
||||
Serial.println(temperature_max);
|
||||
Serial.println(system_temperature_max_dC);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ void send_can_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
|
||||
system_max_design_voltage_dV = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 2000; // 200.0V under this, discharging further is disabled
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,24 +8,26 @@
|
|||
#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)
|
||||
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 uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void setup_battery(void);
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
//Figure out if CAN messages need to be sent to keep the system happy?
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
#define BMU_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to inverter
|
||||
#define BMU_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to inverter
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic
|
||||
static uint8_t BMU_Detected = 0;
|
||||
|
@ -43,30 +41,30 @@ static double max_temp_cel = 20.00;
|
|||
static double min_temp_cel = 19.00;
|
||||
|
||||
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
|
||||
system_real_SOC_pptt = (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
|
||||
system_battery_voltage_dV = (uint16_t)(BMU_PackVoltage * 10); // Multiply by 10 and cast to uint16_t
|
||||
|
||||
battery_current = (BMU_Current * 10); //Todo, scaling?
|
||||
system_battery_current_dA = (BMU_Current * 10); //Todo, scaling?
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX; //Hardcoded to header value
|
||||
system_capacity_Wh = BATTERY_WH_MAX; //Hardcoded to header value
|
||||
|
||||
remaining_capacity_Wh = (uint16_t)((SOC / 10000) * capacity_Wh);
|
||||
system_remaining_capacity_Wh = (uint16_t)((SOC / 10000) * capacity_Wh);
|
||||
|
||||
//We do not know if the max charge power is sent by the battery. So we estimate the value based on SOC%
|
||||
if (SOC == 10000) { //100.00%
|
||||
max_target_charge_power = 0; //When battery is 100% full, set allowed charge W to 0
|
||||
if (system_scaled_SOC_pptt == 10000) { //100.00%
|
||||
system_max_charge_power_W = 0; //When battery is 100% full, set allowed charge W to 0
|
||||
} else {
|
||||
max_target_charge_power = 10000; //Otherwise we can push 10kW into the pack!
|
||||
system_max_charge_power_W = 10000; //Otherwise we can push 10kW into the pack!
|
||||
}
|
||||
|
||||
if (SOC < 200) { //2.00%
|
||||
max_target_discharge_power = 0; //When battery is empty (below 2%), set allowed discharge W to 0
|
||||
if (system_scaled_SOC_pptt < 200) { //2.00%
|
||||
system_max_discharge_power_W = 0; //When battery is empty (below 2%), set allowed discharge W to 0
|
||||
} else {
|
||||
max_target_discharge_power = 10000; //Otherwise we can discharge 10kW from the pack!
|
||||
system_max_discharge_power_W = 10000; //Otherwise we can discharge 10kW from the pack!
|
||||
}
|
||||
|
||||
stat_batt_power = BMU_Power; //TODO: Scaling?
|
||||
system_active_power_W = 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
|
||||
|
@ -98,13 +96,13 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
}
|
||||
|
||||
cell_max_voltage = (uint16_t)(max_volt_cel * 1000);
|
||||
system_cell_max_voltage_mV = (uint16_t)(max_volt_cel * 1000);
|
||||
|
||||
cell_min_voltage = (uint16_t)(min_volt_cel * 1000);
|
||||
system_cell_min_voltage_mV = (uint16_t)(min_volt_cel * 1000);
|
||||
|
||||
temperature_min = (uint16_t)(min_temp_cel * 1000);
|
||||
system_temperature_min_dC = (int16_t)(min_temp_cel * 1000);
|
||||
|
||||
temperature_max = (uint16_t)(max_temp_cel * 1000);
|
||||
system_temperature_min_dC = (int16_t)(max_temp_cel * 1000);
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
|
|
@ -7,25 +7,27 @@
|
|||
|
||||
#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)
|
||||
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
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void setup_battery(void);
|
||||
|
|
|
@ -12,8 +12,6 @@ static const int interval100 = 100; // interval (ms) at which send CAN
|
|||
static const int interval10ms = 10; // interval (ms) at which send CAN Messages
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
|
||||
#define MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter
|
||||
#define MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter
|
||||
#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value
|
||||
#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value
|
||||
#define MAX_CELL_DEVIATION 150 //LED turns yellow on the board if mv delta exceeds this value
|
||||
|
@ -150,52 +148,43 @@ CAN_frame_t KIA64_7E4_ack = {
|
|||
|
||||
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;
|
||||
soc_calculated = MIN_SOC + (MAX_SOC - MIN_SOC) * (soc_calculated - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE);
|
||||
if (soc_calculated < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to Inverter as 0%
|
||||
soc_calculated = 0;
|
||||
}
|
||||
if (soc_calculated > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to Inverter as 100%
|
||||
soc_calculated = 1000;
|
||||
}
|
||||
SOC = (soc_calculated * 10); //increase SOC range from 0-100.0 -> 100.00
|
||||
system_real_SOC_pptt = (SOC_Display * 10); //increase SOC range from 0-100.0 -> 100.00
|
||||
|
||||
StateOfHealth = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00%
|
||||
system_SOH_pptt = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00%
|
||||
|
||||
battery_voltage = batteryVoltage; //value is *10 (3700 = 370.0)
|
||||
system_battery_voltage_dV = batteryVoltage; //value is *10 (3700 = 370.0)
|
||||
|
||||
battery_current = convertToUnsignedInt16(batteryAmps); //value is *10 (150 = 15.0)
|
||||
system_battery_current_dA = batteryAmps; //value is *10 (150 = 15.0)
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX;
|
||||
system_capacity_Wh = BATTERY_WH_MAX;
|
||||
|
||||
remaining_capacity_Wh = static_cast<int>((static_cast<double>(SOC) / 10000) * BATTERY_WH_MAX);
|
||||
system_remaining_capacity_Wh = static_cast<int>((static_cast<double>(SOC) / 10000) * BATTERY_WH_MAX);
|
||||
|
||||
//max_target_charge_power = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts
|
||||
//system_max_charge_power_W = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts
|
||||
//The allowed charge power is not available. We estimate this value
|
||||
if (SOC == 10000) { // When scaled SOC is 100%, set allowed charge power to 0
|
||||
max_target_charge_power = 0;
|
||||
if (system_scaled_SOC_pptt == 10000) { // When scaled SOC is 100%, set allowed charge power to 0
|
||||
system_max_charge_power_W = 0;
|
||||
} else { // No limits, max charging power allowed
|
||||
max_target_charge_power = MAXCHARGEPOWERALLOWED;
|
||||
system_max_charge_power_W = MAXCHARGEPOWERALLOWED;
|
||||
}
|
||||
//max_target_discharge_power = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts
|
||||
if (SOC < 100) { // When scaled SOC is <1%, set allowed charge power to 0
|
||||
max_target_discharge_power = 0;
|
||||
//system_max_discharge_power_W = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts
|
||||
if (system_scaled_SOC_pptt < 100) { // When scaled SOC is <1%, set allowed charge power to 0
|
||||
system_max_discharge_power_W = 0;
|
||||
} else { // No limits, max charging power allowed
|
||||
max_target_discharge_power = MAXDISCHARGEPOWERALLOWED;
|
||||
system_max_discharge_power_W = MAXDISCHARGEPOWERALLOWED;
|
||||
}
|
||||
|
||||
powerWatt = ((batteryVoltage * batteryAmps) / 100);
|
||||
|
||||
stat_batt_power = convertToUnsignedInt16(powerWatt); //Power in watts, Negative = charging batt
|
||||
system_active_power_W = powerWatt; //Power in watts, Negative = charging batt
|
||||
|
||||
temperature_min = convertToUnsignedInt16((int8_t)temperatureMin * 10); //Increase decimals, 17C -> 17.0C
|
||||
system_temperature_min_dC = (int8_t)temperatureMin * 10; //Increase decimals, 17C -> 17.0C
|
||||
|
||||
temperature_max = convertToUnsignedInt16((int8_t)temperatureMax * 10); //Increase decimals, 18C -> 18.0C
|
||||
system_temperature_max_dC = (int8_t)temperatureMax * 10; //Increase decimals, 18C -> 18.0C
|
||||
|
||||
cell_max_voltage = CellVoltMax_mV;
|
||||
system_cell_max_voltage_mV = CellVoltMax_mV;
|
||||
|
||||
cell_min_voltage = CellVoltMin_mV;
|
||||
system_cell_min_voltage_mV = CellVoltMin_mV;
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
@ -228,9 +217,9 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
clear_event(EVENT_CELL_DEVIATION_HIGH);
|
||||
}
|
||||
|
||||
if (bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits
|
||||
max_target_charge_power = 0;
|
||||
max_target_discharge_power = 0;
|
||||
if (system_bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits
|
||||
system_max_charge_power_W = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
}
|
||||
|
||||
/* Safeties verified. Perform USB serial printout if configured to do so */
|
||||
|
@ -249,7 +238,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
Serial.print(" Amps | ");
|
||||
Serial.print((uint16_t)batteryVoltage / 10.0, 1);
|
||||
Serial.print(" Volts | ");
|
||||
Serial.print((int16_t)stat_batt_power);
|
||||
Serial.print((int16_t)system_active_power_W);
|
||||
Serial.println(" Watts");
|
||||
Serial.print("Allowed Charge ");
|
||||
Serial.print((uint16_t)allowedChargePower * 10);
|
||||
|
@ -364,53 +353,53 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
|||
allowedDischargePower = ((rx_frame.data.u8[5] << 8) + rx_frame.data.u8[6]);
|
||||
batteryRelay = rx_frame.data.u8[7];
|
||||
} else if (poll_data_pid == 2) {
|
||||
cellvoltages[0] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[1] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[2] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[3] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[4] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[5] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[0] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[1] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[2] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[3] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[4] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[5] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 3) {
|
||||
cellvoltages[32] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[33] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[34] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[35] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[36] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[37] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[32] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[33] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[34] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[35] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[36] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[37] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 4) {
|
||||
cellvoltages[64] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[65] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[66] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[67] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[68] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[69] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[64] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[65] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[66] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[67] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[68] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[69] = (rx_frame.data.u8[7] * 20);
|
||||
}
|
||||
break;
|
||||
case 0x22: //Second datarow in PID group
|
||||
if (poll_data_pid == 2) {
|
||||
cellvoltages[6] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[7] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[8] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[9] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[10] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[11] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[12] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[6] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[7] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[8] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[9] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[10] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[11] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[12] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 3) {
|
||||
cellvoltages[38] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[39] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[40] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[41] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[42] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[43] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[44] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[38] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[39] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[40] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[41] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[42] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[43] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[44] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 4) {
|
||||
cellvoltages[70] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[71] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[72] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[73] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[74] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[75] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[76] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[70] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[71] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[72] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[73] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[74] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[75] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[76] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 6) {
|
||||
batteryManagementMode = rx_frame.data.u8[5];
|
||||
}
|
||||
|
@ -420,29 +409,29 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
|||
temperature_water_inlet = rx_frame.data.u8[6];
|
||||
CellVoltMax_mV = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV
|
||||
} else if (poll_data_pid == 2) {
|
||||
cellvoltages[13] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[14] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[15] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[16] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[17] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[18] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[19] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[13] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[14] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[15] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[16] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[17] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[18] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[19] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 3) {
|
||||
cellvoltages[45] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[46] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[47] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[48] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[49] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[50] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[51] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[45] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[46] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[47] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[48] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[49] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[50] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[51] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 4) {
|
||||
cellvoltages[77] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[78] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[79] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[80] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[81] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[82] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[83] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[77] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[78] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[79] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[80] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[81] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[82] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[83] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 5) {
|
||||
heatertemp = rx_frame.data.u8[7];
|
||||
}
|
||||
|
@ -453,56 +442,56 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
|||
CellVminNo = rx_frame.data.u8[3];
|
||||
CellVoltMin_mV = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV
|
||||
} else if (poll_data_pid == 2) {
|
||||
cellvoltages[20] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[21] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[22] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[23] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[24] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[25] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[26] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[20] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[21] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[22] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[23] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[24] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[25] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[26] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 3) {
|
||||
cellvoltages[52] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[53] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[54] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[55] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[56] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[57] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[58] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[52] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[53] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[54] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[55] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[56] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[57] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[58] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 4) {
|
||||
cellvoltages[84] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[85] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[86] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[87] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[88] = (rx_frame.data.u8[5] * 20);
|
||||
cellvoltages[89] = (rx_frame.data.u8[6] * 20);
|
||||
cellvoltages[90] = (rx_frame.data.u8[7] * 20);
|
||||
system_cellvoltages_mV[84] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[85] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[86] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[87] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[88] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[89] = (rx_frame.data.u8[6] * 20);
|
||||
system_cellvoltages_mV[90] = (rx_frame.data.u8[7] * 20);
|
||||
} else if (poll_data_pid == 5) {
|
||||
batterySOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]);
|
||||
}
|
||||
break;
|
||||
case 0x25: //Fifth datarow in PID group
|
||||
if (poll_data_pid == 2) {
|
||||
cellvoltages[27] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[28] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[29] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[30] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[31] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[27] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[28] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[29] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[30] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[31] = (rx_frame.data.u8[5] * 20);
|
||||
} else if (poll_data_pid == 3) {
|
||||
cellvoltages[59] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[60] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[61] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[62] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[63] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[59] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[60] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[61] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[62] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[63] = (rx_frame.data.u8[5] * 20);
|
||||
} else if (poll_data_pid == 4) {
|
||||
cellvoltages[91] = (rx_frame.data.u8[1] * 20);
|
||||
cellvoltages[92] = (rx_frame.data.u8[2] * 20);
|
||||
cellvoltages[93] = (rx_frame.data.u8[3] * 20);
|
||||
cellvoltages[94] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[95] = (rx_frame.data.u8[5] * 20);
|
||||
system_cellvoltages_mV[91] = (rx_frame.data.u8[1] * 20);
|
||||
system_cellvoltages_mV[92] = (rx_frame.data.u8[2] * 20);
|
||||
system_cellvoltages_mV[93] = (rx_frame.data.u8[3] * 20);
|
||||
system_cellvoltages_mV[94] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[95] = (rx_frame.data.u8[5] * 20);
|
||||
} else if (poll_data_pid == 5) {
|
||||
cellvoltages[96] = (rx_frame.data.u8[4] * 20);
|
||||
cellvoltages[97] = (rx_frame.data.u8[5] * 20);
|
||||
nof_cellvoltages = 98;
|
||||
system_cellvoltages_mV[96] = (rx_frame.data.u8[4] * 20);
|
||||
system_cellvoltages_mV[97] = (rx_frame.data.u8[5] * 20);
|
||||
system_number_of_cells = 98;
|
||||
}
|
||||
break;
|
||||
case 0x26: //Sixth datarow in PID group
|
||||
|
@ -591,19 +580,11 @@ void send_can_battery() {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t convertToUnsignedInt16(int16_t signed_value) {
|
||||
if (signed_value < 0) {
|
||||
return (65535 + signed_value);
|
||||
} else {
|
||||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,27 +11,28 @@
|
|||
#define MAXDISCHARGEPOWERALLOWED 10000
|
||||
|
||||
// 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 uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
uint16_t convertToUnsignedInt16(int16_t signed_value);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,16 +6,12 @@
|
|||
#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
|
||||
#define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Fronius
|
||||
|
||||
static uint32_t LB_Battery_Voltage = 3700;
|
||||
static uint32_t LB_Charge_Power_Limit_Watts = 0;
|
||||
static uint32_t LB_Discharge_Power_Limit_Watts = 0;
|
||||
static int32_t LB_Current = 0;
|
||||
static int16_t LB_MAX_TEMPERATURE = 0;
|
||||
static int16_t LB_MIN_TEMPERATURE = 0;
|
||||
static uint16_t soc_calculated = 0;
|
||||
static uint16_t LB_SOC = 0;
|
||||
static uint16_t LB_SOH = 0;
|
||||
static uint16_t LB_Discharge_Power_Limit = 0;
|
||||
|
@ -60,66 +56,57 @@ static const int interval100 = 100; // interval (ms) at which send CAN Messag
|
|||
static const int interval1000 = 1000; // interval (ms) at which send CAN Messages
|
||||
|
||||
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
|
||||
soc_calculated = LB_SOC;
|
||||
soc_calculated =
|
||||
LB_MIN_SOC + (LB_MAX_SOC - LB_MIN_SOC) * (soc_calculated - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE);
|
||||
if (soc_calculated < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to Inverter as 0%
|
||||
soc_calculated = 0;
|
||||
}
|
||||
if (soc_calculated > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to Inverter as 100%
|
||||
soc_calculated = 1000;
|
||||
}
|
||||
SOC = (soc_calculated * 10); //increase LB_SOC range from 0-100.0 -> 100.00
|
||||
system_real_SOC_pptt = (LB_SOC * 10); //increase LB_SOC range from 0-100.0 -> 100.00
|
||||
|
||||
battery_voltage = LB_Battery_Voltage;
|
||||
system_SOH_pptt = (LB_SOH * 100); //Increase range from 99% -> 99.00%
|
||||
|
||||
battery_current = LB_Current;
|
||||
system_battery_voltage_dV = LB_Battery_Voltage;
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX; //Hardcoded to header value
|
||||
system_battery_current_dA = LB_Current;
|
||||
|
||||
remaining_capacity_Wh = (uint16_t)((SOC / 10000) * capacity_Wh);
|
||||
system_capacity_Wh = BATTERY_WH_MAX; //Hardcoded to header value
|
||||
|
||||
system_remaining_capacity_Wh = (uint16_t)((system_real_SOC_pptt / 10000) * system_capacity_Wh);
|
||||
|
||||
LB_Discharge_Power_Limit_Watts = (LB_Discharge_Power_Limit * 500); //Convert value fetched from battery to watts
|
||||
/* Define power able to be discharged from battery */
|
||||
if (LB_Discharge_Power_Limit_Watts > 30000) //if >30kW can be pulled from battery
|
||||
{
|
||||
max_target_discharge_power = 30000; //cap value so we don't go over the Fronius limits
|
||||
system_max_discharge_power_W = 30000; //cap value so we don't go over the Fronius limits
|
||||
} else {
|
||||
max_target_discharge_power = LB_Discharge_Power_Limit_Watts;
|
||||
system_max_discharge_power_W = LB_Discharge_Power_Limit_Watts;
|
||||
}
|
||||
if (SOC == 0) //Scaled SOC% value is 0.00%, we should not discharge battery further
|
||||
if (system_scaled_SOC_pptt == 0) //Scaled SOC% value is 0.00%, we should not discharge battery further
|
||||
{
|
||||
max_target_discharge_power = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
}
|
||||
|
||||
LB_Charge_Power_Limit_Watts = (LB_Charge_Power_Limit * 500); //Convert value fetched from battery to watts
|
||||
/* Define power able to be put into the battery */
|
||||
if (LB_Charge_Power_Limit_Watts > 30000) //if >30kW can be put into the battery
|
||||
{
|
||||
max_target_charge_power = 30000; //cap value so we don't go over the Fronius limits
|
||||
system_max_charge_power_W = 30000; //cap value so we don't go over the Fronius limits
|
||||
}
|
||||
if (LB_Charge_Power_Limit_Watts < 0) {
|
||||
max_target_charge_power = 0; //cap calue so we dont do under the Fronius limits
|
||||
system_max_charge_power_W = 0; //cap calue so we dont do under the Fronius limits
|
||||
} else {
|
||||
max_target_charge_power = LB_Charge_Power_Limit_Watts;
|
||||
system_max_charge_power_W = LB_Charge_Power_Limit_Watts;
|
||||
}
|
||||
if (SOC == 10000) //Scaled SOC% value is 100.00%
|
||||
if (system_scaled_SOC_pptt == 10000) //Scaled SOC% value is 100.00%
|
||||
{
|
||||
max_target_charge_power = 0; //No need to charge further, set max power to 0
|
||||
system_max_charge_power_W = 0; //No need to charge further, set max power to 0
|
||||
}
|
||||
|
||||
stat_batt_power = (battery_voltage * LB_Current); //TODO: check if scaling is OK
|
||||
system_active_power_W = (battery_voltage * LB_Current); //TODO: check if scaling is OK
|
||||
|
||||
temperature_min = convert2uint16(LB_MIN_TEMPERATURE * 10);
|
||||
system_temperature_min_dC = (LB_MIN_TEMPERATURE * 10);
|
||||
|
||||
temperature_max = convert2uint16(LB_MAX_TEMPERATURE * 10);
|
||||
system_temperature_max_dC = (LB_MAX_TEMPERATURE * 10);
|
||||
|
||||
cell_min_voltage = LB_Cell_Min_Voltage;
|
||||
system_cell_min_voltage_mV = LB_Cell_Min_Voltage;
|
||||
|
||||
cell_max_voltage = LB_Cell_Max_Voltage;
|
||||
system_cell_max_voltage_mV = LB_Cell_Max_Voltage;
|
||||
|
||||
cell_deviation_mV = (cell_max_voltage - cell_min_voltage);
|
||||
|
||||
|
@ -146,21 +133,21 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Values going to inverter:");
|
||||
Serial.print("SOH%: ");
|
||||
Serial.print(StateOfHealth);
|
||||
Serial.print(system_SOH_pptt);
|
||||
Serial.print(", SOC% scaled: ");
|
||||
Serial.print(SOC);
|
||||
Serial.print(system_scaled_SOC_pptt);
|
||||
Serial.print(", Voltage: ");
|
||||
Serial.print(battery_voltage);
|
||||
Serial.print(system_battery_voltage_dV);
|
||||
Serial.print(", Max discharge power: ");
|
||||
Serial.print(max_target_discharge_power);
|
||||
Serial.print(system_max_discharge_power_W);
|
||||
Serial.print(", Max charge power: ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(", Max temp: ");
|
||||
Serial.print(temperature_max);
|
||||
Serial.print(system_temperature_max_dC);
|
||||
Serial.print(", Min temp: ");
|
||||
Serial.print(temperature_min);
|
||||
Serial.print(system_temperature_min_dC);
|
||||
Serial.print(", BMS Status (3=OK): ");
|
||||
Serial.print(bms_status);
|
||||
Serial.print(system_bms_status);
|
||||
|
||||
Serial.println("Battery values: ");
|
||||
Serial.print("Real SOC: ");
|
||||
|
@ -262,19 +249,11 @@ void send_can_battery() {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t convert2uint16(int16_t signed_value) {
|
||||
if (signed_value < 0) {
|
||||
return (65535 + signed_value);
|
||||
} else {
|
||||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,26 +14,28 @@
|
|||
#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 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 CANerror;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
uint16_t convert2uint16(int16_t signed_value);
|
||||
void setup_battery(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,13 +6,9 @@
|
|||
#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
|
||||
#define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Fronius
|
||||
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic
|
||||
static uint16_t LB_SOC = 50;
|
||||
static uint16_t soc_calculated = 0;
|
||||
static uint16_t LB_SOH = 99;
|
||||
static int16_t LB_MIN_TEMPERATURE = 0;
|
||||
static int16_t LB_MAX_TEMPERATURE = 0;
|
||||
|
@ -45,44 +41,34 @@ static const int interval100 = 100; // interval (ms) at which send CAN Messag
|
|||
static const int interval1000 = 1000; // interval (ms) at which send CAN Messages
|
||||
|
||||
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%
|
||||
system_SOH_pptt = (LB_SOH * 100); //Increase range from 99% -> 99.00%
|
||||
|
||||
//Calculate the SOC% value to send to Fronius
|
||||
soc_calculated = LB_SOC;
|
||||
soc_calculated =
|
||||
LB_MIN_SOC + (LB_MAX_SOC - LB_MIN_SOC) * (soc_calculated - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE);
|
||||
if (soc_calculated < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to Inverter as 0%
|
||||
soc_calculated = 0;
|
||||
}
|
||||
if (soc_calculated > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to Inverter as 100%
|
||||
soc_calculated = 1000;
|
||||
}
|
||||
SOC = (soc_calculated * 10); //increase LB_SOC range from 0-100.0 -> 100.00
|
||||
system_real_SOC_pptt = (LB_SOC * 10); //increase LB_SOC range from 0-100.0 -> 100.00
|
||||
|
||||
battery_voltage = LB_Battery_Voltage;
|
||||
system_battery_voltage_dV = LB_Battery_Voltage;
|
||||
|
||||
battery_current = LB_Current;
|
||||
system_battery_current_dA = LB_Current;
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX; //Use the configured value to avoid overflows
|
||||
system_capacity_Wh = BATTERY_WH_MAX; //Use the configured value to avoid overflows
|
||||
|
||||
//Calculate the remaining Wh amount from SOC% and max Wh value.
|
||||
remaining_capacity_Wh = static_cast<int>((static_cast<double>(SOC) / 10000) * BATTERY_WH_MAX);
|
||||
system_remaining_capacity_Wh = static_cast<int>((static_cast<double>(system_real_SOC_pptt) / 10000) * BATTERY_WH_MAX);
|
||||
|
||||
max_target_discharge_power;
|
||||
system_max_discharge_power_W;
|
||||
|
||||
max_target_charge_power;
|
||||
system_max_charge_power_W;
|
||||
|
||||
stat_batt_power;
|
||||
system_active_power_W;
|
||||
|
||||
temperature_min;
|
||||
system_temperature_min_dC;
|
||||
|
||||
temperature_max;
|
||||
system_temperature_max_dC;
|
||||
|
||||
cell_min_voltage;
|
||||
system_cell_min_voltage_mV;
|
||||
|
||||
cell_max_voltage;
|
||||
system_cell_max_voltage_mV;
|
||||
|
||||
cell_deviation_mV = (cell_max_voltage - cell_min_voltage);
|
||||
cell_deviation_mV = (system_cell_max_voltage_mV - system_cell_min_voltage_mV);
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
@ -107,21 +93,21 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Values going to inverter:");
|
||||
Serial.print("SOH%: ");
|
||||
Serial.print(StateOfHealth);
|
||||
Serial.print(system_SOH_pptt);
|
||||
Serial.print(", SOC% scaled: ");
|
||||
Serial.print(SOC);
|
||||
Serial.print(system_scaled_SOC_pptt);
|
||||
Serial.print(", Voltage: ");
|
||||
Serial.print(battery_voltage);
|
||||
Serial.print(system_battery_voltage_dV);
|
||||
Serial.print(", Max discharge power: ");
|
||||
Serial.print(max_target_discharge_power);
|
||||
Serial.print(system_max_discharge_power_W);
|
||||
Serial.print(", Max charge power: ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(", Max temp: ");
|
||||
Serial.print(temperature_max);
|
||||
Serial.print(system_temperature_max_dC);
|
||||
Serial.print(", Min temp: ");
|
||||
Serial.print(temperature_min);
|
||||
Serial.print(system_temperature_min_dC);
|
||||
Serial.print(", BMS Status (3=OK): ");
|
||||
Serial.print(bms_status);
|
||||
Serial.print(system_bms_status);
|
||||
|
||||
Serial.println("Battery values: ");
|
||||
Serial.print("Real SOC: ");
|
||||
|
@ -169,8 +155,8 @@ void send_can_battery() {
|
|||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,23 +14,26 @@
|
|||
#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 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 CANerror;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
void setup_battery(void);
|
||||
|
|
|
@ -21,9 +21,6 @@ static const int interval10 = 10; // interval (ms) at which send CAN
|
|||
static const int interval100 = 100; // interval (ms) at which send CAN Messages
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
|
||||
#define LB_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to Inverter
|
||||
#define LB_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to Inverter
|
||||
|
||||
static int SOC_1 = 0;
|
||||
static int SOC_2 = 0;
|
||||
static int SOC_3 = 0;
|
||||
|
@ -61,25 +58,25 @@ CAN_frame_t SANTAFE_523 = {.FIR = {.B =
|
|||
|
||||
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
|
||||
SOC;
|
||||
system_real_SOC_pptt;
|
||||
|
||||
battery_voltage;
|
||||
system_battery_voltage_dV;
|
||||
|
||||
battery_current;
|
||||
system_battery_current_dA;
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX;
|
||||
system_capacity_Wh = BATTERY_WH_MAX;
|
||||
|
||||
remaining_capacity_Wh;
|
||||
system_remaining_capacity_Wh;
|
||||
|
||||
max_target_discharge_power;
|
||||
system_max_discharge_power_W;
|
||||
|
||||
max_target_charge_power;
|
||||
system_max_charge_power_W;
|
||||
|
||||
stat_batt_power;
|
||||
system_active_power_W;
|
||||
|
||||
temperature_min;
|
||||
system_temperature_min_dC;
|
||||
|
||||
temperature_max;
|
||||
system_temperature_max_dC;
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if (!CANstillAlive) {
|
||||
|
@ -180,8 +177,8 @@ uint8_t CalculateCRC8(CAN_frame_t rx_frame) {
|
|||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.0V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,24 +7,27 @@
|
|||
|
||||
#define BATTERY_SELECTED
|
||||
|
||||
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
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
uint8_t CalculateCRC8(CAN_frame_t rx_frame);
|
||||
void setup_battery(void);
|
||||
|
|
|
@ -28,25 +28,25 @@ SerialDataLink dataLinkReceive(SerialReceiver, 0, 0x01, sendingNumVariables,
|
|||
static bool batteryFault = false; // used locally - mainly to indicate Battery CAN failure
|
||||
|
||||
void __getData() {
|
||||
SOC = (uint16_t)dataLinkReceive.getReceivedData(0);
|
||||
StateOfHealth = (uint16_t)dataLinkReceive.getReceivedData(1);
|
||||
battery_voltage = (uint16_t)dataLinkReceive.getReceivedData(2);
|
||||
battery_current = (uint16_t)dataLinkReceive.getReceivedData(3);
|
||||
capacity_Wh = (uint16_t)dataLinkReceive.getReceivedData(4);
|
||||
remaining_capacity_Wh = (uint16_t)dataLinkReceive.getReceivedData(5);
|
||||
max_target_discharge_power = (uint16_t)dataLinkReceive.getReceivedData(6);
|
||||
max_target_charge_power = (uint16_t)dataLinkReceive.getReceivedData(7);
|
||||
uint16_t _bms_status = (uint16_t)dataLinkReceive.getReceivedData(8);
|
||||
stat_batt_power = (uint16_t)dataLinkReceive.getReceivedData(9);
|
||||
temperature_min = (uint16_t)dataLinkReceive.getReceivedData(10);
|
||||
temperature_max = (uint16_t)dataLinkReceive.getReceivedData(11);
|
||||
cell_max_voltage = (uint16_t)dataLinkReceive.getReceivedData(12);
|
||||
cell_min_voltage = (uint16_t)dataLinkReceive.getReceivedData(13);
|
||||
system_real_SOC_pptt = (uint16_t)dataLinkReceive.getReceivedData(0);
|
||||
system_SOH_pptt = (uint16_t)dataLinkReceive.getReceivedData(1);
|
||||
system_battery_voltage_dV = (uint16_t)dataLinkReceive.getReceivedData(2);
|
||||
system_battery_current_dA = (int16_t)dataLinkReceive.getReceivedData(3);
|
||||
system_capacity_Wh = (uint32_t)dataLinkReceive.getReceivedData(4);
|
||||
system_remaining_capacity_Wh = (uint32_t)dataLinkReceive.getReceivedData(5);
|
||||
system_max_discharge_power_W = (uint16_t)dataLinkReceive.getReceivedData(6);
|
||||
system_max_charge_power_W = (uint16_t)dataLinkReceive.getReceivedData(7);
|
||||
uint16_t _system_bms_status = (uint16_t)dataLinkReceive.getReceivedData(8);
|
||||
system_active_power_W = (uint16_t)dataLinkReceive.getReceivedData(9);
|
||||
system_temperature_min_dC = (int16_t)dataLinkReceive.getReceivedData(10);
|
||||
system_temperature_max_dC = (int16_t)dataLinkReceive.getReceivedData(11);
|
||||
system_cell_max_voltage_mV = (uint16_t)dataLinkReceive.getReceivedData(12);
|
||||
system_cell_min_voltage_mV = (uint16_t)dataLinkReceive.getReceivedData(13);
|
||||
LFP_Chemistry = (bool)dataLinkReceive.getReceivedData(14);
|
||||
batteryAllowsContactorClosing = (uint16_t)dataLinkReceive.getReceivedData(15);
|
||||
batteryAllowsContactorClosing = (bool)dataLinkReceive.getReceivedData(15);
|
||||
|
||||
batteryFault = false;
|
||||
if (_bms_status == FAULT) {
|
||||
if (_system_bms_status == FAULT) {
|
||||
batteryFault = true;
|
||||
set_event(EVENT_SERIAL_TRANSMITTER_FAILURE, 0);
|
||||
}
|
||||
|
@ -116,13 +116,13 @@ void manageSerialLinkReceiver() {
|
|||
if (minutesLost > 0 && lastGood > 0) {
|
||||
// lose 25% each minute of data loss
|
||||
if (minutesLost < 4) {
|
||||
max_target_charge_power = (lastGoodMaxCharge * (4 - minutesLost)) / 4;
|
||||
max_target_discharge_power = (lastGoodMaxDischarge * (4 - minutesLost)) / 4;
|
||||
system_max_charge_power_W = (lastGoodMaxCharge * (4 - minutesLost)) / 4;
|
||||
system_max_discharge_power_W = (lastGoodMaxDischarge * (4 - minutesLost)) / 4;
|
||||
set_event(EVENT_SERIAL_RX_WARNING, minutesLost);
|
||||
} else {
|
||||
// Times Up -
|
||||
max_target_charge_power = 0;
|
||||
max_target_discharge_power = 0;
|
||||
system_max_charge_power_W = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
set_event(EVENT_SERIAL_RX_FAILURE, uint8_t(min(minutesLost, 255uL)));
|
||||
//----- Throw Error
|
||||
}
|
||||
|
@ -137,9 +137,9 @@ void manageSerialLinkReceiver() {
|
|||
}
|
||||
Serial.print(minutesLost);
|
||||
Serial.print(", max Charge = ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(", max Discharge = ");
|
||||
Serial.println(max_target_discharge_power);
|
||||
Serial.println(system_max_discharge_power_W);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,35 +176,35 @@ void manageSerialLinkReceiver() {
|
|||
void update_values_serial_link() {
|
||||
Serial.println("Values from battery: ");
|
||||
Serial.print("SOC: ");
|
||||
Serial.print(SOC);
|
||||
Serial.print(system_real_SOC_pptt);
|
||||
Serial.print(" SOH: ");
|
||||
Serial.print(StateOfHealth);
|
||||
Serial.print(system_SOH_pptt);
|
||||
Serial.print(" Voltage: ");
|
||||
Serial.print(battery_voltage);
|
||||
Serial.print(system_battery_voltage_dV);
|
||||
Serial.print(" Current: ");
|
||||
Serial.print(battery_current);
|
||||
Serial.print(system_battery_current_dA);
|
||||
Serial.print(" Capacity: ");
|
||||
Serial.print(capacity_Wh);
|
||||
Serial.print(system_capacity_Wh);
|
||||
Serial.print(" Remain cap: ");
|
||||
Serial.print(remaining_capacity_Wh);
|
||||
Serial.print(system_remaining_capacity_Wh);
|
||||
Serial.print(" Max discharge W: ");
|
||||
Serial.print(max_target_discharge_power);
|
||||
Serial.print(system_max_discharge_power_W);
|
||||
Serial.print(" Max charge W: ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(" BMS status: ");
|
||||
Serial.print(bms_status);
|
||||
Serial.print(system_bms_status);
|
||||
Serial.print(" Power: ");
|
||||
Serial.print(stat_batt_power);
|
||||
Serial.print(system_active_power_W);
|
||||
Serial.print(" Temp min: ");
|
||||
Serial.print(temperature_min);
|
||||
Serial.print(system_temperature_min_dC);
|
||||
Serial.print(" Temp max: ");
|
||||
Serial.print(temperature_max);
|
||||
Serial.print(system_temperature_max_dC);
|
||||
Serial.print(" Cell max: ");
|
||||
Serial.print(cell_max_voltage);
|
||||
Serial.print(system_cell_max_voltage_mV);
|
||||
Serial.print(" Cell min: ");
|
||||
Serial.print(cell_min_voltage);
|
||||
Serial.print(system_cell_min_voltage_mV);
|
||||
Serial.print(" LFP : ");
|
||||
Serial.print(LFP_Chemistry);
|
||||
Serial.print(system_LFP_Chemistry);
|
||||
Serial.print(" batteryAllowsContactorClosing: ");
|
||||
Serial.print(batteryAllowsContactorClosing);
|
||||
Serial.print(" inverterAllowsContactorClosing: ");
|
||||
|
|
|
@ -10,27 +10,24 @@
|
|||
|
||||
// https://github.com/mackelec/SerialDataLink
|
||||
|
||||
// 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 uint8_t bms_status; //Enum, 0-5
|
||||
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 bool LFP_Chemistry;
|
||||
extern uint16_t CANerror;
|
||||
|
||||
// These parameters need to be mapped on the battery side
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern bool system_LFP_Chemistry; //Set to true or false depending on cell chemistry
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
// Parameters to send to the transmitter
|
||||
|
|
|
@ -60,7 +60,6 @@ static uint16_t output_current = 0;
|
|||
static uint16_t soc_min = 0;
|
||||
static uint16_t soc_max = 0;
|
||||
static uint16_t soc_vi = 0;
|
||||
static uint16_t soc_calculated = 0;
|
||||
static uint16_t soc_ave = 0;
|
||||
static uint16_t cell_max_v = 3700;
|
||||
static uint16_t cell_min_v = 3700;
|
||||
|
@ -153,8 +152,6 @@ static const char* hvilStatusState[] = {"NOT OK",
|
|||
"UNKNOWN(14)",
|
||||
"UNKNOWN(15)"};
|
||||
|
||||
#define MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to inverter
|
||||
#define MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to inverter
|
||||
#define MAX_CELL_VOLTAGE_NCA_NCM 4250 //Battery is put into emergency stop if one cell goes over this value
|
||||
#define MIN_CELL_VOLTAGE_NCA_NCM 2950 //Battery is put into emergency stop if one cell goes below this value
|
||||
#define MAX_CELL_DEVIATION_NCA_NCM 500 //LED turns yellow on the board if mv delta exceeds this value
|
||||
|
@ -169,62 +166,54 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
//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
|
||||
StateOfHealth =
|
||||
system_SOH_pptt =
|
||||
static_cast<uint16_t>((static_cast<double>(nominal_full_pack_energy) / bat_beginning_of_life) * 10000.0);
|
||||
}
|
||||
//If the value is unavailable, set SOH to 99%
|
||||
if (nominal_full_pack_energy < REASONABLE_ENERGYAMOUNT) {
|
||||
StateOfHealth = 9900;
|
||||
system_SOH_pptt = 9900;
|
||||
}
|
||||
|
||||
//Calculate the SOC% value to send to inverter
|
||||
soc_calculated = soc_vi;
|
||||
soc_calculated = MIN_SOC + (MAX_SOC - MIN_SOC) * (soc_calculated - MINPERCENTAGE) / (MAXPERCENTAGE - MINPERCENTAGE);
|
||||
if (soc_calculated < 0) { //We are in the real SOC% range of 0-20%, always set SOC sent to Inverter as 0%
|
||||
soc_calculated = 0;
|
||||
}
|
||||
if (soc_calculated > 1000) { //We are in the real SOC% range of 80-100%, always set SOC sent to Inverter as 100%
|
||||
soc_calculated = 1000;
|
||||
}
|
||||
SOC = (soc_calculated * 10); //increase SOC range from 0-100.0 -> 100.00
|
||||
system_real_SOC_pptt = (soc_vi * 10); //increase SOC range from 0-100.0 -> 100.00
|
||||
|
||||
battery_voltage = (volts * 10); //One more decimal needed (370 -> 3700)
|
||||
system_battery_voltage_dV = (volts * 10); //One more decimal needed (370 -> 3700)
|
||||
|
||||
battery_current = convert2unsignedInt16(amps); //13.0A
|
||||
system_battery_current_dA = amps; //13.0A
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX; //Use the configured value to avoid overflows
|
||||
system_capacity_Wh = BATTERY_WH_MAX; //Use the configured value to avoid overflows
|
||||
|
||||
//Calculate the remaining Wh amount from SOC% and max Wh value.
|
||||
remaining_capacity_Wh = static_cast<uint16_t>((static_cast<double>(SOC) / 10000) * BATTERY_WH_MAX);
|
||||
system_remaining_capacity_Wh =
|
||||
static_cast<uint32_t>((static_cast<double>(system_real_SOC_pptt) / 10000) * BATTERY_WH_MAX);
|
||||
|
||||
// Define the allowed discharge power
|
||||
max_target_discharge_power = (max_discharge_current * volts);
|
||||
system_max_discharge_power_W = (max_discharge_current * volts);
|
||||
// Cap the allowed discharge power if battery is empty, or discharge power is higher than the maximum discharge power allowed
|
||||
if (SOC == 0) {
|
||||
max_target_discharge_power = 0;
|
||||
} else if (max_target_discharge_power > MAXDISCHARGEPOWERALLOWED) {
|
||||
max_target_discharge_power = MAXDISCHARGEPOWERALLOWED;
|
||||
if (system_scaled_SOC_pptt == 0) {
|
||||
system_max_discharge_power_W = 0;
|
||||
} else if (system_max_discharge_power_W > MAXDISCHARGEPOWERALLOWED) {
|
||||
system_max_discharge_power_W = MAXDISCHARGEPOWERALLOWED;
|
||||
}
|
||||
|
||||
//The allowed charge power behaves strangely. We instead estimate this value
|
||||
if (SOC == 10000) { // When scaled SOC is 100%, set allowed charge power to 0
|
||||
max_target_charge_power = 0;
|
||||
if (system_scaled_SOC_pptt == 10000) { // When scaled SOC is 100%, set allowed charge power to 0
|
||||
system_max_charge_power_W = 0;
|
||||
} else if (soc_vi > 950) { // When real SOC is between 95-99.99%, ramp the value between Max<->0
|
||||
max_target_charge_power = MAXCHARGEPOWERALLOWED * (1 - (soc_vi - 950) / 50.0);
|
||||
system_max_charge_power_W = MAXCHARGEPOWERALLOWED * (1 - (soc_vi - 950) / 50.0);
|
||||
} else { // No limits, max charging power allowed
|
||||
max_target_charge_power = MAXCHARGEPOWERALLOWED;
|
||||
system_max_charge_power_W = MAXCHARGEPOWERALLOWED;
|
||||
}
|
||||
|
||||
power = ((volts / 10) * amps);
|
||||
stat_batt_power = convert2unsignedInt16(power);
|
||||
system_active_power_W = power;
|
||||
|
||||
temperature_min = convert2unsignedInt16(min_temp);
|
||||
system_temperature_min_dC = min_temp;
|
||||
|
||||
temperature_max = convert2unsignedInt16(max_temp);
|
||||
system_temperature_max_dC = max_temp;
|
||||
|
||||
cell_max_voltage = cell_max_v;
|
||||
system_cell_max_voltage_mV = cell_max_v;
|
||||
|
||||
cell_min_voltage = cell_min_v;
|
||||
system_cell_min_voltage_mV = cell_min_v;
|
||||
|
||||
/* Value mapping is completed. Start to check all safeties */
|
||||
|
||||
|
@ -254,7 +243,7 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
}
|
||||
// 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) {
|
||||
if (system_number_of_cells > 101) {
|
||||
LFP_Chemistry = true;
|
||||
}
|
||||
|
||||
|
@ -268,8 +257,9 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
|
||||
//Check if SOC% is plausible
|
||||
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
|
||||
if (system_battery_voltage_dV >
|
||||
(system_max_design_voltage_dV - 100)) { // When pack voltage is close to max, and SOC% is still low, raise FAULT
|
||||
if (system_real_SOC_pptt < 6500) { //When SOC is less than 65.00% when approaching max voltage
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, SOC / 100);
|
||||
}
|
||||
}
|
||||
|
@ -311,8 +301,8 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
}
|
||||
|
||||
if (bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits
|
||||
max_target_charge_power = 0;
|
||||
max_target_discharge_power = 0;
|
||||
system_max_charge_power_W = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
}
|
||||
|
||||
/* Safeties verified. Perform USB serial printout if configured to do so */
|
||||
|
@ -349,7 +339,6 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
if (LFP_Chemistry) {
|
||||
Serial.print("LFP chemistry detected!");
|
||||
}
|
||||
Serial.print(nof_cellvoltages);
|
||||
Serial.println("");
|
||||
Serial.print("Cellstats, Max: ");
|
||||
Serial.print(cell_max_v);
|
||||
|
@ -371,14 +360,14 @@ void update_values_battery() { //This function maps all the values fetched via
|
|||
Serial.println("");
|
||||
|
||||
Serial.println("Values passed to the inverter: ");
|
||||
print_SOC(" SOC: ", SOC);
|
||||
print_int_with_units(" Max discharge power: ", max_target_discharge_power, "W");
|
||||
print_SOC(" SOC: ", system_scaled_SOC_pptt);
|
||||
print_int_with_units(" Max discharge power: ", system_max_discharge_power_W, "W");
|
||||
Serial.print(", ");
|
||||
print_int_with_units(" Max charge power: ", max_target_charge_power, "W");
|
||||
print_int_with_units(" Max charge power: ", system_max_charge_power_W, "W");
|
||||
Serial.println("");
|
||||
print_int_with_units(" Max temperature: ", ((int16_t)temperature_max * 0.1), "°C");
|
||||
print_int_with_units(" Max temperature: ", ((int16_t)system_temperature_min_dC * 0.1), "°C");
|
||||
Serial.print(", ");
|
||||
print_int_with_units(" Min temperature: ", ((int16_t)temperature_min * 0.1), "°C");
|
||||
print_int_with_units(" Min temperature: ", ((int16_t)system_temperature_max_dC * 0.1), "°C");
|
||||
Serial.println("");
|
||||
#endif
|
||||
}
|
||||
|
@ -474,11 +463,11 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
|||
{
|
||||
// Example, frame3=0x89,frame2=0x1D = 35101 / 10 = 3510mV
|
||||
volts = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]) / 10;
|
||||
cellvoltages[mux * 3] = volts;
|
||||
system_cellvoltages_mV[mux * 3] = volts;
|
||||
volts = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]) / 10;
|
||||
cellvoltages[1 + mux * 3] = volts;
|
||||
system_cellvoltages_mV[1 + mux * 3] = volts;
|
||||
volts = ((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]) / 10;
|
||||
cellvoltages[2 + mux * 3] = volts;
|
||||
system_cellvoltages_mV[2 + mux * 3] = volts;
|
||||
|
||||
// Track the max value of mux. If we've seen two 0 values for mux, we've probably gathered all
|
||||
// cell voltages. Then, 2 + mux_max * 3 + 1 is the number of cell voltages.
|
||||
|
@ -487,7 +476,7 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
|||
mux_zero_counter++;
|
||||
if (mux_zero_counter == 2u) {
|
||||
// The max index will be 2 + mux_max * 3 (see above), so "+ 1" for the number of cells
|
||||
nof_cellvoltages = 2 + 3 * mux_max + 1;
|
||||
system_number_of_cells = 2 + 3 * mux_max + 1;
|
||||
// Increase the counter arbitrarily another time to make the initial if-statement evaluate to false
|
||||
mux_zero_counter++;
|
||||
}
|
||||
|
@ -602,13 +591,6 @@ the first, for a few cycles, then stop all messages which causes the contactor
|
|||
}
|
||||
}
|
||||
}
|
||||
uint16_t convert2unsignedInt16(int16_t signed_value) {
|
||||
if (signed_value < 0) {
|
||||
return (65535 + signed_value);
|
||||
} else {
|
||||
return (uint16_t)signed_value;
|
||||
}
|
||||
}
|
||||
|
||||
void print_int_with_units(char* header, int value, char* units) {
|
||||
Serial.print(header);
|
||||
|
@ -704,8 +686,8 @@ void printDebugIfActive(uint8_t symbol, const char* 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
|
||||
system_max_design_voltage_dV = 4030; // 403.0V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 3100; // 310.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,23 +12,25 @@
|
|||
60000 // 60000W we need to cap this value to max 60kW, most inverters overflow otherwise
|
||||
|
||||
// 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 uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool LFP_Chemistry;
|
||||
|
@ -37,7 +39,6 @@ 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
|
||||
|
|
|
@ -19,48 +19,48 @@ void print_units(char* header, int value, char* units) {
|
|||
}
|
||||
|
||||
void update_values_battery() { /* This function puts fake values onto the parameters sent towards the inverter */
|
||||
SOC = 5000; // 50.00%
|
||||
system_real_SOC_pptt = 5000; // 50.00%
|
||||
|
||||
StateOfHealth = 9900; // 99.00%
|
||||
system_SOH_pptt = 9900; // 99.00%
|
||||
|
||||
//battery_voltage = 3700; // 370.0V , value set in startup in .ino file, editable via webUI
|
||||
//system_battery_voltage_dV = 3700; // 370.0V , value set in startup in .ino file, editable via webUI
|
||||
|
||||
battery_current = 0; // 0 A
|
||||
system_battery_current_dA = 0; // 0 A
|
||||
|
||||
capacity_Wh = 30000; // 30kWh
|
||||
system_capacity_Wh = 30000; // 30kWh
|
||||
|
||||
remaining_capacity_Wh = 15000; // 15kWh
|
||||
system_remaining_capacity_Wh = 15000; // 15kWh
|
||||
|
||||
cell_max_voltage = 3596;
|
||||
system_cell_max_voltage_mV = 3596;
|
||||
|
||||
cell_min_voltage = 3500;
|
||||
system_cell_min_voltage_mV = 3500;
|
||||
|
||||
stat_batt_power = 0; // 0W
|
||||
system_active_power_W = 0; // 0W
|
||||
|
||||
temperature_min = 50; // 5.0*C
|
||||
system_temperature_min_dC = 50; // 5.0*C
|
||||
|
||||
temperature_max = 60; // 6.0*C
|
||||
system_temperature_max_dC = 60; // 6.0*C
|
||||
|
||||
max_target_discharge_power = 5000; // 5kW
|
||||
system_max_discharge_power_W = 5000; // 5kW
|
||||
|
||||
max_target_charge_power = 5000; // 5kW
|
||||
system_max_charge_power_W = 5000; // 5kW
|
||||
|
||||
for (int i = 0; i < 97; ++i) {
|
||||
cellvoltages[i] = 3500 + i;
|
||||
system_cellvoltages_mV[i] = 3500 + i;
|
||||
}
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("FAKE Values going to inverter");
|
||||
print_units("SOH%: ", (StateOfHealth * 0.01), "% ");
|
||||
print_units(", SOC%: ", (SOC * 0.01), "% ");
|
||||
print_units(", Voltage: ", (battery_voltage * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", max_target_discharge_power, "W ");
|
||||
print_units(", Max charge power: ", max_target_charge_power, "W ");
|
||||
print_units(", Max temp: ", (temperature_max * 0.1), "°C ");
|
||||
print_units(", Min temp: ", (temperature_min * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", cell_max_voltage, "mV ");
|
||||
print_units(", Min cell voltage: ", cell_min_voltage, "mV ");
|
||||
print_units("SOH%: ", (system_SOH_pptt * 0.01), "% ");
|
||||
print_units(", SOC%: ", (system_scaled_SOC_pptt * 0.01), "% ");
|
||||
print_units(", Voltage: ", (system_battery_voltage_dV * 0.1), "V ");
|
||||
print_units(", Max discharge power: ", system_max_discharge_power_W, "W ");
|
||||
print_units(", Max charge power: ", system_max_charge_power_W, "W ");
|
||||
print_units(", Max temp: ", (system_temperature_max_dC * 0.1), "°C ");
|
||||
print_units(", Min temp: ", (system_temperature_min_dC * 0.1), "°C ");
|
||||
print_units(", Max cell voltage: ", system_cell_max_voltage_mV, "mV ");
|
||||
print_units(", Min cell voltage: ", system_cell_min_voltage_mV, "mV ");
|
||||
Serial.println("");
|
||||
#endif
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ void send_can_battery() {
|
|||
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
|
||||
system_max_design_voltage_dV = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
||||
system_min_design_voltage_dV = 2450; // 245.0V under this, discharging further is disabled
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,25 +8,27 @@
|
|||
#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)
|
||||
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_status; //Enum, 0-5
|
||||
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-5000 per cell
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void setup_battery(void);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "../../USER_SETTINGS.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
|
||||
void send_can_nissanleaf_charger();
|
||||
void receive_can_nissanleaf_charger(CAN_frame_t rx_frame);
|
||||
|
|
|
@ -106,28 +106,26 @@ CAN_frame_t BYD_210 = {.FIR = {.B =
|
|||
.MsgID = 0x210,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
static int discharge_current = 0;
|
||||
static int charge_current = 0;
|
||||
static int initialDataSent = 0;
|
||||
static uint16_t discharge_current = 0;
|
||||
static uint16_t charge_current = 0;
|
||||
static int16_t temperature_average = 0;
|
||||
static int16_t temp_min = 0;
|
||||
static int16_t temp_max = 0;
|
||||
static int inverter_voltage = 0;
|
||||
static int inverter_SOC = 0;
|
||||
static uint16_t inverter_voltage = 0;
|
||||
static uint16_t inverter_SOC = 0;
|
||||
static long inverter_timestamp = 0;
|
||||
static bool initialDataSent = 0;
|
||||
|
||||
void update_values_can_byd() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
//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)
|
||||
charge_current = ((system_max_charge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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)
|
||||
if (charge_current > MAXCHARGEAMP) {
|
||||
charge_current = MAXCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values.
|
||||
}
|
||||
|
||||
discharge_current = ((max_target_discharge_power * 10) /
|
||||
max_voltage); //Charge power in W , max volt in V+1decimal (P=UI, solve for I)
|
||||
discharge_current = ((system_max_discharge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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)
|
||||
if (discharge_current > MAXDISCHARGEAMP) {
|
||||
|
@ -135,17 +133,15 @@ void update_values_can_byd() { //This function maps all the values fetched from
|
|||
MAXDISCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values.
|
||||
}
|
||||
|
||||
temp_min = temperature_min; //Convert from unsigned to signed
|
||||
temp_max = temperature_max;
|
||||
temperature_average = ((temp_max + temp_min) / 2);
|
||||
temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 2);
|
||||
|
||||
//Map values to CAN messages
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long)
|
||||
BYD_110.data.u8[0] = (max_voltage >> 8);
|
||||
BYD_110.data.u8[1] = (max_voltage & 0x00FF);
|
||||
BYD_110.data.u8[0] = (system_max_design_voltage_dV >> 8);
|
||||
BYD_110.data.u8[1] = (system_max_design_voltage_dV & 0x00FF);
|
||||
//Minvoltage (eg 300.0V = 3000 , 16bits long)
|
||||
BYD_110.data.u8[2] = (min_voltage >> 8);
|
||||
BYD_110.data.u8[3] = (min_voltage & 0x00FF);
|
||||
BYD_110.data.u8[2] = (system_min_design_voltage_dV >> 8);
|
||||
BYD_110.data.u8[3] = (system_min_design_voltage_dV & 0x00FF);
|
||||
//Maximum discharge power allowed (Unit: A+1)
|
||||
BYD_110.data.u8[4] = (discharge_current >> 8);
|
||||
BYD_110.data.u8[5] = (discharge_current & 0x00FF);
|
||||
|
@ -154,11 +150,11 @@ void update_values_can_byd() { //This function maps all the values fetched from
|
|||
BYD_110.data.u8[7] = (charge_current & 0x00FF);
|
||||
|
||||
//SOC (100.00%)
|
||||
BYD_150.data.u8[0] = (SOC >> 8);
|
||||
BYD_150.data.u8[1] = (SOC & 0x00FF);
|
||||
BYD_150.data.u8[0] = (system_scaled_SOC_pptt >> 8);
|
||||
BYD_150.data.u8[1] = (system_scaled_SOC_pptt & 0x00FF);
|
||||
//StateOfHealth (100.00%)
|
||||
BYD_150.data.u8[2] = (StateOfHealth >> 8);
|
||||
BYD_150.data.u8[3] = (StateOfHealth & 0x00FF);
|
||||
BYD_150.data.u8[2] = (system_SOH_pptt >> 8);
|
||||
BYD_150.data.u8[3] = (system_SOH_pptt & 0x00FF);
|
||||
//Maximum charge power allowed (Unit: A+1)
|
||||
BYD_150.data.u8[4] = (charge_current >> 8);
|
||||
BYD_150.data.u8[5] = (charge_current & 0x00FF);
|
||||
|
@ -167,21 +163,21 @@ void update_values_can_byd() { //This function maps all the values fetched from
|
|||
BYD_150.data.u8[7] = (discharge_current & 0x00FF);
|
||||
|
||||
//Voltage (ex 370.0)
|
||||
BYD_1D0.data.u8[0] = (battery_voltage >> 8);
|
||||
BYD_1D0.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
BYD_1D0.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
BYD_1D0.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
//Current (ex 81.0A)
|
||||
BYD_1D0.data.u8[2] = (battery_current >> 8);
|
||||
BYD_1D0.data.u8[3] = (battery_current & 0x00FF);
|
||||
BYD_1D0.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
BYD_1D0.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
//Temperature average
|
||||
BYD_1D0.data.u8[4] = (temperature_average >> 8);
|
||||
BYD_1D0.data.u8[5] = (temperature_average & 0x00FF);
|
||||
|
||||
//Temperature max
|
||||
BYD_210.data.u8[0] = (temperature_max >> 8);
|
||||
BYD_210.data.u8[1] = (temperature_max & 0x00FF);
|
||||
BYD_210.data.u8[0] = (system_temperature_max_dC >> 8);
|
||||
BYD_210.data.u8[1] = (system_temperature_max_dC & 0x00FF);
|
||||
//Temperature min
|
||||
BYD_210.data.u8[2] = (temperature_min >> 8);
|
||||
BYD_210.data.u8[3] = (temperature_min & 0x00FF);
|
||||
BYD_210.data.u8[2] = (system_temperature_min_dC >> 8);
|
||||
BYD_210.data.u8[3] = (system_temperature_min_dC & 0x00FF);
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
if (char1_151 != 0) {
|
||||
|
|
|
@ -5,22 +5,28 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
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 min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
// These parameters need to be mapped for the inverter
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void update_values_can_byd();
|
||||
void send_can_byd();
|
||||
|
|
|
@ -14,9 +14,9 @@ void handle_update_data_modbus32051() {
|
|||
system_data[2] = 110; //Goes between 110- -107 [NOTE, SIGNED VALUE]
|
||||
system_data[3] = 0; //Goes between 0 and -1 [NOTE, SIGNED VALUE]
|
||||
system_data[4] = 616; //Goes between 616- -520 [NOTE, SIGNED VALUE]
|
||||
system_data[5] = temperature_max; //Temperature max?
|
||||
system_data[6] = temperature_min; //Temperature min?
|
||||
system_data[7] = (SOC / 100); //SOC 0-100%, no decimals
|
||||
system_data[5] = system_temperature_max_dC; //Temperature max?
|
||||
system_data[6] = system_temperature_min_dC; //Temperature min?
|
||||
system_data[7] = (system_scaled_SOC_pptt / 100); //SOC 0-100%, no decimals
|
||||
system_data[8] = 98; //Always 98 in logs
|
||||
static uint16_t i = 2051;
|
||||
memcpy(&mbPV[i], system_data, sizeof(system_data));
|
||||
|
@ -26,17 +26,17 @@ void handle_update_data_modbus39500() {
|
|||
// Store the data into the array
|
||||
static uint16_t system_data[26];
|
||||
system_data[0] = 0;
|
||||
system_data[1] = capacity_Wh; //Capacity? 5000 with 5kWh battery
|
||||
system_data[1] = system_capacity_Wh; //Capacity? 5000 with 5kWh battery
|
||||
system_data[2] = 0;
|
||||
system_data[3] = capacity_Wh; //Capacity? 5000 with 5kWh battery
|
||||
system_data[3] = system_capacity_Wh; //Capacity? 5000 with 5kWh battery
|
||||
system_data[4] = 0;
|
||||
system_data[5] = 2500; //???
|
||||
system_data[6] = 0;
|
||||
system_data[7] = 2500; //???
|
||||
system_data[8] = (SOC / 100); //SOC 0-100%, no decimals
|
||||
system_data[8] = (system_scaled_SOC_pptt / 100); //SOC 0-100%, no decimals
|
||||
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[10] = system_battery_voltage_dV; //Battery bus voltage (766.5V = 7665)
|
||||
system_data[11] = 9; //TODO: GOES LOWER WITH LOW SOC
|
||||
system_data[12] = 0;
|
||||
system_data[13] = 699; //TODO: GOES LOWER WITH LOW SOC
|
||||
|
@ -50,7 +50,7 @@ void handle_update_data_modbus39500() {
|
|||
system_data[21] = 0;
|
||||
system_data[22] = 0;
|
||||
system_data[23] = 0;
|
||||
system_data[24] = (SOC / 10); //SOC 0-100.0%, 1x decimal
|
||||
system_data[24] = (system_scaled_SOC_pptt / 10); //SOC 0-100.0%, 1x decimal
|
||||
system_data[25] = 0;
|
||||
system_data[26] = 1; //Always 1 in logs
|
||||
static uint16_t i = 9500;
|
||||
|
|
|
@ -6,22 +6,27 @@
|
|||
#define MB_RTU_NUM_VALUES 30000
|
||||
|
||||
extern uint16_t mbPV[MB_RTU_NUM_VALUES];
|
||||
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 max_power;
|
||||
extern uint16_t max_voltage;
|
||||
extern uint16_t min_voltage;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void update_modbus_registers_luna2000();
|
||||
void handle_update_data_modbus32051();
|
||||
|
|
|
@ -182,53 +182,53 @@ void update_values_can_pylon() { //This function maps all the values fetched fr
|
|||
PYLON_4281.data.u8[3] = 0;
|
||||
|
||||
//Voltage (370.0)
|
||||
PYLON_4210.data.u8[0] = (battery_voltage >> 8);
|
||||
PYLON_4210.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
PYLON_4211.data.u8[0] = (battery_voltage >> 8);
|
||||
PYLON_4211.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
PYLON_4210.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
PYLON_4210.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
PYLON_4211.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
PYLON_4211.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
|
||||
//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);
|
||||
PYLON_4211.data.u8[3] = (battery_current & 0x00FF);
|
||||
//Current (15.0)
|
||||
PYLON_4210.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
PYLON_4210.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
PYLON_4211.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
PYLON_4211.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
|
||||
//SOC (100.00%)
|
||||
PYLON_4210.data.u8[6] = (SOC * 0.01); //Remove decimals
|
||||
PYLON_4211.data.u8[6] = (SOC * 0.01); //Remove decimals
|
||||
PYLON_4210.data.u8[6] = (system_scaled_SOC_pptt * 0.01); //Remove decimals
|
||||
PYLON_4211.data.u8[6] = (system_scaled_SOC_pptt * 0.01); //Remove decimals
|
||||
|
||||
//StateOfHealth (100.00%)
|
||||
PYLON_4210.data.u8[7] = (StateOfHealth * 0.01);
|
||||
PYLON_4211.data.u8[7] = (StateOfHealth * 0.01);
|
||||
PYLON_4210.data.u8[7] = (system_SOH_pptt * 0.01);
|
||||
PYLON_4211.data.u8[7] = (system_SOH_pptt * 0.01);
|
||||
|
||||
#ifdef INVERT_VOLTAGE //Useful for Sofar inverters \
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long) Discharge Cutoff Voltage
|
||||
PYLON_4220.data.u8[0] = (max_voltage & 0x00FF);
|
||||
PYLON_4220.data.u8[1] = (max_voltage >> 8);
|
||||
PYLON_4221.data.u8[0] = (max_voltage & 0x00FF);
|
||||
PYLON_4221.data.u8[1] = (max_voltage >> 8);
|
||||
PYLON_4220.data.u8[0] = (system_max_design_voltage_dV & 0x00FF);
|
||||
PYLON_4220.data.u8[1] = (system_max_design_voltage_dV >> 8);
|
||||
PYLON_4221.data.u8[0] = (system_max_design_voltage_dV & 0x00FF);
|
||||
PYLON_4221.data.u8[1] = (system_max_design_voltage_dV >> 8);
|
||||
|
||||
//Minvoltage (eg 300.0V = 3000 , 16bits long) Charge Cutoff Voltage
|
||||
PYLON_4220.data.u8[2] = (min_voltage & 0x00FF);
|
||||
PYLON_4220.data.u8[3] = (min_voltage >> 8);
|
||||
PYLON_4221.data.u8[2] = (min_voltage & 0x00FF);
|
||||
PYLON_4221.data.u8[3] = (min_voltage >> 8);
|
||||
PYLON_4220.data.u8[2] = (system_min_design_voltage_dV & 0x00FF);
|
||||
PYLON_4220.data.u8[3] = (system_min_design_voltage_dV >> 8);
|
||||
PYLON_4221.data.u8[2] = (system_min_design_voltage_dV & 0x00FF);
|
||||
PYLON_4221.data.u8[3] = (system_min_design_voltage_dV >> 8);
|
||||
#else
|
||||
//Minvoltage (eg 300.0V = 3000 , 16bits long) Charge Cutoff Voltage
|
||||
PYLON_4220.data.u8[0] = (min_voltage >> 8);
|
||||
PYLON_4220.data.u8[1] = (min_voltage & 0x00FF);
|
||||
PYLON_4221.data.u8[0] = (min_voltage >> 8);
|
||||
PYLON_4221.data.u8[1] = (min_voltage & 0x00FF);
|
||||
PYLON_4220.data.u8[0] = (system_min_design_voltage_dV >> 8);
|
||||
PYLON_4220.data.u8[1] = (system_min_design_voltage_dV & 0x00FF);
|
||||
PYLON_4221.data.u8[0] = (system_min_design_voltage_dV >> 8);
|
||||
PYLON_4221.data.u8[1] = (system_min_design_voltage_dV & 0x00FF);
|
||||
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long) Discharge Cutoff Voltage
|
||||
PYLON_4220.data.u8[2] = (max_voltage >> 8);
|
||||
PYLON_4220.data.u8[3] = (max_voltage & 0x00FF);
|
||||
PYLON_4221.data.u8[2] = (max_voltage >> 8);
|
||||
PYLON_4221.data.u8[3] = (max_voltage & 0x00FF);
|
||||
PYLON_4220.data.u8[2] = (system_max_design_voltage_dV >> 8);
|
||||
PYLON_4220.data.u8[3] = (system_max_design_voltage_dV & 0x00FF);
|
||||
PYLON_4221.data.u8[2] = (system_max_design_voltage_dV >> 8);
|
||||
PYLON_4221.data.u8[3] = (system_max_design_voltage_dV & 0x00FF);
|
||||
#endif
|
||||
|
||||
//In case we run into any errors/faults, we can set charge / discharge forbidden
|
||||
if (bms_status == FAULT) {
|
||||
if (system_bms_status == FAULT) {
|
||||
PYLON_4280.data.u8[0] = 0xAA;
|
||||
PYLON_4280.data.u8[1] = 0xAA;
|
||||
PYLON_4280.data.u8[2] = 0xAA;
|
||||
|
|
|
@ -5,23 +5,27 @@
|
|||
#include "../devboard/config.h" // Needed for all defines
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
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;
|
||||
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
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void update_values_can_pylon();
|
||||
void receive_can_pylon(CAN_frame_t rx_frame);
|
||||
|
|
|
@ -108,8 +108,8 @@ void manageSerialLinkTransmitter() {
|
|||
Serial.println("SerialDataLink : max_target_discharge_power = 0");
|
||||
Serial.println("SerialDataLink : max_target_charge_power = 0");
|
||||
|
||||
max_target_discharge_power = 0;
|
||||
max_target_charge_power = 0;
|
||||
system_max_discharge_power_W = 0;
|
||||
system_max_charge_power_W = 0;
|
||||
set_event(EVENT_SERIAL_TX_FAILURE, 0);
|
||||
// throw error
|
||||
}
|
||||
|
@ -129,21 +129,21 @@ void manageSerialLinkTransmitter() {
|
|||
|
||||
if (currentTime - updateDataTime > 999) {
|
||||
updateDataTime = currentTime;
|
||||
dataLinkTransmit.updateData(0, SOC);
|
||||
dataLinkTransmit.updateData(1, StateOfHealth);
|
||||
dataLinkTransmit.updateData(2, battery_voltage);
|
||||
dataLinkTransmit.updateData(3, battery_current);
|
||||
dataLinkTransmit.updateData(4, capacity_Wh);
|
||||
dataLinkTransmit.updateData(5, remaining_capacity_Wh);
|
||||
dataLinkTransmit.updateData(6, max_target_discharge_power);
|
||||
dataLinkTransmit.updateData(7, max_target_charge_power);
|
||||
dataLinkTransmit.updateData(8, bms_status);
|
||||
dataLinkTransmit.updateData(9, stat_batt_power);
|
||||
dataLinkTransmit.updateData(10, temperature_min);
|
||||
dataLinkTransmit.updateData(11, temperature_max);
|
||||
dataLinkTransmit.updateData(12, cell_max_voltage);
|
||||
dataLinkTransmit.updateData(13, cell_min_voltage);
|
||||
dataLinkTransmit.updateData(14, (int16_t)LFP_Chemistry);
|
||||
dataLinkTransmit.updateData(0, system_real_SOC_pptt);
|
||||
dataLinkTransmit.updateData(1, system_SOH_pptt);
|
||||
dataLinkTransmit.updateData(2, system_battery_voltage_dV);
|
||||
dataLinkTransmit.updateData(3, system_battery_current_dA);
|
||||
dataLinkTransmit.updateData(4, system_capacity_Wh);
|
||||
dataLinkTransmit.updateData(5, system_remaining_capacity_Wh);
|
||||
dataLinkTransmit.updateData(6, system_max_discharge_power_W);
|
||||
dataLinkTransmit.updateData(7, system_max_charge_power_W);
|
||||
dataLinkTransmit.updateData(8, system_bms_status);
|
||||
dataLinkTransmit.updateData(9, system_active_power_W);
|
||||
dataLinkTransmit.updateData(10, system_temperature_min_dC);
|
||||
dataLinkTransmit.updateData(11, system_temperature_max_dC);
|
||||
dataLinkTransmit.updateData(12, system_cell_max_voltage_mV);
|
||||
dataLinkTransmit.updateData(13, system_cell_min_voltage_mV);
|
||||
dataLinkTransmit.updateData(14, (int16_t)system_LFP_Chemistry);
|
||||
dataLinkTransmit.updateData(15, batteryAllowsContactorClosing);
|
||||
}
|
||||
}
|
||||
|
@ -152,35 +152,35 @@ void manageSerialLinkTransmitter() {
|
|||
void printSendingValues() {
|
||||
Serial.println("Values from battery: ");
|
||||
Serial.print("SOC: ");
|
||||
Serial.print(SOC);
|
||||
Serial.print(system_real_SOC_pptt);
|
||||
Serial.print(" SOH: ");
|
||||
Serial.print(StateOfHealth);
|
||||
Serial.print(system_SOH_pptt);
|
||||
Serial.print(" Voltage: ");
|
||||
Serial.print(battery_voltage);
|
||||
Serial.print(system_battery_voltage_dV);
|
||||
Serial.print(" Current: ");
|
||||
Serial.print(battery_current);
|
||||
Serial.print(system_battery_current_dA);
|
||||
Serial.print(" Capacity: ");
|
||||
Serial.print(capacity_Wh);
|
||||
Serial.print(system_capacity_Wh);
|
||||
Serial.print(" Remain cap: ");
|
||||
Serial.print(remaining_capacity_Wh);
|
||||
Serial.print(system_remaining_capacity_Wh);
|
||||
Serial.print(" Max discharge W: ");
|
||||
Serial.print(max_target_discharge_power);
|
||||
Serial.print(system_max_discharge_power_W);
|
||||
Serial.print(" Max charge W: ");
|
||||
Serial.print(max_target_charge_power);
|
||||
Serial.print(system_max_charge_power_W);
|
||||
Serial.print(" BMS status: ");
|
||||
Serial.print(bms_status);
|
||||
Serial.print(system_bms_status);
|
||||
Serial.print(" Power: ");
|
||||
Serial.print(stat_batt_power);
|
||||
Serial.print(system_active_power_W);
|
||||
Serial.print(" Temp min: ");
|
||||
Serial.print(temperature_min);
|
||||
Serial.print(system_temperature_min_dC);
|
||||
Serial.print(" Temp max: ");
|
||||
Serial.print(temperature_max);
|
||||
Serial.print(system_temperature_max_dC);
|
||||
Serial.print(" Cell max: ");
|
||||
Serial.print(cell_max_voltage);
|
||||
Serial.print(system_cell_max_voltage_mV);
|
||||
Serial.print(" Cell min: ");
|
||||
Serial.print(cell_min_voltage);
|
||||
Serial.print(system_cell_min_voltage_mV);
|
||||
Serial.print(" LFP : ");
|
||||
Serial.print(LFP_Chemistry);
|
||||
Serial.print(system_LFP_Chemistry);
|
||||
Serial.print(" batteryAllowsContactorClosing: ");
|
||||
Serial.print(batteryAllowsContactorClosing);
|
||||
Serial.print(" inverterAllowsContactorClosing: ");
|
||||
|
|
|
@ -9,27 +9,25 @@
|
|||
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
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_status; //Enum, 0-5
|
||||
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 bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
|
||||
extern bool LFP_Chemistry;
|
||||
extern uint16_t CANerror;
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool system_LFP_Chemistry; //Bool, true/false
|
||||
|
||||
// parameters received from receiver
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void manageSerialLinkTransmitter();
|
||||
|
||||
|
|
|
@ -99,36 +99,33 @@ CAN_frame_t SMA_158 = {.FIR = {.B =
|
|||
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
|
||||
charge_current =
|
||||
((max_target_charge_power * 10) / max_voltage); //Charge power in W , max volt in V+1decimal (P=UI, solve for I)
|
||||
charge_current = ((system_max_charge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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)
|
||||
discharge_current = ((system_max_discharge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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)
|
||||
|
||||
temp_min = temperature_min; //Convert from unsigned to signed
|
||||
temp_max = temperature_max;
|
||||
temperature_average = ((temp_max + temp_min) / 2);
|
||||
temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 2);
|
||||
|
||||
ampere_hours_remaining =
|
||||
((remaining_capacity_Wh / battery_voltage) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
((remaining_capacity_Wh / system_battery_voltage_dV) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
|
||||
//Map values to CAN messages
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long)
|
||||
SMA_358.data.u8[0] = (max_voltage >> 8);
|
||||
SMA_358.data.u8[1] = (max_voltage & 0x00FF);
|
||||
SMA_358.data.u8[0] = (system_max_design_voltage_dV >> 8);
|
||||
SMA_358.data.u8[1] = (system_max_design_voltage_dV & 0x00FF);
|
||||
//Minvoltage (eg 300.0V = 3000 , 16bits long)
|
||||
SMA_358.data.u8[2] = (min_voltage >> 8); //Minvoltage behaves strange on SMA, cuts out at 56% of the set value?
|
||||
SMA_358.data.u8[3] = (min_voltage & 0x00FF);
|
||||
SMA_358.data.u8[2] =
|
||||
(system_min_design_voltage_dV >> 8); //Minvoltage behaves strange on SMA, cuts out at 56% of the set value?
|
||||
SMA_358.data.u8[3] = (system_min_design_voltage_dV & 0x00FF);
|
||||
//Discharge limited current, 500 = 50A, (0.1, A)
|
||||
SMA_358.data.u8[4] = (discharge_current >> 8);
|
||||
SMA_358.data.u8[5] = (discharge_current & 0x00FF);
|
||||
|
@ -137,21 +134,21 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
SMA_358.data.u8[7] = (charge_current & 0x00FF);
|
||||
|
||||
//SOC (100.00%)
|
||||
SMA_3D8.data.u8[0] = (SOC >> 8);
|
||||
SMA_3D8.data.u8[1] = (SOC & 0x00FF);
|
||||
SMA_3D8.data.u8[0] = (system_scaled_SOC_pptt >> 8);
|
||||
SMA_3D8.data.u8[1] = (system_scaled_SOC_pptt & 0x00FF);
|
||||
//StateOfHealth (100.00%)
|
||||
SMA_3D8.data.u8[2] = (StateOfHealth >> 8);
|
||||
SMA_3D8.data.u8[3] = (StateOfHealth & 0x00FF);
|
||||
SMA_3D8.data.u8[2] = (system_SOH_pptt >> 8);
|
||||
SMA_3D8.data.u8[3] = (system_SOH_pptt & 0x00FF);
|
||||
//State of charge (AH, 0.1)
|
||||
SMA_3D8.data.u8[4] = (ampere_hours_remaining >> 8);
|
||||
SMA_3D8.data.u8[5] = (ampere_hours_remaining & 0x00FF);
|
||||
|
||||
//Voltage (370.0)
|
||||
SMA_4D8.data.u8[0] = (battery_voltage >> 8);
|
||||
SMA_4D8.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
SMA_4D8.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
SMA_4D8.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
//Current (TODO: signed OK?)
|
||||
SMA_4D8.data.u8[2] = (battery_current >> 8);
|
||||
SMA_4D8.data.u8[3] = (battery_current & 0x00FF);
|
||||
SMA_4D8.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
SMA_4D8.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
//Temperature average
|
||||
SMA_4D8.data.u8[4] = (temperature_average >> 8);
|
||||
SMA_4D8.data.u8[5] = (temperature_average & 0x00FF);
|
||||
|
|
|
@ -5,24 +5,27 @@
|
|||
#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 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 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
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
#define READY_STATE 0x03
|
||||
#define STOP_STATE 0x02
|
||||
|
|
|
@ -161,21 +161,22 @@ 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)
|
||||
charge_current = ((system_max_charge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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)
|
||||
discharge_current = ((system_max_discharge_power_W * 10) /
|
||||
system_max_design_voltage_dV); //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);
|
||||
temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 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)
|
||||
((system_remaining_capacity_Wh / system_battery_voltage_dV) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
ampere_hours_max =
|
||||
((system_capacity_Wh / system_battery_voltage_dV) * 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah)
|
||||
|
||||
batteryState = OPERATE;
|
||||
inverterControlFlags = INVERTER_STAY_ON;
|
||||
|
@ -183,11 +184,11 @@ void update_values_can_sma_tripower() { //This function maps all the values fet
|
|||
//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);
|
||||
SMA_00D.data.u8[0] = (system_max_design_voltage_dV >> 8);
|
||||
SMA_00D.data.u8[1] = (system_max_design_voltage_dV & 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);
|
||||
SMA_00D.data.u8[2] = (system_min_design_voltage_dV >> 8);
|
||||
SMA_00D.data.u8[3] = (system_min_design_voltage_dV & 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);
|
||||
|
@ -197,11 +198,11 @@ void update_values_can_sma_tripower() { //This function maps all the values fet
|
|||
|
||||
// Battery State
|
||||
//SOC (100.00%)
|
||||
SMA_00F.data.u8[0] = (SOC >> 8);
|
||||
SMA_00F.data.u8[1] = (SOC & 0x00FF);
|
||||
SMA_00F.data.u8[0] = (system_scaled_SOC_pptt >> 8);
|
||||
SMA_00F.data.u8[1] = (system_scaled_SOC_pptt & 0x00FF);
|
||||
//StateOfHealth (100.00%)
|
||||
SMA_00F.data.u8[2] = (StateOfHealth >> 8);
|
||||
SMA_00F.data.u8[3] = (StateOfHealth & 0x00FF);
|
||||
SMA_00F.data.u8[2] = (system_SOH_pptt >> 8);
|
||||
SMA_00F.data.u8[3] = (system_SOH_pptt & 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);
|
||||
|
@ -223,11 +224,11 @@ void update_values_can_sma_tripower() { //This function maps all the values fet
|
|||
|
||||
// Battery Measurements
|
||||
//Voltage (370.0)
|
||||
SMA_013.data.u8[0] = (battery_voltage >> 8);
|
||||
SMA_013.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
SMA_013.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
SMA_013.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
//Current (TODO: signed OK?)
|
||||
SMA_013.data.u8[2] = (battery_current >> 8);
|
||||
SMA_013.data.u8[3] = (battery_current & 0x00FF);
|
||||
SMA_013.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
SMA_013.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
//Temperature average
|
||||
SMA_013.data.u8[4] = (temperature_average >> 8);
|
||||
SMA_013.data.u8[5] = (temperature_average & 0x00FF);
|
||||
|
@ -237,11 +238,11 @@ void update_values_can_sma_tripower() { //This function maps all the values fet
|
|||
|
||||
// Battery Temperature and Cellvoltages
|
||||
// Battery max temperature
|
||||
SMA_014.data.u8[0] = (temperature_max >> 8);
|
||||
SMA_014.data.u8[1] = (temperature_max & 0x00FF);
|
||||
SMA_014.data.u8[0] = (system_temperature_max_dC >> 8);
|
||||
SMA_014.data.u8[1] = (system_temperature_max_dC & 0x00FF);
|
||||
// Battery min temperature
|
||||
SMA_014.data.u8[2] = (temperature_min >> 8);
|
||||
SMA_014.data.u8[3] = (temperature_min & 0x00FF);
|
||||
SMA_014.data.u8[2] = (system_temperature_min_dC >> 8);
|
||||
SMA_014.data.u8[3] = (system_temperature_min_dC & 0x00FF);
|
||||
// Battery Cell Voltage (sum)
|
||||
//SMA_014.data.u8[4] = (??? >> 8); //TODO scaling?
|
||||
//SMA_014.data.u8[5] = (??? & 0x00FF); //TODO scaling?
|
||||
|
|
|
@ -5,24 +5,27 @@
|
|||
#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
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
void update_values_can_sma_tripower();
|
||||
void send_can_sma_tripower();
|
||||
|
|
|
@ -281,29 +281,29 @@ CAN_frame_t SOFAR_7C0 = {.FIR = {.B =
|
|||
void update_values_can_sofar() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long) Charge Cutoff Voltage
|
||||
SOFAR_351.data.u8[0] = (max_voltage >> 8);
|
||||
SOFAR_351.data.u8[1] = (max_voltage & 0x00FF);
|
||||
SOFAR_351.data.u8[0] = (system_max_design_voltage_dV >> 8);
|
||||
SOFAR_351.data.u8[1] = (system_max_design_voltage_dV & 0x00FF);
|
||||
//SOFAR_351.data.u8[2] = DC charge current limitation (Default 25.0A)
|
||||
//SOFAR_351.data.u8[3] = DC charge current limitation
|
||||
//SOFAR_351.data.u8[4] = DC discharge current limitation (Default 25.0A)
|
||||
//SOFAR_351.data.u8[5] = DC discharge current limitation
|
||||
//Minvoltage (eg 300.0V = 3000 , 16bits long) Discharge Cutoff Voltage
|
||||
SOFAR_351.data.u8[6] = (min_voltage >> 8);
|
||||
SOFAR_351.data.u8[7] = (min_voltage & 0x00FF);
|
||||
SOFAR_351.data.u8[6] = (system_min_design_voltage_dV >> 8);
|
||||
SOFAR_351.data.u8[7] = (system_min_design_voltage_dV & 0x00FF);
|
||||
|
||||
//SOC
|
||||
SOFAR_355.data.u8[0] = (SOC / 100);
|
||||
SOFAR_355.data.u8[2] = (StateOfHealth / 100);
|
||||
SOFAR_355.data.u8[0] = (system_scaled_SOC_pptt / 100);
|
||||
SOFAR_355.data.u8[2] = (system_SOH_pptt / 100);
|
||||
//SOFAR_355.data.u8[6] = (AH_remaining >> 8);
|
||||
//SOFAR_355.data.u8[7] = (AH_remaining & 0x00FF);
|
||||
|
||||
//Voltage (370.0)
|
||||
SOFAR_356.data.u8[0] = (battery_voltage >> 8);
|
||||
SOFAR_356.data.u8[1] = (battery_voltage & 0x00FF);
|
||||
SOFAR_356.data.u8[2] = (battery_current >> 8);
|
||||
SOFAR_356.data.u8[3] = (battery_current & 0x00FF);
|
||||
SOFAR_356.data.u8[2] = (temperature_max >> 8);
|
||||
SOFAR_356.data.u8[3] = (temperature_max & 0x00FF);
|
||||
SOFAR_356.data.u8[0] = (system_battery_voltage_dV >> 8);
|
||||
SOFAR_356.data.u8[1] = (system_battery_voltage_dV & 0x00FF);
|
||||
SOFAR_356.data.u8[2] = (system_battery_current_dA >> 8);
|
||||
SOFAR_356.data.u8[3] = (system_battery_current_dA & 0x00FF);
|
||||
SOFAR_356.data.u8[2] = (system_temperature_max_dC >> 8);
|
||||
SOFAR_356.data.u8[3] = (system_temperature_max_dC & 0x00FF);
|
||||
}
|
||||
|
||||
void receive_can_sofar(CAN_frame_t rx_frame) {
|
||||
|
|
|
@ -6,21 +6,27 @@
|
|||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
// These parameters need to be mapped for the inverter
|
||||
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 bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
extern uint16_t min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
/* Do not change code below unless you are sure what you are doing */
|
||||
static uint16_t max_charge_rate_amp = 0;
|
||||
static uint16_t max_discharge_rate_amp = 0;
|
||||
static uint16_t temperature_average = 0;
|
||||
static int STATE = BATTERY_ANNOUNCE;
|
||||
static int16_t temperature_average = 0;
|
||||
static uint8_t STATE = BATTERY_ANNOUNCE;
|
||||
static unsigned long LastFrameTime = 0;
|
||||
static int number_of_batteries = 1;
|
||||
static uint8_t number_of_batteries = 1;
|
||||
static uint16_t capped_capacity_Wh;
|
||||
static uint16_t capped_remaining_capacity_Wh;
|
||||
|
||||
//CAN message translations from this amazing repository: https://github.com/rand12345/solax_can_bus
|
||||
|
||||
|
@ -122,64 +124,77 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
STATE = BATTERY_ANNOUNCE;
|
||||
}
|
||||
//Calculate the required values
|
||||
temperature_average = ((temperature_max + temperature_min) / 2);
|
||||
temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 2);
|
||||
|
||||
//max_target_charge_power (30000W max)
|
||||
if (SOC > 9999) //99.99%
|
||||
//system_max_charge_power_W (30000W max)
|
||||
if (system_scaled_SOC_pptt > 9999) //99.99%
|
||||
{ //Additional safety incase SOC% is 100, then do not charge battery further
|
||||
max_charge_rate_amp = 0;
|
||||
} else { //We can pass on the battery charge rate (in W) to the inverter (that takes A)
|
||||
if (max_target_charge_power >= 30000) {
|
||||
if (system_max_charge_power_W >= 30000) {
|
||||
max_charge_rate_amp = 75; //Incase battery can take over 30kW, cap value to 75A
|
||||
} else { //Calculate the W value into A
|
||||
max_charge_rate_amp = (max_target_charge_power / (battery_voltage * 0.1)); // P/U = I
|
||||
max_charge_rate_amp = (system_max_charge_power_W / (system_battery_voltage_dV * 0.1)); // P/U = I
|
||||
}
|
||||
}
|
||||
|
||||
//max_target_discharge_power (30000W max)
|
||||
if (SOC < 100) //1.00%
|
||||
//system_max_discharge_power_W (30000W max)
|
||||
if (system_scaled_SOC_pptt < 100) //1.00%
|
||||
{ //Additional safety incase SOC% is below 1, then do not charge battery further
|
||||
max_discharge_rate_amp = 0;
|
||||
} else { //We can pass on the battery discharge rate to the inverter
|
||||
if (max_target_discharge_power >= 30000) {
|
||||
if (system_max_discharge_power_W >= 30000) {
|
||||
max_discharge_rate_amp = 75; //Incase battery can be charged with over 30kW, cap value to 75A
|
||||
} else { //Calculate the W value into A
|
||||
max_discharge_rate_amp = (max_target_discharge_power / (battery_voltage * 0.1)); // P/U = I
|
||||
max_discharge_rate_amp = (system_max_discharge_power_W / (system_battery_voltage_dV * 0.1)); // P/U = I
|
||||
}
|
||||
}
|
||||
|
||||
// Batteries might be larger than uint16_t value can take
|
||||
if (system_capacity_Wh > 65000) {
|
||||
capped_capacity_Wh = 65000;
|
||||
} else {
|
||||
capped_capacity_Wh = system_capacity_Wh;
|
||||
}
|
||||
// Batteries might be larger than uint16_t value can take
|
||||
if (system_remaining_capacity_Wh > 65000) {
|
||||
capped_remaining_capacity_Wh = 65000;
|
||||
} else {
|
||||
capped_remaining_capacity_Wh = system_remaining_capacity_Wh;
|
||||
}
|
||||
|
||||
//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[1] = (max_voltage >> 8);
|
||||
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[0] = (uint8_t)system_max_design_voltage_dV;
|
||||
SOLAX_1872.data.u8[1] = (system_max_design_voltage_dV >> 8);
|
||||
SOLAX_1872.data.u8[2] = (uint8_t)system_min_design_voltage_dV;
|
||||
SOLAX_1872.data.u8[3] = (system_min_design_voltage_dV >> 8);
|
||||
SOLAX_1872.data.u8[4] = (uint8_t)(max_charge_rate_amp * 10);
|
||||
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);
|
||||
SOLAX_1872.data.u8[7] = ((max_discharge_rate_amp * 10) >> 8);
|
||||
|
||||
//BMS_PackData
|
||||
SOLAX_1873.data.u8[0] = (uint8_t)battery_voltage; // OK
|
||||
SOLAX_1873.data.u8[1] = (battery_voltage >> 8);
|
||||
SOLAX_1873.data.u8[2] = (int8_t)battery_current; // OK, Signed (Active current in Amps x 10)
|
||||
SOLAX_1873.data.u8[3] = (battery_current >> 8);
|
||||
SOLAX_1873.data.u8[4] = (uint8_t)(SOC / 100); //SOC (100.00%)
|
||||
SOLAX_1873.data.u8[0] = (uint8_t)system_battery_voltage_dV; // OK
|
||||
SOLAX_1873.data.u8[1] = (system_battery_voltage_dV >> 8);
|
||||
SOLAX_1873.data.u8[2] = (int8_t)system_battery_current_dA; // OK, Signed (Active current in Amps x 10)
|
||||
SOLAX_1873.data.u8[3] = (system_battery_current_dA >> 8);
|
||||
SOLAX_1873.data.u8[4] = (uint8_t)(system_scaled_SOC_pptt / 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[7] = ((remaining_capacity_Wh / 100) >> 8);
|
||||
SOLAX_1873.data.u8[6] = (uint8_t)(capped_remaining_capacity_Wh / 100); //TODO: scaling OK?
|
||||
SOLAX_1873.data.u8[7] = ((capped_remaining_capacity_Wh / 100) >> 8);
|
||||
|
||||
//BMS_CellData
|
||||
SOLAX_1874.data.u8[0] = (uint8_t)temperature_max;
|
||||
SOLAX_1874.data.u8[1] = (temperature_max >> 8);
|
||||
SOLAX_1874.data.u8[2] = (uint8_t)temperature_min;
|
||||
SOLAX_1874.data.u8[3] = (temperature_min >> 8);
|
||||
SOLAX_1874.data.u8[0] = (int8_t)system_temperature_max_dC;
|
||||
SOLAX_1874.data.u8[1] = (system_temperature_max_dC >> 8);
|
||||
SOLAX_1874.data.u8[2] = (int8_t)system_temperature_min_dC;
|
||||
SOLAX_1874.data.u8[3] = (system_temperature_min_dC >> 8);
|
||||
SOLAX_1874.data.u8[4] =
|
||||
(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);
|
||||
(uint8_t)(system_cell_max_voltage_mV); //TODO: scaling OK? Supposed to be alarm trigger absolute cell max?
|
||||
SOLAX_1874.data.u8[5] = (system_cell_max_voltage_mV >> 8);
|
||||
SOLAX_1874.data.u8[6] =
|
||||
(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);
|
||||
(uint8_t)(system_cell_min_voltage_mV); //TODO: scaling OK? Supposed to be alarm trigger absolute cell min?
|
||||
SOLAX_1874.data.u8[7] = (system_cell_min_voltage_mV >> 8);
|
||||
|
||||
//BMS_Status
|
||||
SOLAX_1875.data.u8[0] = (uint8_t)temperature_average;
|
||||
|
@ -188,11 +203,11 @@ 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[3] = (cell_max_voltage >> 8);
|
||||
SOLAX_1876.data.u8[2] = (uint8_t)system_cell_max_voltage_mV; //TODO: scaling OK?
|
||||
SOLAX_1876.data.u8[3] = (system_cell_max_voltage_mV >> 8);
|
||||
|
||||
SOLAX_1876.data.u8[6] = (uint8_t)cell_min_voltage; //TODO: scaling OK?
|
||||
SOLAX_1876.data.u8[7] = (cell_min_voltage >> 8);
|
||||
SOLAX_1876.data.u8[6] = (uint8_t)system_cell_min_voltage_mV; //TODO: scaling OK?
|
||||
SOLAX_1876.data.u8[7] = (system_cell_min_voltage_mV >> 8);
|
||||
|
||||
//Unknown
|
||||
SOLAX_1877.data.u8[4] = (uint8_t)0x50; // Battery type
|
||||
|
@ -201,11 +216,11 @@ 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[1] = ((battery_voltage) >> 8);
|
||||
SOLAX_1878.data.u8[0] = (uint8_t)(system_battery_voltage_dV); //TODO: should this be max or current voltage?
|
||||
SOLAX_1878.data.u8[1] = ((system_battery_voltage_dV) >> 8);
|
||||
|
||||
SOLAX_1878.data.u8[4] = (uint8_t)capacity_Wh; //TODO: scaling OK?
|
||||
SOLAX_1878.data.u8[5] = (capacity_Wh >> 8);
|
||||
SOLAX_1878.data.u8[4] = (uint8_t)capped_capacity_Wh; //TODO: scaling OK?
|
||||
SOLAX_1878.data.u8[5] = (capped_capacity_Wh >> 8);
|
||||
|
||||
// BMS_Answer
|
||||
SOLAX_1801.data.u8[0] = 2;
|
||||
|
|
|
@ -8,24 +8,27 @@
|
|||
|
||||
extern ACAN2515 can;
|
||||
|
||||
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 min_voltage;
|
||||
extern uint16_t max_voltage;
|
||||
extern uint16_t cell_max_voltage;
|
||||
extern uint16_t cell_min_voltage;
|
||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||
extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh
|
||||
extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0
|
||||
extern int16_t system_active_power_W; //W, -32000 to 32000
|
||||
extern int16_t system_battery_current_dA; //A+1, -1000 - 1000
|
||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000)
|
||||
extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||
extern uint16_t system_max_discharge_power_W; //W, 0-65000
|
||||
extern uint16_t system_max_charge_power_W; //W, 0-65000
|
||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
||||
extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||
extern uint16_t system_cellvoltages_mV[120]; //Array with all cell voltages in mV
|
||||
extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery
|
||||
extern uint8_t system_bms_status; //Enum 0-5
|
||||
extern bool batteryAllowsContactorClosing; //Bool, true/false
|
||||
extern bool inverterAllowsContactorClosing; //Bool, true/false
|
||||
|
||||
// Timeout in milliseconds
|
||||
#define SolaxTimeout 2000
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue