mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-04 18:29:48 +02:00
BYD CAN inverter protocol class
This commit is contained in:
parent
2b608e48b9
commit
d934a3b796
5 changed files with 153 additions and 95 deletions
|
@ -1,91 +1,13 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#ifdef BYD_CAN
|
#ifdef BYD_CAN
|
||||||
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "BYD-CAN.h"
|
#include "BYD-CAN.h"
|
||||||
|
|
||||||
/* 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 previousMillis2s = 0; // will store last time a 2s CAN Message was send
|
|
||||||
static unsigned long previousMillis10s = 0; // will store last time a 10s CAN Message was send
|
|
||||||
static unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send
|
|
||||||
|
|
||||||
#define VOLTAGE_OFFSET_DV 20
|
void BydCanInverter::
|
||||||
|
update_values() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||||
CAN_frame BYD_250 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x250,
|
|
||||||
.data = {FW_MAJOR_VERSION, FW_MINOR_VERSION, 0x00, 0x66, (uint8_t)((BATTERY_WH_MAX / 100) >> 8),
|
|
||||||
(uint8_t)(BATTERY_WH_MAX / 100), 0x02,
|
|
||||||
0x09}}; //0-1 FW version , Capacity kWh byte4&5 (example 24kWh = 240)
|
|
||||||
CAN_frame BYD_290 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x290,
|
|
||||||
.data = {0x06, 0x37, 0x10, 0xD9, 0x00, 0x00, 0x00, 0x00}};
|
|
||||||
CAN_frame BYD_2D0 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x2D0,
|
|
||||||
.data = {0x00, 0x42, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00}}; //BYD
|
|
||||||
CAN_frame BYD_3D0_0 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x3D0,
|
|
||||||
.data = {0x00, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79}}; //Battery
|
|
||||||
CAN_frame BYD_3D0_1 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x3D0,
|
|
||||||
.data = {0x01, 0x2D, 0x42, 0x6F, 0x78, 0x20, 0x50, 0x72}}; //-Box Pr
|
|
||||||
CAN_frame BYD_3D0_2 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x3D0,
|
|
||||||
.data = {0x02, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x48}}; //emium H
|
|
||||||
CAN_frame BYD_3D0_3 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x3D0,
|
|
||||||
.data = {0x03, 0x56, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00}}; //VS
|
|
||||||
//Actual content messages
|
|
||||||
CAN_frame BYD_110 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x110,
|
|
||||||
.data = {0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
|
||||||
CAN_frame BYD_150 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x150,
|
|
||||||
.data = {0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00}};
|
|
||||||
CAN_frame BYD_190 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x190,
|
|
||||||
.data = {0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
|
||||||
CAN_frame BYD_1D0 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x1D0,
|
|
||||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08}};
|
|
||||||
CAN_frame BYD_210 = {.FD = false,
|
|
||||||
.ext_ID = false,
|
|
||||||
.DLC = 8,
|
|
||||||
.ID = 0x210,
|
|
||||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
|
||||||
|
|
||||||
static int16_t temperature_average = 0;
|
|
||||||
static uint16_t inverter_voltage = 0;
|
|
||||||
static uint16_t inverter_SOC = 0;
|
|
||||||
static int16_t inverter_current = 0;
|
|
||||||
static int16_t inverter_temperature = 0;
|
|
||||||
static uint16_t remaining_capacity_ah = 0;
|
|
||||||
static uint16_t fully_charged_capacity_ah = 0;
|
|
||||||
static long inverter_timestamp = 0;
|
|
||||||
static bool initialDataSent = false;
|
|
||||||
static bool inverterStartedUp = false;
|
|
||||||
|
|
||||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
|
||||||
|
|
||||||
/* Calculate temperature */
|
/* Calculate temperature */
|
||||||
temperature_average =
|
temperature_average =
|
||||||
|
@ -167,7 +89,7 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
||||||
BYD_210.data.u8[3] = (datalayer.battery.status.temperature_min_dC & 0x00FF);
|
BYD_210.data.u8[3] = (datalayer.battery.status.temperature_min_dC & 0x00FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
void BydCanInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
||||||
switch (rx_frame.ID) {
|
switch (rx_frame.ID) {
|
||||||
case 0x151: //Message originating from BYD HVS compatible inverter. Reply with CAN identifier!
|
case 0x151: //Message originating from BYD HVS compatible inverter. Reply with CAN identifier!
|
||||||
inverterStartedUp = true;
|
inverterStartedUp = true;
|
||||||
|
@ -204,7 +126,7 @@ void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transmit_can_inverter(unsigned long currentMillis) {
|
void BydCanInverter::transmit_can(unsigned long currentMillis) {
|
||||||
|
|
||||||
if (!inverterStartedUp) {
|
if (!inverterStartedUp) {
|
||||||
//Avoid sending messages towards inverter, unless it has woken up and sent something to us first
|
//Avoid sending messages towards inverter, unless it has woken up and sent something to us first
|
||||||
|
@ -239,7 +161,7 @@ void transmit_can_inverter(unsigned long currentMillis) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_intial_data() {
|
void BydCanInverter::send_intial_data() {
|
||||||
transmit_can_frame(&BYD_250, can_config.inverter);
|
transmit_can_frame(&BYD_250, can_config.inverter);
|
||||||
transmit_can_frame(&BYD_290, can_config.inverter);
|
transmit_can_frame(&BYD_290, can_config.inverter);
|
||||||
transmit_can_frame(&BYD_2D0, can_config.inverter);
|
transmit_can_frame(&BYD_2D0, can_config.inverter);
|
||||||
|
@ -248,7 +170,8 @@ void send_intial_data() {
|
||||||
transmit_can_frame(&BYD_3D0_2, can_config.inverter);
|
transmit_can_frame(&BYD_3D0_2, can_config.inverter);
|
||||||
transmit_can_frame(&BYD_3D0_3, can_config.inverter);
|
transmit_can_frame(&BYD_3D0_3, can_config.inverter);
|
||||||
}
|
}
|
||||||
void setup_inverter(void) { // Performs one time setup at startup over CAN bus
|
|
||||||
|
void BydCanInverter::setup(void) { // Performs one time setup at startup over CAN bus
|
||||||
strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box Premium HVS over CAN Bus", 63);
|
strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box Premium HVS over CAN Bus", 63);
|
||||||
datalayer.system.info.inverter_protocol[63] = '\0';
|
datalayer.system.info.inverter_protocol[63] = '\0';
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,101 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
|
|
||||||
#define CAN_INVERTER_SELECTED
|
#define CAN_INVERTER_SELECTED
|
||||||
|
#define SELECTED_INVERTER_CLASS BydCanInverter
|
||||||
|
|
||||||
#define FW_MAJOR_VERSION 0x03
|
#define FW_MAJOR_VERSION 0x03
|
||||||
#define FW_MINOR_VERSION 0x29
|
#define FW_MINOR_VERSION 0x29
|
||||||
|
|
||||||
void send_intial_data();
|
class BydCanInverter : public CanInverterProtocol {
|
||||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
public:
|
||||||
void setup_inverter(void);
|
void setup();
|
||||||
|
void send_intial_data();
|
||||||
|
void transmit_can(unsigned long currentMillis);
|
||||||
|
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_values();
|
||||||
|
|
||||||
|
unsigned long previousMillis2s = 0; // will store last time a 2s CAN Message was send
|
||||||
|
unsigned long previousMillis10s = 0; // will store last time a 10s CAN Message was send
|
||||||
|
unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send
|
||||||
|
|
||||||
|
#define VOLTAGE_OFFSET_DV 20
|
||||||
|
|
||||||
|
CAN_frame BYD_250 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x250,
|
||||||
|
.data = {FW_MAJOR_VERSION, FW_MINOR_VERSION, 0x00, 0x66, (uint8_t)((BATTERY_WH_MAX / 100) >> 8),
|
||||||
|
(uint8_t)(BATTERY_WH_MAX / 100), 0x02,
|
||||||
|
0x09}}; //0-1 FW version , Capacity kWh byte4&5 (example 24kWh = 240)
|
||||||
|
CAN_frame BYD_290 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x290,
|
||||||
|
.data = {0x06, 0x37, 0x10, 0xD9, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
CAN_frame BYD_2D0 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x2D0,
|
||||||
|
.data = {0x00, 0x42, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00}}; //BYD
|
||||||
|
CAN_frame BYD_3D0_0 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x3D0,
|
||||||
|
.data = {0x00, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79}}; //Battery
|
||||||
|
CAN_frame BYD_3D0_1 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x3D0,
|
||||||
|
.data = {0x01, 0x2D, 0x42, 0x6F, 0x78, 0x20, 0x50, 0x72}}; //-Box Pr
|
||||||
|
CAN_frame BYD_3D0_2 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x3D0,
|
||||||
|
.data = {0x02, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x48}}; //emium H
|
||||||
|
CAN_frame BYD_3D0_3 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x3D0,
|
||||||
|
.data = {0x03, 0x56, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00}}; //VS
|
||||||
|
//Actual content messages
|
||||||
|
CAN_frame BYD_110 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x110,
|
||||||
|
.data = {0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
CAN_frame BYD_150 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x150,
|
||||||
|
.data = {0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00}};
|
||||||
|
CAN_frame BYD_190 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x190,
|
||||||
|
.data = {0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
CAN_frame BYD_1D0 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x1D0,
|
||||||
|
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08}};
|
||||||
|
CAN_frame BYD_210 = {.FD = false,
|
||||||
|
.ext_ID = false,
|
||||||
|
.DLC = 8,
|
||||||
|
.ID = 0x210,
|
||||||
|
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||||
|
|
||||||
|
int16_t temperature_average = 0;
|
||||||
|
uint16_t inverter_voltage = 0;
|
||||||
|
uint16_t inverter_SOC = 0;
|
||||||
|
int16_t inverter_current = 0;
|
||||||
|
int16_t inverter_temperature = 0;
|
||||||
|
uint16_t remaining_capacity_ah = 0;
|
||||||
|
uint16_t fully_charged_capacity_ah = 0;
|
||||||
|
long inverter_timestamp = 0;
|
||||||
|
bool initialDataSent = false;
|
||||||
|
bool inverterStartedUp = false;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
|
|
||||||
#define MODBUS_INVERTER_SELECTED
|
#define MODBUS_INVERTER_SELECTED
|
||||||
#define OO_INVERTER_PROTOCOL_SELECTED
|
#define SELECTED_INVERTER_CLASS BydModbusInverter
|
||||||
|
|
||||||
#define MB_RTU_NUM_VALUES 13100
|
#define MB_RTU_NUM_VALUES 13100
|
||||||
#define MAX_POWER 40960 //BYD Modbus specific value
|
#define MAX_POWER 40960 //BYD Modbus specific value
|
||||||
|
|
|
@ -3,22 +3,54 @@
|
||||||
// These functions adapt the old C-style global functions inverter-API to the
|
// These functions adapt the old C-style global functions inverter-API to the
|
||||||
// object-oriented inverter protocol API.
|
// object-oriented inverter protocol API.
|
||||||
|
|
||||||
#ifdef OO_INVERTER_PROTOCOL_SELECTED
|
#ifdef SELECTED_INVERTER_CLASS
|
||||||
|
|
||||||
ModbusInverterProtocol* inverter;
|
InverterProtocol* inverter;
|
||||||
|
|
||||||
|
#ifdef CAN_INVERTER_SELECTED
|
||||||
|
CanInverterProtocol* can_inverter;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODBUS_INVERTER_SELECTED
|
||||||
|
ModbusInverterProtocol* modbus_inverter;
|
||||||
|
#endif
|
||||||
|
|
||||||
void setup_inverter() {
|
void setup_inverter() {
|
||||||
// Currently only a single inverter protocol is implemented as a class
|
#ifdef MODBUS_INVERTER_SELECTED
|
||||||
inverter = new BydModbusInverter();
|
modbus_inverter = new SELECTED_INVERTER_CLASS();
|
||||||
|
inverter = modbus_inverter;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CAN_INVERTER_SELECTED
|
||||||
|
can_inverter = new SELECTED_INVERTER_CLASS();
|
||||||
|
inverter = can_inverter;
|
||||||
|
#endif
|
||||||
|
|
||||||
inverter->setup();
|
inverter->setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODBUS_INVERTER_SELECTED
|
||||||
void update_modbus_registers_inverter() {
|
void update_modbus_registers_inverter() {
|
||||||
inverter->update_modbus_registers();
|
modbus_inverter->update_modbus_registers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_static_data_modbus() {
|
void handle_static_data_modbus() {
|
||||||
inverter->handle_static_data();
|
modbus_inverter->handle_static_data();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CAN_INVERTER_SELECTED
|
||||||
|
void update_values_can_inverter() {
|
||||||
|
can_inverter->update_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
||||||
|
can_inverter->map_can_frame_to_variable(rx_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transmit_can_inverter(unsigned long currentMillis) {
|
||||||
|
can_inverter->transmit_can(currentMillis);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,18 @@ class ModbusInverterProtocol : public InverterProtocol {
|
||||||
virtual void handle_static_data();
|
virtual void handle_static_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CanInverterProtocol : public InverterProtocol {
|
||||||
|
public:
|
||||||
|
virtual void send_intial_data() = 0;
|
||||||
|
|
||||||
|
//This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||||
|
virtual void update_values() = 0;
|
||||||
|
|
||||||
|
virtual void transmit_can(unsigned long currentMillis) = 0;
|
||||||
|
|
||||||
|
virtual void map_can_frame_to_variable(CAN_frame rx_frame) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../../USER_SETTINGS.h"
|
||||||
|
|
||||||
#ifdef AFORE_CAN
|
#ifdef AFORE_CAN
|
||||||
|
@ -96,6 +108,7 @@ class ModbusInverterProtocol : public InverterProtocol {
|
||||||
void update_values_can_inverter();
|
void update_values_can_inverter();
|
||||||
void map_can_frame_to_variable_inverter(CAN_frame rx_frame);
|
void map_can_frame_to_variable_inverter(CAN_frame rx_frame);
|
||||||
void transmit_can_inverter(unsigned long currentMillis);
|
void transmit_can_inverter(unsigned long currentMillis);
|
||||||
|
void setup_inverter();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODBUS_INVERTER_SELECTED
|
#ifdef MODBUS_INVERTER_SELECTED
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue