Renault Kangoo: Rescale SOC, current and power (#218)

* Rescale SOC, current and power + more testing tweaks
This commit is contained in:
Daniel Öster 2024-05-12 21:45:15 +03:00 committed by GitHub
parent e5c408fb7c
commit 30fb23b703
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 64 additions and 32 deletions

View file

@ -6,6 +6,20 @@
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
#include "RENAULT-KANGOO-BATTERY.h"
/* TODO:
There seems to be some values on the Kangoo that differ between the 22/33 kWh version
- Find some way to autodetect which Kangoo size we are working with
- Fix the mappings of values accordingly
- Values still need fixing
- SOC% is not valid on all packs
-Try to use the 7BB value?
- Max charge power is 0W on some packs
- SOH% is too high on some packs
- Add all cellvoltages from https://github.com/jamiejones85/Kangoo36_canDecode/tree/main
This page has info on the larger 33kWh pack: https://openinverter.org/wiki/Renault_Kangoo_36
*/
/* Do not change code below unless you are sure what you are doing */
static uint32_t LB_Battery_Voltage = 3700;
static uint32_t LB_Charge_Power_Limit_Watts = 0;
@ -21,9 +35,20 @@ static uint16_t LB_kWh_Remaining = 0;
static uint16_t LB_Cell_Max_Voltage = 3700;
static uint16_t LB_Cell_Min_Voltage = 3700;
static uint16_t cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
static uint16_t LB_MaxChargeAllowed_W = 0;
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
static uint8_t LB_Discharge_Power_Limit_Byte1 = 0;
static uint8_t GVI_Pollcounter = 0;
static uint8_t LB_EOCR = 0;
static uint8_t LB_HVBUV = 0;
static uint8_t LB_HVBIR = 0;
static uint8_t LB_CUV = 0;
static uint8_t LB_COV = 0;
static uint8_t LB_HVBOV = 0;
static uint8_t LB_HVBOT = 0;
static uint8_t LB_HVBOC = 0;
static uint8_t LB_MaxInput_kW = 0;
static uint8_t LB_MaxOutput_kW = 0;
static bool GVB_79B_Continue = false;
CAN_frame_t KANGOO_423 = {.FIR = {.B =
@ -32,7 +57,11 @@ CAN_frame_t KANGOO_423 = {.FIR = {.B =
.FF = CAN_frame_std,
}},
.MsgID = 0x423,
.data = {0x33, 0x00, 0xFF, 0xFF, 0x00, 0xE0, 0x00, 0x00}};
.data = {0x0B, 0x1D, 0x00, 0x02, 0xB2, 0x20, 0xB2, 0xD9}}; // Charging
// Driving: 0x07 0x1D 0x00 0x02 0x5D 0x80 0x5D 0xD8
// Charging: 0x0B 0x1D 0x00 0x02 0xB2 0x20 0xB2 0xD9
// Fastcharging: 0x07 0x1E 0x00 0x01 0x5D 0x20 0xB2 0xC7
// Old hardcoded message: .data = {0x33, 0x00, 0xFF, 0xFF, 0x00, 0xE0, 0x00, 0x00}};
CAN_frame_t KANGOO_79B = {.FIR = {.B =
{
.DLC = 8,
@ -53,15 +82,18 @@ static unsigned long previousMillis100 = 0; // will store last time a 100ms CA
static unsigned long previousMillis1000 = 0; // will store last time a 1000ms CAN Message was sent
static unsigned long GVL_pause = 0;
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters
datalayer.battery.status.real_soc = (LB_SOC * 10); //increase LB_SOC range from 0-100.0 -> 100.00
datalayer.battery.status.real_soc = (LB_SOC * 100); //increase LB_SOC range from 0-100 -> 100.00
datalayer.battery.status.soh_pptt = (LB_SOH * 100); //Increase range from 99% -> 99.00%
if (datalayer.battery.status.soh_pptt > 10000) { // Cap value if glitched out
datalayer.battery.status.soh_pptt = 10000;
}
datalayer.battery.status.voltage_dV = LB_Battery_Voltage;
datalayer.battery.status.current_dA = LB_Current;
datalayer.battery.status.current_dA = LB_Current * 10;
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);
@ -80,20 +112,15 @@ void update_values_battery() { //This function maps all the values fetched via
}
LB_Charge_Power_Limit_Watts = (LB_Charge_Power_Limit * 500); //Convert value fetched from battery to watts
/* Define power able to be put into the battery */
if (LB_Charge_Power_Limit_Watts > 60000) //if >60kW can be put into the battery
{
datalayer.battery.status.max_charge_power_W = 60000; //cap value so we don't go over the uint16 limit
//The above value is 0 on some packs. We instead estimate this now.
if (datalayer.battery.status.reported_soc == 10000) { // When scaled SOC is 100.00%, set allowed charge power to 0
datalayer.battery.status.max_charge_power_W = 0;
} else {
datalayer.battery.status.max_charge_power_W = LB_Charge_Power_Limit_Watts;
}
if (datalayer.battery.status.reported_soc == 10000) //Scaled SOC% value is 100.00%
{
datalayer.battery.status.max_charge_power_W = 0; //No need to charge further, set max power to 0
datalayer.battery.status.max_charge_power_W = MAX_CHARGE_POWER_W;
}
datalayer.battery.status.active_power_W =
(datalayer.battery.status.voltage_dV * LB_Current); //TODO: check if scaling is OK
((datalayer.battery.status.voltage_dV * datalayer.battery.status.current_dA) / 100);
datalayer.battery.status.temperature_min_dC = (LB_MIN_TEMPERATURE * 10);
@ -103,7 +130,7 @@ void update_values_battery() { //This function maps all the values fetched via
datalayer.battery.status.cell_max_voltage_mV = LB_Cell_Max_Voltage;
cell_deviation_mV = (datalayer.battery.status.temperature_max_dC - datalayer.battery.status.temperature_min_dC);
cell_deviation_mV = (datalayer.battery.status.cell_max_voltage_mV - datalayer.battery.status.cell_min_voltage_mV);
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
if (!CANstillAlive) {
@ -114,13 +141,13 @@ void update_values_battery() { //This function maps all the values fetched via
}
if (LB_Cell_Max_Voltage >= ABSOLUTE_CELL_MAX_VOLTAGE) {
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
set_event(EVENT_CELL_OVER_VOLTAGE, (LB_Cell_Max_Voltage / 20));
}
if (LB_Cell_Min_Voltage <= ABSOLUTE_CELL_MIN_VOLTAGE) {
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
set_event(EVENT_CELL_UNDER_VOLTAGE, (LB_Cell_Min_Voltage / 20));
}
if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) {
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
set_event(EVENT_CELL_DEVIATION_HIGH, (cell_deviation_mV / 20));
} else {
clear_event(EVENT_CELL_DEVIATION_HIGH);
}
@ -159,29 +186,35 @@ void update_values_battery() { //This function maps all the values fetched via
#endif
}
void receive_can_battery(CAN_frame_t rx_frame) //GKOE reworked
{
void receive_can_battery(CAN_frame_t rx_frame) {
switch (rx_frame.MsgID) {
case 0x155: //BMS1
CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS
LB_MaxChargeAllowed_W = (rx_frame.data.u8[0] * 300);
LB_Current = word((rx_frame.data.u8[1] & 0xF), rx_frame.data.u8[2]) * 0.25 - 500; //OK!
LB_SOC = ((rx_frame.data.u8[4] << 8) | (rx_frame.data.u8[5])) * 0.0025; //OK!
LB_SOC = ((rx_frame.data.u8[4] << 8) | (rx_frame.data.u8[5])) * 0.0025; //OK!
break;
case 0x424: //BMS2
CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS
LB_SOH = (rx_frame.data.u8[5]);
LB_EOCR = (rx_frame.data.u8[0] & 0x03);
LB_HVBUV = (rx_frame.data.u8[0] & 0x0C) >> 2;
LB_HVBIR = (rx_frame.data.u8[0] & 0x30) >> 4;
LB_CUV = (rx_frame.data.u8[0] & 0xC0) >> 6;
LB_COV = (rx_frame.data.u8[1] & 0x03);
LB_HVBOV = (rx_frame.data.u8[1] & 0x0C) >> 2;
LB_HVBOT = (rx_frame.data.u8[1] & 0x30) >> 4;
LB_HVBOC = (rx_frame.data.u8[1] & 0xC0) >> 6;
LB_MaxInput_kW = rx_frame.data.u8[2] / 2;
LB_MaxOutput_kW = rx_frame.data.u8[3] / 2;
LB_SOH = (rx_frame.data.u8[5]); // Only seems valid on Kangoo33?
LB_MIN_TEMPERATURE = ((rx_frame.data.u8[4]) - 40); //OK!
LB_MAX_TEMPERATURE = ((rx_frame.data.u8[7]) - 40); //OK!
break;
case 0x425:
CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS
LB_kWh_Remaining = word((rx_frame.data.u8[0] & 0x1), rx_frame.data.u8[1]) / 10; //OK!
break;
case 0x445:
CANstillAlive = 12; //Indicate that we are still getting CAN messages from the BMS
LB_Cell_Max_Voltage = 1000 + word((rx_frame.data.u8[3] & 0x1), rx_frame.data.u8[4]) * 10; //OK!

View file

@ -6,11 +6,10 @@
#define BATTERY_SELECTED
#define ABSOLUTE_CELL_MAX_VOLTAGE \
4100 // Max Cell Voltage mV! if voltage goes over this, charging is not possible (goes into forced discharge)
#define ABSOLUTE_CELL_MIN_VOLTAGE \
3000 // Min Cell Voltage mV! if voltage goes under this, discharging further is disabled
#define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value
#define ABSOLUTE_CELL_MAX_VOLTAGE 4150 // If cellvoltage goes over this mV, we go into FAULT mode
#define ABSOLUTE_CELL_MIN_VOLTAGE 2500 // If cellvoltage goes under this mV, we go into FAULT mode
#define MAX_CELL_DEVIATION_MV 500 // If cell mV delta exceeds this, we go into WARNING mode
#define MAX_CHARGE_POWER_W 5000 // Battery can be charged with this amount of power
void setup_battery(void);