Refactor CAN sending to interface agnostic

This commit is contained in:
Daniel Öster 2024-08-05 23:47:34 +03:00
parent 28703453f9
commit 4f508dba86
8 changed files with 78 additions and 57 deletions

View file

@ -878,3 +878,41 @@ void check_reset_reason() {
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;
}
}

View file

@ -14,9 +14,11 @@ CAN_ADDON_FD_MCP2518 = Add-on CAN-FD MCP2518 connected to GPIO pins
volatile CAN_Configuration can_config = {
.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? (Not needed for RS485 inverters)
};
.inverter = CAN_NATIVE // Which CAN is your inverter connected to? (No need to configure incase you use RS485)
.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
volatile uint8_t AccessPointEnabled = true; //Set to either true/false to enable direct wifi access point

View file

@ -29,7 +29,7 @@
//#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 */
#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 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
@ -84,11 +84,12 @@
/* 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" */
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 {
CAN_Interface battery;
CAN_Interface battery_double;
CAN_Interface inverter;
CAN_Interface charger;
} CAN_Configuration;
extern volatile CAN_Configuration can_config;
extern volatile uint8_t AccessPointEnabled;

View file

@ -344,17 +344,6 @@ void update_values_battery() { /* This function maps all the values fetched via
#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
/* Start with mapping all values */
@ -611,7 +600,7 @@ void receive_can_battery2(CAN_frame_t rx_frame) {
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.
{
@ -861,8 +850,7 @@ void receive_can_battery(CAN_frame_t rx_frame) {
if (stop_battery_query) { //Leafspy is active, stop our own polling
break;
}
ESP32Can.CANWriteFrame(&LEAF_NEXT_LINE_REQUEST); //Request the next frame for the group
transmit_can(&LEAF_NEXT_LINE_REQUEST, can_config.battery); //Request the next frame for the group
if (group_7bb == 1) //High precision SOC, Current, voltages etc.
{
@ -1026,9 +1014,9 @@ void send_can_battery() {
LEAF_1D4.data.u8[7] = 0xDE;
break;
}
ESP32Can.CANWriteFrame(&LEAF_1D4);
transmit_can(&LEAF_1D4, can_config.battery);
#ifdef DOUBLE_BATTERY
CAN_WriteFrame(&LEAF_1D4); // CAN2
transmit_can(&LEAF_1D4, can_config.battery_double);
#endif // DOUBLE_BATTERY
switch (mprun10r) {
@ -1122,9 +1110,9 @@ void send_can_battery() {
//Only send this message when NISSANLEAF_CHARGER is not defined (otherwise it will collide!)
#ifndef NISSANLEAF_CHARGER
ESP32Can.CANWriteFrame(&LEAF_1F2); //Contains (CHG_STA_RQ == 1 == Normal Charge)
transmit_can(&LEAF_1F2, can_config.battery);
#ifdef DOUBLE_BATTERY
CAN_WriteFrame(&LEAF_1F2); // CAN2
transmit_can(&LEAF_1F2, can_config.battery_double);
#endif // DOUBLE_BATTERY
#endif
@ -1145,9 +1133,9 @@ void send_can_battery() {
}
// 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
CAN_WriteFrame(&LEAF_50B); // CAN2
transmit_can(&LEAF_50B, can_config.battery_double);
#endif // DOUBLE_BATTERY
LEAF_50C.data.u8[3] = mprun100;
@ -1169,9 +1157,9 @@ void send_can_battery() {
LEAF_50C.data.u8[5] = 0x9A;
break;
}
ESP32Can.CANWriteFrame(&LEAF_50C);
transmit_can(&LEAF_50C, can_config.battery);
#ifdef DOUBLE_BATTERY
CAN_WriteFrame(&LEAF_50C); // CAN2
transmit_can(&LEAF_50C, can_config.battery_double);
#endif // DOUBLE_BATTERY
mprun100 = (mprun100 + 1) % 4; // mprun100 cycles between 0-1-2-3-0-1...
@ -1186,9 +1174,9 @@ void send_can_battery() {
group = (group == 1) ? 2 : (group == 2) ? 4 : 1;
// Cycle between group 1, 2, and 4 using ternary operation
LEAF_GROUP_REQUEST.data.u8[2] = group;
ESP32Can.CANWriteFrame(&LEAF_GROUP_REQUEST);
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery);
#ifdef DOUBLE_BATTERY
CAN_WriteFrame(&LEAF_GROUP_REQUEST); // CAN2
transmit_can(&LEAF_GROUP_REQUEST, can_config.battery_double);
#endif // DOUBLE_BATTERY
}
@ -1246,9 +1234,8 @@ void setup_battery(void) { // Performs one time setup at startup
#endif
datalayer.battery.info.number_of_cells = 96;
datalayer.battery.info.max_design_voltage_dV =
4040; // 404.4V, over this, charging is not possible (goes into forced discharge)
datalayer.battery.info.min_design_voltage_dV = 2600; // 260.0V under this, discharging further is disabled
datalayer.battery.info.max_design_voltage_dV = 4040; // 404.4V
datalayer.battery.info.min_design_voltage_dV = 2600; // 260.0V
#ifdef DOUBLE_BATTERY
datalayer.battery2.info.number_of_cells = datalayer.battery.info.number_of_cells;

View file

@ -2,17 +2,15 @@
#define NISSAN_LEAF_BATTERY_H
#include "../include.h"
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
extern ACAN2515 can;
#define BATTERY_SELECTED
#define MAX_CELL_DEVIATION_MV 500
uint16_t Temp_fromRAW_to_F(uint16_t temperature);
bool is_message_corrupt(CAN_frame_t rx_frame);
void setup_battery(void);
void transmit_can(CAN_frame_t* tx_frame, int interface);
#endif

View file

@ -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 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) {
Serial.print(header);
Serial.print(value);
@ -87,6 +95,7 @@ void send_can_battery() {
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
previousMillis100 = currentMillis;
// Put fake messages here incase you want to test sending CAN
transmit_can(&TEST, can_config.battery);
}
}

View file

@ -1,10 +1,12 @@
#ifndef TEST_FAKE_BATTERY_H
#define TEST_FAKE_BATTERY_H
#include "../include.h"
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
#define BATTERY_SELECTED
#define MAX_CELL_DEVIATION_MV 9999
void setup_battery(void);
void transmit_can(CAN_frame_t* tx_frame, int interface);
#endif

View file

@ -3,22 +3,6 @@
#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)
#include "hw_lilygo.h"
#elif defined(HW_STARK)