Rewrite CAN handler. Add Solax

This commit is contained in:
Daniel 2023-07-04 11:54:09 +03:00
parent 0e3af999f0
commit deb664d097
12 changed files with 400 additions and 307 deletions

View file

@ -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

View file

@ -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
View 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

View file

@ -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
{
//printf("New extended frame");
}
}
}
void send_can_leaf_battery()
{
static unsigned long currentMillis = millis();
// Send 100ms CAN Message
if (currentMillis - previousMillis100 >= interval100)
{

View file

@ -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);

View file

@ -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
{
//printf("New extended frame");
}
}
}
void send_can_zoe_battery()
{
static unsigned long currentMillis = millis();
// Send 100ms CAN Message
if (currentMillis - previousMillis100 >= interval100)
{

View file

@ -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
View 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
View 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

View file

@ -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
}

View file

@ -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
{
//printf("New extended frame");
}
}
}
void send_can_tesla_model_3_battery()
{
static unsigned long currentMillis = millis();
// Send 100ms CAN Message
if (currentMillis - previousMillis100 >= interval100)
{

View file

@ -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