mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-04 10:19:29 +02:00
Rewrite CAN handler. Add Solax
This commit is contained in:
parent
0e3af999f0
commit
deb664d097
12 changed files with 400 additions and 307 deletions
|
@ -3,13 +3,12 @@
|
|||
#include "CAN_config.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
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
|
||||
const int interval2s = 2000; // interval (ms) at which send CAN Messages
|
||||
const int interval10s = 10000; // interval (ms) at which send CAN Messages
|
||||
const int interval60s = 60000; // interval (ms) at which send CAN Messages
|
||||
const int rx_queue_size = 10; // Receive Queue size
|
||||
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
|
||||
static const int interval2s = 2000; // interval (ms) at which send CAN Messages
|
||||
static const int interval10s = 10000; // interval (ms) at which send CAN Messages
|
||||
static const int interval60s = 60000; // interval (ms) at which send CAN Messages
|
||||
|
||||
//Constant startup messages
|
||||
const CAN_frame_t BYD_250 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_std,}},.MsgID = 0x250,.data = {0x03, 0x16, 0x00, 0x66, 0x00, 0x33, 0x02, 0x09}};
|
||||
|
@ -74,7 +73,22 @@ void update_values_can_byd()
|
|||
BYD_210.data.u8[3] = (temperature_min & 0x00FF);
|
||||
}
|
||||
|
||||
void handle_can_byd()
|
||||
void receive_can_byd(CAN_frame_t rx_frame)
|
||||
{
|
||||
switch (rx_frame.MsgID)
|
||||
{
|
||||
case 0x151: //Message originating from BYD HVS compatible inverter. Reply with CAN identifier!
|
||||
if(rx_frame.data.u8[0] & 0x01)
|
||||
{
|
||||
send_intial_data();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_byd()
|
||||
{
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 2s CAN Message
|
||||
|
|
|
@ -28,7 +28,8 @@ extern uint16_t max_volt_byd_can;
|
|||
#define UPDATING 5
|
||||
|
||||
void update_values_can_byd();
|
||||
void handle_can_byd();
|
||||
void send_can_byd();
|
||||
void receive_can_byd(CAN_frame_t rx_frame);
|
||||
void send_intial_data();
|
||||
|
||||
#endif
|
12
Software/INVERTERS.h
Normal file
12
Software/INVERTERS.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef INVERTERS_H
|
||||
#define INVERTERS_H
|
||||
|
||||
#ifdef SOLAX_CAN
|
||||
#include "SOLAX-CAN.h"
|
||||
#endif
|
||||
|
||||
#ifdef CAN_BYD
|
||||
#include "BYD-CAN.h"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -274,17 +274,8 @@ void update_values_leaf_battery()
|
|||
}
|
||||
}
|
||||
|
||||
void handle_can_leaf_battery()
|
||||
void receive_can_leaf_battery(CAN_frame_t rx_frame)
|
||||
{
|
||||
CAN_frame_t rx_frame;
|
||||
static unsigned long currentMillis = millis();
|
||||
|
||||
// Receive next CAN frame from queue
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
|
||||
{
|
||||
if (rx_frame.FIR.B.FF == CAN_frame_std)
|
||||
{
|
||||
//printf("New standard frame");
|
||||
switch (rx_frame.MsgID)
|
||||
{
|
||||
case 0x1DB:
|
||||
|
@ -391,23 +382,13 @@ void handle_can_leaf_battery()
|
|||
//ZE1 2018-2023 battery detected!
|
||||
LEAF_Battery_Type = ZE1_BATTERY;
|
||||
break;
|
||||
#ifdef CAN_BYD
|
||||
case 0x151: //Message originating from BYD HVS compatible inverter. Send CAN identifier!
|
||||
if(rx_frame.data.u8[0] & 0x01)
|
||||
{
|
||||
send_intial_data();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
void send_can_leaf_battery()
|
||||
{
|
||||
//printf("New extended frame");
|
||||
}
|
||||
}
|
||||
static unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,8 @@ extern uint16_t CANerror;
|
|||
#define UPDATING 5
|
||||
|
||||
void update_values_leaf_battery();
|
||||
void handle_can_leaf_battery();
|
||||
void receive_can_leaf_battery(CAN_frame_t rx_frame);
|
||||
void send_can_leaf_battery();
|
||||
uint16_t convert2unsignedint16(uint16_t signed_value);
|
||||
bool is_message_corrupt(CAN_frame_t rx_frame);
|
||||
|
||||
|
|
|
@ -120,17 +120,8 @@ void update_values_zoe_battery()
|
|||
}
|
||||
}
|
||||
|
||||
void handle_can_zoe_battery()
|
||||
void receive_can_zoe_battery(CAN_frame_t rx_frame)
|
||||
{
|
||||
CAN_frame_t rx_frame;
|
||||
static unsigned long currentMillis = millis();
|
||||
|
||||
// Receive next CAN frame from queue
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
|
||||
{
|
||||
if (rx_frame.FIR.B.FF == CAN_frame_std)
|
||||
{
|
||||
//printf("New standard frame");
|
||||
switch (rx_frame.MsgID)
|
||||
{
|
||||
case 0x155: //BMS1
|
||||
|
@ -151,23 +142,13 @@ void handle_can_zoe_battery()
|
|||
//LB_Cell_Max_Voltage =
|
||||
//LB_Cell_Min_Voltage =
|
||||
break;
|
||||
#ifdef CAN_BYD
|
||||
case 0x151: //Message originating from BYD HVS compatible inverter. Send CAN identifier!
|
||||
if(rx_frame.data.u8[0] & 0x01)
|
||||
{
|
||||
send_intial_data();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
void send_can_zoe_battery()
|
||||
{
|
||||
//printf("New extended frame");
|
||||
}
|
||||
}
|
||||
static unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,8 @@ extern uint16_t CANerror;
|
|||
#define UPDATING 5
|
||||
|
||||
void update_values_zoe_battery();
|
||||
void handle_can_zoe_battery();
|
||||
void receive_can_zoe_battery(CAN_frame_t rx_frame);
|
||||
void send_can_zoe_battery();
|
||||
uint16_t convert2unsignedint16(uint16_t signed_value);
|
||||
|
||||
#endif
|
49
Software/SOLAX-CAN.cpp
Normal file
49
Software/SOLAX-CAN.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "SOLAX-CAN.h"
|
||||
#include "ESP32CAN.h"
|
||||
#include "CAN_config.h"
|
||||
|
||||
/* 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
|
||||
static const int interval2s = 2000; // interval (ms) at which send CAN Messages
|
||||
static const int interval10s = 10000; // interval (ms) at which send CAN Messages
|
||||
static const int interval60s = 60000; // interval (ms) at which send CAN Messages
|
||||
|
||||
CAN_frame_t SOLAX_1872 = {.FIR = {.B = {.DLC = 8,.FF = CAN_frame_ext,}},.MsgID = 0x1872,.data = {0x03, 0x16, 0x00, 0x66, 0x00, 0x33, 0x02, 0x09}};
|
||||
|
||||
void update_values_can_solax()
|
||||
{ //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
|
||||
}
|
||||
|
||||
void send_can_solax()
|
||||
{
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 2s CAN Message
|
||||
if (currentMillis - previousMillis2s >= interval2s)
|
||||
{
|
||||
previousMillis2s = currentMillis;
|
||||
|
||||
}
|
||||
// Send 10s CAN Message
|
||||
if (currentMillis - previousMillis10s >= interval10s)
|
||||
{
|
||||
previousMillis10s = currentMillis;
|
||||
|
||||
//Serial.println("CAN 10s done");
|
||||
}
|
||||
//Send 60s message
|
||||
if (currentMillis - previousMillis60s >= interval60s)
|
||||
{
|
||||
previousMillis60s = currentMillis;
|
||||
|
||||
//ESP32Can.CANWriteFrame(&BYD_190);
|
||||
//Serial.println("CAN 60s done");
|
||||
}
|
||||
}
|
||||
|
||||
void receive_can_solax(CAN_frame_t rx_frame)
|
||||
{
|
||||
Serial.println("Inverter sending CAN message");
|
||||
}
|
33
Software/SOLAX-CAN.h
Normal file
33
Software/SOLAX-CAN.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef SOLAX_CAN_H
|
||||
#define SOLAX_CAN_H
|
||||
#include <Arduino.h>
|
||||
#include "ESP32CAN.h"
|
||||
|
||||
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;
|
||||
extern uint16_t min_volt_byd_can;
|
||||
extern uint16_t max_volt_byd_can;
|
||||
// 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_can_byd();
|
||||
void send_can_solax();
|
||||
void receive_can_solax(CAN_frame_t rx_frame);
|
||||
#endif
|
|
@ -1,11 +1,12 @@
|
|||
/* Select battery used */
|
||||
//#define BATTERY_TYPE_LEAF // See NISSAN-LEAF-BATTERY.h for more LEAF battery settings
|
||||
#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 RENAULT_ZOE_BATTERY // See RENAULT-ZOE-BATTERY.h for more Zoe battery settings
|
||||
|
||||
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
|
||||
#define MODBUS_BYD //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||
//#define MODBUS_BYD //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||
//#define CAN_BYD //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
|
||||
#define SOLAX_CAN //Enable this line to emulate a "SolaX Triple Power LFP" over CAN bus
|
||||
|
||||
/* Do not change any code below this line unless you are sure what you are doing */
|
||||
/* Only change battery specific settings and limits in their respective .h files */
|
||||
|
@ -13,14 +14,14 @@
|
|||
#include <Arduino.h>
|
||||
#include "HardwareSerial.h"
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
#include "Logging.h"
|
||||
#include "mbServerFCs.h"
|
||||
#include "ModbusServerRTU.h"
|
||||
#include "ESP32CAN.h"
|
||||
#include "CAN_config.h"
|
||||
#include "Adafruit_NeoPixel.h"
|
||||
#include "BATTERIES.h"
|
||||
#include "BYD-CAN.h"
|
||||
#include "INVERTERS.h"
|
||||
//CAN parameters
|
||||
#define MAX_CAN_FAILURES 5000 //Amount of malformed CAN messages to allow before raising a warning
|
||||
CAN_device_t CAN_cfg; // CAN Config
|
||||
|
@ -48,6 +49,8 @@ const uint16_t max_voltage = ABSOLUTE_MAX_VOLTAGE; //if higher charging is not p
|
|||
const uint16_t min_voltage = ABSOLUTE_MIN_VOLTAGE; //if lower Gen24 disables battery
|
||||
uint16_t min_volt_byd_can = min_voltage;
|
||||
uint16_t max_volt_byd_can = max_voltage;
|
||||
uint16_t min_volt_solax_can = min_voltage;
|
||||
uint16_t max_volt_solax_can = max_voltage;
|
||||
uint16_t battery_voltage = 3700;
|
||||
uint16_t battery_current = 0;
|
||||
uint16_t SOC = 5000; //SOC 0-100.00% //Updates later on from CAN
|
||||
|
@ -175,18 +178,52 @@ void loop()
|
|||
}
|
||||
|
||||
void handle_can()
|
||||
{ //Depending on which parts are used, handle their respective CAN routines
|
||||
#ifdef CAN_BYD
|
||||
handle_can_byd();
|
||||
#endif
|
||||
{ //This section checks if we have a complete CAN message incoming
|
||||
//Depending on which battery/inverter is selected, we forward this to their respective CAN routines
|
||||
CAN_frame_t rx_frame;
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
|
||||
{
|
||||
if (rx_frame.FIR.B.FF == CAN_frame_std)
|
||||
{
|
||||
//printf("New standard frame");
|
||||
#ifdef BATTERY_TYPE_LEAF
|
||||
handle_can_leaf_battery();
|
||||
receive_can_leaf_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
handle_can_tesla_model_3_battery();
|
||||
receive_can_tesla_model_3_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
handle_can_zoe_battery();
|
||||
receive_can_zoe_battery(rx_frame);
|
||||
#endif
|
||||
#ifdef CAN_BYD
|
||||
receive_can_byd(rx_frame);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("New extended frame");
|
||||
#ifdef SOLAX_CAN
|
||||
receive_can_solax(rx_frame);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//When we are done checking if a CAN message has arrived, we can focus on sending CAN messages
|
||||
//Inverter sending
|
||||
#ifdef CAN_BYD
|
||||
send_can_byd();
|
||||
#endif
|
||||
#ifdef SOLAX_CAN
|
||||
send_can_solax();
|
||||
#endif
|
||||
//Battery sending
|
||||
#ifdef BATTERY_TYPE_LEAF
|
||||
send_can_leaf_battery();
|
||||
#endif
|
||||
#ifdef TESLA_MODEL_3_BATTERY
|
||||
send_can_tesla_model_3_battery();
|
||||
#endif
|
||||
#ifdef RENAULT_ZOE_BATTERY
|
||||
send_can_zoe_battery();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -177,20 +177,11 @@ void update_values_tesla_model_3_battery()
|
|||
}
|
||||
}
|
||||
|
||||
void handle_can_tesla_model_3_battery()
|
||||
void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame)
|
||||
{
|
||||
CAN_frame_t rx_frame;
|
||||
static unsigned long currentMillis = millis();
|
||||
static int mux = 0;
|
||||
static int temp = 0;
|
||||
|
||||
// Receive next CAN frame from queue
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE)
|
||||
{
|
||||
if (rx_frame.FIR.B.FF == CAN_frame_std)
|
||||
{
|
||||
stillAliveCAN = 6; //We got CAN-messages flowing in!
|
||||
//printf("New standard frame");
|
||||
switch (rx_frame.MsgID)
|
||||
{
|
||||
case 0x352:
|
||||
|
@ -281,23 +272,13 @@ void handle_can_tesla_model_3_battery()
|
|||
high_voltage = (((rx_frame.data.u8[2] << 6) | ((rx_frame.data.u8[1] & 0xFC) >> 2))) * 0.146484;
|
||||
output_current = (((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[3]) / 100;
|
||||
break;
|
||||
#ifdef CAN_BYD
|
||||
case 0x151: //Message originating from BYD HVS compatible inverter. Send CAN identifier!
|
||||
if(rx_frame.data.u8[0] & 0x01)
|
||||
{
|
||||
send_intial_data();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
void send_can_tesla_model_3_battery()
|
||||
{
|
||||
//printf("New extended frame");
|
||||
}
|
||||
}
|
||||
static unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= interval100)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef TESLA_MODEL_3_BATTERY_H
|
||||
#define TESLA_MODEL_3_BATTERY_H
|
||||
#include <Arduino.h>
|
||||
#include "ESP32CAN.h"
|
||||
|
||||
/* User definable settings for the Tesla Model 3 battery */
|
||||
#define BATTERY_WH_MAX 60000 //Battery size in Wh (Maximum value Fronius accepts is 60000 [60kWh] you can use larger 65/75/90 batteries but do set value over 60000!
|
||||
|
@ -34,7 +35,8 @@ extern uint16_t CANerror;
|
|||
#define UPDATING 5
|
||||
|
||||
void update_values_tesla_model_3_battery();
|
||||
void handle_can_tesla_model_3_battery();
|
||||
void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame);
|
||||
void send_can_tesla_model_3_battery();
|
||||
uint16_t convert2unsignedint16(uint16_t signed_value);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue