mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Refactor CAN sending to interface agnostic
This commit is contained in:
parent
28703453f9
commit
4f508dba86
8 changed files with 78 additions and 57 deletions
|
@ -878,3 +878,41 @@ void check_reset_reason() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void transmit_can(CAN_frame_t* tx_frame, int interface) {
|
||||||
|
switch (interface) {
|
||||||
|
case CAN_NATIVE:
|
||||||
|
ESP32Can.CANWriteFrame(tx_frame);
|
||||||
|
break;
|
||||||
|
case CANFD_NATIVE:
|
||||||
|
//TODO for stark
|
||||||
|
break;
|
||||||
|
case CAN_ADDON_MCP2515: {
|
||||||
|
#ifdef DUAL_CAN
|
||||||
|
//Struct with ACAN2515 library format, needed to use the MCP2515 library for CAN2
|
||||||
|
CANMessage MCP2515Frame;
|
||||||
|
MCP2515Frame.id = tx_frame->MsgID;
|
||||||
|
//MCP2515Frame.ext = false; //TODO: Howto handle this?
|
||||||
|
MCP2515Frame.len = tx_frame->FIR.B.DLC;
|
||||||
|
for (uint8_t i = 0; i < MCP2515Frame.len; i++) {
|
||||||
|
MCP2515Frame.data[i] = tx_frame->data.u8[i];
|
||||||
|
}
|
||||||
|
can.tryToSend(MCP2515Frame);
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
case CAN_ADDON_FD_MCP2518:
|
||||||
|
#ifdef CAN_FD
|
||||||
|
CANFDMessage MCP2518Frame;
|
||||||
|
MCP2518Frame.id = tx_frame->MsgID;
|
||||||
|
//MCP2518Frame.ext = false; //TODO: Howto handle this?
|
||||||
|
MCP2518Frame.len = tx_frame->FIR.B.DLC;
|
||||||
|
for (uint8_t i = 0; i < MCP2518Frame.len; i++) {
|
||||||
|
MCP2518Frame.data[i] = tx_frame->data.u8[i];
|
||||||
|
}
|
||||||
|
canfd.tryToSend(MCP2518Frame);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Invalid interface sent with function call. TODO: Raise event that coders messed up
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,10 +13,12 @@ CAN_ADDON_FD_MCP2518 = Add-on CAN-FD MCP2518 connected to GPIO pins
|
||||||
*/
|
*/
|
||||||
|
|
||||||
volatile CAN_Configuration can_config = {
|
volatile CAN_Configuration can_config = {
|
||||||
.battery = CAN_NATIVE, // Which CAN is your battery connected to?
|
.battery = CAN_NATIVE, // Which CAN is your battery connected to?
|
||||||
.battery_double = CAN_ADDON_MCP2515, // Which CAN is your optional second battery connected to?
|
.inverter = CAN_NATIVE // Which CAN is your inverter connected to? (No need to configure incase you use RS485)
|
||||||
.inverter = CAN_NATIVE // Which CAN is your inverter connected to? (Not needed for RS485 inverters)
|
.battery_double = CAN_ADDON_MCP2515, // (OPTIONAL) Which CAN is your second battery connected to?
|
||||||
};
|
.charger = CAN_NATIVE; // (OPTIONAL) Which CAN is your charger connected to?
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
#ifdef WEBSERVER
|
||||||
volatile uint8_t AccessPointEnabled = true; //Set to either true/false to enable direct wifi access point
|
volatile uint8_t AccessPointEnabled = true; //Set to either true/false to enable direct wifi access point
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
//#define DOUBLE_BATTERY //Enable this line if you use two identical batteries at the same time (requires DUAL_CAN setup)
|
//#define DOUBLE_BATTERY //Enable this line if you use two identical batteries at the same time (requires DUAL_CAN setup)
|
||||||
|
|
||||||
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
|
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
|
||||||
#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
|
//#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
|
||||||
//#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
//#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||||
//#define LUNA2000_MODBUS //Enable this line to emulate a "Luna2000 battery" over Modbus RTU
|
//#define LUNA2000_MODBUS //Enable this line to emulate a "Luna2000 battery" over Modbus RTU
|
||||||
//#define PYLON_CAN //Enable this line to emulate a "Pylontech battery" over CAN bus
|
//#define PYLON_CAN //Enable this line to emulate a "Pylontech battery" over CAN bus
|
||||||
|
@ -84,11 +84,12 @@
|
||||||
|
|
||||||
/* Do not change any code below this line unless you are sure what you are doing */
|
/* Do not change any code below this line unless you are sure what you are doing */
|
||||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
||||||
typedef enum { CAN_NATIVE = 0, CAN_ADDON_MCP2515 = 1, CAN_ADDON_FD_MCP2518 = 2 } CAN_Interface;
|
typedef enum { CAN_NATIVE = 0, CANFD_NATIVE = 1, CAN_ADDON_MCP2515 = 2, CAN_ADDON_FD_MCP2518 = 3 } CAN_Interface;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CAN_Interface battery;
|
CAN_Interface battery;
|
||||||
CAN_Interface battery_double;
|
CAN_Interface battery_double;
|
||||||
CAN_Interface inverter;
|
CAN_Interface inverter;
|
||||||
|
CAN_Interface charger;
|
||||||
} CAN_Configuration;
|
} CAN_Configuration;
|
||||||
extern volatile CAN_Configuration can_config;
|
extern volatile CAN_Configuration can_config;
|
||||||
extern volatile uint8_t AccessPointEnabled;
|
extern volatile uint8_t AccessPointEnabled;
|
||||||
|
|
|
@ -344,17 +344,6 @@ void update_values_battery() { /* This function maps all the values fetched via
|
||||||
|
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
|
|
||||||
void CAN_WriteFrame(CAN_frame_t* tx_frame) {
|
|
||||||
CANMessage MCP2515Frame; //Struct with ACAN2515 library format, needed to use the MCP2515 library for CAN2
|
|
||||||
MCP2515Frame.id = tx_frame->MsgID;
|
|
||||||
//MCP2515Frame.ext = tx_frame->FIR.B.FF;
|
|
||||||
MCP2515Frame.len = tx_frame->FIR.B.DLC;
|
|
||||||
for (uint8_t i = 0; i < MCP2515Frame.len; i++) {
|
|
||||||
MCP2515Frame.data[i] = tx_frame->data.u8[i];
|
|
||||||
}
|
|
||||||
can.tryToSend(MCP2515Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_values_battery2() { // Handle the values coming in from battery #2
|
void update_values_battery2() { // Handle the values coming in from battery #2
|
||||||
/* Start with mapping all values */
|
/* Start with mapping all values */
|
||||||
|
|
||||||
|
@ -611,7 +600,7 @@ void receive_can_battery2(CAN_frame_t rx_frame) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAN_WriteFrame(&LEAF_NEXT_LINE_REQUEST); // CAN2
|
transmit_can(&LEAF_NEXT_LINE_REQUEST, can_config.battery_double);
|
||||||
|
|
||||||
if (battery2_group_7bb == 1) //High precision SOC, Current, voltages etc.
|
if (battery2_group_7bb == 1) //High precision SOC, Current, voltages etc.
|
||||||
{
|
{
|
||||||
|
@ -861,8 +850,7 @@ void receive_can_battery(CAN_frame_t rx_frame) {
|
||||||
if (stop_battery_query) { //Leafspy is active, stop our own polling
|
if (stop_battery_query) { //Leafspy is active, stop our own polling
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
transmit_can(&LEAF_NEXT_LINE_REQUEST, can_config.battery); //Request the next frame for the group
|
||||||
ESP32Can.CANWriteFrame(&LEAF_NEXT_LINE_REQUEST); //Request the next frame for the group
|
|
||||||
|
|
||||||
if (group_7bb == 1) //High precision SOC, Current, voltages etc.
|
if (group_7bb == 1) //High precision SOC, Current, voltages etc.
|
||||||
{
|
{
|
||||||
|
@ -1026,10 +1014,10 @@ void send_can_battery() {
|
||||||
LEAF_1D4.data.u8[7] = 0xDE;
|
LEAF_1D4.data.u8[7] = 0xDE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ESP32Can.CANWriteFrame(&LEAF_1D4);
|
transmit_can(&LEAF_1D4, can_config.battery);
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
CAN_WriteFrame(&LEAF_1D4); // CAN2
|
transmit_can(&LEAF_1D4, can_config.battery_double);
|
||||||
#endif // DOUBLE_BATTERY
|
#endif // DOUBLE_BATTERY
|
||||||
|
|
||||||
switch (mprun10r) {
|
switch (mprun10r) {
|
||||||
case (0):
|
case (0):
|
||||||
|
@ -1122,10 +1110,10 @@ void send_can_battery() {
|
||||||
|
|
||||||
//Only send this message when NISSANLEAF_CHARGER is not defined (otherwise it will collide!)
|
//Only send this message when NISSANLEAF_CHARGER is not defined (otherwise it will collide!)
|
||||||
#ifndef NISSANLEAF_CHARGER
|
#ifndef NISSANLEAF_CHARGER
|
||||||
ESP32Can.CANWriteFrame(&LEAF_1F2); //Contains (CHG_STA_RQ == 1 == Normal Charge)
|
transmit_can(&LEAF_1F2, can_config.battery);
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
CAN_WriteFrame(&LEAF_1F2); // CAN2
|
transmit_can(&LEAF_1F2, can_config.battery_double);
|
||||||
#endif // DOUBLE_BATTERY
|
#endif // DOUBLE_BATTERY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mprun10r = (mprun10r + 1) % 20; // 0x1F2 patter repeats after 20 messages. 0-1..19-0
|
mprun10r = (mprun10r + 1) % 20; // 0x1F2 patter repeats after 20 messages. 0-1..19-0
|
||||||
|
@ -1145,10 +1133,10 @@ void send_can_battery() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VCM message, containing info if battery should sleep or stay awake
|
// VCM message, containing info if battery should sleep or stay awake
|
||||||
ESP32Can.CANWriteFrame(&LEAF_50B); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
transmit_can(&LEAF_50B, can_config.battery); // HCM_WakeUpSleepCommand == 11b == WakeUp, and CANMASK = 1
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
CAN_WriteFrame(&LEAF_50B); // CAN2
|
transmit_can(&LEAF_50B, can_config.battery_double);
|
||||||
#endif // DOUBLE_BATTERY
|
#endif // DOUBLE_BATTERY
|
||||||
|
|
||||||
LEAF_50C.data.u8[3] = mprun100;
|
LEAF_50C.data.u8[3] = mprun100;
|
||||||
switch (mprun100) {
|
switch (mprun100) {
|
||||||
|
@ -1169,10 +1157,10 @@ void send_can_battery() {
|
||||||
LEAF_50C.data.u8[5] = 0x9A;
|
LEAF_50C.data.u8[5] = 0x9A;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ESP32Can.CANWriteFrame(&LEAF_50C);
|
transmit_can(&LEAF_50C, can_config.battery);
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
CAN_WriteFrame(&LEAF_50C); // CAN2
|
transmit_can(&LEAF_50C, can_config.battery_double);
|
||||||
#endif // DOUBLE_BATTERY
|
#endif // DOUBLE_BATTERY
|
||||||
|
|
||||||
mprun100 = (mprun100 + 1) % 4; // mprun100 cycles between 0-1-2-3-0-1...
|
mprun100 = (mprun100 + 1) % 4; // mprun100 cycles between 0-1-2-3-0-1...
|
||||||
}
|
}
|
||||||
|
@ -1186,10 +1174,10 @@ void send_can_battery() {
|
||||||
group = (group == 1) ? 2 : (group == 2) ? 4 : 1;
|
group = (group == 1) ? 2 : (group == 2) ? 4 : 1;
|
||||||
// Cycle between group 1, 2, and 4 using ternary operation
|
// Cycle between group 1, 2, and 4 using ternary operation
|
||||||
LEAF_GROUP_REQUEST.data.u8[2] = group;
|
LEAF_GROUP_REQUEST.data.u8[2] = group;
|
||||||
ESP32Can.CANWriteFrame(&LEAF_GROUP_REQUEST);
|
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery);
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
CAN_WriteFrame(&LEAF_GROUP_REQUEST); // CAN2
|
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery_double);
|
||||||
#endif // DOUBLE_BATTERY
|
#endif // DOUBLE_BATTERY
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hold_off_with_polling_10seconds > 0) {
|
if (hold_off_with_polling_10seconds > 0) {
|
||||||
|
@ -1246,9 +1234,8 @@ void setup_battery(void) { // Performs one time setup at startup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
datalayer.battery.info.number_of_cells = 96;
|
datalayer.battery.info.number_of_cells = 96;
|
||||||
datalayer.battery.info.max_design_voltage_dV =
|
datalayer.battery.info.max_design_voltage_dV = 4040; // 404.4V
|
||||||
4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
|
datalayer.battery.info.min_design_voltage_dV = 2600; // 260.0V
|
||||||
datalayer.battery.info.min_design_voltage_dV = 2600; // 260.0V under this, discharging further is disabled
|
|
||||||
|
|
||||||
#ifdef DOUBLE_BATTERY
|
#ifdef DOUBLE_BATTERY
|
||||||
datalayer.battery2.info.number_of_cells = datalayer.battery.info.number_of_cells;
|
datalayer.battery2.info.number_of_cells = datalayer.battery.info.number_of_cells;
|
||||||
|
|
|
@ -2,17 +2,15 @@
|
||||||
#define NISSAN_LEAF_BATTERY_H
|
#define NISSAN_LEAF_BATTERY_H
|
||||||
|
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
|
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
|
||||||
|
|
||||||
extern ACAN2515 can;
|
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
#define MAX_CELL_DEVIATION_MV 500
|
#define MAX_CELL_DEVIATION_MV 500
|
||||||
|
|
||||||
uint16_t Temp_fromRAW_to_F(uint16_t temperature);
|
uint16_t Temp_fromRAW_to_F(uint16_t temperature);
|
||||||
bool is_message_corrupt(CAN_frame_t rx_frame);
|
bool is_message_corrupt(CAN_frame_t rx_frame);
|
||||||
void setup_battery(void);
|
void setup_battery(void);
|
||||||
|
void transmit_can(CAN_frame_t* tx_frame, int interface);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,14 @@ static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN
|
||||||
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send
|
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send
|
||||||
static unsigned long previousMillis10s = 0; // will store last time a 1s CAN Message was send
|
static unsigned long previousMillis10s = 0; // will store last time a 1s CAN Message was send
|
||||||
|
|
||||||
|
CAN_frame_t TEST = {.FIR = {.B =
|
||||||
|
{
|
||||||
|
.DLC = 8,
|
||||||
|
.FF = CAN_frame_std,
|
||||||
|
}},
|
||||||
|
.MsgID = 0x123,
|
||||||
|
.data = {0x10, 0x64, 0x00, 0xB0, 0x00, 0x1E, 0x00, 0x8F}};
|
||||||
|
|
||||||
void print_units(char* header, int value, char* units) {
|
void print_units(char* header, int value, char* units) {
|
||||||
Serial.print(header);
|
Serial.print(header);
|
||||||
Serial.print(value);
|
Serial.print(value);
|
||||||
|
@ -87,6 +95,7 @@ void send_can_battery() {
|
||||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||||
previousMillis100 = currentMillis;
|
previousMillis100 = currentMillis;
|
||||||
// Put fake messages here incase you want to test sending CAN
|
// Put fake messages here incase you want to test sending CAN
|
||||||
|
transmit_can(&TEST, can_config.battery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#ifndef TEST_FAKE_BATTERY_H
|
#ifndef TEST_FAKE_BATTERY_H
|
||||||
#define TEST_FAKE_BATTERY_H
|
#define TEST_FAKE_BATTERY_H
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
#define MAX_CELL_DEVIATION_MV 9999
|
#define MAX_CELL_DEVIATION_MV 9999
|
||||||
|
|
||||||
void setup_battery(void);
|
void setup_battery(void);
|
||||||
|
void transmit_can(CAN_frame_t* tx_frame, int interface);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,22 +3,6 @@
|
||||||
|
|
||||||
#include "../../../USER_SETTINGS.h"
|
#include "../../../USER_SETTINGS.h"
|
||||||
|
|
||||||
/* Enumeration for CAN interfaces
|
|
||||||
typedef enum {
|
|
||||||
CAN_NATIVE = 0,
|
|
||||||
CANFD_NATIVE = 1,
|
|
||||||
CAN_ADDON_MCP2515 = 2,
|
|
||||||
CAN_ADDON_FD_MCP2518 = 3
|
|
||||||
} CAN_Interface;
|
|
||||||
|
|
||||||
/* Struct to hold CAN assignments for components
|
|
||||||
typedef struct {
|
|
||||||
CAN_Interface battery;
|
|
||||||
CAN_Interface battery_double;
|
|
||||||
CAN_Interface inverter;
|
|
||||||
} CAN_Configuration;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(HW_LILYGO)
|
#if defined(HW_LILYGO)
|
||||||
#include "hw_lilygo.h"
|
#include "hw_lilygo.h"
|
||||||
#elif defined(HW_STARK)
|
#elif defined(HW_STARK)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue