mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Merge pull request #33 from dalathegreat/i-miev-support
Add initial imiev support
This commit is contained in:
commit
f4349e4ae6
4 changed files with 215 additions and 3 deletions
|
@ -13,6 +13,10 @@
|
|||
#include "RENAULT-ZOE-BATTERY.h" //See this file for more Zoe battery settings
|
||||
#endif
|
||||
|
||||
#ifdef IMIEV_ION_CZERO_BATTERY
|
||||
#include "IMIEV-CZERO-ION-BATTERY.h" //See this file for more triplet battery settings
|
||||
#endif
|
||||
|
||||
#ifdef CHADEMO
|
||||
#include "CHADEMO-BATTERY.h" //See this file for more Chademo settings
|
||||
#endif
|
||||
|
|
154
Software/IMIEV-CZERO-ION-BATTERY.cpp
Normal file
154
Software/IMIEV-CZERO-ION-BATTERY.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||
#include "ESP32CAN.h"
|
||||
#include "CAN_config.h"
|
||||
|
||||
//Code still very WIP
|
||||
//TODO: Add CMU warning incase we detect a direct connection to the CMUs. It wont be safe to use the battery in this mode
|
||||
//Map the missing values
|
||||
//Check scaling of all values
|
||||
//Generate messages towards BMU to keep it happy?
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
#define BMU_MAX_SOC 1000 //BMS never goes over this value. We use this info to rescale SOC% sent to inverter
|
||||
#define BMU_MIN_SOC 0 //BMS never goes below this value. We use this info to rescale SOC% sent to inverter
|
||||
static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive
|
||||
static uint8_t errorCode = 0; //stores if we have an error code active from battery control logic
|
||||
static uint8_t BMU_Detected = 0;
|
||||
static uint8_t CMU_Detected = 0;
|
||||
|
||||
static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN Message was sent
|
||||
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was sent
|
||||
static const int interval10 = 10; // interval (ms) at which send CAN Messages
|
||||
static const int interval100 = 100; // interval (ms) at which send CAN Messages
|
||||
|
||||
static int pid_index = 0;
|
||||
static int cmu_id = 0;
|
||||
static int voltage_index = 0;
|
||||
static int temp_index = 0;
|
||||
static int BMU_SOC = 0;
|
||||
static double temp1 = 0;
|
||||
static double temp2 = 0;
|
||||
static double temp3 = 0;
|
||||
static double voltage1 = 0;
|
||||
static double voltage2 = 0;
|
||||
static double BMU_Current = 0;
|
||||
static double BMU_PackVoltage = 0;
|
||||
static double BMU_Power = 0;
|
||||
static uint16_t cell_voltages[89]; //array with all the cellvoltages //Todo, what is max array size? 80/88 cells?
|
||||
static uint16_t cell_temperatures[89]; //array with all the celltemperatures //Todo, what is max array size? 80/88cells?
|
||||
|
||||
|
||||
void update_values_imiev_battery()
|
||||
{ //This function maps all the values fetched via CAN to the correct parameters used for modbus
|
||||
bms_status = ACTIVE; //Startout in active mode
|
||||
|
||||
SOC = BMU_SOC; //Todo, scaling?
|
||||
|
||||
battery_voltage = (BMU_PackVoltage*10); //Todo, scaling?
|
||||
|
||||
battery_current = (BMU_Current*10); //Todo, scaling?
|
||||
|
||||
capacity_Wh = BATTERY_WH_MAX; //Hardcoded to header value
|
||||
|
||||
remaining_capacity_Wh = (SOC/100)*capacity_Wh;
|
||||
|
||||
max_target_charge_power; //TODO, map
|
||||
|
||||
max_target_discharge_power; //TODO, map
|
||||
|
||||
stat_batt_power = BMU_Power; //TODO, Scaling?
|
||||
|
||||
temperature_min; //TODO, map
|
||||
|
||||
temperature_max; //TODO, map
|
||||
|
||||
/* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/
|
||||
if(!CANstillAlive)
|
||||
{
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
}
|
||||
else
|
||||
{
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
||||
if(printValues)
|
||||
{ //values heading towards the modbus registers
|
||||
Serial.print("BMU SOC: ");
|
||||
Serial.println(BMU_SOC);
|
||||
Serial.print("BMU Current: ");
|
||||
Serial.println(BMU_Current);
|
||||
Serial.print("BMU Battery Voltage: ");
|
||||
Serial.println(BMU_PackVoltage);
|
||||
}
|
||||
}
|
||||
|
||||
void receive_can_imiev_battery(CAN_frame_t rx_frame)
|
||||
{
|
||||
switch (rx_frame.MsgID)
|
||||
{
|
||||
CANstillAlive = 12; //Todo, move this inside a known message ID to prevent CAN inverter from keeping battery alive detection going
|
||||
case 0x374: //BMU message, 10ms - SOC
|
||||
BMU_SOC = ((rx_frame.data.u8[1] - 10) / 2);
|
||||
break;
|
||||
case 0x373: //BMU message, 100ms - Pack Voltage and current
|
||||
BMU_Current = ((((((rx_frame.data.u8[2] * 256.0) + rx_frame.data.u8[3])) - 32768)) * 0.01);
|
||||
BMU_PackVoltage = ((rx_frame.data.u8[4] * 256.0 + rx_frame.data.u8[5]) * 0.1);
|
||||
BMU_Power = (BMU_Current * BMU_PackVoltage);
|
||||
break;
|
||||
case 0x6e1: //BMU message, 25ms - Battery temperatures and voltages
|
||||
case 0x6e2:
|
||||
case 0x6e3:
|
||||
case 0x6e4:
|
||||
BMU_Detected = 1;
|
||||
//Pid index 0-3
|
||||
pid_index = (rx_frame.MsgID) - 1761;
|
||||
//cmu index 1-12: ignore high order nibble which appears to sometimes contain other status bits
|
||||
cmu_id = (rx_frame.data.u8[0] & 0x0f);
|
||||
//
|
||||
temp1 = rx_frame.data.u8[1] - 50.0;
|
||||
temp2 = rx_frame.data.u8[2] - 50.0;
|
||||
temp3 = rx_frame.data.u8[3] - 50.0;
|
||||
|
||||
voltage1 = (((rx_frame.data.u8[4] * 256.0 + rx_frame.data.u8[5]) * 0.005) + 2.1);
|
||||
voltage2 = (((rx_frame.data.u8[6] * 256.0 + rx_frame.data.u8[7]) * 0.005) + 2.1);
|
||||
|
||||
voltage_index = ((cmu_id - 1) * 8 + (2 * pid_index));
|
||||
temp_index = ((cmu_id - 1) * 6 + (2 * pid_index));
|
||||
if (cmu_id >= 7)
|
||||
{
|
||||
voltage_index -= 4;
|
||||
temp_index -= 3;
|
||||
}
|
||||
cell_voltages[voltage_index] = voltage1;
|
||||
cell_voltages[voltage_index + 1] = voltage2;
|
||||
|
||||
if (pid_index == 0)
|
||||
{
|
||||
cell_temperatures[temp_index] = temp2;
|
||||
cell_temperatures[temp_index + 1] = temp3;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell_temperatures[temp_index] = temp1;
|
||||
if (cmu_id != 6 && cmu_id != 12)
|
||||
{
|
||||
cell_temperatures[temp_index + 1] = temp2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_imiev_battery()
|
||||
{
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100)
|
||||
{
|
||||
previousMillis100 = currentMillis;
|
||||
}
|
||||
}
|
40
Software/IMIEV-CZERO-ION-BATTERY.h
Normal file
40
Software/IMIEV-CZERO-ION-BATTERY.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef IMIEV_CZERO_ION_BATTERY_H
|
||||
#define IMIEV_CZERO_ION_BATTERY_H
|
||||
#include <Arduino.h>
|
||||
#include "ESP32CAN.h"
|
||||
|
||||
#define BATTERY_WH_MAX 22000 //Battery size in Wh (Maximum value Fronius accepts is 60000 [60kWh] you can use larger batteries but do set value over 60000
|
||||
#define ABSOLUTE_MAX_VOLTAGE 4040 // 404.4V,if battery voltage goes over this, charging is not possible (goes into forced discharge)
|
||||
#define ABSOLUTE_MIN_VOLTAGE 3100 // 310.0V if battery voltage goes under this, discharging further is disabled
|
||||
#define MAXPERCENTAGE_ZOE 800 //80.0% , Max percentage the battery will charge to (App will show 100% once this value is reached)
|
||||
#define MINPERCENTAGE_ZOE 200 //20.0% , Min percentage the battery will discharge to (App will show 0% once this value is reached)
|
||||
static byte printValues = 1; //Should modbus values be printed to serial output?
|
||||
|
||||
// These parameters need to be mapped for the Gen24
|
||||
extern uint16_t SOC;
|
||||
extern uint16_t StateOfHealth;
|
||||
extern uint16_t battery_voltage;
|
||||
extern uint16_t battery_current;
|
||||
extern uint16_t capacity_Wh;
|
||||
extern uint16_t remaining_capacity_Wh;
|
||||
extern uint16_t max_target_discharge_power;
|
||||
extern uint16_t max_target_charge_power;
|
||||
extern uint16_t bms_status;
|
||||
extern uint16_t bms_char_dis_status;
|
||||
extern uint16_t stat_batt_power;
|
||||
extern uint16_t temperature_min;
|
||||
extern uint16_t temperature_max;
|
||||
extern uint16_t CANerror;
|
||||
// Definitions for BMS status
|
||||
#define STANDBY 0
|
||||
#define INACTIVE 1
|
||||
#define DARKSTART 2
|
||||
#define ACTIVE 3
|
||||
#define FAULT 4
|
||||
#define UPDATING 5
|
||||
|
||||
void update_values_imiev_battery();
|
||||
void receive_can_imiev_battery(CAN_frame_t rx_frame);
|
||||
void send_can_imiev_battery();
|
||||
|
||||
#endif
|
|
@ -2,6 +2,7 @@
|
|||
#define BATTERY_TYPE_LEAF // See NISSAN-LEAF-BATTERY.h for more LEAF battery settings
|
||||
//#define TESLA_MODEL_3_BATTERY // See TESLA-MODEL-3-BATTERY.h for more Tesla battery settings
|
||||
//#define RENAULT_ZOE_BATTERY // See RENAULT-ZOE-BATTERY.h for more Zoe battery settings
|
||||
//#define IMIEV_ION_CZERO_BATTERY // See IMIEV-CZERO-ION-BATTERY.h for more triplet battery settings
|
||||
//#define CHADEMO // See CHADEMO.h for more Chademo related settings
|
||||
|
||||
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
|
||||
|
@ -167,8 +168,11 @@ void setup()
|
|||
Serial.println("Tesla Model 3 battery selected");
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
Serial.println("Renault Zoe battery selected");
|
||||
Serial.println("Renault Zoe / Kangoo battery selected");
|
||||
#endif
|
||||
#ifdef IMIEV_ION_CZERO_BATTERY
|
||||
Serial.println("Mitsubishi i-MiEV / Citroen C-Zero / Peugeot Ion battery selected");
|
||||
#endif
|
||||
}
|
||||
|
||||
// perform main program functions
|
||||
|
@ -208,12 +212,16 @@ void handle_can()
|
|||
#ifdef RENAULT_ZOE_BATTERY
|
||||
receive_can_zoe_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef IMIEV_ION_CZERO_BATTERY
|
||||
receive_can_imiev_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef CAN_BYD
|
||||
receive_can_byd(rx_frame);
|
||||
#endif
|
||||
#ifdef CHADEMO
|
||||
#ifdef CHADEMO
|
||||
receive_can_chademo(rx_frame);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -244,6 +252,9 @@ void handle_can()
|
|||
#ifdef RENAULT_ZOE_BATTERY
|
||||
send_can_zoe_battery();
|
||||
#endif
|
||||
#ifdef IMIEV_ION_CZERO_BATTERY
|
||||
send_can_imiev_battery();
|
||||
#endif
|
||||
#ifdef CHADEMO
|
||||
send_can_chademo_battery();
|
||||
#endif
|
||||
|
@ -260,6 +271,9 @@ void handle_inverter()
|
|||
#ifdef RENAULT_ZOE_BATTERY
|
||||
update_values_zoe_battery(); //Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef IMIEV_ION_CZERO_BATTERY
|
||||
update_values_imiev_battery(); //Map the values to the correct registers
|
||||
#endif
|
||||
#ifdef SOLAX_CAN
|
||||
update_values_can_solax();
|
||||
#endif
|
||||
|
@ -269,7 +283,7 @@ void handle_inverter()
|
|||
#ifdef PYLON_CAN
|
||||
update_values_can_pylon();
|
||||
#endif
|
||||
#ifdef CHADEMO
|
||||
#ifdef CHADEMO
|
||||
update_values_can_chademo();
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue