Add Relion battery protocol

This commit is contained in:
Daniel Öster 2025-08-20 12:58:45 +03:00
parent 10a60abd1a
commit 37f9d3e8f8
6 changed files with 133 additions and 0 deletions

View file

@ -35,6 +35,7 @@
//#define DALY_BMS //#define DALY_BMS
//#define RJXZS_BMS //#define RJXZS_BMS
//#define RANGE_ROVER_PHEV_BATTERY //#define RANGE_ROVER_PHEV_BATTERY
//#define RELION_BATTERY
//#define RENAULT_KANGOO_BATTERY //#define RENAULT_KANGOO_BATTERY
//#define RENAULT_TWIZY_BATTERY //#define RENAULT_TWIZY_BATTERY
//#define RENAULT_ZOE_GEN1_BATTERY //#define RENAULT_ZOE_GEN1_BATTERY

View file

@ -108,6 +108,8 @@ const char* name_for_battery_type(BatteryType type) {
return RjxzsBms::Name; return RjxzsBms::Name;
case BatteryType::RangeRoverPhev: case BatteryType::RangeRoverPhev:
return RangeRoverPhevBattery::Name; return RangeRoverPhevBattery::Name;
case BatteryType::RelionBattery:
return RelionBattery::Name;
case BatteryType::RenaultKangoo: case BatteryType::RenaultKangoo:
return RenaultKangooBattery::Name; return RenaultKangooBattery::Name;
case BatteryType::RenaultTwizy: case BatteryType::RenaultTwizy:
@ -209,6 +211,8 @@ Battery* create_battery(BatteryType type) {
return new RjxzsBms(); return new RjxzsBms();
case BatteryType::RangeRoverPhev: case BatteryType::RangeRoverPhev:
return new RangeRoverPhevBattery(); return new RangeRoverPhevBattery();
case BatteryType::RelionBattery:
return new RelionBattery();
case BatteryType::RenaultKangoo: case BatteryType::RenaultKangoo:
return new RenaultKangooBattery(); return new RenaultKangooBattery();
case BatteryType::RenaultTwizy: case BatteryType::RenaultTwizy:

View file

@ -39,6 +39,7 @@ void setup_can_shunt();
#include "ORION-BMS.h" #include "ORION-BMS.h"
#include "PYLON-BATTERY.h" #include "PYLON-BATTERY.h"
#include "RANGE-ROVER-PHEV-BATTERY.h" #include "RANGE-ROVER-PHEV-BATTERY.h"
#include "RELION-LV-BATTERY.h"
#include "RENAULT-KANGOO-BATTERY.h" #include "RENAULT-KANGOO-BATTERY.h"
#include "RENAULT-TWIZY.h" #include "RENAULT-TWIZY.h"
#include "RENAULT-ZOE-GEN1-BATTERY.h" #include "RENAULT-ZOE-GEN1-BATTERY.h"

View file

@ -45,6 +45,7 @@ enum class BatteryType {
MgHsPhev = 37, MgHsPhev = 37,
SamsungSdiLv = 38, SamsungSdiLv = 38,
HyundaiIoniq28 = 39, HyundaiIoniq28 = 39,
RelionBattery = 40,
Highest Highest
}; };

View file

@ -0,0 +1,83 @@
#include "RELION-LV-BATTERY.h"
#include "../battery/BATTERIES.h"
#include "../communication/can/comm_can.h"
#include "../datalayer/datalayer.h"
#include "../devboard/utils/events.h"
/*CAN Type:CAN2.0(Extended)
BPS:250kbps
Data Length: 8
Data Encoded Format:Motorola*/
void RelionBattery::update_values() {
datalayer.battery.status.real_soc = battery_soc * 100;
datalayer.battery.status.remaining_capacity_Wh = static_cast<uint32_t>(
(static_cast<double>(datalayer.battery.status.real_soc) / 10000) * datalayer.battery.info.total_capacity_Wh);
datalayer.battery.status.soh_pptt = battery_soh * 100;
datalayer.battery.status.voltage_dV = battery_total_voltage;
datalayer.battery.status.current_dA = battery_total_current; //Charging negative, discharge positive
datalayer.battery.status.max_charge_power_W =
((battery_total_voltage / 10) * charge_current_A); //90A recommended charge current
datalayer.battery.status.max_discharge_power_W =
((battery_total_voltage / 10) * discharge_current_A); //150A max continous discharge current
datalayer.battery.status.temperature_min_dC = max_cell_temperature * 10;
datalayer.battery.status.temperature_max_dC = max_cell_temperature * 10;
datalayer.battery.status.cell_max_voltage_mV = max_cell_voltage;
datalayer.battery.status.cell_min_voltage_mV = min_cell_voltage;
}
void RelionBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
switch (rx_frame.ID) {
case 0x02018100: //ID1
battery_total_voltage = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]);
break;
case 0x02028100: //ID2
battery_total_current = ((rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]);
system_state = rx_frame.data.u8[2];
battery_soc = rx_frame.data.u8[3];
battery_soh = rx_frame.data.u8[4];
most_serious_fault = rx_frame.data.u8[5];
break;
case 0x02038100: //ID3
max_cell_voltage = ((rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]);
min_cell_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]);
break;
case 0x02628100: //Temperatures
max_cell_temperature = rx_frame.data.u8[0] - 50;
min_cell_temperature = rx_frame.data.u8[2] - 50;
break;
case 0x02648100: //Charging limitis
charge_current_A = ((rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]) - 800;
regen_charge_current_A = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]) - 800;
discharge_current_A = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]) - 800;
break;
default:
break;
}
}
void RelionBattery::transmit_can(unsigned long currentMillis) {
// No periodic sending for this protocol
}
void RelionBattery::setup(void) { // Performs one time setup at startup
strncpy(datalayer.system.info.battery_protocol, Name, 63);
datalayer.system.info.battery_protocol[63] = '\0';
datalayer.battery.info.chemistry = LFP;
datalayer.battery.info.number_of_cells = 16;
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
datalayer.system.status.battery_allows_contactor_closing = true;
}

View file

@ -0,0 +1,43 @@
#ifndef RELION_BATTERY_H
#define RELION_BATTERY_H
#include "../system_settings.h"
#include "CanBattery.h"
#ifdef RELION_BATTERY
#define SELECTED_BATTERY_CLASS RelionBattery
#endif
class RelionBattery : public CanBattery {
public:
RelionBattery() : CanBattery(CAN_Speed::CAN_SPEED_250KBPS) {}
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr const char* Name = "Relion LV protocol via 250kbps CAN";
private:
static const int MAX_PACK_VOLTAGE_DV = 584; //58.4V recommended charge voltage. BMS protection steps in at 60.8V
static const int MIN_PACK_VOLTAGE_DV = 440; //44.0V Recommended LV disconnect. BMS protection steps in at 40.0V
static const int MAX_CELL_DEVIATION_MV = 300;
static const int MAX_CELL_VOLTAGE_MV = 3800; //Battery is put into emergency stop if one cell goes over this value
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
uint16_t battery_total_voltage = 500;
int16_t battery_total_current = 0;
uint8_t system_state = 0;
uint8_t battery_soc = 50;
uint8_t battery_soh = 99;
uint8_t most_serious_fault = 0;
uint16_t max_cell_voltage = 3300;
uint16_t min_cell_voltage = 3300;
int16_t max_cell_temperature = 0;
int16_t min_cell_temperature = 0;
int16_t charge_current_A = 0;
int16_t regen_charge_current_A = 0;
int16_t discharge_current_A = 0;
};
#endif