mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 19:42:08 +02:00
Convert Solax inverter to use the base class
This commit is contained in:
parent
09e719690f
commit
4c09166b9e
2 changed files with 117 additions and 106 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "../include.h"
|
||||
#ifdef SOLAX_CAN
|
||||
#include "../communication/can/comm_can.h"
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "SOLAX-CAN.h"
|
||||
|
@ -9,104 +10,13 @@
|
|||
// If you are having BattVoltFault issues, configure the above values according to wiki page
|
||||
// https://github.com/dalathegreat/Battery-Emulator/wiki/Solax-inverters
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static int16_t temperature_average = 0;
|
||||
static uint8_t STATE = BATTERY_ANNOUNCE;
|
||||
static unsigned long LastFrameTime = 0;
|
||||
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
|
||||
|
||||
CAN_frame SOLAX_1801 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1801,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1872 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1872,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_Limits
|
||||
CAN_frame SOLAX_1873 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1873,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_PackData
|
||||
CAN_frame SOLAX_1874 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1874,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_CellData
|
||||
CAN_frame SOLAX_1875 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1875,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_Status
|
||||
CAN_frame SOLAX_1876 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1876,
|
||||
.data = {0x0, 0x0, 0xE2, 0x0C, 0x0, 0x0, 0xD7, 0x0C}}; //BMS_PackTemps
|
||||
CAN_frame SOLAX_1877 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1877,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1878 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1878,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_PackStats
|
||||
CAN_frame SOLAX_1879 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1879,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187E = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187E,
|
||||
.data = {0x60, 0xEA, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187D = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187D,
|
||||
.data = {0x8B, 0x01, 0x0, 0x0, 0x8B, 0x1, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187C = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187C,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187B = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187B,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187A = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187A,
|
||||
.data = {0x01, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1881 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1881,
|
||||
.data = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; // E.g.: 0 6 S B M S F A
|
||||
CAN_frame SOLAX_1882 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1882,
|
||||
.data = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; // E.g.: 0 2 3 A B 0 5 2
|
||||
CAN_frame SOLAX_100A001 = {.FD = false, .ext_ID = true, .DLC = 0, .ID = 0x100A001, .data = {}};
|
||||
|
||||
// __builtin_bswap64 needed to convert to ESP32 little endian format
|
||||
// Byte[4] defines the requested contactor state: 1 = Closed , 0 = Open
|
||||
#define Contactor_Open_Payload __builtin_bswap64(0x0200010000000000)
|
||||
#define Contactor_Close_Payload __builtin_bswap64(0x0200010001000000)
|
||||
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void SolaxInverter::
|
||||
update_values() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
// If not receiveing any communication from the inverter, open contactors and return to battery announce state
|
||||
if (millis() - LastFrameTime >= SolaxTimeout) {
|
||||
datalayer.system.status.inverter_allows_contactor_closing = false;
|
||||
|
@ -206,11 +116,11 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
|||
SOLAX_187E.data.u8[5] = (uint8_t)(datalayer.battery.status.reported_soc / 100);
|
||||
}
|
||||
|
||||
void transmit_can_inverter(unsigned long currentMillis) {
|
||||
void SolaxInverter::transmit_can(unsigned long currentMillis) {
|
||||
// No periodic sending used on this protocol, we react only on incoming CAN messages!
|
||||
}
|
||||
|
||||
void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
||||
void SolaxInverter::map_can_frame_to_variable(CAN_frame rx_frame) {
|
||||
|
||||
if (rx_frame.ID == 0x1871) {
|
||||
datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE;
|
||||
|
@ -297,7 +207,8 @@ void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
void setup_inverter(void) { // Performs one time setup at startup
|
||||
|
||||
void SolaxInverter::setup(void) { // Performs one time setup at startup
|
||||
strncpy(datalayer.system.info.inverter_protocol, "SolaX Triple Power LFP over CAN bus", 63);
|
||||
datalayer.system.info.inverter_protocol[63] = '\0';
|
||||
datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first
|
||||
|
|
|
@ -2,19 +2,119 @@
|
|||
#define SOLAX_CAN_H
|
||||
#include "../include.h"
|
||||
|
||||
#include "CanInverterProtocol.h"
|
||||
|
||||
#define CAN_INVERTER_SELECTED
|
||||
#define SELECTED_INVERTER_CLASS SolaxInverter
|
||||
|
||||
// Timeout in milliseconds
|
||||
#define SolaxTimeout 2000
|
||||
class SolaxInverter : public CanInverterProtocol {
|
||||
public:
|
||||
void setup();
|
||||
void update_values();
|
||||
void transmit_can(unsigned long currentMillis);
|
||||
void map_can_frame_to_variable(CAN_frame rx_frame);
|
||||
|
||||
//SOLAX BMS States Definition
|
||||
#define BATTERY_ANNOUNCE 0
|
||||
#define WAITING_FOR_CONTACTOR 1
|
||||
#define CONTACTOR_CLOSED 2
|
||||
#define FAULT_SOLAX 3
|
||||
#define UPDATING_FW 4
|
||||
private:
|
||||
// Timeout in milliseconds
|
||||
static const int SolaxTimeout = 2000;
|
||||
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||
void setup_inverter(void);
|
||||
//SOLAX BMS States Definition
|
||||
static const int BATTERY_ANNOUNCE = 0;
|
||||
static const int WAITING_FOR_CONTACTOR = 1;
|
||||
static const int CONTACTOR_CLOSED = 2;
|
||||
static const int FAULT_SOLAX = 3;
|
||||
static const int UPDATING_FW = 4;
|
||||
|
||||
int16_t temperature_average = 0;
|
||||
uint8_t STATE = BATTERY_ANNOUNCE;
|
||||
unsigned long LastFrameTime = 0;
|
||||
uint8_t number_of_batteries = 1;
|
||||
uint16_t capped_capacity_Wh;
|
||||
uint16_t capped_remaining_capacity_Wh;
|
||||
|
||||
//CAN message translations from this amazing repository: https://github.com/rand12345/solax_can_bus
|
||||
|
||||
CAN_frame SOLAX_1801 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1801,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1872 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1872,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_Limits
|
||||
CAN_frame SOLAX_1873 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1873,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_PackData
|
||||
CAN_frame SOLAX_1874 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1874,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_CellData
|
||||
CAN_frame SOLAX_1875 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1875,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_Status
|
||||
CAN_frame SOLAX_1876 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1876,
|
||||
.data = {0x0, 0x0, 0xE2, 0x0C, 0x0, 0x0, 0xD7, 0x0C}}; //BMS_PackTemps
|
||||
CAN_frame SOLAX_1877 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1877,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1878 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1878,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; //BMS_PackStats
|
||||
CAN_frame SOLAX_1879 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1879,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187E = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187E,
|
||||
.data = {0x60, 0xEA, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187D = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187D,
|
||||
.data = {0x8B, 0x01, 0x0, 0x0, 0x8B, 0x1, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187C = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187C,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187B = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187B,
|
||||
.data = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_187A = {.FD = false, //Needed for Ultra
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x187A,
|
||||
.data = {0x01, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
CAN_frame SOLAX_1881 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1881,
|
||||
.data = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; // E.g.: 0 6 S B M S F A
|
||||
CAN_frame SOLAX_1882 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 8,
|
||||
.ID = 0x1882,
|
||||
.data = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; // E.g.: 0 2 3 A B 0 5 2
|
||||
CAN_frame SOLAX_100A001 = {.FD = false, .ext_ID = true, .DLC = 0, .ID = 0x100A001, .data = {}};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue