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