From 2c0e5be5daf96b20b3bdd968c22e807def3413ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96ster?= Date: Tue, 4 Mar 2025 10:15:15 +0200 Subject: [PATCH] Remove serial-link (double LilyGo) as an option --- .github/workflows/compile-all-batteries.yml | 1 - ...ll-combinations-part1-batteries-A-to-M.yml | 1 - ...ll-combinations-part2-batteries-N-to-Z.yml | 1 - .github/workflows/compile-all-inverters.yml | 1 - README.md | 1 - Software/Software.ino | 9 +- Software/USER_SETTINGS.h | 2 - Software/src/battery/BATTERIES.h | 4 - .../SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp | 230 ------- .../SERIAL-LINK-RECEIVER-FROM-BATTERY.h | 15 - .../src/communication/rs485/comm_rs485.cpp | 3 - .../seriallink/comm_seriallink.cpp | 35 - .../seriallink/comm_seriallink.h | 17 - Software/src/include.h | 14 - Software/src/inverter/INVERTERS.h | 4 - .../SERIAL-LINK-TRANSMITTER-INVERTER.cpp | 195 ------ .../SERIAL-LINK-TRANSMITTER-INVERTER.h | 11 - .../SerialDataLink.cpp | 607 ------------------ .../mackelec-SerialDataLink/SerialDataLink.h | 185 ------ 19 files changed, 1 insertion(+), 1335 deletions(-) delete mode 100644 Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp delete mode 100644 Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h delete mode 100644 Software/src/communication/seriallink/comm_seriallink.cpp delete mode 100644 Software/src/communication/seriallink/comm_seriallink.h delete mode 100644 Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp delete mode 100644 Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h delete mode 100644 Software/src/lib/mackelec-SerialDataLink/SerialDataLink.cpp delete mode 100644 Software/src/lib/mackelec-SerialDataLink/SerialDataLink.h diff --git a/.github/workflows/compile-all-batteries.yml b/.github/workflows/compile-all-batteries.yml index aa553e24..50ffc6e9 100644 --- a/.github/workflows/compile-all-batteries.yml +++ b/.github/workflows/compile-all-batteries.yml @@ -78,7 +78,6 @@ jobs: - TESLA_MODEL_SX_BATTERY - VOLVO_SPA_BATTERY - TEST_FAKE_BATTERY - - SERIAL_LINK_RECEIVER # These are the emulated inverter communication protocols for which the code will be compiled. inverter: - BYD_CAN diff --git a/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml b/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml index 5955fe9b..4791150b 100644 --- a/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml +++ b/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml @@ -86,7 +86,6 @@ jobs: - SMA_TRIPOWER_CAN - SOFAR_CAN - SOLAX_CAN - - SERIAL_LINK_TRANSMITTER # These are the supported hardware platforms for which the code will be compiled. hardware: - HW_LILYGO diff --git a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml index a522b186..8d0906ba 100644 --- a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml +++ b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml @@ -86,7 +86,6 @@ jobs: - SMA_TRIPOWER_CAN - SOFAR_CAN - SOLAX_CAN - - SERIAL_LINK_TRANSMITTER # These are the supported hardware platforms for which the code will be compiled. hardware: - HW_LILYGO diff --git a/.github/workflows/compile-all-inverters.yml b/.github/workflows/compile-all-inverters.yml index e01bb44d..5084f154 100644 --- a/.github/workflows/compile-all-inverters.yml +++ b/.github/workflows/compile-all-inverters.yml @@ -72,7 +72,6 @@ jobs: - SOFAR_CAN - SOLAX_CAN - SUNGROW_CAN - - SERIAL_LINK_TRANSMITTER - NISSANLEAF_CHARGER # Last element is not an inverter, but good to also test if the charger compiles # These are the supported hardware platforms for which the code will be compiled. hardware: diff --git a/README.md b/README.md index 5ff2741a..fa9f4978 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,6 @@ This code uses the following excellent libraries: - [ayushsharma82/ElegantOTA](https://github.com/ayushsharma82/ElegantOTA) AGPL-3.0 license - [bblanchon/ArduinoJson](https://github.com/bblanchon/ArduinoJson) MIT-License - [eModbus/eModbus](https://github.com/eModbus/eModbus) MIT-License -- [mackelec/SerialDataLink](https://github.com/mackelec/SerialDataLink) - [ESP32Async/AsyncTCP](https://github.com/ESP32Async/AsyncTCP) LGPL-3.0 license - [ESP32Async/ESPAsyncWebServer](https://github.com/ESP32Async/ESPAsyncWebServer) LGPL-3.0 license - [miwagner/ESP32-Arduino-CAN](https://github.com/miwagner/ESP32-Arduino-CAN/) MIT-License diff --git a/Software/Software.ino b/Software/Software.ino index 97e6db10..afc9f221 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -15,7 +15,6 @@ #include "src/communication/nvm/comm_nvm.h" #include "src/communication/precharge_control/precharge_control.h" #include "src/communication/rs485/comm_rs485.h" -#include "src/communication/seriallink/comm_seriallink.h" #include "src/datalayer/datalayer.h" #include "src/devboard/sdcard/sdcard.h" #include "src/devboard/utils/events.h" @@ -109,7 +108,6 @@ void setup() { init_rs485(); - init_serialDataLink(); #if defined(CAN_INVERTER_SELECTED) || defined(MODBUS_INVERTER_SELECTED) || defined(RS485_INVERTER_SELECTED) setup_inverter(); #endif @@ -237,9 +235,6 @@ void core_loop(void* task_time_us) { #if defined(RS485_INVERTER_SELECTED) || defined(RS485_BATTERY_SELECTED) receive_RS485(); // Process serial2 RS485 interface #endif // RS485_INVERTER_SELECTED -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) - run_serialDataLink(); -#endif // SERIAL_LINK_RECEIVER || SERIAL_LINK_TRANSMITTER END_TIME_MEASUREMENT_MAX(comm, datalayer.system.status.time_comm_us); #ifdef WEBSERVER START_TIME_MEASUREMENT(ota); @@ -268,9 +263,7 @@ void core_loop(void* task_time_us) { check_interconnect_available(); #endif // DOUBLE_BATTERY update_calculated_values(); -#ifndef SERIAL_LINK_RECEIVER - update_machineryprotection(); // Check safeties (Not on serial link reciever board) -#endif // SERIAL_LINK_RECEIVER + update_machineryprotection(); // Check safeties update_values_inverter(); // Update values heading towards inverter } END_TIME_MEASUREMENT_MAX(time_values, datalayer.system.status.time_values_us); diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 19dc3a5b..eada030f 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -44,7 +44,6 @@ //#define VOLVO_SPA_HYBRID_BATTERY //#define TEST_FAKE_BATTERY //#define DOUBLE_BATTERY //Enable this line if you use two identical batteries at the same time (requires CAN_ADDON setup) -//#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery) /* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */ //#define AFORE_CAN //Enable this line to emulate an "Afore battery" over CAN bus @@ -65,7 +64,6 @@ //#define SOFAR_CAN //Enable this line to emulate a "Sofar Energy Storage Inverter High Voltage BMS General Protocol (Extended Frame)" over CAN bus //#define SOLAX_CAN //Enable this line to emulate a "SolaX Triple Power LFP" over CAN bus //#define SUNGROW_CAN //Enable this line to emulate a "Sungrow SBR064" over CAN bus -//#define SERIAL_LINK_RECEIVER //Enable this line to receive battery data over RS485 pins from another Lilygo (This LilyGo interfaces with inverter) /* Select hardware used for Battery-Emulator */ //#define HW_LILYGO diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index 149b9965..e50f3633 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -143,10 +143,6 @@ void setup_can_shunt(); #include "VOLVO-SPA-HYBRID-BATTERY.h" #endif -#ifdef SERIAL_LINK_RECEIVER -#include "SERIAL-LINK-RECEIVER-FROM-BATTERY.h" -#endif - void setup_battery(void); void update_values_battery(); diff --git a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp deleted file mode 100644 index 35a7104c..00000000 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include "../include.h" -#ifdef SERIAL_LINK_RECEIVER -#include "../datalayer/datalayer.h" -#include "../devboard/utils/events.h" -#include "SERIAL-LINK-RECEIVER-FROM-BATTERY.h" - -#define INVERTER_SEND_NUM_VARIABLES 1 -#define INVERTER_RECV_NUM_VARIABLES 16 - -#ifdef INVERTER_SEND_NUM_VARIABLES -const uint8_t sendingNumVariables = INVERTER_SEND_NUM_VARIABLES; -#else -const uint8_t sendingNumVariables = 0; -#endif - -#ifdef TESTBENCH -// In the testbench environment, the receiver uses Serial3 -#define SerialReceiver Serial3 -#else -// In the production environment, the receiver uses Serial2 -#define SerialReceiver Serial2 -#endif - -// txid,rxid, num_send,num_recv -SerialDataLink dataLinkReceive(SerialReceiver, 0, 0x01, sendingNumVariables, - INVERTER_RECV_NUM_VARIABLES); // ... - -static bool batteryFault = false; // used locally - mainly to indicate Battery CAN failure - -void __getData() { - datalayer.battery.status.real_soc = (uint16_t)dataLinkReceive.getReceivedData(0); - datalayer.battery.status.soh_pptt = (uint16_t)dataLinkReceive.getReceivedData(1); - datalayer.battery.status.voltage_dV = (uint16_t)dataLinkReceive.getReceivedData(2); - datalayer.battery.status.current_dA = (int16_t)dataLinkReceive.getReceivedData(3); - datalayer.battery.info.total_capacity_Wh = - (uint32_t)(dataLinkReceive.getReceivedData(4) * 10); //add back missing decimal - datalayer.battery.status.remaining_capacity_Wh = - (uint32_t)(dataLinkReceive.getReceivedData(5) * 10); //add back missing decimal - datalayer.battery.status.max_discharge_power_W = - (uint32_t)(dataLinkReceive.getReceivedData(6) * 10); //add back missing decimal - datalayer.battery.status.max_charge_power_W = - (uint32_t)(dataLinkReceive.getReceivedData(7) * 10); //add back missing decimal - uint16_t _system_bms_status = (uint16_t)dataLinkReceive.getReceivedData(8); - datalayer.battery.status.active_power_W = - (uint32_t)(dataLinkReceive.getReceivedData(9) * 10); //add back missing decimal - datalayer.battery.status.temperature_min_dC = (int16_t)dataLinkReceive.getReceivedData(10); - datalayer.battery.status.temperature_max_dC = (int16_t)dataLinkReceive.getReceivedData(11); - datalayer.battery.status.cell_max_voltage_mV = (uint16_t)dataLinkReceive.getReceivedData(12); - datalayer.battery.status.cell_min_voltage_mV = (uint16_t)dataLinkReceive.getReceivedData(13); - datalayer.battery.info.chemistry = (battery_chemistry_enum)dataLinkReceive.getReceivedData(14); - datalayer.system.status.battery_allows_contactor_closing = (bool)dataLinkReceive.getReceivedData(15); - - batteryFault = false; - if (_system_bms_status == FAULT) { - batteryFault = true; - set_event(EVENT_SERIAL_TRANSMITTER_FAILURE, 0); - } -} - -void updateData() { - // --- update with fresh data - dataLinkReceive.updateData(0, datalayer.system.status.inverter_allows_contactor_closing); - //dataLinkReceive.updateData(1,var2); // For future expansion, - //dataLinkReceive.updateData(2,var3); // if inverter needs to send data to battery -} - -/* -* @ 9600bps, assume void manageSerialLinkReceiver() -* is called every 1mS -*/ - -void manageSerialLinkReceiver() { - - static bool lasterror = false; - static unsigned long last_minutesLost = 0; - static unsigned long lastGood; - static uint16_t lastGoodMaxCharge; - static uint16_t lastGoodMaxDischarge; - static bool initLink = false; - static unsigned long reportTime = 0; - static uint16_t reads = 0; - static uint16_t errors = 0; - unsigned long currentTime = millis(); - - if (!initLink) { - initLink = true; - // sends variables every 5000mS even if no change - dataLinkReceive.setUpdateInterval(5000); -#ifdef SERIALDATALINK_MUTEACK - dataLinkReceive.muteACK(true); -#endif - } - dataLinkReceive.run(); - bool readError = dataLinkReceive.checkReadError(true); // check for error & clear error flag - - if (readError) { - logging.print(currentTime); - logging.println(" - ERROR: SerialDataLink - Read Error"); - lasterror = true; - errors++; - } - - if (dataLinkReceive.checkNewData(true)) // true = clear Flag - { - __getData(); - reads++; - lastGoodMaxCharge = datalayer.battery.status.max_charge_power_W; - lastGoodMaxDischarge = datalayer.battery.status.max_discharge_power_W; - //--- if BatteryFault then assume Data is stale - if (!batteryFault) - lastGood = currentTime; - //bms_status = ACTIVE; // just testing - if (lasterror) { - lasterror = false; - logging.print(currentTime); - logging.println(" - RECOVERY: SerialDataLink - Read GOOD"); - } - } - - unsigned long minutesLost = (currentTime - lastGood) / 60000UL; - if (minutesLost > 0 && lastGood > 0) { - // lose 25% each minute of data loss - if (minutesLost < 4) { - datalayer.battery.status.max_charge_power_W = (lastGoodMaxCharge * (4 - minutesLost)) / 4; - datalayer.battery.status.max_discharge_power_W = (lastGoodMaxDischarge * (4 - minutesLost)) / 4; - set_event(EVENT_SERIAL_RX_WARNING, minutesLost); - } else { - // Times Up - - datalayer.battery.status.max_charge_power_W = 0; - datalayer.battery.status.max_discharge_power_W = 0; - set_event(EVENT_SERIAL_RX_FAILURE, uint8_t(min(minutesLost, 255uL))); - //----- Throw Error - } - // report Lost data & Max charge / Discharge reductions - if (minutesLost != last_minutesLost) { - last_minutesLost = minutesLost; - logging.print(currentTime); - if (batteryFault) { - logging.print("Battery Fault (minutes) : "); - } else { - logging.print(" - Minutes without data : "); - } - logging.print(minutesLost); - logging.print(", max Charge = "); - logging.print(datalayer.battery.status.max_charge_power_W); - logging.print(", max Discharge = "); - logging.println(datalayer.battery.status.max_discharge_power_W); - } - } - - if (currentTime - reportTime > 59999) { - reportTime = currentTime; - logging.print(currentTime); - logging.print(" SerialDataLink-Receiver - NewData :"); - logging.print(reads); - logging.print(" Errors : "); - logging.println(errors); - reads = 0; - errors = 0; - -// --- printUsefullData(); -//logging.print("SOC = "); -//logging.println(SOC); -#ifdef DEBUG_LOG - update_values_serial_link(); -#endif - } - - static unsigned long updateTime = 0; - -#ifdef INVERTER_SEND_NUM_VARIABLES - if (currentTime - updateTime > 100) { - updateTime = currentTime; - dataLinkReceive.run(); - bool sendError = dataLinkReceive.checkTransmissionError(true); // check for error & clear error flag - updateData(); - } -#endif -} - -void update_values_serial_link() { - logging.println("Values from battery: "); - logging.print("SOC: "); - logging.print(datalayer.battery.status.real_soc); - logging.print(" SOH: "); - logging.print(datalayer.battery.status.soh_pptt); - logging.print(" Voltage: "); - logging.print(datalayer.battery.status.voltage_dV); - logging.print(" Current: "); - logging.print(datalayer.battery.status.current_dA); - logging.print(" Capacity: "); - logging.print(datalayer.battery.info.total_capacity_Wh); - logging.print(" Remain cap: "); - logging.print(datalayer.battery.status.remaining_capacity_Wh); - logging.print(" Max discharge W: "); - logging.print(datalayer.battery.status.max_discharge_power_W); - logging.print(" Max charge W: "); - logging.print(datalayer.battery.status.max_charge_power_W); - logging.print(" BMS status: "); - logging.print(datalayer.battery.status.bms_status); - logging.print(" Power: "); - logging.print(datalayer.battery.status.active_power_W); - logging.print(" Temp min: "); - logging.print(datalayer.battery.status.temperature_min_dC); - logging.print(" Temp max: "); - logging.print(datalayer.battery.status.temperature_max_dC); - logging.print(" Cell max: "); - logging.print(datalayer.battery.status.cell_max_voltage_mV); - logging.print(" Cell min: "); - logging.print(datalayer.battery.status.cell_min_voltage_mV); - logging.print(" LFP : "); - logging.print(datalayer.battery.info.chemistry); - logging.print(" Battery Allows Contactor Closing: "); - logging.print(datalayer.system.status.battery_allows_contactor_closing); - logging.print(" Inverter Allows Contactor Closing: "); - logging.print(datalayer.system.status.inverter_allows_contactor_closing); - - logging.println(""); -} - -void setup_battery(void) { - strncpy(datalayer.system.info.battery_protocol, "Serial link to another LilyGo board", 63); - datalayer.system.info.battery_protocol[63] = '\0'; -} -// Needed to make the compiler happy -void update_values_battery() {} -void transmit_can_battery() {} -void handle_incoming_can_frame_battery(CAN_frame rx_frame) {} - -#endif diff --git a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h deleted file mode 100644 index 6be72424..00000000 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h +++ /dev/null @@ -1,15 +0,0 @@ -// SERIAL-LINK-RECEIVER-FROM-BATTERY.h - -#ifndef SERIAL_LINK_RECEIVER_FROM_BATTERY_H -#define SERIAL_LINK_RECEIVER_FROM_BATTERY_H - -#define BATTERY_SELECTED - -#include "../include.h" -#include "../lib/mackelec-SerialDataLink/SerialDataLink.h" - -void manageSerialLinkReceiver(); -void update_values_serial_link(); -void setup_battery(void); - -#endif diff --git a/Software/src/communication/rs485/comm_rs485.cpp b/Software/src/communication/rs485/comm_rs485.cpp index 4d5ba508..1288baf6 100644 --- a/Software/src/communication/rs485/comm_rs485.cpp +++ b/Software/src/communication/rs485/comm_rs485.cpp @@ -9,9 +9,6 @@ uint16_t mbPV[MB_RTU_NUM_VALUES]; // Process variable memory // Create a ModbusRTU server instance listening on Serial2 with 2000ms timeout ModbusServerRTU MBserver(Serial2, 2000); #endif -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) -#define SERIAL_LINK_BAUDRATE 112500 -#endif // Initialization functions diff --git a/Software/src/communication/seriallink/comm_seriallink.cpp b/Software/src/communication/seriallink/comm_seriallink.cpp deleted file mode 100644 index b355ae97..00000000 --- a/Software/src/communication/seriallink/comm_seriallink.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "comm_seriallink.h" -#include "../../include.h" - -// Parameters - -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) -#define SERIAL_LINK_BAUDRATE 112500 -#endif - -// Initialization functions - -void init_serialDataLink() { -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) - Serial2.begin(SERIAL_LINK_BAUDRATE, SERIAL_8N1, RS485_RX_PIN, RS485_TX_PIN); -#endif // SERIAL_LINK_RECEIVER || SERIAL_LINK_TRANSMITTER -} - -// Main functions - -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) -void run_serialDataLink() { - static unsigned long updateTime = 0; - unsigned long currentMillis = millis(); - - if ((currentMillis - updateTime) > 1) { //Every 2ms - updateTime = currentMillis; -#ifdef SERIAL_LINK_RECEIVER - manageSerialLinkReceiver(); -#endif -#ifdef SERIAL_LINK_TRANSMITTER - manageSerialLinkTransmitter(); -#endif - } -} -#endif // SERIAL_LINK_RECEIVER || SERIAL_LINK_TRANSMITTER diff --git a/Software/src/communication/seriallink/comm_seriallink.h b/Software/src/communication/seriallink/comm_seriallink.h deleted file mode 100644 index c88b3437..00000000 --- a/Software/src/communication/seriallink/comm_seriallink.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _COMM_SERIALLINK_H_ -#define _COMM_SERIALLINK_H_ - -#include "../../include.h" - -/** - * @brief Initialization of serial data link - * - * @param[in] void - * - * @return void - */ -void init_serialDataLink(); - -void run_serialDataLink(); - -#endif diff --git a/Software/src/include.h b/Software/src/include.h index 2d0817ed..d06d89dd 100644 --- a/Software/src/include.h +++ b/Software/src/include.h @@ -30,20 +30,6 @@ #endif #endif -#ifdef MODBUS_INVERTER_SELECTED -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) -// Check that Dual LilyGo via RS485 option isn't enabled, this collides with Modbus! -#error MODBUS CANNOT BE USED IN DOUBLE LILYGO SETUPS! CHECK USER SETTINGS! -#endif -#endif - -#ifdef RS485_INVERTER_SELECTED -#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) -// Check that Dual LilyGo via RS485 option isn't enabled, this collides with Modbus! -#error RS485 CANNOT BE USED IN DOUBLE LILYGO SETUPS! CHECK USER SETTINGS! -#endif -#endif - #ifdef HW_LILYGO #if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET) #if defined(CAN_ADDON) || defined(CANFD_ADDON) || defined(CHADEMO_BATTERY) diff --git a/Software/src/inverter/INVERTERS.h b/Software/src/inverter/INVERTERS.h index 3a73ff5f..8b222874 100644 --- a/Software/src/inverter/INVERTERS.h +++ b/Software/src/inverter/INVERTERS.h @@ -75,10 +75,6 @@ #include "SUNGROW-CAN.h" #endif -#ifdef SERIAL_LINK_TRANSMITTER -#include "SERIAL-LINK-TRANSMITTER-INVERTER.h" -#endif - #ifdef CAN_INVERTER_SELECTED void update_values_can_inverter(); void map_can_frame_to_variable_inverter(CAN_frame rx_frame); diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp deleted file mode 100644 index 35772e4a..00000000 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "../include.h" -#ifdef SERIAL_LINK_TRANSMITTER - -#include "../datalayer/datalayer.h" -#include "../devboard/utils/events.h" -#include "SERIAL-LINK-TRANSMITTER-INVERTER.h" - -/* -* SerialDataLink -* txid=1, rxid=0 gives this the startup transmit priority_queue -* Will transmit max 16 int variable - receive none -*/ - -#define BATTERY_SEND_NUM_VARIABLES 16 -#define BATTERY_RECV_NUM_VARIABLES 1 - -#ifdef BATTERY_RECV_NUM_VARIABLES -const uint8_t receivingNumVariables = BATTERY_RECV_NUM_VARIABLES; -#else -const uint8_t receivingNumVariables = 0; -#endif - -// txid,rxid,num_tx,num_rx -SerialDataLink dataLinkTransmit(Serial2, 0x01, 0, BATTERY_SEND_NUM_VARIABLES, receivingNumVariables); - -void printSendingValues(); - -void _getData() { - datalayer.system.status.inverter_allows_contactor_closing = dataLinkTransmit.getReceivedData(0); - //var2 = dataLinkTransmit.getReceivedData(1); // For future expansion, - //var3 = dataLinkTransmit.getReceivedData(2); // if inverter needs to send data to battery -} - -void manageSerialLinkTransmitter() { - static bool initLink = false; - static unsigned long updateTime = 0; - static bool lasterror = false; - //static unsigned long lastNoError = 0; - static unsigned long transmitGoodSince = 0; - static unsigned long lastGood = 0; - - unsigned long currentTime = millis(); - - dataLinkTransmit.run(); - -#ifdef BATTERY_RECV_NUM_VARIABLES - bool readError = dataLinkTransmit.checkReadError(true); // check for error & clear error flag - if (dataLinkTransmit.checkNewData(true)) // true = clear Flag - { - _getData(); - } -#endif - - if (currentTime - updateTime > INTERVAL_100_MS) { - updateTime = currentTime; - if (!initLink) { - initLink = true; - transmitGoodSince = currentTime; - dataLinkTransmit.setUpdateInterval(INTERVAL_10_S); - } - bool sendError = dataLinkTransmit.checkTransmissionError(true); - if (sendError) { - logging.print(currentTime); - logging.println(" - ERROR: Serial Data Link - SEND Error"); - lasterror = true; - transmitGoodSince = currentTime; - } - - /* new feature */ - /* @getLastAcknowledge(bool resetFlag) - * - returns: - * -2 NACK received from receiver - * -1 no ACK received - * 0 no activity - * 1 ACK received - * resetFlag = true will clear to 0 - */ - - int ackReceived = dataLinkTransmit.getLastAcknowledge(true); - if (ackReceived > 0) - lastGood = currentTime; - - if (lasterror && (ackReceived > 0)) { - lasterror = false; - logging.print(currentTime); - logging.println(" - RECOVERY: Serial Data Link - Send GOOD"); - } - - //--- reporting every 60 seconds that transmission is good - if (currentTime - transmitGoodSince > INTERVAL_60_S) { - transmitGoodSince = currentTime; - logging.print(currentTime); - logging.println(" - Transmit Good"); -// printUsefullData(); -#ifdef DEBUG_LOG - void printSendingValues(); -#endif - } - - //--- report that Errors been ocurring for > 60 seconds - if (currentTime - lastGood > INTERVAL_60_S) { - lastGood = currentTime; - logging.print(currentTime); - logging.println(" - Transmit Failed : 60 seconds"); - // print the max_ data - logging.println("SerialDataLink : bms_status=4"); - logging.println("SerialDataLink : LEDcolor = RED"); - logging.println("SerialDataLink : max_target_discharge_power = 0"); - logging.println("SerialDataLink : max_target_charge_power = 0"); - - datalayer.battery.status.max_discharge_power_W = 0; - datalayer.battery.status.max_charge_power_W = 0; - set_event(EVENT_SERIAL_TX_FAILURE, 0); - // throw error - } - /* - // lastMessageReceived from CAN bus (Battery) - if (currentTime - lastMessageReceived > (5 * 60000) ) // 5 minutes - { - logging.print(millis()); - logging.println(" - Data Stale : 5 minutes"); - // throw error - - // stop transmitting until fresh - } - */ - - static unsigned long updateDataTime = 0; - - if (currentTime - updateDataTime > INTERVAL_1_S) { - strncpy(datalayer.system.info.inverter_protocol, "Serial link to another LilyGo board", 63); - datalayer.system.info.inverter_protocol[63] = '\0'; - updateDataTime = currentTime; - dataLinkTransmit.updateData(0, datalayer.battery.status.real_soc); - dataLinkTransmit.updateData(1, datalayer.battery.status.soh_pptt); - dataLinkTransmit.updateData(2, datalayer.battery.status.voltage_dV); - dataLinkTransmit.updateData(3, datalayer.battery.status.current_dA); - dataLinkTransmit.updateData(4, datalayer.battery.info.total_capacity_Wh / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(5, - datalayer.battery.status.remaining_capacity_Wh / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(6, - datalayer.battery.status.max_discharge_power_W / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(7, datalayer.battery.status.max_charge_power_W / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(8, datalayer.battery.status.bms_status); - dataLinkTransmit.updateData(9, datalayer.battery.status.active_power_W / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(10, datalayer.battery.status.temperature_min_dC); - dataLinkTransmit.updateData(11, datalayer.battery.status.temperature_max_dC); - dataLinkTransmit.updateData(12, datalayer.battery.status.cell_max_voltage_mV); - dataLinkTransmit.updateData(13, datalayer.battery.status.cell_min_voltage_mV); - dataLinkTransmit.updateData(14, (int16_t)datalayer.battery.info.chemistry); - dataLinkTransmit.updateData(15, datalayer.system.status.battery_allows_contactor_closing); - } - } -} - -void printSendingValues() { - logging.println("Values from battery: "); - logging.print("SOC: "); - logging.print(datalayer.battery.status.real_soc); - logging.print(" SOH: "); - logging.print(datalayer.battery.status.soh_pptt); - logging.print(" Voltage: "); - logging.print(datalayer.battery.status.voltage_dV); - logging.print(" Current: "); - logging.print(datalayer.battery.status.current_dA); - logging.print(" Capacity: "); - logging.print(datalayer.battery.info.total_capacity_Wh); - logging.print(" Remain cap: "); - logging.print(datalayer.battery.status.remaining_capacity_Wh); - logging.print(" Max discharge W: "); - logging.print(datalayer.battery.status.max_discharge_power_W); - logging.print(" Max charge W: "); - logging.print(datalayer.battery.status.max_charge_power_W); - logging.print(" BMS status: "); - logging.print(datalayer.battery.status.bms_status); - logging.print(" Power: "); - logging.print(datalayer.battery.status.active_power_W); - logging.print(" Temp min: "); - logging.print(datalayer.battery.status.temperature_min_dC); - logging.print(" Temp max: "); - logging.print(datalayer.battery.status.temperature_max_dC); - logging.print(" Cell max: "); - logging.print(datalayer.battery.status.cell_max_voltage_mV); - logging.print(" Cell min: "); - logging.print(datalayer.battery.status.cell_min_voltage_mV); - logging.print(" LFP : "); - logging.print(datalayer.battery.info.chemistry); - logging.print(" Battery Allows Contactor Closing: "); - logging.print(datalayer.system.status.battery_allows_contactor_closing); - logging.print(" Inverter Allows Contactor Closing: "); - logging.print(datalayer.system.status.inverter_allows_contactor_closing); - - logging.println(""); -} -#endif diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h deleted file mode 100644 index 1637e6bd..00000000 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SERIAL_LINK_TRANSMITTER_INVERTER_H -#define SERIAL_LINK_TRANSMITTER_INVERTER_H - -#include -#include "../include.h" -#include "../lib/mackelec-SerialDataLink/SerialDataLink.h" - -void manageSerialLinkTransmitter(); -void setup_inverter(void); - -#endif diff --git a/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.cpp b/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.cpp deleted file mode 100644 index f055fe8f..00000000 --- a/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.cpp +++ /dev/null @@ -1,607 +0,0 @@ -// SerialDataLink.cpp - -#include "SerialDataLink.h" - - -const uint16_t crcTable[256] = { - 0, 32773, 32783, 10, 32795, 30, 20, 32785, - 32819, 54, 60, 32825, 40, 32813, 32807, 34, - 32867, 102, 108, 32873, 120, 32893, 32887, 114, - 80, 32853, 32863, 90, 32843, 78, 68, 32833, - 32963, 198, 204, 32969, 216, 32989, 32983, 210, - 240, 33013, 33023, 250, 33003, 238, 228, 32993, - 160, 32933, 32943, 170, 32955, 190, 180, 32945, - 32915, 150, 156, 32921, 136, 32909, 32903, 130, - 33155, 390, 396, 33161, 408, 33181, 33175, 402, - 432, 33205, 33215, 442, 33195, 430, 420, 33185, - 480, 33253, 33263, 490, 33275, 510, 500, 33265, - 33235, 470, 476, 33241, 456, 33229, 33223, 450, - 320, 33093, 33103, 330, 33115, 350, 340, 33105, - 33139, 374, 380, 33145, 360, 33133, 33127, 354, - 33059, 294, 300, 33065, 312, 33085, 33079, 306, - 272, 33045, 33055, 282, 33035, 270, 260, 33025, - 33539, 774, 780, 33545, 792, 33565, 33559, 786, - 816, 33589, 33599, 826, 33579, 814, 804, 33569, - 864, 33637, 33647, 874, 33659, 894, 884, 33649, - 33619, 854, 860, 33625, 840, 33613, 33607, 834, - 960, 33733, 33743, 970, 33755, 990, 980, 33745, - 33779, 1014, 1020, 33785, 1000, 33773, 33767, 994, - 33699, 934, 940, 33705, 952, 33725, 33719, 946, - 912, 33685, 33695, 922, 33675, 910, 900, 33665, - 640, 33413, 33423, 650, 33435, 670, 660, 33425, - 33459, 694, 700, 33465, 680, 33453, 33447, 674, - 33507, 742, 748, 33513, 760, 33533, 33527, 754, - 720, 33493, 33503, 730, 33483, 718, 708, 33473, - 33347, 582, 588, 33353, 600, 33373, 33367, 594, - 624, 33397, 33407, 634, 33387, 622, 612, 33377, - 544, 33317, 33327, 554, 33339, 574, 564, 33329, - 33299, 534, 540, 33305, 520, 33293, 33287, 514 -}; - -union Convert -{ - uint16_t u16; - int16_t i16; - struct - { - byte low; - byte high; - }; -}convert; - -/* -#define SET_PA6() (GPIOA->BSRR = GPIO_BSRR_BS6) -#define CLEAR_PA6() (GPIOA->BSRR = GPIO_BSRR_BR6) -// Macro to toggle PA6 -#define TOGGLE_PA6() (GPIOA->ODR ^= GPIO_ODR_ODR6) -*/ - -// Constructor -SerialDataLink::SerialDataLink(Stream &serial, uint8_t transmitID, uint8_t receiveID, uint8_t maxIndexTX, uint8_t maxIndexRX, bool enableRetransmit) - : serial(serial), transmitID(transmitID), receiveID(receiveID), maxIndexTX(maxIndexTX), maxIndexRX(maxIndexRX), retransmitEnabled(enableRetransmit) { - // Initialize buffers and state variables - txBufferIndex = 0; - isTransmitting = false; - isReceiving = false; - transmissionError = false; - readError = false; - newData = false; - - // Initialize data arrays and update flags - - memset(dataArrayTX, 0, sizeof(dataArrayTX)); - memset(dataArrayRX, 0, sizeof(dataArrayRX)); - memset(dataUpdated, 0, sizeof(dataUpdated)); - memset(lastSent , 0, sizeof(lastSent )); - - // Additional initialization as required -} - -void SerialDataLink::updateData(uint8_t index, int16_t value) -{ - if (index < maxIndexTX) - { - if (dataArrayTX[index] != value) - { - dataArrayTX[index] = value; - dataUpdated[index] = true; - lastSent[index] = millis(); - } - } -} - -int16_t SerialDataLink::getReceivedData(uint8_t index) -{ - if (index < dataArraySizeRX) { - return dataArrayRX[index]; - } else { - // Handle the case where the index is out of bounds - return -1; - } -} - -bool SerialDataLink::checkTransmissionError(bool resetFlag) -{ - bool currentStatus = transmissionError; - if (resetFlag && transmissionError) { - transmissionError = false; - } - return currentStatus; -} - -int SerialDataLink::getLastAcknowledge(bool resetFlag) -{ - int result = lastAcknowledgeStatus; - if (resetFlag) - { - lastAcknowledgeStatus = 0; // Reset to default state - } - return result; -} - -bool SerialDataLink::checkReadError(bool reset) -{ - bool error = readError; - if (reset) { - readError = false; - } - return error; -} - - -bool SerialDataLink::checkNewData(bool resetFlag) { - bool currentStatus = newData; - if (resetFlag && newData) { - newData = false; - } - return currentStatus; -} - -void SerialDataLink::muteACK(bool mute) -{ - muteAcknowledgement = mute; -} - -void SerialDataLink::run() -{ - unsigned long currentTime = millis(); - static DataLinkState oldstate; - - - // Check if state has not changed for a prolonged period - if (oldstate != currentState) - { - lastStateChangeTime = currentTime; - oldstate = currentState; - } - if ((currentTime - lastStateChangeTime) > stateChangeTimeout) { - // Reset the state to Idle and perform necessary cleanup - currentState = DataLinkState::Idle; - // Perform any additional cleanup or reinitialization here - // ... - - lastStateChangeTime = currentTime; // Reset the last state change time - } - - switch (currentState) - { - case DataLinkState::Idle: - // Decide if the device should start transmitting - currentState = DataLinkState::Receiving; - if (shouldTransmit()) - { - currentState = DataLinkState::WaitTobuildPacket; - } - break; - - case DataLinkState::WaitTobuildPacket: - constructPacket(); - if (isTransmitting) - { - currentState = DataLinkState::Transmitting; - } - break; - - case DataLinkState::Transmitting: - sendNextByte(); - - // Check if the transmission is complete - if (transmissionComplete) - { - transmissionComplete = false; - isTransmitting = false; - currentState = DataLinkState::WaitingForAck; // Move to WaitingForAck state - } - break; - - case DataLinkState::WaitingForAck: - - if (ackTimeout()) - { - // Handle ACK timeout scenario - transmissionError = true; - lastAcknowledgeStatus = -1; - //--- if no ACK's etc received may as well move to Transmitting - currentState = DataLinkState::Idle; - } - if (ackReceived()) - { - // No data to send from the other device - currentState = DataLinkState::Idle; - } - if (requestToSend) - { - // The other device has data to send (indicated by ACK+RTT) - currentState = DataLinkState::Receiving; - requestToSend = false; - } - break; - - - case DataLinkState::Receiving: - read(); - if (readComplete) - { - readComplete = false; - currentState = DataLinkState::SendingAck; - } - break; - - case DataLinkState::SendingAck: - - constructPacket(); - - if (muteAcknowledgement && (needToACK || needToNACK)) - { - needToACK = false; - needToNACK = false; - } - uint8_t ack; - // now it is known which acknoledge need sending since last Reception - if (needToACK) - { - needToACK = false; - ack = (txBufferIndex > 5) ? ACK_RTT_CODE : ACK_CODE; - serial.write(ack); - } - if (needToNACK) - { - needToNACK = false; - ack = (txBufferIndex > 5) ? NACK_RTT_CODE : NACK_CODE; - serial.write(ack); - } - - currentState = DataLinkState::Idle; - if (isTransmitting) - { - currentState = DataLinkState::Wait; - } - break; - - case DataLinkState::Wait: - { - static unsigned long waitTimer=0; - if (waitTimer == 0) waitTimer = currentTime; - if (currentTime - waitTimer > 20) - { - waitTimer=0; - currentState = DataLinkState::Transmitting; - } - } - break; - - default: - currentState = DataLinkState::Idle; - } -} - -void SerialDataLink::updateState(DataLinkState newState) -{ - if (currentState != newState) - { - currentState = newState; - lastStateChangeTime = millis(); - } -} - -bool SerialDataLink::shouldTransmit() -{ - // Priority condition: Device with transmitID = 1 and receiveID = 0 has the highest priority - if (transmitID == 1 && receiveID == 0) - { - return true; - } - return false; -} - -void SerialDataLink::constructPacket() -{ - if (maxIndexTX <1) return; - if (!isTransmitting) - { - lastTransmissionTime = millis(); - txBufferIndex = 0; // Reset the TX buffer index - addToTxBuffer(headerChar); - addToTxBuffer(transmitID); - addToTxBuffer(0); // EOT position - place holder - unsigned long currentTime = millis(); - int count = txBufferIndex; - for (uint8_t i = 0; i < maxIndexTX; i++) - { - if (dataUpdated[i] || (currentTime - lastSent[i] >= updateInterval)) - { - addToTxBuffer(i); - convert.i16 = dataArrayTX[i]; - addToTxBuffer(convert.high); - addToTxBuffer(convert.low); - - dataUpdated[i] = false; - lastSent[i] = currentTime; // Update the last sent time for this index - } - } - - if (count == txBufferIndex) - { - // No data was added to the buffer, so no need to send a packet - return; - } - - addToTxBuffer(eotChar); - //----- assign EOT position - txBuffer[2] = txBufferIndex - 1; - uint16_t crc = calculateCRC16(txBuffer, txBufferIndex); - convert.u16 = crc; - addToTxBuffer(convert.high); - addToTxBuffer(convert.low); - isTransmitting = true; - } -} - - -void SerialDataLink::addToTxBuffer(uint8_t byte) -{ - if (txBufferIndex < txBufferSize) - { - txBuffer[txBufferIndex] = byte; - txBufferIndex++; - } -} - -bool SerialDataLink::sendNextByte() -{ - if (!isTransmitting) return false; - - if (txBufferIndex >= txBufferSize) - { - txBufferIndex = 0; // Reset the TX buffer index - isTransmitting = false; - return false; // Buffer was fully sent, end transmission - } - serial.write(txBuffer[sendBufferIndex]); - sendBufferIndex++; - - if (sendBufferIndex >= txBufferIndex) - { - isTransmitting = false; - txBufferIndex = 0; // Reset the TX buffer index for the next packet - sendBufferIndex = 0; - transmissionComplete = true; - return true; // Packet was fully sent - } - return false; // More bytes remain to be sent -} - -bool SerialDataLink::ackReceived() -{ - - // Check if there is data available to read - int count = 0; - if (serial.available() ) - { - count++; - // Peek at the next byte without removing it from the buffer - uint8_t nextByte = serial.peek(); - - if (nextByte == headerChar) - { - requestToSend = true; - transmissionError = true; - return false; - } - - uint8_t receivedByte = serial.read(); - - switch (receivedByte) - { - case ACK_CODE: - // Handle standard ACK - lastAcknowledgeStatus = 1; - return true; - - case ACK_RTT_CODE: - // Handle ACK with request to transmit - requestToSend = true; - lastAcknowledgeStatus = 1; - return true; - - case NACK_RTT_CODE: - requestToSend = true; - case NACK_CODE: - transmissionError = true; - lastAcknowledgeStatus = -2; - return true; - break; - default: - break; - } - } - - return false; // No ACK, NACK, or new packet received -} - -bool SerialDataLink::ackTimeout() -{ - // Check if the current time has exceeded the last transmission time by the ACK timeout period - - if (millis() - lastTransmissionTime > ACK_TIMEOUT) - { - return true; // Timeout occurred - } - return false; // No timeout -} - - - -void SerialDataLink::read() -{ - if (maxIndexRX < 1) return; - int count = 0; - while (serial.available() && count < 10) - { - count++; - if (millis() - lastHeaderTime > PACKET_TIMEOUT && rxBufferIndex > 0) - { - // Timeout occurred, reset buffer and pointer - rxBufferIndex = 0; - eotPosition = 0; - readError = true; - } - uint8_t incomingByte = serial.read(); - switch (rxBufferIndex) { - case 0: // Looking for the header - if (incomingByte == headerChar) - { - lastHeaderTime = millis(); - rxBuffer[rxBufferIndex] = incomingByte; - rxBufferIndex++; - } - break; - - case 1: // Looking for the address - if (incomingByte == receiveID) { - rxBuffer[rxBufferIndex] = incomingByte; - rxBufferIndex++; - } else { - // Address mismatch, reset to look for a new packet - rxBufferIndex = 0; - } - break; - - case 2: // EOT position - eotPosition = incomingByte; - rxBuffer[rxBufferIndex] = incomingByte; - rxBufferIndex++; - break; - - default: - // Normal data handling - rxBuffer[rxBufferIndex] = incomingByte; - rxBufferIndex++; - - if (isCompletePacket()) - { - processPacket(); - rxBufferIndex = 0; // Reset for the next packet - readComplete = true; // Indicate that read operation is complete - } - - // Check for buffer overflow - if (rxBufferIndex >= rxBufferSize) - { - rxBufferIndex = 0; - } - break; - } - } -} - -bool SerialDataLink::isCompletePacket() { - if (rxBufferIndex - 3 < eotPosition) return false; - // Ensure there are enough bytes for EOT + 2-byte CRC - - // Check if the third-last byte is the EOT character - if (rxBuffer[eotPosition] == eotChar) - { - return true; - } - return false; -} - -bool SerialDataLink::checkCRC() -{ - uint16_t receivedCrc; - if (rxBufferIndex < 3) - { - // Not enough data for CRC check - return false; - } - - - convert.high = rxBuffer[rxBufferIndex - 2]; - convert.low = rxBuffer[rxBufferIndex - 1]; - receivedCrc = convert.u16; - - // Calculate CRC for the received data (excluding the CRC bytes themselves) - uint16_t calculatedCrc = calculateCRC16(rxBuffer, rxBufferIndex - 2); - return receivedCrc == calculatedCrc; -} - - -void SerialDataLink::processPacket() -{ - - if (!checkCRC()) { - // CRC check failed, handle the error - readError = true; - return; - } - - // Start from index 3 to skip the SOT and ADDRESS and EOT Position characters - uint8_t i = 3; - while (i < eotPosition) - { - uint8_t arrayID = rxBuffer[i++]; - - // Make sure there's enough data for a complete int16 (2 bytes) - if (i + 1 >= rxBufferIndex) { - readError = true; - needToNACK = true; - return; // Incomplete packet or buffer overflow - } - - // Combine the next two bytes into an int16 value - int16_t value = (int16_t(rxBuffer[i]) << 8) | int16_t(rxBuffer[i + 1]); - i += 2; - - // Handle the array ID and value here - if (arrayID < dataArraySizeRX) { - dataArrayRX[arrayID] = value; - } - else - { - // Handle invalid array ID - readError = true; - needToNACK = true; - return; - } - newData = true; - needToACK = true; - } -} - - - -void SerialDataLink::setUpdateInterval(unsigned long interval) { - updateInterval = interval; -} - -void SerialDataLink::setAckTimeout(unsigned long timeout) { - ACK_TIMEOUT = timeout; -} - -void SerialDataLink::setPacketTimeout(unsigned long timeout) { - PACKET_TIMEOUT = timeout; -} - -void SerialDataLink::setHeaderChar(char header) -{ - headerChar = header; -} - -void SerialDataLink::setEOTChar(char eot) -{ - eotChar = eot; -} - - - -uint16_t SerialDataLink::calculateCRC16(const uint8_t* data, size_t length) -{ - uint16_t crc = 0xFFFF; // Start value for CRC - for (size_t i = 0; i < length; i++) - { - uint8_t index = (crc >> 8) ^ data[i]; - crc = (crc << 8) ^ crcTable[index]; - } - return crc; -} diff --git a/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.h b/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.h deleted file mode 100644 index 98c44b2c..00000000 --- a/Software/src/lib/mackelec-SerialDataLink/SerialDataLink.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file SerialDataLink.h - * @brief Half-Duplex Serial Data Link for Arduino - * - * This file contains the definition of the SerialDataLink class, designed to facilitate - * half-duplex communication between Arduino controllers. The class employs a non-blocking, - * poll-based approach to transmit and receive data, making it suitable for applications - * where continuous monitoring and variable transfer between controllers are required. - * - * The half-duplex nature of this implementation allows for data transfer in both directions, - * but not simultaneously, ensuring a controlled communication flow and reducing the likelihood - * of data collision. - * - * - * @author MackElec - * @web https://github.com/mackelec/SerialDataLink - * @license MIT - */ - -// ... Class definition ... - -/** - * @class SerialDataLink - * @brief Class for managing half-duplex serial communication. - * - * Provides functions to send and receive data in a half-duplex manner over a serial link. - * It supports non-blocking operation with a polling approach to check for new data and - * transmission errors. - * - * Public Methods: - * - SerialDataLink(): Constructor to initialize the communication parameters. - * - run(): Main method to be called frequently to handle data transmission and reception. - * - updateData(): Method to update data to be transmitted. - * - getReceivedData(): Retrieves data received from the serial link. - * - checkNewData(): Checks if new data has been received. - * - checkTransmissionError(): Checks for transmission errors. - * - checkReadError(): Checks for read errors. - * - setUpdateInterval(): Sets the interval for data updates. - * - setAckTimeout(): Sets the timeout for acknowledgments. - * - setPacketTimeout(): Sets the timeout for packet reception. - * - setHeaderChar(): Sets the character used to denote the start of a packet. - * - setEOTChar(): Sets the character used to denote the end of a packet. - */ - - - - -#ifndef SERIALDATALINK_H -#define SERIALDATALINK_H - -#include - - - -class SerialDataLink { -public: - // Constructor - SerialDataLink(Stream &serial, uint8_t transmitID, uint8_t receiveID, uint8_t maxIndexTX, uint8_t maxIndexRX, bool enableRetransmit = false); - - // Method to handle data transmission and reception - void run(); - - void updateData(uint8_t index, int16_t value); - - // Check if new data has been received - bool checkNewData(bool resetFlag); - int16_t getReceivedData(uint8_t index); - - // Check for errors - bool checkTransmissionError(bool resetFlag); - int getLastAcknowledge(bool resetFlag); - bool checkReadError(bool resetFlag); - - // Setter methods for various parameters and special characters - - void setUpdateInterval(unsigned long interval); - void setAckTimeout(unsigned long timeout); - void setPacketTimeout(unsigned long timeout); - - void setHeaderChar(char header); - void setEOTChar(char eot); - void muteACK(bool mute); - -private: - enum class DataLinkState - { - Idle, - WaitTobuildPacket, - Transmitting, - WaitingForAck, - Receiving, - SendingAck, - Wait, - Error - }; - - DataLinkState currentState; - Stream &serial; - uint8_t transmitID; - uint8_t receiveID; - - // Separate max indices for TX and RX - const uint8_t maxIndexTX; - const uint8_t maxIndexRX; - - - // Buffer and state management - static const uint8_t txBufferSize = 128; // Adjust size as needed - static const uint8_t rxBufferSize = 128; // Adjust size as needed - - uint8_t txBuffer[txBufferSize]; - uint8_t rxBuffer[rxBufferSize]; - - uint8_t txBufferIndex; - uint8_t rxBufferIndex; - uint8_t sendBufferIndex = 0; - - bool isTransmitting; - bool transmissionComplete = false; - bool isReceiving; - bool readComplete = false; - bool retransmitEnabled; - bool transmissionError = false; - int lastAcknowledgeStatus = 0; - bool readError = false; - bool muteAcknowledgement = false; - - // Data arrays and update management - - static const uint8_t dataArraySizeTX = 20; // Adjust size as needed for TX - static const uint8_t dataArraySizeRX = 20; // Adjust size as needed for RX - - int16_t dataArrayTX[dataArraySizeTX]; - int16_t dataArrayRX[dataArraySizeRX]; - bool dataUpdated[dataArraySizeTX]; - unsigned long lastSent[dataArraySizeTX]; - - // times in milliseconds - unsigned long updateInterval = 1000; - unsigned long ACK_TIMEOUT = 200; - unsigned long PACKET_TIMEOUT = 200; - unsigned long stateChangeTimeout = 300; - - unsigned long lastStateChangeTime = 0; - - - // Special characters for packet framing - char headerChar = '<'; - char eotChar = '>'; - - static const uint8_t ACK_CODE = 0x06; // Standard acknowledgment - static const uint8_t ACK_RTT_CODE = 0x07; // Acknowledgment with request to transmit - static const uint8_t NACK_CODE = 0x08; // Negative acknowledgment - static const uint8_t NACK_RTT_CODE = 0x09; // Negative acknowledgment with request to transmit - - - - // Internal methods for packet construction, transmission, and reception - bool shouldTransmit(); - void constructPacket(); - void addToTxBuffer(uint8_t byte); - bool sendNextByte(); - bool ackReceived(); - bool ackTimeout(); - void updateState(DataLinkState newState); - - // Internal methods for reception - void read(); - void handleResendRequest(); - bool isCompletePacket(); - void processPacket(); - void sendACK(); - bool checkCRC(); - uint16_t calculateCRC16(const uint8_t* data, size_t length); - - unsigned long lastTransmissionTime; - bool requestToSend = false; - unsigned long lastHeaderTime = 0; - bool newData = false; - bool needToACK = false; - bool needToNACK = false; - uint8_t eotPosition = 0; -}; - -#endif // SERIALDATALINK_H