diff --git a/Software/Software.ino b/Software/Software.ino index 6d19d1ad..3b089a5b 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -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; + } +} diff --git a/Software/USER_SETTINGS.cpp b/Software/USER_SETTINGS.cpp index adb95348..780b995a 100644 --- a/Software/USER_SETTINGS.cpp +++ b/Software/USER_SETTINGS.cpp @@ -13,10 +13,12 @@ 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) -}; + .battery = CAN_NATIVE, // Which CAN is your battery connected to? + .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 diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 998258c9..0e409c6b 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -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; diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp index bfa08fb5..d15d3eb2 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp @@ -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,10 +1014,10 @@ 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 -#endif // DOUBLE_BATTERY + transmit_can(&LEAF_1D4, can_config.battery_double); +#endif // DOUBLE_BATTERY switch (mprun10r) { case (0): @@ -1122,10 +1110,10 @@ 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 -#endif // DOUBLE_BATTERY + transmit_can(&LEAF_1F2, can_config.battery_double); +#endif // DOUBLE_BATTERY #endif 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 - 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 -#endif // DOUBLE_BATTERY + transmit_can(&LEAF_50B, can_config.battery_double); +#endif // DOUBLE_BATTERY LEAF_50C.data.u8[3] = mprun100; switch (mprun100) { @@ -1169,10 +1157,10 @@ 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 -#endif // DOUBLE_BATTERY + 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,10 +1174,10 @@ 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 -#endif // DOUBLE_BATTERY + transmit_can(&LEAF_GROUP_REQUEST, can_config.battery_double); +#endif // DOUBLE_BATTERY } if (hold_off_with_polling_10seconds > 0) { @@ -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; diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index e7649a03..cf7fc1e3 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -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 diff --git a/Software/src/battery/TEST-FAKE-BATTERY.cpp b/Software/src/battery/TEST-FAKE-BATTERY.cpp index a0b4a2e1..67ef68e5 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.cpp +++ b/Software/src/battery/TEST-FAKE-BATTERY.cpp @@ -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); } } diff --git a/Software/src/battery/TEST-FAKE-BATTERY.h b/Software/src/battery/TEST-FAKE-BATTERY.h index 432fb6ab..db9edb1b 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.h +++ b/Software/src/battery/TEST-FAKE-BATTERY.h @@ -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 diff --git a/Software/src/devboard/hal/hal.h b/Software/src/devboard/hal/hal.h index b563019a..5e904d89 100644 --- a/Software/src/devboard/hal/hal.h +++ b/Software/src/devboard/hal/hal.h @@ -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)