mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
fixed blocking delay() and added battery nominal voltage
This commit is contained in:
parent
a3058b3fa5
commit
a2f5e33eaf
3 changed files with 21 additions and 17 deletions
|
@ -88,6 +88,8 @@
|
||||||
#define BATTERY_MAX_CHARGE_AMP 300
|
#define BATTERY_MAX_CHARGE_AMP 300
|
||||||
// 300 = 30.0A , BYD CAN specific setting, Max discharge in Amp (Some inverters needs to be limited)
|
// 300 = 30.0A , BYD CAN specific setting, Max discharge in Amp (Some inverters needs to be limited)
|
||||||
#define BATTERY_MAX_DISCHARGE_AMP 300
|
#define BATTERY_MAX_DISCHARGE_AMP 300
|
||||||
|
// Battery nominal voltage dV
|
||||||
|
#define BATTERY_NOMINAL_VOLTAGE 3600
|
||||||
|
|
||||||
/* Do not change any code below this line unless you are sure what you are doing */
|
/* Do not change any code below this line unless you are sure what you are doing */
|
||||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
||||||
|
|
|
@ -17,6 +17,8 @@ typedef struct {
|
||||||
uint16_t max_charge_amp_dA = BATTERY_MAX_CHARGE_AMP;
|
uint16_t max_charge_amp_dA = BATTERY_MAX_CHARGE_AMP;
|
||||||
/** BYD CAN specific setting, max discharge in deciAmpere. 300 = 30.0 A */
|
/** BYD CAN specific setting, max discharge in deciAmpere. 300 = 30.0 A */
|
||||||
uint16_t max_discharge_amp_dA = BATTERY_MAX_DISCHARGE_AMP;
|
uint16_t max_discharge_amp_dA = BATTERY_MAX_DISCHARGE_AMP;
|
||||||
|
/** Kostal specific setting, */
|
||||||
|
uint16_t nominal_dV = BATTERY_NOMINAL_VOLTAGE ;
|
||||||
|
|
||||||
/** uint8_t */
|
/** uint8_t */
|
||||||
/** Total number of cells in the pack */
|
/** Total number of cells in the pack */
|
||||||
|
|
|
@ -15,6 +15,8 @@ static int16_t average_temperature_dC = 0;
|
||||||
static uint8_t incoming_message_counter = RS485_HEALTHY;
|
static uint8_t incoming_message_counter = RS485_HEALTHY;
|
||||||
static int8_t f2_startup_count = 0;
|
static int8_t f2_startup_count = 0;
|
||||||
|
|
||||||
|
static boolean B1_delay = false;
|
||||||
|
static unsigned long B1_last_millis = 0;
|
||||||
|
|
||||||
union f32b {
|
union f32b {
|
||||||
float f;
|
float f;
|
||||||
|
@ -154,8 +156,6 @@ bool check_kostal_frame_crc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void update_RS485_registers_inverter() {
|
void update_RS485_registers_inverter() {
|
||||||
|
|
||||||
if (datalayer.battery.status.voltage_dV > 10) { // Only update value when we have voltage available to avoid div0
|
if (datalayer.battery.status.voltage_dV > 10) { // Only update value when we have voltage available to avoid div0
|
||||||
|
@ -172,7 +172,6 @@ void update_RS485_registers_inverter() {
|
||||||
discharge_current_dA = (discharge_current_dA * 10); //Value needs a decimal before getting sent to inverter (81.0A)
|
discharge_current_dA = (discharge_current_dA * 10); //Value needs a decimal before getting sent to inverter (81.0A)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (charge_current_dA > datalayer.battery.info.max_charge_amp_dA) {
|
if (charge_current_dA > datalayer.battery.info.max_charge_amp_dA) {
|
||||||
charge_current_dA =
|
charge_current_dA =
|
||||||
datalayer.battery.info
|
datalayer.battery.info
|
||||||
|
@ -191,8 +190,6 @@ void update_RS485_registers_inverter() {
|
||||||
average_temperature_dC = 0;
|
average_temperature_dC = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (f2_startup_count>8)
|
if (f2_startup_count>8)
|
||||||
{
|
{
|
||||||
float2frame(frame2, (float)datalayer.battery.status.voltage_dV / 10, 6); // Confirmed OK mapping
|
float2frame(frame2, (float)datalayer.battery.status.voltage_dV / 10, 6); // Confirmed OK mapping
|
||||||
|
@ -204,7 +201,7 @@ void update_RS485_registers_inverter() {
|
||||||
frame2[0]=0x06;
|
frame2[0]=0x06;
|
||||||
float2frame(frame2, 0.0, 6);
|
float2frame(frame2, 0.0, 6);
|
||||||
}
|
}
|
||||||
float2frameMSB(frame1, (float)datalayer.battery.status.voltage_dV / 10, 8); // This shall be nominal voltage, but not available
|
float2frameMSB(frame1, (float)datalayer.battery.info.nominal_dV / 10, 8);
|
||||||
|
|
||||||
float2frameMSB(frame2, (float)datalayer.battery.info.max_design_voltage_dV / 10, 12);
|
float2frameMSB(frame2, (float)datalayer.battery.info.max_design_voltage_dV / 10, 12);
|
||||||
|
|
||||||
|
@ -268,12 +265,19 @@ static uint8_t rx_index = 0;
|
||||||
|
|
||||||
void receive_RS485() // Runs as fast as possible to handle the serial stream
|
void receive_RS485() // Runs as fast as possible to handle the serial stream
|
||||||
{
|
{
|
||||||
if (Serial2.available()) {
|
unsigned long currentMillis = millis();
|
||||||
|
if(B1_delay)
|
||||||
|
{
|
||||||
|
if ((currentMillis - B1_last_millis) >1000)
|
||||||
|
{
|
||||||
|
send_kostal(frameB1b, 8);
|
||||||
|
B1_delay=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Serial2.available()) {
|
||||||
RS485_RXFRAME[rx_index] = Serial2.read();
|
RS485_RXFRAME[rx_index] = Serial2.read();
|
||||||
rx_index++;
|
rx_index++;
|
||||||
if (RS485_RXFRAME[rx_index - 1] == 0x00) {
|
if (RS485_RXFRAME[rx_index - 1] == 0x00) {
|
||||||
|
|
||||||
|
|
||||||
if ((rx_index == 10) && (RS485_RXFRAME[0] == 0x09) && register_content_ok) {
|
if ((rx_index == 10) && (RS485_RXFRAME[0] == 0x09) && register_content_ok) {
|
||||||
#ifdef DEBUG_KOSTAL_RS485_DATA
|
#ifdef DEBUG_KOSTAL_RS485_DATA
|
||||||
Serial.print("RX: ");
|
Serial.print("RX: ");
|
||||||
|
@ -300,31 +304,27 @@ void receive_RS485() // Runs as fast as possible to handle the serial stream
|
||||||
// "frame B1", maybe reset request, seen after battery power on/partial data
|
// "frame B1", maybe reset request, seen after battery power on/partial data
|
||||||
if (headerB && (RS485_RXFRAME[6] == 0x5E) && (RS485_RXFRAME[7] == 0xFF)) {
|
if (headerB && (RS485_RXFRAME[6] == 0x5E) && (RS485_RXFRAME[7] == 0xFF)) {
|
||||||
send_kostal(frameB1, 10);
|
send_kostal(frameB1, 10);
|
||||||
Serial2.flush();
|
B1_delay=true;
|
||||||
delay(1);
|
B1_last_millis=currentMillis;
|
||||||
send_kostal(frameB1b, 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// "frame B1", maybe reset request, seen after battery power on/partial data
|
// "frame B1", maybe reset request, seen after battery power on/partial data
|
||||||
if (headerB && (RS485_RXFRAME[6] == 0x5E) && (RS485_RXFRAME[7] == 0x04)) {
|
if (headerB && (RS485_RXFRAME[6] == 0x5E) && (RS485_RXFRAME[7] == 0x04)) {
|
||||||
send_kostal(frame4, 8);
|
send_kostal(frame4, 8);
|
||||||
datalayer.system.status.inverter_allows_contactor_closing = false;
|
// This needs more reverse engineering, disabled...
|
||||||
Serial2.flush();
|
// datalayer.system.status.inverter_allows_contactor_closing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headerA && (RS485_RXFRAME[6] == 0x4A) && (RS485_RXFRAME[7] == 0x08)) { // "frame 1"
|
if (headerA && (RS485_RXFRAME[6] == 0x4A) && (RS485_RXFRAME[7] == 0x08)) { // "frame 1"
|
||||||
send_kostal(frame1, 40);
|
send_kostal(frame1, 40);
|
||||||
}
|
}
|
||||||
if (headerA && (RS485_RXFRAME[6] == 0x4A) && (RS485_RXFRAME[7] == 0x04)) { // "frame 2"
|
if (headerA && (RS485_RXFRAME[6] == 0x4A) && (RS485_RXFRAME[7] == 0x04)) { // "frame 2"
|
||||||
|
|
||||||
update_values_battery();
|
update_values_battery();
|
||||||
update_RS485_registers_inverter();
|
update_RS485_registers_inverter();
|
||||||
if (f2_startup_count<15)
|
if (f2_startup_count<15)
|
||||||
{
|
{
|
||||||
f2_startup_count++;
|
f2_startup_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte tmpframe[64]; //copy values to prevent data manipulation during rewrite/crc calculation
|
byte tmpframe[64]; //copy values to prevent data manipulation during rewrite/crc calculation
|
||||||
memcpy(tmpframe, frame2, 64);
|
memcpy(tmpframe, frame2, 64);
|
||||||
for (int i = 1; i < 63; i++) {
|
for (int i = 1; i < 63; i++) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue