From 7cbfd1f05f3d468817b9b73b7fba56e94296efca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96ster?= Date: Sun, 7 Apr 2024 11:43:00 +0300 Subject: [PATCH 01/10] Add include file Fix compilation error for Volvo --- Software/src/battery/VOLVO-SPA-BATTERY.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.cpp b/Software/src/battery/VOLVO-SPA-BATTERY.cpp index b502cb11..8cc0c996 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.cpp +++ b/Software/src/battery/VOLVO-SPA-BATTERY.cpp @@ -1,3 +1,4 @@ +#include "BATTERIES.h" #ifdef VOLVO_SPA_BATTERY #include "VOLVO-SPA-BATTERY.h" #include "../devboard/utils/events.h" From fa3c3d0565d380bb21374a3443aa92646d9f80a2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 7 Apr 2024 11:45:42 +0300 Subject: [PATCH 02/10] Pre-commit fix --- Software/src/battery/VOLVO-SPA-BATTERY.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.cpp b/Software/src/battery/VOLVO-SPA-BATTERY.cpp index 8cc0c996..daa0cf3b 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.cpp +++ b/Software/src/battery/VOLVO-SPA-BATTERY.cpp @@ -1,9 +1,9 @@ #include "BATTERIES.h" #ifdef VOLVO_SPA_BATTERY -#include "VOLVO-SPA-BATTERY.h" #include "../devboard/utils/events.h" #include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h" #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" +#include "VOLVO-SPA-BATTERY.h" /* Do not change code below unless you are sure what you are doing */ static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send From cfb88adc861e6883e9fb65fa65ee040d9d197ed3 Mon Sep 17 00:00:00 2001 From: itpr-gwis2 Date: Sun, 7 Apr 2024 12:22:27 +0300 Subject: [PATCH 03/10] platformio --- platformio.ini | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 platformio.ini diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 00000000..20b7c24e --- /dev/null +++ b/platformio.ini @@ -0,0 +1,20 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +src_dir = ./Software + +[env:esp32dev] +platform = espressif32 +board = esp32dev +monitor_speed = 115200 +framework = arduino +build_flags = -I include +lib_deps = From bff2de990c32ca8d44167aa34263e7de1baa6566 Mon Sep 17 00:00:00 2001 From: itpr-gwis2 Date: Sun, 7 Apr 2024 12:24:11 +0300 Subject: [PATCH 04/10] platformio gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 309ff8ff..283ec4ef 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,10 @@ # Ignore .exe (unit tests) *.exe **/.DS_Store + +#ignore platformio +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json +.pio \ No newline at end of file From 6c1777550d25821fc4ab933787ec52f84a6d7f22 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 7 Apr 2024 20:13:32 +0300 Subject: [PATCH 05/10] Increase datatypes for W over 60kW --- Software/Software.ino | 16 ++++++++-------- Software/src/battery/BMW-I3-BATTERY.h | 16 ++++++++-------- Software/src/battery/CHADEMO-BATTERY.h | 16 ++++++++-------- Software/src/battery/IMIEV-CZERO-ION-BATTERY.h | 16 ++++++++-------- Software/src/battery/NISSAN-LEAF-BATTERY.h | 16 ++++++++-------- Software/src/battery/RENAULT-KANGOO-BATTERY.h | 16 ++++++++-------- Software/src/battery/RENAULT-ZOE-BATTERY.h | 16 ++++++++-------- Software/src/battery/SANTA-FE-PHEV-BATTERY.h | 16 ++++++++-------- .../SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp | 6 +++--- .../battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h | 16 ++++++++-------- Software/src/battery/TESLA-MODEL-3-BATTERY.h | 16 ++++++++-------- Software/src/battery/TEST-FAKE-BATTERY.h | 16 ++++++++-------- Software/src/battery/VOLVO-SPA-BATTERY.h | 16 ++++++++-------- Software/src/charger/NISSAN-LEAF-CHARGER.h | 2 +- Software/src/devboard/mqtt/mqtt.h | 4 ++-- Software/src/devboard/webserver/settings_html.h | 2 +- Software/src/devboard/webserver/webserver.h | 16 ++++++++-------- Software/src/inverter/BYD-CAN.h | 16 ++++++++-------- Software/src/inverter/BYD-MODBUS.h | 16 ++++++++-------- Software/src/inverter/LUNA2000-MODBUS.h | 16 ++++++++-------- Software/src/inverter/PYLON-CAN.h | 16 ++++++++-------- .../SERIAL-LINK-TRANSMITTER-INVERTER.cpp | 6 +++--- .../inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h | 12 ++++++------ Software/src/inverter/SMA-CAN.cpp | 7 +++++++ Software/src/inverter/SMA-CAN.h | 16 ++++++++-------- Software/src/inverter/SMA-TRIPOWER-CAN.cpp | 17 ++++++++++++----- Software/src/inverter/SMA-TRIPOWER-CAN.h | 16 ++++++++-------- Software/src/inverter/SOFAR-CAN.h | 16 ++++++++-------- Software/src/inverter/SOLAX-CAN.h | 16 ++++++++-------- 29 files changed, 203 insertions(+), 189 deletions(-) diff --git a/Software/Software.ino b/Software/Software.ino index ae9c9db8..0411aa70 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -56,20 +56,20 @@ ModbusServerRTU MBserver(Serial2, 2000); #endif // Common system parameters. Batteries map their values to these variables -uint32_t system_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-150000Wh -uint32_t system_remaining_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-150000Wh +uint32_t system_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-250000 Wh +uint32_t system_remaining_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-250000 Wh int16_t system_temperature_max_dC = 0; //C+1, -50.0 - 50.0 int16_t system_temperature_min_dC = 0; //C+1, -50.0 - 50.0 -int16_t system_active_power_W = 0; //Watts, -32000 to 32000 +int32_t system_active_power_W = 0; //Watts, -200000 to 200000 W int16_t system_battery_current_dA = 0; //A+1, -1000 - 1000 -uint16_t system_battery_voltage_dV = 3700; //V+1, 0-500.0 (0-5000) -uint16_t system_max_design_voltage_dV = 5000; //V+1, 0-500.0 (0-5000) -uint16_t system_min_design_voltage_dV = 2500; //V+1, 0-500.0 (0-5000) +uint16_t system_battery_voltage_dV = 3700; //V+1, 0-1000.0 (0-10000) +uint16_t system_max_design_voltage_dV = 5000; //V+1, 0-1000.0 (0-10000) +uint16_t system_min_design_voltage_dV = 2500; //V+1, 0-1000.0 (0-10000) uint16_t system_scaled_SOC_pptt = 5000; //SOC%, 0-100.00 (0-10000) uint16_t system_real_SOC_pptt = 5000; //SOC%, 0-100.00 (0-10000) uint16_t system_SOH_pptt = 9900; //SOH%, 0-100.00 (0-10000) -uint16_t system_max_discharge_power_W = 0; //Watts, 0 to 65535 -uint16_t system_max_charge_power_W = 4312; //Watts, 0 to 65535 +uint32_t system_max_discharge_power_W = 0; //Watts, 0 to 100000 +uint32_t system_max_charge_power_W = 4312; //Watts, 0 to 100000 uint16_t system_cell_max_voltage_mV = 3700; //mV, 0-5000 , Stores the highest cell millivolt value uint16_t system_cell_min_voltage_mV = 3700; //mV, 0-5000, Stores the minimum cell millivolt value uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages. Oversized to accomodate all setups diff --git a/Software/src/battery/BMW-I3-BATTERY.h b/Software/src/battery/BMW-I3-BATTERY.h index 8c0d7145..df96edd2 100644 --- a/Software/src/battery/BMW-I3-BATTERY.h +++ b/Software/src/battery/BMW-I3-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/CHADEMO-BATTERY.h b/Software/src/battery/CHADEMO-BATTERY.h index 9af21b66..8aaf34c8 100644 --- a/Software/src/battery/CHADEMO-BATTERY.h +++ b/Software/src/battery/CHADEMO-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h index 9b88b506..a1bc02bc 100644 --- a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h +++ b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index 506781cc..a94dd7cc 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/RENAULT-KANGOO-BATTERY.h b/Software/src/battery/RENAULT-KANGOO-BATTERY.h index c2c5e7a5..a29cf62b 100644 --- a/Software/src/battery/RENAULT-KANGOO-BATTERY.h +++ b/Software/src/battery/RENAULT-KANGOO-BATTERY.h @@ -14,20 +14,20 @@ #define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/RENAULT-ZOE-BATTERY.h b/Software/src/battery/RENAULT-ZOE-BATTERY.h index 83ef9a8f..acfaccf7 100644 --- a/Software/src/battery/RENAULT-ZOE-BATTERY.h +++ b/Software/src/battery/RENAULT-ZOE-BATTERY.h @@ -14,20 +14,20 @@ #define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h index 8d4e13cb..a7a8fb69 100644 --- a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h +++ b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp index 49c5b0b6..b5dcd788 100644 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp +++ b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp @@ -34,10 +34,10 @@ void __getData() { system_battery_current_dA = (int16_t)dataLinkReceive.getReceivedData(3); system_capacity_Wh = (uint32_t)(dataLinkReceive.getReceivedData(4) * 10); //add back missing decimal system_remaining_capacity_Wh = (uint32_t)(dataLinkReceive.getReceivedData(5) * 10); //add back missing decimal - system_max_discharge_power_W = (uint16_t)dataLinkReceive.getReceivedData(6); - system_max_charge_power_W = (uint16_t)dataLinkReceive.getReceivedData(7); + system_max_discharge_power_W = (uint32_t)(dataLinkReceive.getReceivedData(6) * 10); //add back missing decimal + system_max_charge_power_W = (uint32_t)(dataLinkReceive.getReceivedData(7) * 10); //add back missing decimal uint16_t _system_bms_status = (uint16_t)dataLinkReceive.getReceivedData(8); - system_active_power_W = (uint16_t)dataLinkReceive.getReceivedData(9); + system_active_power_W = (uint32_t)(dataLinkReceive.getReceivedData(9) * 10); //add back missing decimal system_temperature_min_dC = (int16_t)dataLinkReceive.getReceivedData(10); system_temperature_max_dC = (int16_t)dataLinkReceive.getReceivedData(11); system_cell_max_voltage_mV = (uint16_t)dataLinkReceive.getReceivedData(12); diff --git a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h index 8c4ab623..398b25cd 100644 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h +++ b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h @@ -13,18 +13,18 @@ // https://github.com/mackelec/SerialDataLink // These parameters need to be mapped on the battery side -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint8_t system_bms_status; //Enum 0-5 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value diff --git a/Software/src/battery/TESLA-MODEL-3-BATTERY.h b/Software/src/battery/TESLA-MODEL-3-BATTERY.h index 824bafe9..006a3668 100644 --- a/Software/src/battery/TESLA-MODEL-3-BATTERY.h +++ b/Software/src/battery/TESLA-MODEL-3-BATTERY.h @@ -21,20 +21,20 @@ #define MIN_PACK_VOLTAGE_LFP 2968 // V+1, if pack voltage goes below this, discharge stops // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/TEST-FAKE-BATTERY.h b/Software/src/battery/TEST-FAKE-BATTERY.h index f0c868ca..4b138ec4 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.h +++ b/Software/src/battery/TEST-FAKE-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.h b/Software/src/battery/VOLVO-SPA-BATTERY.h index 72691dfe..6a518c2b 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.h +++ b/Software/src/battery/VOLVO-SPA-BATTERY.h @@ -8,20 +8,20 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/charger/NISSAN-LEAF-CHARGER.h b/Software/src/charger/NISSAN-LEAF-CHARGER.h index f2f3b9a0..133b90ad 100644 --- a/Software/src/charger/NISSAN-LEAF-CHARGER.h +++ b/Software/src/charger/NISSAN-LEAF-CHARGER.h @@ -5,7 +5,7 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) void send_can_nissanleaf_charger(); void receive_can_nissanleaf_charger(CAN_frame_t rx_frame); diff --git a/Software/src/devboard/mqtt/mqtt.h b/Software/src/devboard/mqtt/mqtt.h index 6b699a32..e43a1ae2 100644 --- a/Software/src/devboard/mqtt/mqtt.h +++ b/Software/src/devboard/mqtt/mqtt.h @@ -44,9 +44,9 @@ extern const char* version_number; // The current software version, used for mq extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) diff --git a/Software/src/devboard/webserver/settings_html.h b/Software/src/devboard/webserver/settings_html.h index 4829fba2..7c87883f 100644 --- a/Software/src/devboard/webserver/settings_html.h +++ b/Software/src/devboard/webserver/settings_html.h @@ -4,7 +4,7 @@ #include #include "../../../USER_SETTINGS.h" // Needed for WiFi ssid and password -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) /** * @brief Replaces placeholder with content section in web page diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index ad748147..6c551840 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -17,20 +17,20 @@ #endif extern const char* version_number; // The current software version, shown on webserver -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern int32_t system_active_power_W; //W, -200000 to 200000 +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000 , Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/BYD-CAN.h b/Software/src/inverter/BYD-CAN.h index 5cf9ee46..82ae0cb6 100644 --- a/Software/src/inverter/BYD-CAN.h +++ b/Software/src/inverter/BYD-CAN.h @@ -6,20 +6,20 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/BYD-MODBUS.h b/Software/src/inverter/BYD-MODBUS.h index 9735a5e6..a491de60 100644 --- a/Software/src/inverter/BYD-MODBUS.h +++ b/Software/src/inverter/BYD-MODBUS.h @@ -7,20 +7,20 @@ #define MAX_POWER 40960 //BYD Modbus specific value extern uint16_t mbPV[MB_RTU_NUM_VALUES]; -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern int32_t system_active_power_W; //W, -200000 to 200000 +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint8_t system_bms_status; //Enum 0-5 extern bool batteryAllowsContactorClosing; //Bool, true/false extern bool inverterAllowsContactorClosing; //Bool, true/false diff --git a/Software/src/inverter/LUNA2000-MODBUS.h b/Software/src/inverter/LUNA2000-MODBUS.h index ec78c58f..6bbb4a2c 100644 --- a/Software/src/inverter/LUNA2000-MODBUS.h +++ b/Software/src/inverter/LUNA2000-MODBUS.h @@ -6,20 +6,20 @@ #define MB_RTU_NUM_VALUES 30000 extern uint16_t mbPV[MB_RTU_NUM_VALUES]; -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/PYLON-CAN.h b/Software/src/inverter/PYLON-CAN.h index d7e57cfc..7ab765dc 100644 --- a/Software/src/inverter/PYLON-CAN.h +++ b/Software/src/inverter/PYLON-CAN.h @@ -5,20 +5,20 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp index e93d7637..41ddb034 100644 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp +++ b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp @@ -133,10 +133,10 @@ void manageSerialLinkTransmitter() { dataLinkTransmit.updateData(3, system_battery_current_dA); dataLinkTransmit.updateData(4, system_capacity_Wh / 10); //u32, remove .0 to fit 16bit dataLinkTransmit.updateData(5, system_remaining_capacity_Wh / 10); //u32, remove .0 to fit 16bit - dataLinkTransmit.updateData(6, system_max_discharge_power_W); - dataLinkTransmit.updateData(7, system_max_charge_power_W); + dataLinkTransmit.updateData(6, system_max_discharge_power_W / 10); //u32, remove .0 to fit 16bit + dataLinkTransmit.updateData(7, system_max_charge_power_W / 10); //u32, remove .0 to fit 16bit dataLinkTransmit.updateData(8, system_bms_status); - dataLinkTransmit.updateData(9, system_active_power_W); + dataLinkTransmit.updateData(9, system_active_power_W / 10); //u32, remove .0 to fit 16bit dataLinkTransmit.updateData(10, system_temperature_min_dC); dataLinkTransmit.updateData(11, system_temperature_max_dC); dataLinkTransmit.updateData(12, system_cell_max_voltage_mV); diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h index 6078c941..b11eb940 100644 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h +++ b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h @@ -9,14 +9,14 @@ // These parameters need to be mapped for the inverter extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint8_t system_bms_status; //Enum 0-5 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value diff --git a/Software/src/inverter/SMA-CAN.cpp b/Software/src/inverter/SMA-CAN.cpp index 8981d9c0..bac73133 100644 --- a/Software/src/inverter/SMA-CAN.cpp +++ b/Software/src/inverter/SMA-CAN.cpp @@ -106,11 +106,18 @@ void update_values_can_sma() { //This function maps all the values fetched from system_max_design_voltage_dV); //Charge power in W , max volt in V+1decimal (P=UI, solve for I) //The above calculation results in (30 000*10)/3700=81A charge_current = (charge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A) + if (charge_current > MAXCHARGEAMP) { + charge_current = MAXCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values. + } discharge_current = ((system_max_discharge_power_W * 10) / system_max_design_voltage_dV); //Charge power in W , max volt in V+1decimal (P=UI, solve for I) //The above calculation results in (30 000*10)/3700=81A discharge_current = (discharge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A) + if (discharge_current > MAXDISCHARGEAMP) { + discharge_current = + MAXDISCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values. + } temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 2); diff --git a/Software/src/inverter/SMA-CAN.h b/Software/src/inverter/SMA-CAN.h index b86e5e64..95cc81f9 100644 --- a/Software/src/inverter/SMA-CAN.h +++ b/Software/src/inverter/SMA-CAN.h @@ -5,20 +5,20 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp index 370ad5d2..cc9c6255 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp @@ -119,11 +119,11 @@ static CAN_frame_t SMA_018 = { // Battery Name .MsgID = 0x018, .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -static int discharge_current = 0; -static int charge_current = 0; -static int temperature_average = 0; -static int ampere_hours_remaining = 0; -static int ampere_hours_max = 0; +static uint16_t discharge_current = 0; +static uint16_t charge_current = 0; +static int16_t temperature_average = 0; +static uint16_t ampere_hours_remaining = 0; +static uint16_t ampere_hours_max = 0; static bool batteryAlarm = false; static bool BMSevent = false; @@ -164,11 +164,18 @@ void update_values_can_sma_tripower() { //This function maps all the values fet system_max_design_voltage_dV); //Charge power in W , max volt in V+1decimal (P=UI, solve for I) //The above calculation results in (30 000*10)/3700=81A charge_current = (charge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A) + if (charge_current > MAXCHARGEAMP) { + charge_current = MAXCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values. + } discharge_current = ((system_max_discharge_power_W * 10) / system_max_design_voltage_dV); //Charge power in W , max volt in V+1decimal (P=UI, solve for I) //The above calculation results in (30 000*10)/3700=81A discharge_current = (discharge_current * 10); //Value needs a decimal before getting sent to inverter (81.0A) + if (discharge_current > MAXDISCHARGEAMP) { + discharge_current = + MAXDISCHARGEAMP; //Cap the value to the max allowed Amp. Some inverters cannot handle large values. + } temperature_average = ((system_temperature_max_dC + system_temperature_min_dC) / 2); diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.h b/Software/src/inverter/SMA-TRIPOWER-CAN.h index 1c56cadb..66682bb5 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.h +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.h @@ -5,20 +5,20 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SOFAR-CAN.h b/Software/src/inverter/SOFAR-CAN.h index 02a3772d..99aeeea4 100644 --- a/Software/src/inverter/SOFAR-CAN.h +++ b/Software/src/inverter/SOFAR-CAN.h @@ -6,20 +6,20 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SOLAX-CAN.h b/Software/src/inverter/SOLAX-CAN.h index e2fc3544..21f2c0c7 100644 --- a/Software/src/inverter/SOLAX-CAN.h +++ b/Software/src/inverter/SOLAX-CAN.h @@ -8,20 +8,20 @@ extern ACAN2515 can; -extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-100000 +extern uint32_t system_max_charge_power_W; //W, 0-100000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV From 6b129edd4ba4090621e0d9df9ead563cd0cf087b Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 7 Apr 2024 22:16:00 +0300 Subject: [PATCH 06/10] Fix compilation error --- Software/src/battery/KIA-HYUNDAI-64-BATTERY.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h index 58508222..cc8ce2e3 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.h @@ -15,16 +15,16 @@ extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 -extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int32_t system_active_power_W; //W, -32000 to 32000 extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) -extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-1000.0 (0-10000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-10000) extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint16_t system_max_discharge_power_W; //W, 0-65000 -extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV From 2c4f6f4a0692546e1fd18e34af484433335e7173 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 7 Apr 2024 22:36:23 +0300 Subject: [PATCH 07/10] Update comment on max value --- Software/Software.ino | 8 ++++---- Software/USER_SETTINGS.h | 2 +- Software/src/battery/BMW-I3-BATTERY.h | 8 ++++---- Software/src/battery/CHADEMO-BATTERY.h | 8 ++++---- Software/src/battery/IMIEV-CZERO-ION-BATTERY.h | 8 ++++---- Software/src/battery/NISSAN-LEAF-BATTERY.h | 8 ++++---- Software/src/battery/RENAULT-KANGOO-BATTERY.h | 8 ++++---- Software/src/battery/RENAULT-ZOE-BATTERY.h | 8 ++++---- Software/src/battery/SANTA-FE-PHEV-BATTERY.h | 8 ++++---- Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h | 8 ++++---- Software/src/battery/TESLA-MODEL-3-BATTERY.h | 8 ++++---- Software/src/battery/TEST-FAKE-BATTERY.h | 8 ++++---- Software/src/battery/VOLVO-SPA-BATTERY.h | 8 ++++---- Software/src/devboard/webserver/webserver.h | 8 ++++---- Software/src/inverter/BYD-CAN.h | 8 ++++---- Software/src/inverter/BYD-MODBUS.h | 8 ++++---- Software/src/inverter/LUNA2000-MODBUS.h | 8 ++++---- Software/src/inverter/PYLON-CAN.h | 8 ++++---- Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h | 8 ++++---- Software/src/inverter/SMA-CAN.h | 8 ++++---- Software/src/inverter/SMA-TRIPOWER-CAN.h | 8 ++++---- Software/src/inverter/SOFAR-CAN.h | 8 ++++---- Software/src/inverter/SOLAX-CAN.h | 8 ++++---- 23 files changed, 89 insertions(+), 89 deletions(-) diff --git a/Software/Software.ino b/Software/Software.ino index 0411aa70..d4fa43a0 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -56,8 +56,8 @@ ModbusServerRTU MBserver(Serial2, 2000); #endif // Common system parameters. Batteries map their values to these variables -uint32_t system_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-250000 Wh -uint32_t system_remaining_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-250000 Wh +uint32_t system_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-500000 Wh +uint32_t system_remaining_capacity_Wh = BATTERY_WH_MAX; //Wh, 0-500000 Wh int16_t system_temperature_max_dC = 0; //C+1, -50.0 - 50.0 int16_t system_temperature_min_dC = 0; //C+1, -50.0 - 50.0 int32_t system_active_power_W = 0; //Watts, -200000 to 200000 W @@ -68,8 +68,8 @@ uint16_t system_min_design_voltage_dV = 2500; //V+1, 0-1000.0 (0-100 uint16_t system_scaled_SOC_pptt = 5000; //SOC%, 0-100.00 (0-10000) uint16_t system_real_SOC_pptt = 5000; //SOC%, 0-100.00 (0-10000) uint16_t system_SOH_pptt = 9900; //SOH%, 0-100.00 (0-10000) -uint32_t system_max_discharge_power_W = 0; //Watts, 0 to 100000 -uint32_t system_max_charge_power_W = 4312; //Watts, 0 to 100000 +uint32_t system_max_discharge_power_W = 0; //Watts, 0 to 200000 +uint32_t system_max_charge_power_W = 4312; //Watts, 0 to 200000 uint16_t system_cell_max_voltage_mV = 3700; //mV, 0-5000 , Stores the highest cell millivolt value uint16_t system_cell_min_voltage_mV = 3700; //mV, 0-5000, Stores the minimum cell millivolt value uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages. Oversized to accomodate all setups diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index bda91cd4..84deef81 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -11,7 +11,7 @@ //#define BMW_I3_BATTERY //#define CHADEMO_BATTERY //#define IMIEV_CZERO_ION_BATTERY -//#define KIA_HYUNDAI_64_BATTERY +#define KIA_HYUNDAI_64_BATTERY //#define NISSAN_LEAF_BATTERY //#define RENAULT_KANGOO_BATTERY //#define RENAULT_ZOE_BATTERY diff --git a/Software/src/battery/BMW-I3-BATTERY.h b/Software/src/battery/BMW-I3-BATTERY.h index df96edd2..fa915e14 100644 --- a/Software/src/battery/BMW-I3-BATTERY.h +++ b/Software/src/battery/BMW-I3-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/CHADEMO-BATTERY.h b/Software/src/battery/CHADEMO-BATTERY.h index 8aaf34c8..af56af4f 100644 --- a/Software/src/battery/CHADEMO-BATTERY.h +++ b/Software/src/battery/CHADEMO-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h index a1bc02bc..0a43314b 100644 --- a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h +++ b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index a94dd7cc..43225b1b 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/RENAULT-KANGOO-BATTERY.h b/Software/src/battery/RENAULT-KANGOO-BATTERY.h index a29cf62b..e43756ac 100644 --- a/Software/src/battery/RENAULT-KANGOO-BATTERY.h +++ b/Software/src/battery/RENAULT-KANGOO-BATTERY.h @@ -14,8 +14,8 @@ #define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -26,8 +26,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/RENAULT-ZOE-BATTERY.h b/Software/src/battery/RENAULT-ZOE-BATTERY.h index acfaccf7..4791ec93 100644 --- a/Software/src/battery/RENAULT-ZOE-BATTERY.h +++ b/Software/src/battery/RENAULT-ZOE-BATTERY.h @@ -14,8 +14,8 @@ #define MAX_CELL_DEVIATION_MV 500 //LED turns yellow on the board if mv delta exceeds this value // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -26,8 +26,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h index a7a8fb69..f5dc9d14 100644 --- a/Software/src/battery/SANTA-FE-PHEV-BATTERY.h +++ b/Software/src/battery/SANTA-FE-PHEV-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h index 398b25cd..605fe208 100644 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h +++ b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.h @@ -19,10 +19,10 @@ extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint8_t system_bms_status; //Enum 0-5 extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 diff --git a/Software/src/battery/TESLA-MODEL-3-BATTERY.h b/Software/src/battery/TESLA-MODEL-3-BATTERY.h index 006a3668..5c0ccdcb 100644 --- a/Software/src/battery/TESLA-MODEL-3-BATTERY.h +++ b/Software/src/battery/TESLA-MODEL-3-BATTERY.h @@ -21,8 +21,8 @@ #define MIN_PACK_VOLTAGE_LFP 2968 // V+1, if pack voltage goes below this, discharge stops // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -33,8 +33,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/TEST-FAKE-BATTERY.h b/Software/src/battery/TEST-FAKE-BATTERY.h index 4b138ec4..f4651eea 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.h +++ b/Software/src/battery/TEST-FAKE-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.h b/Software/src/battery/VOLVO-SPA-BATTERY.h index 6a518c2b..74ed5d91 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.h +++ b/Software/src/battery/VOLVO-SPA-BATTERY.h @@ -8,8 +8,8 @@ #define BATTERY_SELECTED // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index 6c551840..527223ef 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -17,8 +17,8 @@ #endif extern const char* version_number; // The current software version, shown on webserver -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 @@ -29,8 +29,8 @@ extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-1 extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000 , Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/BYD-CAN.h b/Software/src/inverter/BYD-CAN.h index 82ae0cb6..10efc600 100644 --- a/Software/src/inverter/BYD-CAN.h +++ b/Software/src/inverter/BYD-CAN.h @@ -6,8 +6,8 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -18,8 +18,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/BYD-MODBUS.h b/Software/src/inverter/BYD-MODBUS.h index a491de60..7df14d46 100644 --- a/Software/src/inverter/BYD-MODBUS.h +++ b/Software/src/inverter/BYD-MODBUS.h @@ -7,8 +7,8 @@ #define MAX_POWER 40960 //BYD Modbus specific value extern uint16_t mbPV[MB_RTU_NUM_VALUES]; -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 @@ -19,8 +19,8 @@ extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint8_t system_bms_status; //Enum 0-5 extern bool batteryAllowsContactorClosing; //Bool, true/false extern bool inverterAllowsContactorClosing; //Bool, true/false diff --git a/Software/src/inverter/LUNA2000-MODBUS.h b/Software/src/inverter/LUNA2000-MODBUS.h index 6bbb4a2c..d3360e47 100644 --- a/Software/src/inverter/LUNA2000-MODBUS.h +++ b/Software/src/inverter/LUNA2000-MODBUS.h @@ -6,8 +6,8 @@ #define MB_RTU_NUM_VALUES 30000 extern uint16_t mbPV[MB_RTU_NUM_VALUES]; -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -18,8 +18,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/PYLON-CAN.h b/Software/src/inverter/PYLON-CAN.h index 7ab765dc..e36af2a6 100644 --- a/Software/src/inverter/PYLON-CAN.h +++ b/Software/src/inverter/PYLON-CAN.h @@ -5,8 +5,8 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -17,8 +17,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h index b11eb940..b2c1193b 100644 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h +++ b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h @@ -11,10 +11,10 @@ extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000) extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint8_t system_bms_status; //Enum 0-5 extern int32_t system_active_power_W; //W, -200000 to 200000 extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 diff --git a/Software/src/inverter/SMA-CAN.h b/Software/src/inverter/SMA-CAN.h index 95cc81f9..891cafd4 100644 --- a/Software/src/inverter/SMA-CAN.h +++ b/Software/src/inverter/SMA-CAN.h @@ -5,8 +5,8 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -17,8 +17,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.h b/Software/src/inverter/SMA-TRIPOWER-CAN.h index 66682bb5..4ddbde23 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.h +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.h @@ -5,8 +5,8 @@ #include "../devboard/config.h" // Needed for all defines #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -17,8 +17,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SOFAR-CAN.h b/Software/src/inverter/SOFAR-CAN.h index 99aeeea4..04229569 100644 --- a/Software/src/inverter/SOFAR-CAN.h +++ b/Software/src/inverter/SOFAR-CAN.h @@ -6,8 +6,8 @@ #include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // These parameters need to be mapped for the inverter -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -18,8 +18,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV diff --git a/Software/src/inverter/SOLAX-CAN.h b/Software/src/inverter/SOLAX-CAN.h index 21f2c0c7..73c2199b 100644 --- a/Software/src/inverter/SOLAX-CAN.h +++ b/Software/src/inverter/SOLAX-CAN.h @@ -8,8 +8,8 @@ extern ACAN2515 can; -extern uint32_t system_capacity_Wh; //Wh, 0-250000Wh -extern uint32_t system_remaining_capacity_Wh; //Wh, 0-250000Wh +extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 extern int32_t system_active_power_W; //W, -200000 to 200000 @@ -20,8 +20,8 @@ extern uint16_t system_min_design_voltage_dV; //V+1, 0-1000.0 (0-1 extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) -extern uint32_t system_max_discharge_power_W; //W, 0-100000 -extern uint32_t system_max_charge_power_W; //W, 0-100000 +extern uint32_t system_max_discharge_power_W; //W, 0-200000 +extern uint32_t system_max_charge_power_W; //W, 0-200000 extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV From 745b20729d79aab2299a1feb29bda0373172b948 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 7 Apr 2024 22:39:09 +0300 Subject: [PATCH 08/10] Remove configured battery --- Software/USER_SETTINGS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 84deef81..bda91cd4 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -11,7 +11,7 @@ //#define BMW_I3_BATTERY //#define CHADEMO_BATTERY //#define IMIEV_CZERO_ION_BATTERY -#define KIA_HYUNDAI_64_BATTERY +//#define KIA_HYUNDAI_64_BATTERY //#define NISSAN_LEAF_BATTERY //#define RENAULT_KANGOO_BATTERY //#define RENAULT_ZOE_BATTERY From 63371c8b6098bfb0848772b1a05140afa82b883a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96ster?= Date: Mon, 8 Apr 2024 20:45:14 +0300 Subject: [PATCH 09/10] Feature: CAN-FD + EGMP batteries! (#244) * ACAN2517FD lib addition, integrate support for canfd, and add initial EGMP battery capability --- Software/Software.ino | 63 +- Software/USER_SETTINGS.h | 2 + Software/src/battery/BATTERIES.h | 10 + Software/src/battery/KIA-E-GMP-BATTERY.cpp | 423 ++++++ Software/src/battery/KIA-E-GMP-BATTERY.h | 41 + Software/src/devboard/config.h | 20 + Software/src/devboard/utils/events.cpp | 6 + Software/src/devboard/utils/events.h | 2 + Software/src/devboard/webserver/webserver.cpp | 3 + .../pierremolinaro-ACAN2517FD/ACAN2517FD.cpp | 1347 +++++++++++++++++ .../pierremolinaro-ACAN2517FD/ACAN2517FD.h | 350 +++++ .../ACAN2517FDFilters.h | 238 +++ .../ACAN2517FDSettings.cpp | 355 +++++ .../ACAN2517FDSettings.h | 296 ++++ .../pierremolinaro-ACAN2517FD/ACANFDBuffer.h | 119 ++ .../ACANFD_DataBitRateFactor.h | 35 + .../pierremolinaro-ACAN2517FD/CANFDMessage.h | 134 ++ .../pierremolinaro-ACAN2517FD/CANMessage.h | 49 + .../src/lib/pierremolinaro-ACAN2517FD/LICENSE | 21 + .../lib/pierremolinaro-ACAN2517FD/README.md | 118 ++ 20 files changed, 3626 insertions(+), 6 deletions(-) create mode 100644 Software/src/battery/KIA-E-GMP-BATTERY.cpp create mode 100644 Software/src/battery/KIA-E-GMP-BATTERY.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.cpp create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDFilters.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.cpp create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACANFDBuffer.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/ACANFD_DataBitRateFactor.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/CANFDMessage.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/CANMessage.h create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/LICENSE create mode 100644 Software/src/lib/pierremolinaro-ACAN2517FD/README.md diff --git a/Software/Software.ino b/Software/Software.ino index d4fa43a0..7d3284d7 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -46,6 +46,10 @@ static const uint32_t QUARTZ_FREQUENCY = 8UL * 1000UL * 1000UL; // 8 MHz ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT); static ACAN2515_Buffer16 gBuffer; #endif +#ifdef CAN_FD +#include "src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h" +ACAN2517FD canfd(MCP2517_CS, SPI, MCP2517_INT); +#endif // ModbusRTU parameters #if defined(BYD_MODBUS) || defined(LUNA2000_MODBUS) @@ -179,8 +183,11 @@ void mainLoop(void* pvParameters) { // Input receive_can(); // Receive CAN messages. Runs as fast as possible +#ifdef CAN_FD + receive_canfd(); // Receive CAN-FD messages. Runs as fast as possible +#endif #ifdef DUAL_CAN - receive_can2(); + receive_can2(); // Receive CAN messages on CAN2. Runs as fast as possible #endif #if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER) runSerialDataLink(); @@ -299,9 +306,46 @@ void init_CAN() { gBuffer.initWithSize(25); SPI.begin(MCP2515_SCK, MCP2515_MISO, MCP2515_MOSI); ACAN2515Settings settings(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s - settings.mRequestedMode = ACAN2515Settings::NormalMode; // Select loopback mode + settings.mRequestedMode = ACAN2515Settings::NormalMode; can.begin(settings, [] { can.isr(); }); #endif + +#ifdef CAN_FD +#ifdef DEBUG_VIA_USB + Serial.println("CAN FD add-on (ESP32+MCP2517) selected"); +#endif + SPI.begin(MCP2517_SCK, MCP2517_SDO, MCP2517_SDI); + ACAN2517FDSettings settings(ACAN2517FDSettings::OSC_40MHz, 500 * 1000, + DataBitRateFactor::x4); // Arbitration bit rate: 500 kbit/s, data bit rate: 2 Mbit/s + settings.mRequestedMode = ACAN2517FDSettings::NormalFD; // ListenOnly / Normal20B / NormalFD + const uint32_t errorCode = canfd.begin(settings, [] { canfd.isr(); }); + if (errorCode == 0) { +#ifdef DEBUG_VIA_USB + Serial.print("Bit Rate prescaler: "); + Serial.println(settings.mBitRatePrescaler); + Serial.print("Arbitration Phase segment 1: "); + Serial.println(settings.mArbitrationPhaseSegment1); + Serial.print("Arbitration Phase segment 2: "); + Serial.println(settings.mArbitrationPhaseSegment2); + Serial.print("Arbitration SJW:"); + Serial.println(settings.mArbitrationSJW); + Serial.print("Actual Arbitration Bit Rate: "); + Serial.print(settings.actualArbitrationBitRate()); + Serial.println(" bit/s"); + Serial.print("Exact Arbitration Bit Rate ? "); + Serial.println(settings.exactArbitrationBitRate() ? "yes" : "no"); + Serial.print("Arbitration Sample point: "); + Serial.print(settings.arbitrationSamplePointFromBitStart()); + Serial.println("%"); +#endif + } else { +#ifdef DEBUG_VIA_USB + Serial.print("CAN-FD Configuration error 0x"); + Serial.println(errorCode, HEX); +#endif + set_event(EVENT_CANFD_INIT_FAILURE, (uint8_t)errorCode); + } +#endif } void init_LED() { @@ -342,10 +386,6 @@ void init_modbus() { #ifdef BYD_MODBUS // Init Static data to the RTU Modbus handle_static_data_modbus_byd(); -#endif -#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 // Init Serial2 connected to the RTU Modbus @@ -416,7 +456,17 @@ void init_battery() { #endif } +#ifdef CAN_FD // Functions +void receive_canfd() { // This section checks if we have a complete CAN-FD message incoming + CANFDMessage frame; + if (canfd.available()) { + canfd.receive(frame); + receive_canfd_battery(frame); + } +} +#endif + void receive_can() { // 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; @@ -474,6 +524,7 @@ void send_can() { #endif // Battery send_can_battery(); + // Charger #ifdef CHEVYVOLT_CHARGER send_can_chevyvolt_charger(); #endif diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index bda91cd4..a6e3a459 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -12,6 +12,7 @@ //#define CHADEMO_BATTERY //#define IMIEV_CZERO_ION_BATTERY //#define KIA_HYUNDAI_64_BATTERY +//#define KIA_E_GMP_BATTERY //#define NISSAN_LEAF_BATTERY //#define RENAULT_KANGOO_BATTERY //#define RENAULT_ZOE_BATTERY @@ -36,6 +37,7 @@ //#define CONTACTOR_CONTROL //Enable this line to have pins 25,32,33 handle automatic precharge/contactor+/contactor- closing sequence //#define PWM_CONTACTOR_CONTROL //Enable this line to use PWM logic for contactors, which lower power consumption and heat generation //#define DUAL_CAN //Enable this line to activate an isolated secondary CAN Bus using add-on MCP2515 controller (Needed for FoxESS inverters) +//#define CAN_FD //Enable this line to activate an isolated secondary CAN-FD bus using add-on MCP2517FD controller (Needed for some batteries) //#define SERIAL_LINK_RECEIVER //Enable this line to receive battery data over RS485 pins from another Lilygo (This LilyGo interfaces with inverter) //#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery) #define WEBSERVER //Enable this line to enable WiFi, and to run the webserver. See USER_SETTINGS.cpp for the Wifi settings. diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index 0c1c141b..7dcb0e2b 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -15,6 +15,13 @@ #include "IMIEV-CZERO-ION-BATTERY.h" //See this file for more triplet battery settings #endif +#ifdef KIA_E_GMP_BATTERY +#include "KIA-E-GMP-BATTERY.h" //See this file for more GMP battery settings +#ifndef CAN_FD +#error KIA HYUNDAI EGMP BATTERIES CANNOT BE USED WITHOUT CAN FD +#endif +#endif + #ifdef KIA_HYUNDAI_64_BATTERY #include "KIA-HYUNDAI-64-BATTERY.h" //See this file for more 64kWh battery settings #endif @@ -56,6 +63,9 @@ void receive_can_battery(); #else void receive_can_battery(CAN_frame_t rx_frame); #endif +#ifdef CAN_FD +void receive_canfd_battery(CANFDMessage frame); +#endif void update_values_battery(); void send_can_battery(); void setup_battery(void); diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.cpp b/Software/src/battery/KIA-E-GMP-BATTERY.cpp new file mode 100644 index 00000000..6741a1a7 --- /dev/null +++ b/Software/src/battery/KIA-E-GMP-BATTERY.cpp @@ -0,0 +1,423 @@ +#include "BATTERIES.h" +#ifdef KIA_E_GMP_BATTERY +#include "../devboard/utils/events.h" +#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h" +#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" +#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h" +#include "KIA-E-GMP-BATTERY.h" + +/* Do not change code below unless you are sure what you are doing */ +static unsigned long previousMillis500ms = 0; // will store last time a 500ms CAN Message was send +static uint8_t CANstillAlive = 12; //counter for checking if CAN is still alive + +#define MAX_CELL_VOLTAGE 4250 //Battery is put into emergency stop if one cell goes over this value +#define MIN_CELL_VOLTAGE 2950 //Battery is put into emergency stop if one cell goes below this value +#define MAX_CELL_DEVIATION 150 //LED turns yellow on the board if mv delta exceeds this value + +static uint16_t inverterVoltageFrameHigh = 0; +static uint16_t inverterVoltage = 0; +static uint16_t soc_calculated = 0; +static uint16_t SOC_BMS = 0; +static uint16_t SOC_Display = 0; +static uint16_t batterySOH = 1000; +static uint16_t CellVoltMax_mV = 3700; +static uint16_t CellVoltMin_mV = 3700; +static uint16_t cell_deviation_mV = 0; +static uint16_t batteryVoltage = 0; +static int16_t leadAcidBatteryVoltage = 120; +static int16_t batteryAmps = 0; +static int16_t powerWatt = 0; +static int16_t temperatureMax = 0; +static int16_t temperatureMin = 0; +static int16_t allowedDischargePower = 0; +static int16_t allowedChargePower = 0; +static int16_t poll_data_pid = 0; +static uint8_t CellVmaxNo = 0; +static uint8_t CellVminNo = 0; +static uint8_t batteryManagementMode = 0; +static uint8_t BMS_ign = 0; +static uint8_t batteryRelay = 0; +static uint8_t waterleakageSensor = 164; +static uint8_t startedUp = false; +static uint8_t counter_200 = 0; +static uint8_t KIA_7E4_COUNTER = 0x01; +static int8_t temperature_water_inlet = 0; +static int8_t powerRelayTemperature = 0; +static int8_t heatertemp = 0; + +CANFDMessage EGMP_7E4; +CANFDMessage EGMP_7E4_ack; + +void set_cell_voltages(CANFDMessage frame, int start, int length, int startCell) { + for (size_t i = 0; i < length; i++) { + system_cellvoltages_mV[startCell + i] = (frame.data[start + i] * 20); + } +} + +void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus + + system_real_SOC_pptt = (SOC_Display * 10); //increase SOC range from 0-100.0 -> 100.00 + + system_SOH_pptt = (batterySOH * 10); //Increase decimals from 100.0% -> 100.00% + + system_battery_voltage_dV = batteryVoltage; //value is *10 (3700 = 370.0) + + system_battery_current_dA = batteryAmps; //value is *10 (150 = 15.0) + + system_capacity_Wh = BATTERY_WH_MAX; + + system_remaining_capacity_Wh = static_cast((static_cast(system_real_SOC_pptt) / 10000) * BATTERY_WH_MAX); + + //system_max_charge_power_W = (uint16_t)allowedChargePower * 10; //From kW*100 to Watts + //The allowed charge power is not available. We estimate this value + if (system_scaled_SOC_pptt == 10000) { // When scaled SOC is 100%, set allowed charge power to 0 + system_max_charge_power_W = 0; + } else { // No limits, max charging power allowed + system_max_charge_power_W = MAXCHARGEPOWERALLOWED; + } + //system_max_discharge_power_W = (uint16_t)allowedDischargePower * 10; //From kW*100 to Watts + if (system_scaled_SOC_pptt < 100) { // When scaled SOC is <1%, set allowed charge power to 0 + system_max_discharge_power_W = 0; + } else { // No limits, max charging power allowed + system_max_discharge_power_W = MAXDISCHARGEPOWERALLOWED; + } + + powerWatt = ((batteryVoltage * batteryAmps) / 100); + + system_active_power_W = powerWatt; //Power in watts, Negative = charging batt + + system_temperature_min_dC = (int8_t)temperatureMin * 10; //Increase decimals, 17C -> 17.0C + + system_temperature_max_dC = (int8_t)temperatureMax * 10; //Increase decimals, 18C -> 18.0C + + system_cell_max_voltage_mV = CellVoltMax_mV; + + system_cell_min_voltage_mV = CellVoltMin_mV; + + /* Check if the BMS is still sending CAN messages. If we go 60s without messages we raise an error*/ + if (!CANstillAlive) { + set_event(EVENT_CANFD_RX_FAILURE, 0); + } else { + CANstillAlive--; + clear_event(EVENT_CANFD_RX_FAILURE); + } + + if (waterleakageSensor == 0) { + set_event(EVENT_WATER_INGRESS, 0); + } + + if (leadAcidBatteryVoltage < 110) { + set_event(EVENT_12V_LOW, leadAcidBatteryVoltage); + } + + // Check if cell voltages are within allowed range + cell_deviation_mV = (system_cell_max_voltage_mV - system_cell_min_voltage_mV); + + if (CellVoltMax_mV >= MAX_CELL_VOLTAGE) { + set_event(EVENT_CELL_OVER_VOLTAGE, 0); + } + if (CellVoltMin_mV <= MIN_CELL_VOLTAGE) { + set_event(EVENT_CELL_UNDER_VOLTAGE, 0); + } + if (cell_deviation_mV > MAX_CELL_DEVIATION) { + set_event(EVENT_CELL_DEVIATION_HIGH, 0); + } else { + clear_event(EVENT_CELL_DEVIATION_HIGH); + } + + if (system_bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits + system_max_charge_power_W = 0; + system_max_discharge_power_W = 0; + } + + /* Safeties verified. Perform USB serial printout if configured to do so */ + +#ifdef DEBUG_VIA_USB + Serial.println(); //sepatator + Serial.println("Values from battery: "); + Serial.print("SOC BMS: "); + Serial.print((uint16_t)SOC_BMS / 10.0, 1); + Serial.print("% | SOC Display: "); + Serial.print((uint16_t)SOC_Display / 10.0, 1); + Serial.print("% | SOH "); + Serial.print((uint16_t)batterySOH / 10.0, 1); + Serial.println("%"); + Serial.print((int16_t)batteryAmps / 10.0, 1); + Serial.print(" Amps | "); + Serial.print((uint16_t)batteryVoltage / 10.0, 1); + Serial.print(" Volts | "); + Serial.print((int16_t)system_active_power_W); + Serial.println(" Watts"); + Serial.print("Allowed Charge "); + Serial.print((uint16_t)allowedChargePower * 10); + Serial.print(" W | Allowed Discharge "); + Serial.print((uint16_t)allowedDischargePower * 10); + Serial.println(" W"); + Serial.print("MaxCellVolt "); + Serial.print(CellVoltMax_mV); + Serial.print(" mV No "); + Serial.print(CellVmaxNo); + Serial.print(" | MinCellVolt "); + Serial.print(CellVoltMin_mV); + Serial.print(" mV No "); + Serial.println(CellVminNo); + Serial.print("TempHi "); + Serial.print((int16_t)temperatureMax); + Serial.print("°C TempLo "); + Serial.print((int16_t)temperatureMin); + Serial.print("°C WaterInlet "); + Serial.print((int8_t)temperature_water_inlet); + Serial.print("°C PowerRelay "); + Serial.print((int8_t)powerRelayTemperature * 2); + Serial.println("°C"); + Serial.print("Aux12volt: "); + Serial.print((int16_t)leadAcidBatteryVoltage / 10.0, 1); + Serial.println("V | "); + Serial.print("BmsManagementMode "); + Serial.print((uint8_t)batteryManagementMode, BIN); + if (bitRead((uint8_t)BMS_ign, 2) == 1) { + Serial.print(" | BmsIgnition ON"); + } else { + Serial.print(" | BmsIgnition OFF"); + } + + if (bitRead((uint8_t)batteryRelay, 0) == 1) { + Serial.print(" | PowerRelay ON"); + } else { + Serial.print(" | PowerRelay OFF"); + } + Serial.print(" | Inverter "); + Serial.print(inverterVoltage); + Serial.println(" Volts"); +#endif +} + +void receive_canfd_battery(CANFDMessage frame) { + CANstillAlive = 12; + switch (frame.id) { + case 0x7EC: + // printFrame(frame); + switch (frame.data[0]) { + case 0x10: //"PID Header" + // Serial.println ("Send ack"); + poll_data_pid = frame.data[4]; + // if (frame.data[4] == poll_data_pid) { + canfd.tryToSend(EGMP_7E4_ack); //Send ack to BMS if the same frame is sent as polled + // } + break; + case 0x21: //First frame in PID group + if (poll_data_pid == 1) { + allowedChargePower = ((frame.data[3] << 8) + frame.data[4]); + allowedDischargePower = ((frame.data[5] << 8) + frame.data[6]); + SOC_BMS = frame.data[2] * 5; //100% = 200 ( 200 * 5 = 1000 ) + + } else if (poll_data_pid == 2) { + // set cell voltages data, start bite, data length from start, start cell + set_cell_voltages(frame, 2, 6, 0); + } else if (poll_data_pid == 3) { + set_cell_voltages(frame, 2, 6, 32); + } else if (poll_data_pid == 4) { + set_cell_voltages(frame, 2, 6, 64); + } else if (poll_data_pid == 0x0A) { + set_cell_voltages(frame, 2, 6, 96); + } else if (poll_data_pid == 0x0B) { + set_cell_voltages(frame, 2, 6, 128); + } else if (poll_data_pid == 0x0C) { + set_cell_voltages(frame, 2, 6, 160); + } + break; + case 0x22: //Second datarow in PID group + if (poll_data_pid == 1) { + batteryVoltage = (frame.data[3] << 8) + frame.data[4]; + batteryAmps = (frame.data[1] << 8) + frame.data[2]; + temperatureMax = frame.data[5]; + temperatureMin = frame.data[6]; + // temp1 = frame.data[7]; + } else if (poll_data_pid == 2) { + set_cell_voltages(frame, 1, 7, 6); + } else if (poll_data_pid == 3) { + set_cell_voltages(frame, 1, 7, 38); + } else if (poll_data_pid == 4) { + set_cell_voltages(frame, 1, 7, 70); + } else if (poll_data_pid == 0x0A) { + set_cell_voltages(frame, 1, 7, 102); + } else if (poll_data_pid == 0x0B) { + set_cell_voltages(frame, 1, 7, 134); + } else if (poll_data_pid == 0x0C) { + set_cell_voltages(frame, 1, 7, 166); + } else if (poll_data_pid == 6) { + batteryManagementMode = frame.data[5]; + } + break; + case 0x23: //Third datarow in PID group + if (poll_data_pid == 1) { + temperature_water_inlet = frame.data[6]; + CellVoltMax_mV = (frame.data[7] * 20); //(volts *50) *20 =mV + // temp2 = frame.data[1]; + // temp3 = frame.data[2]; + // temp4 = frame.data[3]; + } else if (poll_data_pid == 2) { + set_cell_voltages(frame, 1, 7, 13); + } else if (poll_data_pid == 3) { + set_cell_voltages(frame, 1, 7, 45); + } else if (poll_data_pid == 4) { + set_cell_voltages(frame, 1, 7, 77); + } else if (poll_data_pid == 0x0A) { + set_cell_voltages(frame, 1, 7, 109); + } else if (poll_data_pid == 0x0B) { + set_cell_voltages(frame, 1, 7, 141); + } else if (poll_data_pid == 0x0C) { + set_cell_voltages(frame, 1, 7, 173); + } else if (poll_data_pid == 5) { + // ac = frame.data[3]; + // Vdiff = frame.data[4]; + + // airbag = frame.data[6]; + heatertemp = frame.data[7]; + } + break; + case 0x24: //Fourth datarow in PID group + if (poll_data_pid == 1) { + CellVmaxNo = frame.data[1]; + CellVoltMin_mV = (frame.data[2] * 20); //(volts *50) *20 =mV + CellVminNo = frame.data[3]; + // fanMod = frame.data[4]; + // fanSpeed = frame.data[5]; + leadAcidBatteryVoltage = frame.data[6]; //12v Battery Volts + //cumulative_charge_current[0] = frame.data[7]; + } else if (poll_data_pid == 2) { + set_cell_voltages(frame, 1, 7, 20); + } else if (poll_data_pid == 3) { + set_cell_voltages(frame, 1, 7, 52); + } else if (poll_data_pid == 4) { + set_cell_voltages(frame, 1, 7, 84); + } else if (poll_data_pid == 0x0A) { + set_cell_voltages(frame, 1, 7, 116); + } else if (poll_data_pid == 0x0B) { + set_cell_voltages(frame, 1, 7, 148); + } else if (poll_data_pid == 0x0C) { + set_cell_voltages(frame, 1, 7, 180); + } else if (poll_data_pid == 5) { + batterySOH = ((frame.data[2] << 8) + frame.data[3]); + // maxDetCell = frame.data[4]; + // minDet = (frame.data[5] << 8) + frame.data[6]; + // minDetCell = frame.data[7]; + } + break; + case 0x25: //Fifth datarow in PID group + if (poll_data_pid == 1) { + //cumulative_charge_current[1] = frame.data[1]; + //cumulative_charge_current[2] = frame.data[2]; + //cumulative_charge_current[3] = frame.data[3]; + //cumulative_discharge_current[0] = frame.data[4]; + //cumulative_discharge_current[1] = frame.data[5]; + //cumulative_discharge_current[2] = frame.data[6]; + //cumulative_discharge_current[3] = frame.data[7]; + //set_cumulative_charge_current(); + //set_cumulative_discharge_current(); + } else if (poll_data_pid == 2) { + set_cell_voltages(frame, 1, 5, 27); + } else if (poll_data_pid == 3) { + set_cell_voltages(frame, 1, 5, 59); + } else if (poll_data_pid == 4) { + set_cell_voltages(frame, 1, 5, 91); + } else if (poll_data_pid == 0x0A) { + set_cell_voltages(frame, 1, 5, 123); + } else if (poll_data_pid == 0x0B) { + set_cell_voltages(frame, 1, 5, 155); + } else if (poll_data_pid == 0x0C) { + set_cell_voltages(frame, 1, 5, 187); + //set_cell_count(); + } else if (poll_data_pid == 5) { + // system_number_of_cells = 98; + SOC_Display = frame.data[1] * 5; + } + break; + case 0x26: //Sixth datarow in PID group + if (poll_data_pid == 1) { + //cumulative_energy_charged[0] = frame.data[1]; + // cumulative_energy_charged[1] = frame.data[2]; + //cumulative_energy_charged[2] = frame.data[3]; + //cumulative_energy_charged[3] = frame.data[4]; + //cumulative_energy_discharged[0] = frame.data[5]; + //cumulative_energy_discharged[1] = frame.data[6]; + //cumulative_energy_discharged[2] = frame.data[7]; + // set_cumulative_energy_charged(); + } + break; + case 0x27: //Seventh datarow in PID group + if (poll_data_pid == 1) { + //cumulative_energy_discharged[3] = frame.data[1]; + + //opTimeBytes[0] = frame.data[2]; + //opTimeBytes[1] = frame.data[3]; + //opTimeBytes[2] = frame.data[4]; + //opTimeBytes[3] = frame.data[5]; + + BMS_ign = frame.data[6]; + inverterVoltageFrameHigh = frame.data[7]; // BMS Capacitoir + + // set_cumulative_energy_discharged(); + // set_opTime(); + } + break; + case 0x28: //Eighth datarow in PID group + if (poll_data_pid == 1) { + inverterVoltage = (inverterVoltageFrameHigh << 8) + frame.data[1]; // BMS Capacitoir + } + break; + } + break; + default: + break; + } +} + +void receive_can_battery(CAN_frame_t frame) {} // Not used on CAN-FD battery, just included to compile + +void send_can_battery() { + + unsigned long currentMillis = millis(); + //Send 500ms CANFD message + if (currentMillis - previousMillis500ms >= INTERVAL_500_MS) { + + // Check if sending of CAN messages has been delayed too much. + if ((currentMillis - previousMillis500ms >= INTERVAL_500_MS_DELAYED) && (currentMillis > BOOTUP_TIME)) { + set_event(EVENT_CAN_OVERRUN, (currentMillis - previousMillis500ms)); + } + previousMillis500ms = currentMillis; + EGMP_7E4.data[3] = KIA_7E4_COUNTER; + canfd.tryToSend(EGMP_7E4); + + KIA_7E4_COUNTER++; + if (KIA_7E4_COUNTER > 0x0D) { // gets up to 0x010C before repeating + KIA_7E4_COUNTER = 0x01; + } + } +} + +void setup_battery(void) { // Performs one time setup at startup +#ifdef DEBUG_VIA_USB + Serial.println("Hyundai E-GMP (Electric Global Modular Platform) battery selected"); +#endif + + system_number_of_cells = 192; // TODO: will vary depending on battery + + system_max_design_voltage_dV = + 8064; // TODO: define when battery is known, charging is not possible (goes into forced discharge) + system_min_design_voltage_dV = 4320; // TODO: define when battery is known. discharging further is disabled + + EGMP_7E4.id = 0x7E4; + EGMP_7E4.ext = false; + EGMP_7E4.len = 8; + uint8_t dataEGMP_7E4[8] = {0x03, 0x22, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}; //Poll PID 03 22 01 01 + memcpy(EGMP_7E4.data, dataEGMP_7E4, sizeof(dataEGMP_7E4)); + + EGMP_7E4_ack.id = 0x7E4; + EGMP_7E4_ack.ext = false; + EGMP_7E4_ack.len = 8; + uint8_t dataEGMP_7E4_ack[8] = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //Ack frame, correct PID is returned + memcpy(EGMP_7E4_ack.data, dataEGMP_7E4_ack, sizeof(dataEGMP_7E4_ack)); +} + +#endif diff --git a/Software/src/battery/KIA-E-GMP-BATTERY.h b/Software/src/battery/KIA-E-GMP-BATTERY.h new file mode 100644 index 00000000..7e66e193 --- /dev/null +++ b/Software/src/battery/KIA-E-GMP-BATTERY.h @@ -0,0 +1,41 @@ +#ifndef KIA_E_GMP_BATTERY_H +#define KIA_E_GMP_BATTERY_H +#include +#include "../../USER_SETTINGS.h" +#include "../devboard/config.h" // Needed for all defines +#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" +#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h" + +extern ACAN2517FD canfd; + +#define BATTERY_SELECTED + +#define MAXCHARGEPOWERALLOWED 10000 +#define MAXDISCHARGEPOWERALLOWED 10000 + +// These parameters need to be mapped for the inverter +extern uint32_t system_capacity_Wh; //Wh, 0-150000Wh +extern uint32_t system_remaining_capacity_Wh; //Wh, 0-150000Wh +extern int16_t system_temperature_min_dC; //C+1, -50.0 - 50.0 +extern int16_t system_temperature_max_dC; //C+1, -50.0 - 50.0 +extern int16_t system_active_power_W; //W, -32000 to 32000 +extern int16_t system_battery_current_dA; //A+1, -1000 - 1000 +extern uint16_t system_battery_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_max_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_min_design_voltage_dV; //V+1, 0-500.0 (0-5000) +extern uint16_t system_scaled_SOC_pptt; //SOC%, 0-100.00 (0-10000) +extern uint16_t system_real_SOC_pptt; //SOC%, 0-100.00 (0-10000) +extern uint16_t system_SOH_pptt; //SOH%, 0-100.00 (0-10000) +extern uint16_t system_max_discharge_power_W; //W, 0-65000 +extern uint16_t system_max_charge_power_W; //W, 0-65000 +extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value +extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value +extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV +extern uint8_t system_number_of_cells; //Total number of cell voltages, set by each battery +extern uint8_t system_bms_status; //Enum 0-5 +extern bool batteryAllowsContactorClosing; //Bool, true/false +extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false + +void setup_battery(void); + +#endif diff --git a/Software/src/devboard/config.h b/Software/src/devboard/config.h index f634ed25..8fb403ba 100644 --- a/Software/src/devboard/config.h +++ b/Software/src/devboard/config.h @@ -20,6 +20,14 @@ #define MCP2515_INT 35 // INT output of MCP2515 | | Pin 35 is input only, without pullup/down resistors #endif +#ifdef CAN_FD +#define MCP2517_SCK 12 // SCK input of MCP2517 +#define MCP2517_SDI 5 // SDI input of MCP2517 +#define MCP2517_SDO 34 // SDO output of MCP2517 +#define MCP2517_CS 18 // CS input of MCP2517 +#define MCP2517_INT 35 // INT output of MCP2517 +#endif + #ifdef CONTACTOR_CONTROL #define POSITIVE_CONTACTOR_PIN 32 #define NEGATIVE_CONTACTOR_PIN 33 @@ -75,7 +83,19 @@ #define INTERVAL_20_MS_DELAYED 30 #define INTERVAL_30_MS_DELAYED 40 #define INTERVAL_100_MS_DELAYED 120 +#define INTERVAL_500_MS_DELAYED 550 #define BOOTUP_TIME 1000 // Time in ms it takes before system is considered fully started up +#if defined(DUAL_CAN) && defined(CAN_FD) +// Check that user did not try to use dual can and fd-can on same hardware pins +#error CAN-FD AND DUAL-CAN CANNOT BE USED SIMULTANEOUSLY +#endif +#if defined(BYD_MODBUS) || defined(LUNA2000_MODBUS) +#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 + #endif diff --git a/Software/src/devboard/utils/events.cpp b/Software/src/devboard/utils/events.cpp index 6191f853..f53fb7a4 100644 --- a/Software/src/devboard/utils/events.cpp +++ b/Software/src/devboard/utils/events.cpp @@ -125,8 +125,10 @@ void init_events(void) { events.entries[i].log = true; } + events.entries[EVENT_CANFD_INIT_FAILURE].level = EVENT_LEVEL_WARNING; events.entries[EVENT_CAN_OVERRUN].level = EVENT_LEVEL_INFO; events.entries[EVENT_CAN_RX_FAILURE].level = EVENT_LEVEL_ERROR; + events.entries[EVENT_CANFD_RX_FAILURE].level = EVENT_LEVEL_ERROR; events.entries[EVENT_CAN_RX_WARNING].level = EVENT_LEVEL_WARNING; events.entries[EVENT_CAN_TX_FAILURE].level = EVENT_LEVEL_ERROR; events.entries[EVENT_WATER_INGRESS].level = EVENT_LEVEL_ERROR; @@ -183,10 +185,14 @@ void clear_event(EVENTS_ENUM_TYPE event) { const char* get_event_message_string(EVENTS_ENUM_TYPE event) { switch (event) { + case EVENT_CANFD_INIT_FAILURE: + return "CAN-FD initialization failed. Check hardware or bitrate settings"; case EVENT_CAN_OVERRUN: return "CAN message failed to send within defined time. Contact developers, CPU load might be too high."; case EVENT_CAN_RX_FAILURE: return "No CAN communication detected for 60s. Shutting down battery control."; + case EVENT_CANFD_RX_FAILURE: + return "No CANFD communication detected for 60s. Shutting down battery control."; case EVENT_CAN_RX_WARNING: return "ERROR: High amount of corrupted CAN messages detected. Check CAN wire shielding!"; case EVENT_CAN_TX_FAILURE: diff --git a/Software/src/devboard/utils/events.h b/Software/src/devboard/utils/events.h index 0374c8fb..16874d58 100644 --- a/Software/src/devboard/utils/events.h +++ b/Software/src/devboard/utils/events.h @@ -28,8 +28,10 @@ */ #define EVENTS_ENUM_TYPE(XX) \ + XX(EVENT_CANFD_INIT_FAILURE) \ XX(EVENT_CAN_OVERRUN) \ XX(EVENT_CAN_RX_FAILURE) \ + XX(EVENT_CANFD_RX_FAILURE) \ XX(EVENT_CAN_RX_WARNING) \ XX(EVENT_CAN_TX_FAILURE) \ XX(EVENT_WATER_INGRESS) \ diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index c2edeea4..bfd73b39 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -427,6 +427,9 @@ String processor(const String& var) { #ifdef KIA_HYUNDAI_64_BATTERY content += "Kia/Hyundai 64kWh"; #endif +#ifdef KIA_E_GMP_BATTERY + content += "Kia/Hyundai EGMP platform"; +#endif #ifdef NISSAN_LEAF_BATTERY content += "Nissan LEAF"; #endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.cpp b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.cpp new file mode 100644 index 00000000..5a1b8667 --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.cpp @@ -0,0 +1,1347 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CAN driver for MCP2517FD, CANFD mode +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#include "ACAN2517FD.h" + +//---------------------------------------------------------------------------------------------------------------------- + +static const uint8_t TXBWS = 0 ; + +//---------------------------------------------------------------------------------------------------------------------- +// Note about ESP32 +//---------------------------------------------------------------------------------------------------------------------- +// +// It appears that Arduino ESP32 interrupts are managed in a completely different way from "usual" Arduino: +// - SPI.usingInterrupt is not implemented; +// - noInterrupts() and interrupts() are NOPs: use taskDISABLE_INTERRUPTS and taskENABLE_INTERRUPTS; +// - interrupt service routines should be fast, otherwise you get an "Guru Meditation Error: Core 1 panic'ed +// (Interrupt wdt timeout on CPU1)". +// +// So we handle the ESP32 interrupt in the following way: +// - interrupt service routine performs a xSemaphoreGiveFromISR on mISRSemaphore of can driver +// - this activates the myESP32Task task that performs "isr_poll_core" that is done by interrupt service routine +// in "usual" Arduino; +// - as this task runs in parallel with setup / loop routines, SPI access is natively protected by the +// beginTransaction / endTransaction pair, that manages a mutex; +// - (May 29, 2019) it appears that MCP2717FD wants the CS line to deasserted as soon as possible (thanks for +// Nick Kirkby for having signaled me this point, see https://github.com/pierremolinaro/acan2517/issues/5); +// so we mask interrupts when we access the MCP2517FD, the sequence becomes: +// mSPI.beginTransaction (mSPISettings) ; +// #ifdef ARDUINO_ARCH_ESP32 +// taskDISABLE_INTERRUPTS () ; +// #endif +// assertCS () ; +// ... Access the MCP2517FD ... +// deassertCS () ; +// #ifdef ARDUINO_ARCH_ESP32 +// taskENABLE_INTERRUPTS () ; +// #endif +// mSPI.endTransaction () ; +// +//---------------------------------------------------------------------------------------------------------------------- + +#ifdef ARDUINO_ARCH_ESP32 + static void myESP32Task (void * pData) { + ACAN2517FD * canDriver = (ACAN2517FD *) pData ; + while (1) { + xSemaphoreTake (canDriver->mISRSemaphore, portMAX_DELAY) ; + canDriver->isr_poll_core () ; + } + } +#endif + +//---------------------------------------------------------------------------------------------------------------------- +// ACAN2517FD register addresses +//---------------------------------------------------------------------------------------------------------------------- + +static const uint16_t CON_REGISTER = 0x000 ; +static const uint16_t NBTCFG_REGISTER = 0x004 ; +static const uint16_t DBTCFG_REGISTER = 0x008 ; +static const uint16_t TDC_REGISTER = 0x00C ; + +static const uint16_t TREC_REGISTER = 0x034 ; +static const uint16_t BDIAG0_REGISTER = 0x038 ; +static const uint16_t BDIAG1_REGISTER = 0x03C ; + +//······················································································································ +// TXQ REGISTERS +//······················································································································ + +static const uint16_t TXQCON_REGISTER = 0x050 ; +static const uint16_t TXQSTA_REGISTER = 0x054 ; +static const uint16_t TXQUA_REGISTER = 0x058 ; + +//······················································································································ +// INTERRUPT REGISTERS +//······················································································································ + +static const uint16_t INT_REGISTER = 0x01C ; + +//······················································································································ +// FIFO REGISTERS +//······················································································································ + +static uint16_t FIFOCON_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 + return 0x05C + 12 * (inFIFOIndex - 1) ; +} + +//······················································································································ + +static uint16_t FIFOSTA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 + return 0x060 + 12 * (inFIFOIndex - 1) ; +} + +//······················································································································ + +static uint16_t FIFOUA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 + return 0x064 + 12 * (inFIFOIndex - 1) ; +} + +//······················································································································ +// FILTER REGISTERS +//······················································································································ + +static uint16_t FLTCON_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 58) + return 0x1D0 + inFilterIndex ; +} + +//······················································································································ + +static uint16_t FLTOBJ_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 60) + return 0x1F0 + 8 * inFilterIndex ; +} + +//······················································································································ + +static uint16_t MASK_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 61) + return 0x1F4 + 8 * inFilterIndex ; +} + +//······················································································································ +// OSCILLATOR REGISTER +//······················································································································ + +static const uint16_t OSC_REGISTER = 0xE00 ; + +//······················································································································ +// INPUT / OUPUT CONTROL REGISTER +//······················································································································ + +static const uint16_t IOCON_REGISTER_00_07 = 0xE04 ; +static const uint16_t IOCON_REGISTER_08_15 = 0xE05 ; +static const uint16_t IOCON_REGISTER_16_23 = 0xE06 ; +static const uint16_t IOCON_REGISTER_24_31 = 0xE07 ; + +//---------------------------------------------------------------------------------------------------------------------- +// RECEIVE FIFO INDEX +//---------------------------------------------------------------------------------------------------------------------- + +static const uint8_t RECEIVE_FIFO_INDEX = 1 ; +static const uint8_t TRANSMIT_FIFO_INDEX = 2 ; + +//---------------------------------------------------------------------------------------------------------------------- +// BYTE BUFFER UTILITY FUNCTIONS +//---------------------------------------------------------------------------------------------------------------------- + +static void enterU32InBufferAtIndex (const uint32_t inValue, uint8_t ioBuffer [], const uint8_t inIndex) { + ioBuffer [inIndex + 0] = (uint8_t) inValue ; + ioBuffer [inIndex + 1] = (uint8_t) (inValue >> 8) ; + ioBuffer [inIndex + 2] = (uint8_t) (inValue >> 16) ; + ioBuffer [inIndex + 3] = (uint8_t) (inValue >> 24) ; +} + +//······················································································································ + +static uint32_t u32FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) { + uint32_t result = (uint32_t) ioBuffer [inIndex + 0] ; + result |= ((uint32_t) ioBuffer [inIndex + 1]) << 8 ; + result |= ((uint32_t) ioBuffer [inIndex + 2]) << 16 ; + result |= ((uint32_t) ioBuffer [inIndex + 3]) << 24 ; + return result ; +} + +//······················································································································ + +static uint16_t u16FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) { + uint16_t result = (uint16_t) ioBuffer [inIndex + 0] ; + result |= ((uint16_t) ioBuffer [inIndex + 1]) << 8 ; + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +ACAN2517FD::ACAN2517FD (const uint8_t inCS, // CS input of MCP2517FD + SPIClass & inSPI, // Hardware SPI object + const uint8_t inINT) : // INT output of MCP2517FD +mSPISettings (), +mSPI (inSPI), +mCS (inCS), +mINT (inINT), +mUsesTXQ (false), +mHardwareTxFIFOFull (false), +mRxInterruptEnabled (true), +mHasDataBitRate (false), +mTransmitFIFOPayload (0), +mTXQBufferPayload (0), +mReceiveFIFOPayload (0), +mTXBWS_RequestedMode (0), +mHardwareReceiveBufferOverflowCount (0), +mDriverReceiveBuffer (), +mDriverTransmitBuffer () +#ifdef ARDUINO_ARCH_ESP32 + , mISRSemaphore (xSemaphoreCreateCounting (10, 0)) +#endif +{ +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings, + void (* inInterruptServiceRoutine) (void)) { +//--- Add pass-all filter + ACAN2517FDFilters filters ; + filters.appendPassAllFilter (NULL) ; +//--- + return begin (inSettings, inInterruptServiceRoutine, filters) ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings, + void (* inInterruptServiceRoutine) (void), + const ACAN2517FDFilters & inFilters) { + uint32_t errorCode = 0 ; // Means no error +//----------------------------------- If ok, check if settings are correct + if (!inSettings.mArbitrationBitRateClosedToDesiredRate) { + errorCode |= kTooFarFromDesiredBitRate ; + } + if (inSettings.CANBitSettingConsistency () != 0) { + errorCode |= kInconsistentBitRateSettings ; + } +//----------------------------------- Check mINT has interrupt capability + const int8_t itPin = digitalPinToInterrupt (mINT) ; + if ((mINT != 255) && (itPin == NOT_AN_INTERRUPT)) { + errorCode = kINTPinIsNotAnInterrupt ; + } +//----------------------------------- Check interrupt service routine is not null + if ((mINT != 255) && (inInterruptServiceRoutine == NULL)) { + errorCode |= kISRIsNull ; + } +//----------------------------------- Check consistency between ISR and INT pin + if ((mINT == 255) && (inInterruptServiceRoutine != NULL)) { + errorCode |= kISRNotNullAndNoIntPin ; + } +//----------------------------------- Check TXQ size is <= 32 + if (inSettings.mControllerTXQSize > 32) { + errorCode |= kControllerTXQSizeGreaterThan32 ; + } +//----------------------------------- Check TXQ priority is <= 31 + if (inSettings.mControllerTXQBufferPriority > 31) { + errorCode |= kControllerTXQPriorityGreaterThan31 ; + } +//----------------------------------- Check controller receive FIFO size is 1 ... 32 + if (inSettings.mControllerReceiveFIFOSize == 0) { + errorCode |= kControllerReceiveFIFOSizeIsZero ; + }else if (inSettings.mControllerReceiveFIFOSize > 32) { + errorCode |= kControllerReceiveFIFOSizeGreaterThan32 ; + } +//----------------------------------- Check controller transmit FIFO size is 1 ... 32 + if (inSettings.mControllerTransmitFIFOSize == 0) { + errorCode |= kControllerTransmitFIFOSizeIsZero ; + }else if (inSettings.mControllerTransmitFIFOSize > 32) { + errorCode |= kControllerTransmitFIFOSizeGreaterThan32 ; + } +//----------------------------------- Check Transmit FIFO priority is <= 31 + if (inSettings.mControllerTransmitFIFOPriority > 31) { + errorCode |= kControllerTransmitFIFOPriorityGreaterThan31 ; + } +//----------------------------------- Check MCP2517FD controller RAM usage is <= 2048 bytes + if (inSettings.ramUsage () > 2048) { + errorCode |= kControllerRamUsageGreaterThan2048 ; + } +//----------------------------------- Check Filter definition + if (inFilters.filterCount () > 32) { + errorCode |= kMoreThan32Filters ; + } + if (inFilters.filterStatus () != ACAN2517FDFilters::kFiltersOk) { + errorCode |= kFilterDefinitionError ; + } +//----------------------------------- Check TDCO value + if ((inSettings.mTDCO > 63) || (inSettings.mTDCO < -64)) { + errorCode |= kInvalidTDCO ; + } +//----------------------------------- INT, CS pins, reset MCP2517FD + if (errorCode == 0) { + if (mINT != 255) { // 255 means interrupt is not used (thanks to Tyler Lewis) + pinMode (mINT, INPUT_PULLUP) ; + } + initCS () ; + //----------------------------------- Set SPI clock to 800 kHz + mSPISettings = SPISettings (800UL * 1000, MSBFIRST, SPI_MODE0) ; + //----------------------------------- Request configuration mode + bool wait = true ; + const uint32_t startTime = millis () ; + while (wait) { + writeRegister8 (CON_REGISTER + 3, 0x04 | (1 << 3)) ; // Request configuration mode, abort all transmissions + const uint8_t actualMode = (readRegister8 (CON_REGISTER + 2) >> 5) & 0x07 ; + wait = actualMode != 0x04 ; + if (wait && ((millis () - startTime) > 2)) { // Wait (2 ms max) until the configuration mode is reached + errorCode |= kRequestedConfigurationModeTimeOut ; + wait = false ; + } + } + //----------------------------------- Reset MCP2517FD (always use a 800 kHz clock) + reset2517FD () ; + } +//----------------------------------- Check SPI connection is on (with a 800 kHz clock) +// We write and the read back MCP2517FD RAM at address 0x400 + for (uint32_t i=1 ; (i != 0) && (errorCode == 0) ; i <<= 1) { + const uint16_t RAM_WORD_ADDRESS = 0x400 ; + writeRegister32 (RAM_WORD_ADDRESS, i) ; + const uint32_t readBackValue = readRegister32 (RAM_WORD_ADDRESS) ; + if (readBackValue != i) { + errorCode = kReadBackErrorWith1MHzSPIClock ; + } + } +//----------------------------------- Now, set internal clock with OSC register +// Bit 0: (rw) 1 --> 10xPLL +// Bit 4: (rw) 0 --> SCLK is divided by 1, 1 --> SCLK is divided by 2 +// Bits 5-6: Clock Output Divisor + if (errorCode == 0) { + uint8_t pll = 0 ; // No PLL + uint8_t osc = 0 ; // Divide by 1 + switch (inSettings.oscillator ()) { + case ACAN2517FDSettings::OSC_4MHz: + case ACAN2517FDSettings::OSC_20MHz: + case ACAN2517FDSettings::OSC_40MHz: + break ; + case ACAN2517FDSettings::OSC_4MHz_DIVIDED_BY_2: + case ACAN2517FDSettings::OSC_20MHz_DIVIDED_BY_2: + case ACAN2517FDSettings::OSC_40MHz_DIVIDED_BY_2: + osc = 1 << 4 ; // Divide by 2 + break ; + case ACAN2517FDSettings::OSC_4MHz10xPLL_DIVIDED_BY_2 : + pll = 1 ; // Enable 10x PLL + osc = 1 << 4 ; // Divide by 2 + break ; + case ACAN2517FDSettings::OSC_4MHz10xPLL : + pll = 1 ; // Enable 10x PLL + break ; + } + osc |= pll ; + if (inSettings.mCLKOPin != ACAN2517FDSettings::SOF) { + osc |= ((uint8_t) inSettings.mCLKOPin) << 5 ; + } + writeRegister8 (OSC_REGISTER, osc) ; // DS20005688B, page 16 + //--- Wait for PLL is ready (wait max 2 ms) + if (pll != 0) { + bool wait = true ; + const uint32_t startTime = millis () ; + while (wait) { + wait = (readRegister8 (OSC_REGISTER + 1) & 0x1) == 0 ; // DS20005688B, page 16 + if (wait && ((millis () - startTime) > 2)) { + errorCode = kX10PLLNotReadyWithin1MS ; + wait = false ; + } + } + } + } +//----------------------------------- Set full speed clock + mSPISettings = SPISettings ((inSettings.sysClock () * 2) / 5, MSBFIRST, SPI_MODE0) ; +//----------------------------------- Checking SPI connection is on (with a full speed clock) +// We write and read back 2517 RAM at address 0x400 + for (uint32_t i=1 ; (i != 0) && (errorCode == 0) ; i <<= 1) { + writeRegister32 (0x400, i) ; + const uint32_t readBackValue = readRegister32 (0x400) ; + if (readBackValue != i) { + errorCode = kReadBackErrorWithFullSpeedSPIClock ; + } + } +//----------------------------------- Install interrupt, configure external interrupt + if (errorCode == 0) { + //----------------------------------- Configure transmit and receive buffers + mDriverTransmitBuffer.initWithSize (inSettings.mDriverTransmitFIFOSize) ; + mDriverReceiveBuffer.initWithSize (inSettings.mDriverReceiveFIFOSize) ; + //----------------------------------- Reset RAM + for (uint16_t address = 0x400 ; address < 0xC00 ; address += 4) { + writeRegister32 (address, 0) ; + } + //----------------------------------- Configure CLKO pin + uint8_t data8 = 0x03 ; // Respect PM1-PM0 default values + if (inSettings.mCLKOPin == ACAN2517FDSettings::SOF) { + data8 |= 1 << 5 ; // SOF + } + if (inSettings.mTXCANIsOpenDrain) { + data8 |= 1 << 4 ; // TXCANOD + } + if (inSettings.mINTIsOpenDrain) { + data8 |= 1 << 6 ; // INTOD + } + writeRegister8 (IOCON_REGISTER_24_31, data8) ; // DS20005688B, page 24 + //----------------------------------- Configure ISO CRC Enable bit + data8 = 1 << 6 ; // PXEDIS <-- 1 + if (inSettings.mISOCRCEnabled) { + data8 |= 1 << 5 ; // Enable ISO CRC in CAN FD Frames bit + } + writeRegister8 (CON_REGISTER, data8) ; // DS20005688B, page 24 + //----------------------------------- Configure DTC (DS20005688B, page 29) + uint32_t data32 = 1UL << 25 ; // Enable Edge Filtering during Bus Integration state bit (added in 1.1.4) + if (inSettings.mTDCO != 0) { + data32 |= 1UL << 17 ; // Auto TDC + const uint32_t TCDO = uint32_t (inSettings.mTDCO) & 0x7F ; + data32 |= TCDO << 8 ; + } + writeRegister32 (TDC_REGISTER, data32) ; + //----------------------------------- Configure TXQ + data8 = inSettings.mControllerTXQBufferRetransmissionAttempts ; + data8 <<= 5 ; + data8 |= inSettings.mControllerTXQBufferPriority ; + writeRegister8 (TXQCON_REGISTER + 2, data8) ; // DS20005688B, page 48 + // Bit 5-7: Payload Size bits + // Bit 4-0: TXQ size + mUsesTXQ = inSettings.mControllerTXQSize > 0 ; + data8 = inSettings.mControllerTXQSize - 1 ; + data8 |= inSettings.mControllerTXQBufferPayload << 5 ; // Payload + writeRegister8 (TXQCON_REGISTER + 3, data8) ; // DS20005688B, page 48 + mTXQBufferPayload = ACAN2517FDSettings::objectSizeForPayload (inSettings.mControllerTXQBufferPayload) ; + //----------------------------------- Configure TXQ and TEF + // Bit 4: Enable Transmit Queue bit ---> 1: Enable TXQ and reserves space in RAM + // Bit 3: Store in Transmit Event FIFO bit ---> 0: Don’t save transmitted messages in TEF + // Bit 0: RTXAT ---> 1: Enable CiFIFOCONm.TXAT to control retransmission attempts + data8 = 0x01 ; // Enable RTXAT to limit retransmissions (Flole) + data8 |= mUsesTXQ ? (1 << 4) : 0x00 ; // Bug fix in 1.1.4 (thanks to danielhenz) + writeRegister8 (CON_REGISTER + 2, data8) ; // DS20005688B, page 24 + //----------------------------------- Configure RX FIFO (FIFOCON, DS20005688B, page 52) + data8 = inSettings.mControllerReceiveFIFOSize - 1 ; // Set receive FIFO size + data8 |= inSettings.mControllerReceiveFIFOPayload << 5 ; // Payload + writeRegister8 (FIFOCON_REGISTER (RECEIVE_FIFO_INDEX) + 3, data8) ; + data8 = 1 << 0 ; // Interrupt Enabled for FIFO not Empty (TFNRFNIE) + data8 |= 1 << 3 ; // Interrupt Enabled for FIFO Overflow (RXOVIE) + writeRegister8 (FIFOCON_REGISTER (RECEIVE_FIFO_INDEX), data8) ; + mReceiveFIFOPayload = ACAN2517FDSettings::objectSizeForPayload (inSettings.mControllerReceiveFIFOPayload) ; + //----------------------------------- Configure TX FIFO (FIFOCON, DS20005688B, page 52) + data8 = inSettings.mControllerTransmitFIFORetransmissionAttempts ; + data8 <<= 5 ; + data8 |= inSettings.mControllerTransmitFIFOPriority ; + writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 2, data8) ; + data8 = inSettings.mControllerTransmitFIFOSize - 1 ; // Set transmit FIFO size + data8 |= inSettings.mControllerTransmitFIFOPayload << 5 ; // Payload + writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 3, data8) ; + data8 = 1 << 7 ; // FIFO is a Tx FIFO + data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt + writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ; + mTransmitFIFOPayload = ACAN2517FDSettings::objectSizeForPayload (inSettings.mControllerTransmitFIFOPayload) ; + //----------------------------------- Configure receive filters + uint8_t filterIndex = 0 ; + ACAN2517FDFilters::Filter * filter = inFilters.mFirstFilter ; + mCallBackFunctionArray = new ACANFDCallBackRoutine [inFilters.filterCount ()] ; + while (NULL != filter) { + mCallBackFunctionArray [filterIndex] = filter->mCallBackRoutine ; + writeRegister32 (MASK_REGISTER (filterIndex), filter->mFilterMask) ; // DS20005688B, page 61 + writeRegister32 (FLTOBJ_REGISTER (filterIndex), filter->mAcceptanceFilter) ; // DS20005688B, page 60 + data8 = 1 << 7 ; // Filter is enabled + data8 |= 1 ; // Message matching filter is stored in FIFO1 + writeRegister8 (FLTCON_REGISTER (filterIndex), data8) ; // DS20005688B, page 58 + filter = filter->mNextFilter ; + filterIndex += 1 ; + } + //----------------------------------- Activate interrupts (INT, DS20005688B page 34) + data8 = (1 << 1) ; // Receive FIFO Interrupt Enable + data8 |= (1 << 0) ; // Transmit FIFO Interrupt Enable + writeRegister8 (INT_REGISTER + 2, data8) ; + data8 = (1 << 2) ; // TXATIE ---> 1: Transmit Attempt Interrupt Enable bit + writeRegister8 (INT_REGISTER + 3, data8) ; + //----------------------------------- Program nominal bit rate (NBTCFG register) + // bits 31-24: BRP - 1 + // bits 23-16: TSEG1 - 1 + // bit 15: unused + // bits 14-8: TSEG2 - 1 + // bit 7: unused + // bits 6-0: SJW - 1 + uint32_t data = inSettings.mBitRatePrescaler - 1 ; + data <<= 8 ; + data |= inSettings.mArbitrationPhaseSegment1 - 1 ; + data <<= 8 ; + data |= inSettings.mArbitrationPhaseSegment2 - 1 ; + data <<= 8 ; + data |= inSettings.mArbitrationSJW - 1 ; + writeRegister32 (NBTCFG_REGISTER, data); + //----------------------------------- Program data bit rate (DBTCFG register) + // bits 31-24: BRP - 1 + // bits 23-21: unused + // bits 20-16: TSEG1 - 1 + // bits 15-12: unused + // bits 11-8: TSEG2 - 1 + // bits 7-4: unused + // bits 3-0: SJW - 1 + mHasDataBitRate = inSettings.mDataBitRateFactor != ::DataBitRateFactor::x1 ; + if (mHasDataBitRate) { + data = inSettings.mBitRatePrescaler - 1 ; + data <<= 8 ; + data |= inSettings.mDataPhaseSegment1 - 1 ; + data <<= 8 ; + data |= inSettings.mDataPhaseSegment2 - 1 ; + data <<= 8 ; + data |= inSettings.mDataSJW - 1 ; + writeRegister32 (DBTCFG_REGISTER, data) ; + } + //----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24) + // bits 7-4: Transmit Bandwith Sharing Bits ---> 0 + // bit 3: Abort All Pending Transmissions bit --> 0 + mTXBWS_RequestedMode = inSettings.mRequestedMode | (TXBWS << 4) ; + writeRegister8 (CON_REGISTER + 3, mTXBWS_RequestedMode); + //----------------------------------- Wait (10 ms max) until requested mode is reached + bool wait = true ; + const uint32_t startTime = millis () ; + while (wait) { + const uint8_t actualMode = (readRegister8 (CON_REGISTER + 2) >> 5) & 0x07 ; + wait = actualMode != inSettings.mRequestedMode ; + if (wait && ((millis () - startTime) > 10)) { + errorCode |= kRequestedModeTimeOut ; + wait = false ; + } + } + #ifdef ARDUINO_ARCH_ESP32 + xTaskCreate (myESP32Task, "ACAN2517Handler", 1024, this, 256, &mESP32TaskHandle) ; + #endif + if (mINT != 255) { // 255 means interrupt is not used + #ifdef ARDUINO_ARCH_ESP32 + attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ; + #else + attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ; // Thank to Flole998 + mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32 + #endif + } + // If you begin() multiple times without constructor, + // mHardwareTxFIFOFull = true will block the transmitter. + mHardwareTxFIFOFull = false ; + mHardwareReceiveBufferOverflowCount = 0 ; + } +//--- + return errorCode ; +} + +//······················································································································ +// end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin) +//······················································································································ + +bool ACAN2517FD::end (void) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + //--- Detach interrupt pin + if (mINT != 255) { // 255 means interrupt is not used + const int8_t itPin = digitalPinToInterrupt (mINT) ; + detachInterrupt (itPin) ; // Available for ESP32 and Arduino + } + //--- Request configuration mode + bool wait = true ; + bool ok = false ; + const uint32_t startTime = millis () ; + while (wait) { + writeRegister8Assume_SPI_transaction (CON_REGISTER + 3, 0x04 | (1 << 3)) ; // Request configuration mode, abort all transmissions + const uint8_t actualMode = (readRegister8Assume_SPI_transaction (CON_REGISTER + 2) >> 5) & 0x07 ; + ok = actualMode == 0x04 ; + wait = !ok ; + if (wait && ((millis () - startTime) > 2)) { // Wait (2 ms max) until the configuration mode is reached + wait = false ; + } + } + //--- Reset MCP2517FD + assertCS () ; + mSPI.transfer16 (0x00) ; // Reset instruction: 0x0000 + deassertCS () ; + //--- ESP32: delete associated task + #ifdef ARDUINO_ARCH_ESP32 + if (mESP32TaskHandle != nullptr) { + vTaskDelete (mESP32TaskHandle) ; + mESP32TaskHandle = nullptr ; + } + #endif + //--- Deallocate buffers + delete [] mCallBackFunctionArray ; mCallBackFunctionArray = nullptr ; + mDriverReceiveBuffer.initWithSize (0) ; + mDriverTransmitBuffer.initWithSize (0) ; + //--- + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; +//--- + return ok ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// SEND FRAME +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) { + bool ok = inMessage.isValid () ; + if (ok) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + if (inMessage.idx == 0) { + ok = inMessage.len <= mTransmitFIFOPayload ; + if (ok) { + ok = enterInTransmitBuffer (inMessage) ; + } + }else if (inMessage.idx == 255) { + ok = inMessage.len <= mTXQBufferPayload ; + if (ok) { + ok = sendViaTXQ (inMessage) ; + } + } + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + } + return ok ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) { + bool result ; + if (mHardwareTxFIFOFull) { + result = mDriverTransmitBuffer.append (inMessage) ; + }else{ + result = true ; + appendInControllerTxFIFO (inMessage) ; + //--- If controller FIFO is full, enable "FIFO not full" interrupt + const uint8_t status = readRegister8Assume_SPI_transaction (FIFOSTA_REGISTER (TRANSMIT_FIFO_INDEX)) ; + if ((status & 1) == 0) { // FIFO is full + uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO + data8 |= 1 ; // Enable "FIFO not full" interrupt + data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt + writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ; + mHardwareTxFIFOFull = true ; + } + } + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +static uint32_t lengthCodeForLength (const uint8_t inLength) { + uint32_t result = inLength & 0x0F ; + switch (inLength) { + case 12 : result = 9 ; break ; + case 16 : result = 10 ; break ; + case 20 : result = 11 ; break ; + case 24 : result = 12 ; break ; + case 32 : result = 13 ; break ; + case 48 : result = 14 ; break ; + case 64 : result = 15 ; break ; + } + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) { + const uint16_t ramAddr = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (TRANSMIT_FIFO_INDEX))) ; +//--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27) + uint32_t idf = inMessage.id ; + if (inMessage.ext) { + idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ; + } +//--- Write DLC field, FDF, BRS, RTR, IDE bits + uint32_t flags = lengthCodeForLength (inMessage.len) ; + if (inMessage.ext) { + flags |= 1 << 4 ; // Set EXT bit + } + switch (inMessage.type) { + case CANFDMessage::CAN_REMOTE : + flags |= 1 << 5 ; // Set RTR bit + break ; + case CANFDMessage::CAN_DATA : + break ; + case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH : + flags |= 1 << 7 ; // Set FDF bit + break ; + case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH : + flags |= 1 << 7 ; // Set FDF bit + if (mHasDataBitRate) { + flags |= 1 << 6 ; // Set BRS bit + } + break ; + } +//--- Word count + const uint32_t wordCount = (inMessage.len + 3) / 4 ; +//--- Write word register via 6-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [74] = {0} ; +//--- Enter command + const uint16_t writeCommand = (ramAddr & 0x0FFF) | (0b0010 << 12) ; + buffer [0] = writeCommand >> 8 ; + buffer [1] = writeCommand & 0xFF ; +//--- Enter values + enterU32InBufferAtIndex (idf, buffer, 2) ; + enterU32InBufferAtIndex (flags, buffer, 6) ; + for (uint32_t i=0 ; i < wordCount ; i++) { + enterU32InBufferAtIndex (inMessage.data32 [i], buffer, 10 + 4 * i) ; + } +//--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 10 + 4 * wordCount) ; + deassertCS () ; +//--- Increment FIFO, send message (see DS20005688B, page 48) + const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit + writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 1, data8); +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) { + bool ok = mUsesTXQ ; + if (ok) { + uint8_t sta = readRegister8Assume_SPI_transaction (TXQSTA_REGISTER) ; + //--- Check Transmit Attempts Exhausted Interrupt Pending bit + ok = (sta & (1 << 4)) != 0 ; + if (ok) { + writeRegister8Assume_SPI_transaction (TXQSTA_REGISTER, ~ (1 << 4)) ; + }else{ + //--- Enter message only if TXQ FIFO is not full (see DS20005688B, page 50) + ok = (sta & 1) != 0 ; + } + if (ok) { + const uint16_t ramAddress = (uint16_t) (0x400 + readRegister32Assume_SPI_transaction (TXQUA_REGISTER)) ; + //--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27) + uint32_t idf = inMessage.id ; + if (inMessage.ext) { + idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ; + } + //--- Write DLC field, FDF, BRS, RTR, IDE bits + uint32_t flags = lengthCodeForLength (inMessage.len) ; + if (inMessage.ext) { + flags |= 1 << 4 ; // Set EXT bit + } + switch (inMessage.type) { + case CANFDMessage::CAN_REMOTE : + flags |= 1 << 5 ; // Set RTR bit + break ; + case CANFDMessage::CAN_DATA : + break ; + case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH : + flags |= 1 << 7 ; // Set FDF bit + break ; + case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH : + flags |= 1 << 7 ; // Set FDF bit + if (mHasDataBitRate) { + flags |= 1 << 6 ; // Set BRS bit + } + break ; + } + //--- Word count + const uint32_t wordCount = (inMessage.len + 3) / 4 ; + //--- Transfer frame to the MCP2517FD + uint8_t buffer [74] = {0} ; + //--- Enter command + const uint16_t writeCommand = (ramAddress & 0x0FFF) | (0b0010 << 12) ; + buffer [0] = writeCommand >> 8 ; + buffer [1] = writeCommand & 0xFF ; + //--- Enter values + enterU32InBufferAtIndex (idf, buffer, 2) ; + enterU32InBufferAtIndex (flags, buffer, 6) ; + for (uint32_t i=0 ; i < wordCount ; i++) { + enterU32InBufferAtIndex (inMessage.data32 [i], buffer, 10 + 4 * i) ; + } + //--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 10 + 4 * wordCount) ; + deassertCS () ; + //--- Increment FIFO, send message (see DS20005688B, page 48) + const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit + writeRegister8Assume_SPI_transaction (TXQCON_REGISTER + 1, data8); + } + } + return ok ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// RECEIVE FRAME +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::available (void) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + const bool hasReceivedMessage = mDriverReceiveBuffer.count () > 0 ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + return hasReceivedMessage ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::receive (CANFDMessage & outMessage) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + const bool hasReceivedMessage = mDriverReceiveBuffer.remove (outMessage) ; + //--- If receive interrupt is disabled, enable it (added in release 2.17) + if (mINT == 255) { // No interrupt pin + mRxInterruptEnabled = true ; + isr_poll_core () ; // Perform polling + }else if (!mRxInterruptEnabled) { + mRxInterruptEnabled = true ; + uint8_t data8 = readRegister8Assume_SPI_transaction (INT_REGISTER + 2) ; + data8 |= (1 << 1) ; // Receive FIFO Interrupt Enable + writeRegister8Assume_SPI_transaction (INT_REGISTER + 2, data8) ; + } + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + return hasReceivedMessage ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMatchCallBack) { + CANFDMessage receivedMessage ; + const bool hasReceived = receive (receivedMessage) ; + if (hasReceived) { + const uint32_t filterIndex = receivedMessage.idx ; + if (NULL != inFilterMatchCallBack) { + inFilterMatchCallBack (filterIndex) ; + } + ACANFDCallBackRoutine callBackFunction = (mCallBackFunctionArray == NULL) ? NULL : mCallBackFunctionArray [filterIndex] ; + if (NULL != callBackFunction) { + callBackFunction (receivedMessage) ; + } + } + return hasReceived ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// POLLING (ESP32) +//---------------------------------------------------------------------------------------------------------------------- + +#ifdef ARDUINO_ARCH_ESP32 + void ACAN2517FD::poll (void) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE ; + xSemaphoreGiveFromISR (mISRSemaphore, &xHigherPriorityTaskWoken) ; + portYIELD_FROM_ISR () ; + } +#endif + +//---------------------------------------------------------------------------------------------------------------------- +// POLLING (other than ESP32) +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef ARDUINO_ARCH_ESP32 + void ACAN2517FD::poll (void) { + noInterrupts () ; + isr_poll_core () ; + interrupts () ; + } +#endif + +//---------------------------------------------------------------------------------------------------------------------- +// INTERRUPT SERVICE ROUTINE (ESP32) +// https://stackoverflow.com/questions/51750377/how-to-disable-interrupt-watchdog-in-esp32-or-increase-isr-time-limit +//---------------------------------------------------------------------------------------------------------------------- + +#ifdef ARDUINO_ARCH_ESP32 + void ACAN2517FD::isr (void) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE ; + xSemaphoreGiveFromISR (mISRSemaphore, &xHigherPriorityTaskWoken) ; + portYIELD_FROM_ISR () ; + } +#endif + +//---------------------------------------------------------------------------------------------------------------------- +// INTERRUPT SERVICE ROUTINE (other than ESP32) +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef ARDUINO_ARCH_ESP32 + void ACAN2517FD::isr (void) { + isr_poll_core () ; + } +#endif + +//---------------------------------------------------------------------------------------------------------------------- +// INTERRUPT SERVICE ROUTINES (common) +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::isr_poll_core (void) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #endif + bool handled = true ; + while (handled) { + handled = false ; + const uint16_t it = readRegister16Assume_SPI_transaction (INT_REGISTER) ; // DS20005688B, page 34 + if (mRxInterruptEnabled && ((it & (1 << 1)) != 0)) { // Receive FIFO interrupt + receiveInterrupt () ; + handled = true ; + } + if ((it & (1 << 10)) != 0) { // Transmit Attempt interrupt + //--- Clear Pending Transmit Attempt interrupt bit + writeRegister8Assume_SPI_transaction (FIFOSTA_REGISTER (TRANSMIT_FIFO_INDEX), ~ (1 << 4)) ; + transmitInterrupt () ; + handled = true ; + }else if ((it & (1 << 0)) != 0) { // Transmit FIFO interrupt + transmitInterrupt () ; + handled = true ; + } + if ((it & (1 << 2)) != 0) { // TBCIF interrupt + writeRegister8Assume_SPI_transaction (INT_REGISTER, ~ (1 << 2)) ; + handled = true ; + } + if ((it & (1 << 3)) != 0) { // MODIF interrupt + writeRegister8Assume_SPI_transaction (INT_REGISTER, ~ (1 << 3)) ; + handled = true ; + } + if ((it & (1 << 12)) != 0) { // SERRIF interrupt + writeRegister8Assume_SPI_transaction (INT_REGISTER + 1, ~ (1 << 4)) ; + handled = true ; + } + if ((it & (1 << 11)) != 0) { // RXOVIF interrupt + handled = true ; + if (mHardwareReceiveBufferOverflowCount < 255) { + mHardwareReceiveBufferOverflowCount += 1 ; + } + writeRegister8Assume_SPI_transaction (FIFOSTA_REGISTER (RECEIVE_FIFO_INDEX), ~ (1 << 3)) ; + } + } + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #endif + mSPI.endTransaction () ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FIFO is not full + CANFDMessage message ; + const bool hasMessage = mDriverTransmitBuffer.remove (message) ; + if (hasMessage) { + appendInControllerTxFIFO (message) ; + }else{ // No message in transmit FIFO: disable "FIFO not full" interrupt + uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO + data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt + writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ; + mHardwareTxFIFOFull = false ; + } +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::receiveInterrupt (void) { + const uint16_t ramAddress = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (RECEIVE_FIFO_INDEX))) ; + CANFDMessage message ; +//--- Read word register via 6-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [74] = {0} ; +//--- Enter command + const uint16_t readCommand = (ramAddress & 0x0FFF) | (0b0011 << 12) ; + buffer [0] = readCommand >> 8 ; + buffer [1] = readCommand & 0xFF ; +//--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 74) ; + //--- Read identifier (see DS20005678A, page 42) + message.id = u32FromBufferAtIndex (buffer, 2) ; + //--- Read DLC, RTR, IDE bits, and match filter index + const uint32_t flags = u32FromBufferAtIndex (buffer, 6) ; + static const uint8_t kLength [16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64} ; + message.len = kLength [flags & 0x0F] ; + //--- Write data (Swap data if processor is big endian) + const uint32_t wordCount = (message.len + 3) / 4 ; + for (uint32_t i=0 ; i < wordCount ; i++) { + message.data32 [i] = u32FromBufferAtIndex (buffer, 10 + 4 * i) ; + } + deassertCS () ; +//--- Increment FIFO + const uint8_t data8 = 1 << 0 ; // Set UINC bit (DS20005688B, page 52) + writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (RECEIVE_FIFO_INDEX) + 1, data8) ; + message.idx = uint8_t ((flags >> 11) & 0x1F) ; +//--- Message type (DS20005678B, page 42) + if ((flags & (1 << 5)) != 0 ) { // RTR bit + message.type = CANFDMessage::CAN_REMOTE ; + }else if ((flags & (1 << 7)) == 0) { // FDF bit + message.type = CANFDMessage::CAN_DATA ; + }else if ((flags & (1 << 6)) == 0) { // BRS bit + message.type = CANFDMessage::CANFD_NO_BIT_RATE_SWITCH ; + }else{ + message.type = CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH ; + } +//--- If an extended frame is received, identifier bits should be reordered (see DS20005678B, page 42) + message.ext = (flags & (1 << 4)) != 0 ; + if (message.ext) { + const uint32_t tempID = message.id ; + message.id = ((tempID >> 11) & 0x3FFFF) | ((tempID & 0x7FF) << 18) ; + } +//--- Append message to driver receive FIFO + mDriverReceiveBuffer.append (message) ; +//--- If mDriverReceiveBuffer is full, disable receive interrupt (added in release 2.17) + if (mDriverReceiveBuffer.isFull ()) { + mRxInterruptEnabled = false ; + if (mINT != 255) { + uint8_t data8 = readRegister8Assume_SPI_transaction (INT_REGISTER + 2) ; + data8 &= ~ (1 << 1) ; // Receive FIFO Interrupt disable + writeRegister8Assume_SPI_transaction (INT_REGISTER + 2, data8) ; + } + } +} + +//---------------------------------------------------------------------------------------------------------------------- +// MCP2517FD REGISTER ACCESS, SECOND LEVEL FUNCTIONS (HANDLE CS, ASSUME WITHIN SPI TRANSACTION) +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress, + const uint32_t inValue) { +//--- Write word register via 6-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [6] = {0} ; +//--- Enter command + const uint16_t writeCommand = (inRegisterAddress & 0x0FFF) | (0b0010 << 12) ; + buffer [0] = writeCommand >> 8 ; + buffer [1] = writeCommand & 0xFF ; +//--- Enter register value + enterU32InBufferAtIndex (inValue, buffer, 2) ; +//--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 6) ; + deassertCS () ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress, + const uint8_t inValue) { +//--- Write byte register via 3-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [3] = {0} ; + const uint16_t writeCommand = (inRegisterAddress & 0x0FFF) | (0b0010 << 12) ; + buffer [0] = writeCommand >> 8 ; + buffer [1] = writeCommand & 0xFF ; + buffer [2] = inValue ; + assertCS () ; + mSPI.transfer (buffer, 3) ; + deassertCS () ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::readRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress) { +//--- Read word register via 6-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [6] = {0} ; +//--- Enter command + const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ; + buffer [0] = readCommand >> 8 ; + buffer [1] = readCommand & 0xFF ; +//--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 6) ; + deassertCS () ; +//--- Get result + const uint32_t result = u32FromBufferAtIndex (buffer, 2) ; +//--- + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint16_t ACAN2517FD::readRegister16Assume_SPI_transaction (const uint16_t inRegisterAddress) { +//--- Read half-word register via 4-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [4] = {0} ; +//--- Enter command + const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ; + buffer [0] = readCommand >> 8 ; + buffer [1] = readCommand & 0xFF ; +//--- SPI transfer + assertCS () ; + mSPI.transfer (buffer, 4) ; + deassertCS () ; +//--- Get result + const uint16_t result = u16FromBufferAtIndex (buffer, 2) ; +//--- + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint8_t ACAN2517FD::readRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress) { +//--- Read byte register via 3-byte buffer (speed enhancement, thanks to thomasfla) + uint8_t buffer [3] = {0} ; + const uint16_t readCommand = (inRegisterAddress & 0x0FFF) | (0b0011 << 12) ; + buffer [0] = readCommand >> 8; + buffer [1] = readCommand & 0xFF; + assertCS () ; + mSPI.transfer(buffer, 3) ; + deassertCS () ; + return buffer [2] ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// MCP2517FD REGISTER ACCESS, THIRD LEVEL FUNCTIONS (HANDLE CS AND SPI TRANSACTION) +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t inValue) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + writeRegister8Assume_SPI_transaction (inRegisterAddress, inValue) ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint8_t ACAN2517FD::readRegister8 (const uint16_t inRegisterAddress) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + const uint8_t result = readRegister8Assume_SPI_transaction (inRegisterAddress) ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint16_t ACAN2517FD::readRegister16 (const uint16_t inRegisterAddress) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + const uint16_t result = readRegister16Assume_SPI_transaction (inRegisterAddress) ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::writeRegister32 (const uint16_t inRegisterAddress, const uint32_t inValue) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + writeRegister32Assume_SPI_transaction (inRegisterAddress, inValue) ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::readRegister32 (const uint16_t inRegisterAddress) { + mSPI.beginTransaction (mSPISettings) ; + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + const uint32_t result = readRegister32Assume_SPI_transaction (inRegisterAddress) ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; + return result ; +} + +//······················································································································ +// Current MCP2517FD Operation Mode +//······················································································································ + +ACAN2517FDSettings::OperationMode ACAN2517FD::currentOperationMode (void) { + const uint8_t mode = readRegister8 (CON_REGISTER + 2) >> 5 ; + return ACAN2517FDSettings::OperationMode (mode) ; +} + +//······················································································································ + +bool ACAN2517FD::recoverFromRestrictedOperationMode (void) { + bool recoveryDone = false ; + if (currentOperationMode () == ACAN2517FDSettings::RestrictedOperation) { // In Restricted Operation Mode + //----------------------------------- Request mode (CON_REGISTER + 3) + // bits 7-4: Transmit Bandwith Sharing Bits ---> 0 + // bit 3: Abort All Pending Transmission bits --> 0 + writeRegister8 (CON_REGISTER + 3, mTXBWS_RequestedMode); + //----------------------------------- Wait (10 ms max) until requested mode is reached + bool wait = true ; + const uint32_t startTime = millis () ; + while (wait) { + const uint8_t actualMode = (readRegister8 (CON_REGISTER + 2) >> 5) & 0x07 ; + wait = actualMode != (mTXBWS_RequestedMode & 0x07) ; + recoveryDone = !wait ; + if (wait && ((millis () - startTime) > 10)) { + wait = false ; + } + } + } + return recoveryDone ; +} + +//······················································································································ +// Set MCP2517FD Operation Mode +//······················································································································ + +void ACAN2517FD::setOperationMode (const ACAN2517FDSettings::OperationMode inOperationMode) { +// bits 7-4: Transmit Bandwith Sharing Bits ---> 0 +// bit 3: Abort All Pending Transmission bits --> 0 + writeRegister8 (CON_REGISTER + 3, uint8_t (inOperationMode)); +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::reset2517FD (void) { + mSPI.beginTransaction (mSPISettings) ; // Check RESET is performed with 800 kHz clock + #ifdef ARDUINO_ARCH_ESP32 + taskDISABLE_INTERRUPTS () ; + #else + noInterrupts () ; + #endif + assertCS () ; + mSPI.transfer16 (0x00) ; // Reset instruction: 0x0000 + deassertCS () ; + #ifdef ARDUINO_ARCH_ESP32 + taskENABLE_INTERRUPTS () ; + #else + interrupts () ; + #endif + mSPI.endTransaction () ; +} + +//······················································································································ +// Sleep Mode to Configuration Mode +// (returns true if MCP2517FD was in sleep mode) +//······················································································································ +// The device exits Sleep mode due to a dominant edge on RXCAN or by enabling the oscillator (clearing OSC.OSCDIS). +// The module will transition automatically to Configuration mode. + +bool ACAN2517FD::performSleepModeToConfigurationMode (void) { + uint8_t value = readRegister8 (OSC_REGISTER) ; + const bool inSleepMode = (value & (1 << 2)) != 0 ; + if (inSleepMode) { + value &= ~ (1 << 2) ; // Reset OSCDIS bit + writeRegister8 (OSC_REGISTER, value) ; + //--- Wait Clock is ready, ie OSC.OSCRDY is 1 + bool wait = true ; + while (wait) { + wait = (readRegister8 (OSC_REGISTER + 1) & (1 << 2)) == 0 ; + } + } + return inSleepMode ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::errorCounters (void) { + return readRegister32 (TREC_REGISTER) ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FD::diagInfos (const int inIndex) { // thanks to Flole998 and turmary + return readRegister32 (inIndex ? BDIAG1_REGISTER: BDIAG0_REGISTER) ; +} + +//······················································································································ +// GPIO +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::gpioSetMode (const uint8_t inPin, const uint8_t inMode) { + if (inPin <= 1) { + uint8_t value = readRegister8 (IOCON_REGISTER_00_07) ; + if (inMode == INPUT) { + value |= (1 << inPin) ; + if (inPin == 0) { + value &= 3 ; // Clear XSBTYEN + } + }else if (inMode == OUTPUT) { + value &= ~ (1 << inPin) ; + if (inPin == 0) { + value &= 3 ; // Clear XSBTYEN + } + } + writeRegister8 (IOCON_REGISTER_00_07, value) ; + } +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::gpioWrite (const uint8_t inPin, const uint8_t inLevel) { + if (inPin <= 1) { + uint8_t value = readRegister8 (IOCON_REGISTER_08_15) ; + if (inLevel == 0) { // LOW + value &= ~ (1 << inPin) ; + }else{ + value |= (1 << inPin) ; + } + writeRegister8 (IOCON_REGISTER_08_15, value) ; + } +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FD::gpioRead (const uint8_t inPin) { + const uint8_t value = readRegister8 (IOCON_REGISTER_16_23) ; + return (value >> inPin) & 1 ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +void ACAN2517FD::configureGPIO0AsXSTBY (void) { + uint8_t value = readRegister8 (IOCON_REGISTER_00_07) ; + value |= (1 << 6) ; // Enable XSBTYEN + writeRegister8 (IOCON_REGISTER_00_07, value) ; +} + +//---------------------------------------------------------------------------------------------------------------------- diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h new file mode 100644 index 00000000..c695e80a --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h @@ -0,0 +1,350 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CAN driver for MCP2517FD, CANFD mode +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//---------------------------------------------------------------------------------------------------------------------- + +#include "ACAN2517FDSettings.h" +#include "ACANFDBuffer.h" +#include "CANMessage.h" +#include "ACAN2517FDFilters.h" +#include + +//---------------------------------------------------------------------------------------------------------------------- +// ACAN2517FD class +//---------------------------------------------------------------------------------------------------------------------- + +class ACAN2517FD { + +//······················································································································ +// CONSTRUCTOR +//······················································································································ + + public: ACAN2517FD (const uint8_t inCS, // CS input of MCP2517FD + SPIClass & inSPI, // Hardware SPI object + const uint8_t inINT) ; // INT output of MCP2517FD + +//······················································································································ +// begin method (returns 0 if no error) +//······················································································································ + + public: uint32_t begin (const ACAN2517FDSettings & inSettings, + void (* inInterruptServiceRoutine) (void)) ; + + public: uint32_t begin (const ACAN2517FDSettings & inSettings, + void (* inInterruptServiceRoutine) (void), + const ACAN2517FDFilters & inFilters) ; + +//--- Error code returned by begin + public: static const uint32_t kRequestedConfigurationModeTimeOut = uint32_t (1) << 0 ; + public: static const uint32_t kReadBackErrorWith1MHzSPIClock = uint32_t (1) << 1 ; + public: static const uint32_t kTooFarFromDesiredBitRate = uint32_t (1) << 2 ; + public: static const uint32_t kInconsistentBitRateSettings = uint32_t (1) << 3 ; + public: static const uint32_t kINTPinIsNotAnInterrupt = uint32_t (1) << 4 ; + public: static const uint32_t kISRIsNull = uint32_t (1) << 5 ; + public: static const uint32_t kFilterDefinitionError = uint32_t (1) << 6 ; + public: static const uint32_t kMoreThan32Filters = uint32_t (1) << 7 ; + public: static const uint32_t kControllerReceiveFIFOSizeIsZero = uint32_t (1) << 8 ; + public: static const uint32_t kControllerReceiveFIFOSizeGreaterThan32 = uint32_t (1) << 9 ; + public: static const uint32_t kControllerTransmitFIFOSizeIsZero = uint32_t (1) << 10 ; + public: static const uint32_t kControllerTransmitFIFOSizeGreaterThan32 = uint32_t (1) << 11 ; + public: static const uint32_t kControllerRamUsageGreaterThan2048 = uint32_t (1) << 12 ; + public: static const uint32_t kControllerTXQPriorityGreaterThan31 = uint32_t (1) << 13 ; + public: static const uint32_t kControllerTransmitFIFOPriorityGreaterThan31 = uint32_t (1) << 14 ; + public: static const uint32_t kControllerTXQSizeGreaterThan32 = uint32_t (1) << 15 ; + public: static const uint32_t kRequestedModeTimeOut = uint32_t (1) << 16 ; + public: static const uint32_t kX10PLLNotReadyWithin1MS = uint32_t (1) << 17 ; + public: static const uint32_t kReadBackErrorWithFullSpeedSPIClock = uint32_t (1) << 18 ; + public: static const uint32_t kISRNotNullAndNoIntPin = uint32_t (1) << 19 ; + public: static const uint32_t kInvalidTDCO = uint32_t (1) << 20 ; + +//······················································································································ +// end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin) +// Return true if end method succeeds, and false otherwise +//······················································································································ + + public: bool end (void) ; + +//······················································································································ +// Send a message +//······················································································································ + + public: bool tryToSend (const CANFDMessage & inMessage) ; + +//······················································································································ +// Receive a message +//······················································································································ + + public: bool receive (CANFDMessage & outMessage) ; + public: bool available (void) ; + public: typedef void (*tFilterMatchCallBack) (const uint32_t inFilterIndex) ; + public: bool dispatchReceivedMessage (const tFilterMatchCallBack inFilterMatchCallBack = NULL) ; + +//--- Call back function array + private: ACANFDCallBackRoutine * mCallBackFunctionArray = NULL ; + +//······················································································································ +// Get error counters +//······················································································································ + + public: uint32_t errorCounters (void) ; + +//······················································································································ +// Get diagnostic information (thanks to Flole998 and turmary) +// inIndex == 0 returns BDIAG0_REGISTER +// inIndex != 0 returns BDIAG1_REGISTER +//······················································································································ + + public: uint32_t diagInfos (const int inIndex = 1) ; + +//······················································································································ +// Operation Mode +//······················································································································ + + public: ACAN2517FDSettings::OperationMode currentOperationMode (void) ; + + public: void setOperationMode (const ACAN2517FDSettings::OperationMode inMode) ; + +//······················································································································ +// Recovery from Restricted Operation Mode +//······················································································································ + + public: bool recoverFromRestrictedOperationMode (void) ; + +//······················································································································ +// Sleep Mode to Configuration Mode +// (returns true if MCP2517FD was in sleep mode) +//······················································································································ + + public: bool performSleepModeToConfigurationMode (void) ; + +//······················································································································ +// Private properties +//······················································································································ + + #ifdef ARDUINO_ARCH_ESP32 + private: TaskHandle_t mESP32TaskHandle = nullptr ; + #endif + private: SPISettings mSPISettings ; + private: SPIClass & mSPI ; + private: const uint8_t mCS ; + private: const uint8_t mINT ; + private: bool mUsesTXQ ; + private: bool mHardwareTxFIFOFull ; + private: bool mRxInterruptEnabled ; // Added in 2.1.7 + private: bool mHasDataBitRate ; + private: uint8_t mTransmitFIFOPayload ; // in byte count + private: uint8_t mTXQBufferPayload ; // in byte count + private: uint8_t mReceiveFIFOPayload ; // in byte count + private: uint8_t mTXBWS_RequestedMode ; + private: uint8_t mHardwareReceiveBufferOverflowCount ; + +//······················································································································ +// Receive buffer +//······················································································································ + + private: ACANFDBuffer mDriverReceiveBuffer ; + + public: uint32_t driverReceiveBufferPeakCount (void) const { return mDriverReceiveBuffer.peakCount () ; } + + public: uint8_t hardwareReceiveBufferOverflowCount (void) const { return mHardwareReceiveBufferOverflowCount ; } + + public: void resetHardwareReceiveBufferOverflowCount (void) { mHardwareReceiveBufferOverflowCount = 0 ; } + +//······················································································································ +// Transmit buffer +//······················································································································ + + private: ACANFDBuffer mDriverTransmitBuffer ; + + public: uint32_t driverTransmitBufferSize (void) const { return mDriverTransmitBuffer.size () ; } + + public: uint32_t driverTransmitBufferCount (void) const { return mDriverTransmitBuffer.count () ; } + + public: uint32_t driverTransmitBufferPeakCount (void) const { return mDriverTransmitBuffer.peakCount () ; } + +//······················································································································ +// Private methods +//······················································································································ + + private: void writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint32_t inValue) ; + private: void writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint8_t inValue) ; + + private: uint32_t readRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress) ; + private: uint8_t readRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress) ; + private: uint16_t readRegister16Assume_SPI_transaction (const uint16_t inRegisterAddress) ; + + private: void reset2517FD (void) ; + + private: void writeRegister8 (const uint16_t inRegisterAddress, const uint8_t inValue) ; + private: void writeRegister32 (const uint16_t inAddress, const uint32_t inValue) ; + + private: uint8_t readRegister8 (const uint16_t inAddress) ; + private: uint16_t readRegister16 (const uint16_t inAddress) ; + private: uint32_t readRegister32 (const uint16_t inAddress) ; + + private: bool sendViaTXQ (const CANFDMessage & inMessage) ; + private: bool enterInTransmitBuffer (const CANFDMessage & inMessage) ; + private: void appendInControllerTxFIFO (const CANFDMessage & inMessage) ; + +//······················································································································ +// Polling +//······················································································································ + + public: void poll (void) ; + +//······················································································································ +// Interrupt service routine +//······················································································································ + + public: void isr (void) ; + public: void isr_poll_core (void) ; + private: void receiveInterrupt (void) ; + private: void transmitInterrupt (void) ; + #ifdef ARDUINO_ARCH_ESP32 + public: SemaphoreHandle_t mISRSemaphore ; + #endif + +//---------------------------------------------------------------------------------------------------------------------- +// Optimized CS handling (thanks to Flole998) +//······················································································································ + + #if defined(__AVR__) + private: volatile uint8_t *cs_pin_reg; + private: uint8_t cs_pin_mask; + private: inline void initCS () { + cs_pin_reg = portOutputRegister(digitalPinToPort(mCS)); + cs_pin_mask = digitalPinToBitMask(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg) &= ~cs_pin_mask; + } + private: inline void deassertCS() { + *(cs_pin_reg) |= cs_pin_mask; + } + #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) + private: volatile uint8_t *cs_pin_reg; + private: inline void initCS () { + cs_pin_reg = portOutputRegister(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg+256) = 1; + } + private: inline void deassertCS() { + *(cs_pin_reg+128) = 1; + } + #elif defined(__MKL26Z64__) + private: volatile uint8_t *cs_pin_reg; + private: uint8_t cs_pin_mask; + private: inline void initCS () { + cs_pin_reg = portOutputRegister(digitalPinToPort(mCS)); + cs_pin_mask = digitalPinToBitMask(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg+8) = cs_pin_mask; + } + private: inline void deassertCS() { + *(cs_pin_reg+4) = cs_pin_mask; + } + #elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) + private: volatile uint32_t *cs_pin_reg; + private: uint32_t cs_pin_mask; + private: inline void initCS () { + cs_pin_reg = &(digitalPinToPort(mCS)->PIO_PER); + cs_pin_mask = digitalPinToBitMask(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg+13) = cs_pin_mask; + } + private: inline void deassertCS() { + *(cs_pin_reg+12) = cs_pin_mask; + } + #elif defined(__PIC32MX__) + private: volatile uint32_t *cs_pin_reg; + private: uint32_t cs_pin_mask; + private: inline void initCS () { + cs_pin_reg = portModeRegister(digitalPinToPort(mCS)); + cs_pin_mask = digitalPinToBitMask(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg+8+1) = cs_pin_mask; + } + private: inline void deassertCS() { + *(cs_pin_reg+8+2) = cs_pin_mask; + } + #elif defined(ARDUINO_ARCH_ESP8266) + // private: volatile uint32_t *cs_pin_reg; + private: uint32_t cs_pin_mask; + private: inline void initCS () { + // cs_pin_reg = (volatile uint32_t*)GPO; + cs_pin_mask = 1 << mCS; + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + GPOC = cs_pin_mask; + } + private: inline void deassertCS() { + GPOS = cs_pin_mask; + } + + #elif defined(__SAMD21G18A__) + private: volatile uint32_t *cs_pin_reg; + private: uint32_t cs_pin_mask; + private: inline void initCS () { + cs_pin_reg = portModeRegister(digitalPinToPort(mCS)); + cs_pin_mask = digitalPinToBitMask(mCS); + pinMode(mCS, OUTPUT); + } + private: inline void assertCS() { + *(cs_pin_reg+5) = cs_pin_mask; + } + private: inline void deassertCS() { + *(cs_pin_reg+6) = cs_pin_mask; + } + #else + private: inline void initCS () { + pinMode (mCS, OUTPUT); + } + private: inline void assertCS() { + digitalWrite(mCS, LOW); + } + private: inline void deassertCS() { + digitalWrite(mCS, HIGH); + } + #endif + +//······················································································································ +// GPIO +//······················································································································ + + public: void gpioSetMode (const uint8_t inPin, const uint8_t inMode) ; + + public: void gpioWrite (const uint8_t inPin, const uint8_t inLevel) ; + + public: bool gpioRead (const uint8_t inPin) ; + + public: void configureGPIO0AsXSTBY (void) ; + +//······················································································································ +// No copy +//······················································································································ + + private: ACAN2517FD (const ACAN2517FD &) = delete ; + private: ACAN2517FD & operator = (const ACAN2517FD &) = delete ; + +//······················································································································ + +} ; + +//---------------------------------------------------------------------------------------------------------------------- + diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDFilters.h b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDFilters.h new file mode 100644 index 00000000..69895acb --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDFilters.h @@ -0,0 +1,238 @@ +//---------------------------------------------------------------------------------------------------------------------- +// An utility class for: +// - ACAN2517FD CAN driver for MCP2517FD (CANFD mode) +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef ACAN2517FD_FILTERS_CLASS_DEFINED +#define ACAN2517FD_FILTERS_CLASS_DEFINED + +//---------------------------------------------------------------------------------------------------------------------- + +#include "CANFDMessage.h" + +//---------------------------------------------------------------------------------------------------------------------- +// ACAN2517FDFilters class +//---------------------------------------------------------------------------------------------------------------------- + +class ACAN2517FDFilters { + +//······················································································································ +// EMBEDDED CLASS +//······················································································································ + + private: class Filter { + public: Filter * mNextFilter ; + public: const uint32_t mFilterMask ; + public: const uint32_t mAcceptanceFilter ; + public: const ACANFDCallBackRoutine mCallBackRoutine ; + + public: Filter (const uint32_t inFilterMask, + const uint32_t inAcceptanceFilter, + const ACANFDCallBackRoutine inCallBackRoutine) : + mNextFilter (NULL), + mFilterMask (inFilterMask), + mAcceptanceFilter (inAcceptanceFilter), + mCallBackRoutine (inCallBackRoutine) { + } + + //--- No copy + private: Filter (const Filter &) ; + private: Filter & operator = (const Filter &) ; + } ; + +//······················································································································ +// ENUMERATED TYPE +//······················································································································ + + public: typedef enum { + kFiltersOk, + kStandardIdentifierTooLarge, + kExtendedIdentifierTooLarge, + kStandardAcceptanceTooLarge, + kExtendedAcceptanceTooLarge, + kStandardMaskTooLarge, + kExtendedMaskTooLarge, + kInconsistencyBetweenMaskAndAcceptance + } FilterStatus ; + +//······················································································································ +// CONSTRUCTOR +//······················································································································ + + public: ACAN2517FDFilters (void) {} + +//······················································································································ +// DESTRUCTOR +//······················································································································ + + public: ~ ACAN2517FDFilters (void) { + while (mFirstFilter != NULL) { + Filter * next = mFirstFilter->mNextFilter ; + delete mFirstFilter ; + mFirstFilter = next ; + } + } + +//······················································································································ +// RECEIVE FILTERS +//······················································································································ + + public: void appendPassAllFilter (const ACANFDCallBackRoutine inCallBackRoutine) { // Accept any frame + Filter * f = new Filter (0, 0, inCallBackRoutine) ; + if (mFirstFilter == NULL) { + mFirstFilter = f ; + }else{ + mLastFilter->mNextFilter = f ; + } + mLastFilter = f ; + mFilterCount += 1 ; + } + +//······················································································································ + + public: void appendFormatFilter (const tFrameFormat inFormat, // Accept any identifier + const ACANFDCallBackRoutine inCallBackRoutine) { + Filter * f = new Filter (((uint32_t) 1) << 30, + (inFormat == kExtended) ? (((uint32_t) 1) << 30) : 0, + inCallBackRoutine) ; + if (mFirstFilter == NULL) { + mFirstFilter = f ; + }else{ + mLastFilter->mNextFilter = f ; + } + mLastFilter = f ; + mFilterCount += 1 ; + } + +//······················································································································ + + public: void appendFrameFilter (const tFrameFormat inFormat, + const uint32_t inIdentifier, + const ACANFDCallBackRoutine inCallBackRoutine) { + //--- Check identifier + if (inFormat == kExtended) { + if (inIdentifier > 0x1FFFFFFF) { + mFilterStatus = kExtendedIdentifierTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + }else if (inIdentifier > 0x7FF) { + mFilterStatus = kStandardIdentifierTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + //--- Re order bits if extended filter + const uint32_t mask = (((uint32_t) 1) << 30) | ((inFormat == kExtended) ? 0x1FFFFFFF : 0x7FF) ; + uint32_t acceptance ; + if (inFormat == kExtended) { + acceptance = ((inIdentifier >> 18) & 0x7FF) | ((inIdentifier & 0x3FFFF) << 11) | (((uint32_t) 1) << 30) ; + }else{ + acceptance = inIdentifier ; + } + //--- Enter filter + Filter * f = new Filter (mask, acceptance, inCallBackRoutine) ; + if (mFirstFilter == NULL) { + mFirstFilter = f ; + }else{ + mLastFilter->mNextFilter = f ; + } + mLastFilter = f ; + mFilterCount += 1 ; + } + +//······················································································································ + + public: void appendFilter (const tFrameFormat inFormat, + const uint32_t inMask, + const uint32_t inAcceptance, + const ACANFDCallBackRoutine inCallBackRoutine) { + //--- Check consistency between mask and acceptance + if ((inMask & inAcceptance) != inAcceptance) { + mFilterStatus = kInconsistencyBetweenMaskAndAcceptance ; + mFilterErrorIndex = mFilterCount ; + } + //--- Check identifier + if (inFormat == kExtended) { + if (inAcceptance > 0x1FFFFFFF) { + mFilterStatus = kExtendedAcceptanceTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + }else if (inAcceptance > 0x7FF) { + mFilterStatus = kStandardAcceptanceTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + //--- Check mask + if (inFormat == kExtended) { + if (inMask > 0x1FFFFFFF) { + mFilterStatus = kExtendedMaskTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + }else if (inMask > 0x7FF) { + mFilterStatus = kStandardMaskTooLarge ; + mFilterErrorIndex = mFilterCount ; + } + //--- Re order bits if extended filter + uint32_t mask = ((uint32_t) 1) << 30 ; + if (inFormat == kExtended) { + mask |= ((inMask >> 18) & 0x7FF) | ((inMask & 0x3FFFF) << 11) ; + }else{ + mask |= inMask ; + } + uint32_t acceptance ; + if (inFormat == kExtended) { + acceptance = ((inAcceptance >> 18) & 0x7FF) | ((inAcceptance & 0x3FFFF) << 11) | (((uint32_t) 1) << 30) ; + }else{ + acceptance = inAcceptance ; + } + //--- Enter filter + Filter * f = new Filter (mask, acceptance, inCallBackRoutine) ; + if (mFirstFilter == NULL) { + mFirstFilter = f ; + }else{ + mLastFilter->mNextFilter = f ; + } + mLastFilter = f ; + mFilterCount += 1 ; + } + +//······················································································································ +// ACCESSORS +//······················································································································ + + public: FilterStatus filterStatus (void) const { return mFilterStatus ; } + + public: uint8_t filterErrorIndex (void) const { return mFilterErrorIndex ; } + + public: uint8_t filterCount (void) const { return mFilterCount ; } + +//······················································································································ +// PRIVATE PROPERTIES +//······················································································································ + + private: uint8_t mFilterCount = 0 ; + private: Filter * mFirstFilter = NULL ; + private: Filter * mLastFilter = NULL ; + private: FilterStatus mFilterStatus = kFiltersOk ; + private: uint8_t mFilterErrorIndex = 0 ; + +//······················································································································ +// NO COPY +//······················································································································ + + private: ACAN2517FDFilters (const ACAN2517FDFilters &) = delete ; + private: ACAN2517FDFilters & operator = (const ACAN2517FDFilters &) = delete ; + +//······················································································································ +// Friend +//······················································································································ + + friend class ACAN2517FD ; + +//······················································································································ + +} ; + +//---------------------------------------------------------------------------------------------------------------------- + +#endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.cpp b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.cpp new file mode 100644 index 00000000..0a97683a --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.cpp @@ -0,0 +1,355 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CAN driver for MCP2517FD (CANFD mode) +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#include "ACAN2517FDSettings.h" + +//---------------------------------------------------------------------------------------------------------------------- + +#pragma GCC diagnostic error "-Wswitch-enum" + +//---------------------------------------------------------------------------------------------------------------------- +// sysClock +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) { + uint32_t sysClock = 40UL * 1000 * 1000 ; + switch (inOscillator) { + case OSC_4MHz: + sysClock = 4UL * 1000 * 1000 ; + break ; + case OSC_4MHz_DIVIDED_BY_2: + sysClock = 2UL * 1000 * 1000 ; + break ; + case OSC_4MHz10xPLL_DIVIDED_BY_2 : + case OSC_40MHz_DIVIDED_BY_2: + case OSC_20MHz: + sysClock = 20UL * 1000 * 1000 ; + break ; + case OSC_20MHz_DIVIDED_BY_2: + sysClock = 10UL * 1000 * 1000 ; + break ; + case OSC_4MHz10xPLL: + case OSC_40MHz: + break ; + } + return sysClock ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// CONSTRUCTOR +//---------------------------------------------------------------------------------------------------------------------- + +ACAN2517FDSettings::ACAN2517FDSettings (const Oscillator inOscillator, + const uint32_t inDesiredArbitrationBitRate, + const DataBitRateFactor inDataBitRateFactor, + const uint32_t inTolerancePPM) : +mOscillator (inOscillator), +mSysClock (sysClock (inOscillator)), +mDesiredArbitrationBitRate (inDesiredArbitrationBitRate), +mDataBitRateFactor (inDataBitRateFactor) { + if (inDataBitRateFactor == DataBitRateFactor::x1) { // Single bit rate + const uint32_t maxTQCount = MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1 ; // Setting for slowest bit rate + uint32_t BRP = MAX_BRP ; + uint32_t smallestError = UINT32_MAX ; + uint32_t bestBRP = 1 ; // Setting for highest bit rate + uint32_t bestTQCount = 4 ; // Setting for highest bit rate + uint32_t TQCount = mSysClock / inDesiredArbitrationBitRate / BRP ; + //--- Loop for finding best BRP and best TQCount + while ((TQCount <= (MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1)) && (BRP > 0)) { + //--- Compute error using TQCount + if ((TQCount >= 4) && (TQCount <= maxTQCount)) { + const uint32_t error = mSysClock - inDesiredArbitrationBitRate * TQCount * BRP ; // error is always >= 0 + if (error <= smallestError) { + smallestError = error ; + bestBRP = BRP ; + bestTQCount = TQCount ; + } + } + //--- Compute error using TQCount+1 + if ((TQCount >= 3) && (TQCount < maxTQCount)) { + const uint32_t error = inDesiredArbitrationBitRate * (TQCount + 1) * BRP - mSysClock ; // error is always >= 0 + if (error <= smallestError) { + smallestError = error ; + bestBRP = BRP ; + bestTQCount = TQCount + 1 ; + } + } + //--- Continue with next value of BRP + BRP -- ; + TQCount = (BRP == 0) ? (maxTQCount + 1) : (mSysClock / inDesiredArbitrationBitRate / BRP) ; + } + //--- Compute PS2 (1 <= PS2 <= 128) + uint32_t PS2 = bestTQCount / 5 ; // For sampling point at 80% + if (PS2 == 0) { + PS2 = 1 ; + }else if (PS2 > MAX_ARBITRATION_PHASE_SEGMENT_2) { + PS2 = MAX_ARBITRATION_PHASE_SEGMENT_2 ; + } + //--- Compute PS1 (1 <= PS1 <= 256) + uint32_t PS1 = bestTQCount - PS2 - 1 /* Sync Seg */ ; + if (PS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) { + PS2 += PS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ; + PS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ; + } + //--- + mBitRatePrescaler = (uint16_t) bestBRP ; + mArbitrationPhaseSegment1 = (uint16_t) PS1 ; + mArbitrationPhaseSegment2 = (uint8_t) PS2 ; + mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2 + //--- Final check of the nominal configuration + const uint32_t W = bestTQCount * mDesiredArbitrationBitRate * bestBRP ; + const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ; + const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno + mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ; + }else{ // Dual bit rate, first compute data bit rate + const uint32_t maxDataTQCount = MAX_DATA_PHASE_SEGMENT_1 + MAX_DATA_PHASE_SEGMENT_2 ; // Setting for slowest bit rate + const uint32_t desiredDataBitRate = inDesiredArbitrationBitRate * uint8_t (inDataBitRateFactor) ; + uint32_t smallestError = UINT32_MAX ; + uint32_t bestBRP = MAX_BRP ; // Setting for lowest bit rate + uint32_t bestDataTQCount = maxDataTQCount ; // Setting for lowest bit rate + uint32_t dataTQCount = 4 ; + uint32_t brp = mSysClock / desiredDataBitRate / dataTQCount ; + //--- Loop for finding best BRP and best TQCount + while ((dataTQCount <= maxDataTQCount) && (brp > 0)) { + //--- Compute error using brp + if (brp <= MAX_BRP) { + const uint32_t error = mSysClock - desiredDataBitRate * dataTQCount * brp ; // error is always >= 0 + if (error <= smallestError) { + smallestError = error ; + bestBRP = brp ; + bestDataTQCount = dataTQCount ; + } + } + //--- Compute error using brp+1 + if (brp < MAX_BRP) { + const uint32_t error = desiredDataBitRate * dataTQCount * (brp + 1) - mSysClock ; // error is always >= 0 + if (error <= smallestError) { + smallestError = error ; + bestBRP = brp + 1 ; + bestDataTQCount = dataTQCount ; + } + } + //--- Continue with next value of BRP + dataTQCount += 1 ; + brp = mSysClock / desiredDataBitRate / dataTQCount ; + } + //--- Compute data PS2 (1 <= PS2 <= 16) + uint32_t dataPS2 = bestDataTQCount / 5 ; // For sampling point at 80% + if (dataPS2 == 0) { + dataPS2 = 1 ; + } + //--- Compute data PS1 (1 <= PS1 <= 32) + uint32_t dataPS1 = bestDataTQCount - dataPS2 - 1 /* Sync Seg */ ; + if (dataPS1 > MAX_DATA_PHASE_SEGMENT_1) { + dataPS2 += dataPS1 - MAX_DATA_PHASE_SEGMENT_1 ; + dataPS1 = MAX_DATA_PHASE_SEGMENT_1 ; + } + //--- + if ((mDesiredArbitrationBitRate * uint32_t (inDataBitRateFactor)) <= (1000UL * 1000)) { + mTDCO = 0 ; + }else{ + const int TDCO = bestBRP * dataPS1 ; // According to DS20005678D, §3.4.8 Page 20 + mTDCO = (TDCO > 63) ? 63 : (int8_t) TDCO ; + } + mDataPhaseSegment1 = (uint8_t) dataPS1 ; + mDataPhaseSegment2 = (uint8_t) dataPS2 ; + mDataSJW = mDataPhaseSegment2 ; + const uint32_t arbitrationTQCount = bestDataTQCount * uint8_t (mDataBitRateFactor) ; + //--- Compute arbiration PS2 (1 <= PS2 <= 128) + uint32_t arbitrationPS2 = arbitrationTQCount / 5 ; // For sampling point at 80% + if (arbitrationPS2 == 0) { + arbitrationPS2 = 1 ; + } + //--- Compute PS1 (1 <= PS1 <= 256) + uint32_t arbitrationPS1 = arbitrationTQCount - arbitrationPS2 - 1 /* Sync Seg */ ; + if (arbitrationPS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) { + arbitrationPS2 += arbitrationPS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ; + arbitrationPS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ; + } + //--- + mBitRatePrescaler = (uint16_t) bestBRP ; + mArbitrationPhaseSegment1 = (uint16_t) arbitrationPS1 ; + mArbitrationPhaseSegment2 = (uint8_t) arbitrationPS2 ; + mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2 + //--- Final check of the nominal configuration + const uint32_t W = arbitrationTQCount * mDesiredArbitrationBitRate * bestBRP ; + const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ; + const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno + mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ; + } +} ; + +//---------------------------------------------------------------------------------------------------------------------- +// ACCESSORS +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::actualArbitrationBitRate (void) const { + const uint32_t arbitrationTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; + return mSysClock / mBitRatePrescaler / arbitrationTQCount ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::actualDataBitRate (void) const { + if (mDataBitRateFactor == DataBitRateFactor::x1) { + return actualArbitrationBitRate () ; + }else{ + const uint32_t dataTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ; + return mSysClock / mBitRatePrescaler / dataTQCount ; + } +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FDSettings::exactArbitrationBitRate (void) const { + const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; + return mSysClock == (mBitRatePrescaler * mDesiredArbitrationBitRate * TQCount) ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FDSettings::exactDataBitRate (void) const { + if (mDataBitRateFactor == DataBitRateFactor::x1) { + return exactArbitrationBitRate () ; + }else{ + const uint32_t TQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ; + return mSysClock == (mBitRatePrescaler * mDesiredArbitrationBitRate * TQCount * uint8_t (mDataBitRateFactor)) ; + } +} + +//---------------------------------------------------------------------------------------------------------------------- + +bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const { + bool result = mDataBitRateFactor == DataBitRateFactor::x1 ; + if (!result) { + const uint32_t dataTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ; + const uint32_t arbitrationTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; + result = arbitrationTQCount == (dataTQCount * uint8_t (mDataBitRateFactor)) ; + } + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::ppmFromDesiredArbitrationBitRate (void) const { + const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; + const uint32_t W = TQCount * mDesiredArbitrationBitRate * mBitRatePrescaler ; + const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ; + const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno + return (uint32_t) ((diff * ppm) / W) ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const { + const uint32_t nominalTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; + const uint32_t samplePoint = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 ; + const uint32_t partPerCent = 100 ; + return (samplePoint * partPerCent) / nominalTQCount ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const { + const uint32_t nominalTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ; + const uint32_t samplePoint = 1 /* Sync Seg */ + mDataPhaseSegment1 ; + const uint32_t partPerCent = 100 ; + return (samplePoint * partPerCent) / nominalTQCount ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const { + uint32_t errorCode = 0 ; // Means no error +//--- Bit rate prescaler + if (mBitRatePrescaler == 0) { + errorCode |= kBitRatePrescalerIsZero ; + }else if (mBitRatePrescaler > MAX_BRP) { + errorCode |= kBitRatePrescalerIsGreaterThan256 ; + } +//--- Arbitration Phase Segment 1 + if (mArbitrationPhaseSegment1 < 2) { + errorCode |= kArbitrationPhaseSegment1IsLowerThan2 ; + }else if (mArbitrationPhaseSegment1 > MAX_ARBITRATION_PHASE_SEGMENT_1) { + errorCode |= kArbitrationPhaseSegment1IsGreaterThan256 ; + } +//--- Arbitration Phase Segment 2 + if (mArbitrationPhaseSegment2 == 0) { + errorCode |= kArbitrationPhaseSegment2IsZero ; + }else if (mArbitrationPhaseSegment2 > MAX_ARBITRATION_PHASE_SEGMENT_2) { + errorCode |= kArbitrationPhaseSegment2IsGreaterThan128 ; + } +//--- Arbitration SJW + if (mArbitrationSJW == 0) { + errorCode |= kArbitrationSJWIsZero ; + }else if (mArbitrationSJW > MAX_ARBITRATION_SJW) { + errorCode |= kArbitrationSJWIsGreaterThan128 ; + } + if (mArbitrationSJW > mArbitrationPhaseSegment1) { + errorCode |= kArbitrationSJWIsGreaterThanPhaseSegment1 ; + } + if (mArbitrationSJW > mArbitrationPhaseSegment2) { + errorCode |= kArbitrationSJWIsGreaterThanPhaseSegment2 ; + } +//--- Data bit rate ? + if (mDataBitRateFactor != DataBitRateFactor::x1) { + if (! dataBitRateIsAMultipleOfArbitrationBitRate ()) { + errorCode |= kArbitrationTQCountNotDivisibleByDataBitRateFactor ; + } + //--- Data Phase Segment 1 + if (mDataPhaseSegment1 < 2) { + errorCode |= kDataPhaseSegment1IsLowerThan2 ; + }else if (mDataPhaseSegment1 > MAX_DATA_PHASE_SEGMENT_1) { + errorCode |= kDataPhaseSegment1IsGreaterThan32 ; + } + //--- Data Phase Segment 2 + if (mDataPhaseSegment2 == 0) { + errorCode |= kDataPhaseSegment2IsZero ; + }else if (mDataPhaseSegment2 > MAX_DATA_PHASE_SEGMENT_2) { + errorCode |= kDataPhaseSegment2IsGreaterThan16 ; + } + //--- Data SJW + if (mDataSJW == 0) { + errorCode |= kDataSJWIsZero ; + }else if (mDataSJW > MAX_DATA_SJW) { + errorCode |= kDataSJWIsGreaterThan16 ; + } + if (mDataSJW > mDataPhaseSegment1) { + errorCode |= kDataSJWIsGreaterThanPhaseSegment1 ; + } + if (mDataSJW > mDataPhaseSegment2) { + errorCode |= kDataSJWIsGreaterThanPhaseSegment2 ; + } + } +//--- + return errorCode ; +} + +//---------------------------------------------------------------------------------------------------------------------- +// RAM USAGE +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::ramUsage (void) const { + uint32_t result = 0 ; +//--- TXQ + result += objectSizeForPayload (mControllerTXQBufferPayload) * mControllerTXQSize ; +//--- Receive FIFO (FIFO #1) + result += objectSizeForPayload (mControllerReceiveFIFOPayload) * mControllerReceiveFIFOSize ; +//--- Send FIFO (FIFO #2) + result += objectSizeForPayload (mControllerTransmitFIFOPayload) * mControllerTransmitFIFOSize ; +//--- + return result ; +} + +//---------------------------------------------------------------------------------------------------------------------- + +uint32_t ACAN2517FDSettings::objectSizeForPayload (const PayloadSize inPayload) { + static const uint8_t kPayload [8] = {16, 20, 24, 28, 32, 40, 56, 72} ; + return kPayload [inPayload] ; +} + +//---------------------------------------------------------------------------------------------------------------------- diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.h b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.h new file mode 100644 index 00000000..8e27392f --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACAN2517FDSettings.h @@ -0,0 +1,296 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CAN driver for MCP2517FD (CANFD mode) +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//---------------------------------------------------------------------------------------------------------------------- + +#include "ACANFD_DataBitRateFactor.h" + +//---------------------------------------------------------------------------------------------------------------------- +// ACAN2517FDSettings class +//---------------------------------------------------------------------------------------------------------------------- + +class ACAN2517FDSettings { + +//······················································································································ +// ENUMERATED TYPES +//······················································································································ + + public: typedef enum : uint8_t { + OSC_4MHz, + OSC_4MHz_DIVIDED_BY_2, + OSC_4MHz10xPLL, + OSC_4MHz10xPLL_DIVIDED_BY_2, + OSC_20MHz, + OSC_20MHz_DIVIDED_BY_2, + OSC_40MHz, + OSC_40MHz_DIVIDED_BY_2 + } Oscillator ; + + public: typedef enum : uint8_t { + CLKO_DIVIDED_BY_1, + CLKO_DIVIDED_BY_2, + CLKO_DIVIDED_BY_4, + CLKO_DIVIDED_BY_10, + SOF + } CLKOpin ; + + public: typedef enum : uint8_t { + NormalFD = 0, + Sleep = 1, + InternalLoopBack = 2, + ListenOnly = 3, + Configuration = 4, + ExternalLoopBack = 5, + Normal20B = 6, + RestrictedOperation = 7 + } OperationMode ; + + public: typedef enum : uint8_t {Disabled, ThreeAttempts, UnlimitedNumber} RetransmissionAttempts ; + + public: typedef enum : uint8_t { + PAYLOAD_8 = 0, + PAYLOAD_12 = 1, + PAYLOAD_16 = 2, + PAYLOAD_20 = 3, + PAYLOAD_24 = 4, + PAYLOAD_32 = 5, + PAYLOAD_48 = 6, + PAYLOAD_64 = 7 + } PayloadSize ; + +//······················································································································ +// Deprecated enumeration (now use DataBitRateFactor declared in ACANFD_DataBitRateFactor.h) +//······················································································································ + + public : typedef enum : uint8_t { + DATA_BITRATE_x1 = 1, + DATA_BITRATE_x2 = 2, + DATA_BITRATE_x3 = 3, + DATA_BITRATE_x4 = 4, + DATA_BITRATE_x5 = 5, + DATA_BITRATE_x6 = 6, + DATA_BITRATE_x7 = 7, + DATA_BITRATE_x8 = 8, + DATA_BITRATE_x9 = 9, + DATA_BITRATE_x10 = 10 + } DataBitRateFactor_Deprecated ; + +//······················································································································ +// CONSTRUCTOR +//······················································································································ + + public: ACAN2517FDSettings (const Oscillator inOscillator, + const uint32_t inDesiredArbitrationBitRate, + const DataBitRateFactor inDataBitRateFactor, + const uint32_t inTolerancePPM = 1000) ; + +//······················································································································ +// DEPRECATED CONSTRUCTOR (for compatibility with version < 2.1.0) +//······················································································································ + + public: ACAN2517FDSettings (const Oscillator inOscillator, + const uint32_t inDesiredArbitrationBitRate, + const DataBitRateFactor_Deprecated inDataBitRateFactor, + const uint32_t inTolerancePPM = 1000) : + ACAN2517FDSettings (inOscillator, inDesiredArbitrationBitRate, DataBitRateFactor (inDataBitRateFactor), inTolerancePPM) { + } + +//······················································································································ +// CAN BIT TIMING +//······················································································································ + + private: Oscillator mOscillator ; + private: uint32_t mSysClock ; // In Hz + public: const uint32_t mDesiredArbitrationBitRate ; // In kb/s + public: const DataBitRateFactor mDataBitRateFactor ; +//--- Data bit rate; if mDataBitRateFactor==1, theses properties are not used for configuring the MCP2517FD. + public: uint8_t mDataPhaseSegment1 = 0 ; // if mDataBitRateFactor > 1: 2...32, else equal to mArbitrationPhaseSegment1 + public: uint8_t mDataPhaseSegment2 = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationPhaseSegment2 + public: uint8_t mDataSJW = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationSJW +//--- Bit rate prescaler is common to arbitration and data bit rates + public: uint16_t mBitRatePrescaler = 0 ; // 1...256 +//--- Arbitration bit rate + public: uint16_t mArbitrationPhaseSegment1 = 0 ; // 2...256 + public: uint8_t mArbitrationPhaseSegment2 = 0 ; // 1...128 + public: uint8_t mArbitrationSJW = 0 ; // 1...128 + public: bool mArbitrationBitRateClosedToDesiredRate = false ; // The above configuration is not correct +//--- Transmitter Delay Compensation Offset + public: int8_t mTDCO = 0 ; // -64 ... +63 + +//······················································································································ +// MCP2517FD TXCAN pin is Open Drain ? +//······················································································································ + + public: bool mTXCANIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output + +//······················································································································ +// MCP2517FD INT pin is Open Drain ? +//······················································································································ + + public: bool mINTIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output + +//······················································································································ +// ISO CRC Enable +//······················································································································ + +// false --> Do NOT include Stuff Bit Count in CRC Field and use CRC Initialization Vector with all zeros +// true --> Include Stuff Bit Count in CRC Field and use Non-Zero CRC Initialization Vector according to ISO 11898-1:2015 + public: bool mISOCRCEnabled = true ; + +//······················································································································ +// CLKO pin function (default value is MCP2517FD power on setting) +//······················································································································ + + public: CLKOpin mCLKOPin = CLKO_DIVIDED_BY_10 ; + +//······················································································································ +// Requested mode +//······················································································································ + + public: OperationMode mRequestedMode = NormalFD ; + +//······················································································································ +// TRANSMIT FIFO +//······················································································································ + +//--- Driver transmit buffer size + public: uint16_t mDriverTransmitFIFOSize = 16 ; // >= 0 + +//--- Controller transmit FIFO size + public: uint8_t mControllerTransmitFIFOSize = 1 ; // 1 ... 32 + +//--- Payload controller transmit FIFO size + public: PayloadSize mControllerTransmitFIFOPayload = PAYLOAD_64 ; + +//--- Controller transmit FIFO priority (0 --> lowest, 31 --> highest) + public: uint8_t mControllerTransmitFIFOPriority = 0 ; // 0 ... 31 + +//--- Controller transmit FIFO retransmission attempts + public: RetransmissionAttempts mControllerTransmitFIFORetransmissionAttempts = UnlimitedNumber ; + +//······················································································································ +// TXQ BUFFER +//······················································································································ + +//--- TXQ buffer size (0 --> TXQ disabled) + public: uint8_t mControllerTXQSize = 0 ; // 0 ... 32 + +//--- Payload controller TXQ buffer size + public: PayloadSize mControllerTXQBufferPayload = PAYLOAD_64 ; + +//--- TXQ buffer priority (0 --> lowest, 31 --> highest) + public: uint8_t mControllerTXQBufferPriority = 31 ; // 0 ... 31 + +//--- Controller TXQ buffer retransmission attempts + public: RetransmissionAttempts mControllerTXQBufferRetransmissionAttempts = UnlimitedNumber ; + + +//······················································································································ +// RECEIVE FIFO +//······················································································································ + +//--- Driver receive buffer size + public: uint16_t mDriverReceiveFIFOSize = 32 ; // > 0 + +//--- Payload receive FIFO size + public: PayloadSize mControllerReceiveFIFOPayload = PAYLOAD_64 ; + +//--- Controller receive FIFO size + public: uint8_t mControllerReceiveFIFOSize = 27 ; // 1 ... 32 + +//······················································································································ +// SYSCLOCK frequency computation +//······················································································································ + + public: static uint32_t sysClock (const Oscillator inOscillator) ; + +//······················································································································ +// Accessors +//······················································································································ + + public: Oscillator oscillator (void) const { return mOscillator ; } + public: uint32_t sysClock (void) const { return mSysClock ; } + public: uint32_t actualArbitrationBitRate (void) const ; + public: uint32_t actualDataBitRate (void) const ; + public: bool exactArbitrationBitRate (void) const ; + public: bool exactDataBitRate (void) const ; + public: bool dataBitRateIsAMultipleOfArbitrationBitRate (void) const ; + +//······················································································································ +// RAM USAGE +//······················································································································ + + public: uint32_t ramUsage (void) const ; + + public: static uint32_t objectSizeForPayload (const PayloadSize inPayload) ; + +//······················································································································ +// Distance between actual bit rate and requested bit rate (in ppm, part-per-million) +//······················································································································ + + public: uint32_t ppmFromDesiredArbitrationBitRate (void) const ; + public: uint32_t ppmFromDesiredDataBitRate (void) const ; + +//······················································································································ +// Distance of sample point from bit start (in ppc, part-per-cent, denoted by %) +//······················································································································ + + public: uint32_t arbitrationSamplePointFromBitStart (void) const ; + public: uint32_t dataSamplePointFromBitStart (void) const ; + +//······················································································································ +// Bit settings are consistent ? (returns 0 if ok) +//······················································································································ + + public: uint32_t CANBitSettingConsistency (void) const ; + +//······················································································································ +// Constants returned by CANBitSettingConsistency +//······················································································································ + + public: static const uint32_t kBitRatePrescalerIsZero = ((uint32_t) 1) << 0 ; + public: static const uint32_t kBitRatePrescalerIsGreaterThan256 = ((uint32_t) 1) << 1 ; + public: static const uint32_t kArbitrationPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 2 ; + public: static const uint32_t kArbitrationPhaseSegment1IsGreaterThan256 = ((uint32_t) 1) << 3 ; + public: static const uint32_t kArbitrationPhaseSegment2IsZero = ((uint32_t) 1) << 4 ; + public: static const uint32_t kArbitrationPhaseSegment2IsGreaterThan128 = ((uint32_t) 1) << 5 ; + public: static const uint32_t kArbitrationSJWIsZero = ((uint32_t) 1) << 6 ; + public: static const uint32_t kArbitrationSJWIsGreaterThan128 = ((uint32_t) 1) << 7 ; + public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 8 ; + public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment2 = ((uint32_t) 1) << 9 ; + public: static const uint32_t kArbitrationTQCountNotDivisibleByDataBitRateFactor = ((uint32_t) 1) << 10 ; + public: static const uint32_t kDataPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 11 ; + public: static const uint32_t kDataPhaseSegment1IsGreaterThan32 = ((uint32_t) 1) << 12 ; + public: static const uint32_t kDataPhaseSegment2IsZero = ((uint32_t) 1) << 13 ; + public: static const uint32_t kDataPhaseSegment2IsGreaterThan16 = ((uint32_t) 1) << 14 ; + public: static const uint32_t kDataSJWIsZero = ((uint32_t) 1) << 15 ; + public: static const uint32_t kDataSJWIsGreaterThan16 = ((uint32_t) 1) << 16 ; + public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 17 ; + public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment2 = ((uint32_t) 1) << 18 ; + +//······················································································································ +// Max values +//······················································································································ + + public: static const uint16_t MAX_BRP = 256 ; + + public: static const uint16_t MAX_ARBITRATION_PHASE_SEGMENT_1 = 256 ; + public: static const uint8_t MAX_ARBITRATION_PHASE_SEGMENT_2 = 128 ; + public: static const uint8_t MAX_ARBITRATION_SJW = 128 ; + + public: static const uint16_t MAX_DATA_PHASE_SEGMENT_1 = 32 ; + public: static const uint8_t MAX_DATA_PHASE_SEGMENT_2 = 16 ; + public: static const uint8_t MAX_DATA_SJW = 16 ; + +//······················································································································ + +} ; + +//---------------------------------------------------------------------------------------------------------------------- + diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFDBuffer.h b/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFDBuffer.h new file mode 100644 index 00000000..75de5ef8 --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFDBuffer.h @@ -0,0 +1,119 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CAN driver for MCP2517FD CAN Controller in CANFD mode +// by Pierre Molinaro +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef ACANFD_BUFFER_CLASS_DEFINED +#define ACANFD_BUFFER_CLASS_DEFINED + +//---------------------------------------------------------------------------------------------------------------------- + +#include "CANFDMessage.h" + +//---------------------------------------------------------------------------------------------------------------------- + +class ACANFDBuffer { + +//······················································································································ +// Default constructor +//······················································································································ + + public: ACANFDBuffer (void) : + mBuffer (NULL), + mSize (0), + mReadIndex (0), + mCount (0), + mPeakCount (0) { + } + +//······················································································································ +// Destructor +//······················································································································ + + public: ~ ACANFDBuffer (void) { + delete [] mBuffer ; + } + +//······················································································································ +// Private properties +//······················································································································ + + private: CANFDMessage * mBuffer ; + private: uint32_t mSize ; + private: uint32_t mReadIndex ; + private: uint32_t mCount ; + private: uint32_t mPeakCount ; // > mSize if overflow did occur + +//······················································································································ +// Accessors +//······················································································································ + + public: inline uint32_t size (void) const { return mSize ; } + public: inline uint32_t count (void) const { return mCount ; } + public: inline bool isFull (void) const { return mCount == mSize ; } // Added in release 2.17 (thanks to Flole998) + public: inline uint32_t peakCount (void) const { return mPeakCount ; } + +//······················································································································ +// initWithSize +//······················································································································ + + public: void initWithSize (const uint32_t inSize) { + delete [] mBuffer ; mBuffer = new CANFDMessage [inSize] ; + mSize = inSize ; + mReadIndex = 0 ; + mCount = 0 ; + mPeakCount = 0 ; + } + +//······················································································································ +// append +//······················································································································ + + public: bool append (const CANFDMessage & inMessage) { + const bool ok = mCount < mSize ; + if (ok) { + uint32_t writeIndex = mReadIndex + mCount ; + if (writeIndex >= mSize) { + writeIndex -= mSize ; + } + mBuffer [writeIndex] = inMessage ; + mCount += 1 ; + if (mPeakCount < mCount) { + mPeakCount = mCount ; + } + }else{ + mPeakCount = mSize + 1 ; + } + return ok ; + } + +//······················································································································ +// Remove +//······················································································································ + + public: bool remove (CANFDMessage & outMessage) { + const bool ok = mCount > 0 ; + if (ok) { + outMessage = mBuffer [mReadIndex] ; + mCount -= 1 ; + mReadIndex += 1 ; + if (mReadIndex == mSize) { + mReadIndex = 0 ; + } + } + return ok ; + } + +//······················································································································ +// No copy +//······················································································································ + + private: ACANFDBuffer (const ACANFDBuffer &) = delete ; + private: ACANFDBuffer & operator = (const ACANFDBuffer &) = delete ; +} ; + +//---------------------------------------------------------------------------------------------------------------------- + +#endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFD_DataBitRateFactor.h b/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFD_DataBitRateFactor.h new file mode 100644 index 00000000..7177cae4 --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/ACANFD_DataBitRateFactor.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------------------------------------------------------- +// A CANFD driver +// by Pierre Molinaro + +// This header is common to libraries +// https://github.com/pierremolinaro/ACAN_T4 +// https://github.com/pierremolinaro/ACAN2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef ACANFD_DATA_BIT_RATE_FACTOR_DEFINED +#define ACANFD_DATA_BIT_RATE_FACTOR_DEFINED + +//---------------------------------------------------------------------------------------------------------------------- + +#include + +//---------------------------------------------------------------------------------------------------------------------- + +enum class DataBitRateFactor : uint8_t { + x1 = 1, + x2 = 2, + x3 = 3, + x4 = 4, + x5 = 5, + x6 = 6, + x7 = 7, + x8 = 8, + x9 = 9, + x10 = 10 +} ; + +//---------------------------------------------------------------------------------------------------------------------- + +#endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/CANFDMessage.h b/Software/src/lib/pierremolinaro-ACAN2517FD/CANFDMessage.h new file mode 100644 index 00000000..10cf7d3b --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/CANFDMessage.h @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Generic CANFD Message +// by Pierre Molinaro +// +// https://github.com/pierremolinaro/acan2517FD +// +//----------------------------------------------------------------------------- + +#ifndef GENERIC_CANFD_MESSAGE_DEFINED +#define GENERIC_CANFD_MESSAGE_DEFINED + +//----------------------------------------------------------------------------- + +#include "CANMessage.h" + +//----------------------------------------------------------------------------- +// CANFDMessage class +//----------------------------------------------------------------------------- +// Note that "len" field contains the actual length, not its encoding in CANFD frames +// Valid values are: 0, 1, ..., 8, 12, 16, 20, 24, 32, 48, 64. +// Having other values is an error that prevents frame to be sent by tryToSend +// You can use the "pad" method for padding with 0 bytes to the next valid length + +class CANFDMessage { + +//············································································· +// Constructors +//············································································· + + public : CANFDMessage (void) : + id (0), // Frame identifier + ext (false), // false -> base frame, true -> extended frame + type (CANFD_WITH_BIT_RATE_SWITCH), + idx (0), // This field is used by the driver + len (0), // Length of data (0 ... 64) + data () { + } + +//············································································· + + public : CANFDMessage (const CANMessage & inMessage) : + id (inMessage.id), // Frame identifier + ext (inMessage.ext), // false -> base frame, true -> extended frame + type (inMessage.rtr ? CAN_REMOTE : CAN_DATA), + idx (inMessage.idx), // This field is used by the driver + len (inMessage.len), // Length of data (0 ... 64) + data () { + data64 [0] = inMessage.data64 ; + } + +//············································································· +// Enumerated Type +//············································································· + + public: typedef enum : uint8_t { + CAN_REMOTE, + CAN_DATA, + CANFD_NO_BIT_RATE_SWITCH, + CANFD_WITH_BIT_RATE_SWITCH + } Type ; + +//············································································· +// Properties +//············································································· + + public : uint32_t id ; // Frame identifier + public : bool ext ; // false -> base frame, true -> extended frame + public : Type type ; + public : uint8_t idx ; // This field is used by the driver + public : uint8_t len ; // Length of data (0 ... 64) + public : union { + uint64_t data64 [ 8] ; // Caution: subject to endianness + int64_t data_s64 [ 8] ; // Caution: subject to endianness + uint32_t data32 [16] ; // Caution: subject to endianness + int32_t data_s32 [16] ; // Caution: subject to endianness + float dataFloat [16] ; // Caution: subject to endianness + uint16_t data16 [32] ; // Caution: subject to endianness + int16_t data_s16 [32] ; // Caution: subject to endianness + int8_t data_s8 [64] ; + uint8_t data [64] ; + } ; + +//············································································· +// Methods +//············································································· + + public: void pad (void) { + uint8_t paddedLength = len ; + if ((len > 8) && (len < 12)) { + paddedLength = 12 ; + }else if ((len > 12) && (len < 16)) { + paddedLength = 16 ; + }else if ((len > 16) && (len < 20)) { + paddedLength = 20 ; + }else if ((len > 20) && (len < 24)) { + paddedLength = 24 ; + }else if ((len > 24) && (len < 32)) { + paddedLength = 32 ; + }else if ((len > 32) && (len < 48)) { + paddedLength = 48 ; + }else if ((len > 48) && (len < 64)) { + paddedLength = 64 ; + } + while (len < paddedLength) { + data [len] = 0 ; + len += 1 ; + } + } + +//············································································· + + public: bool isValid (void) const { + if ((type == CAN_REMOTE) || (type == CAN_DATA)) { // Remote frame + return len <= 8 ; + }else{ // Data frame + return + (len <= 8) || (len == 12) || (len == 16) || (len == 20) + || + (len == 24) || (len == 32) || (len == 48) || (len == 64) + ; + } + } + +//············································································· + +} ; + +//----------------------------------------------------------------------------- + +typedef void (*ACANFDCallBackRoutine) (const CANFDMessage & inMessage) ; + +//----------------------------------------------------------------------------- + +#endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/CANMessage.h b/Software/src/lib/pierremolinaro-ACAN2517FD/CANMessage.h new file mode 100644 index 00000000..6c687d7e --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/CANMessage.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------------------------------------------------------- +// Generic CAN Message +// by Pierre Molinaro +// +// This file is common to the following libraries +// https://github.com/pierremolinaro/acan +// https://github.com/pierremolinaro/acan2515 +// https://github.com/pierremolinaro/acan2517 +// https://github.com/pierremolinaro/acan2517FD +// +//---------------------------------------------------------------------------------------------------------------------- + +#ifndef GENERIC_CAN_MESSAGE_DEFINED +#define GENERIC_CAN_MESSAGE_DEFINED + +//---------------------------------------------------------------------------------------------------------------------- + +#include + +//---------------------------------------------------------------------------------------------------------------------- + +class CANMessage { + public : uint32_t id = 0 ; // Frame identifier + public : bool ext = false ; // false -> standard frame, true -> extended frame + public : bool rtr = false ; // false -> data frame, true -> remote frame + public : uint8_t idx = 0 ; // This field is used by the driver + public : uint8_t len = 0 ; // Length of data (0 ... 8) + public : union { + uint64_t data64 ; // Caution: subject to endianness + int64_t data_s64 ; // Caution: subject to endianness + uint32_t data32 [2] ; // Caution: subject to endianness + int32_t data_s32 [2] ; // Caution: subject to endianness + float dataFloat [2] ; // Caution: subject to endianness + uint16_t data16 [4] ; // Caution: subject to endianness + int16_t data_s16 [4] ; // Caution: subject to endianness + int8_t data_s8 [8] ; + uint8_t data [8] = {0, 0, 0, 0, 0, 0, 0, 0} ; + } ; +} ; + +//---------------------------------------------------------------------------------------------------------------------- + +typedef enum {kStandard, kExtended} tFrameFormat ; +typedef enum {kData, kRemote} tFrameKind ; +typedef void (*ACANCallBackRoutine) (const CANMessage & inMessage) ; + +//---------------------------------------------------------------------------------------------------------------------- + +#endif diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/LICENSE b/Software/src/lib/pierremolinaro-ACAN2517FD/LICENSE new file mode 100644 index 00000000..0e01a11a --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Pierre Molinaro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Software/src/lib/pierremolinaro-ACAN2517FD/README.md b/Software/src/lib/pierremolinaro-ACAN2517FD/README.md new file mode 100644 index 00000000..73d10716 --- /dev/null +++ b/Software/src/lib/pierremolinaro-ACAN2517FD/README.md @@ -0,0 +1,118 @@ +## MCP2517FD and MCP2518FD CAN Controller Library for Arduino (in CAN FD mode) + + +### Compatibility with the other ACAN libraries + +This library is fully compatible with the Teensy 3.x ACAN library https://github.com/pierremolinaro/acan, ACAN2515 library https://github.com/pierremolinaro/acan2515, and the ACAN2517 library https://github.com/pierremolinaro/acan2517, it uses a very similar API. + +### ACAN2517FD library description +ACAN2517FD is a driver for the MCP2517FD and MCP2518FD CAN Controllers, in CAN FD mode. It runs on any Arduino compatible board. + +> The ACAN2517 library handles the MCP2517FD and MCP2518FD CAN Controller, in CAN 2.0B mode. + + +The library supports the 4MHz, 20 MHz and 40 MHz oscillator clock. + +The driver supports many bit rates: the CAN bit timing calculator finds settings for standard 62.5 kbit/s, 125 kbit/s, 250 kbit/s, 500 kbit/s, 1 Mbit/s, but also for an exotic bit rate as 727 kbit/s. If the desired bit rate cannot be achieved, the `begin` method does not configure the hardware and returns an error code. + +> Driver API is fully described by the PDF file in the `extras` directory. + +### Demo Sketch + +> The demo sketch is in the `examples/LoopBackDemo` directory. + +Configuration is a four-step operation. + +1. Instanciation of the `settings` object : the constructor has one parameter: the wished CAN bit rate. The `settings` is fully initialized. +2. You can override default settings. Here, we set the `mRequestedMode` property to true, enabling to run demo code without any additional hardware (no CAN transceiver needed). We can also for example change the receive buffer size by setting the `mReceiveBufferSize` property. +3. Calling the `begin` method configures the driver and starts CAN bus participation. Any message can be sent, any frame on the bus is received. No default filter to provide. +4. You check the `errorCode` value to detect configuration error(s). + +```cpp +static const byte MCP2517_CS = 20 ; // CS input of MCP2517FD, adapt to your design +static const byte MCP2517_INT = 37 ; // INT output of MCP2517FD, adapt to your design + +ACAN2517FD can (MCP2517_CS, SPI, MCP2517_INT) ; // You can use SPI2, SPI3, if provided by your microcontroller + +void setup () { + Serial.begin (9600) ; + while (!Serial) {} + Serial.println ("Hello") ; + // Arbitration bit rate: 125 kbit/s, data bit rate: 500 kbit/s + ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, + 125 * 1000, ACAN2517FDSettings::DATA_BITRATE_x4) ; + settings.mRequestedMode = ACAN2517FDSettings::InternalLoopBack ; // Select loopback mode + const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }) ; + if (0 == errorCode) { + Serial.println ("Can ok") ; + }else{ + Serial.print ("Error Can: 0x") ; + Serial.println (errorCode, HEX) ; + } +} +``` + +Now, an example of the `loop` function. As we have selected loop back mode, every sent frame is received. + +```cpp +static unsigned gSendDate = 0 ; +static unsigned gSentCount = 0 ; +static unsigned gReceivedCount = 0 ; + +void loop () { + CANFDMessage message ; + if (gSendDate < millis ()) { + message.id = 0x542 ; + const bool ok = can.tryToSend (message) ; + if (ok) { + gSendDate += 2000 ; + gSentCount += 1 ; + Serial.print ("Sent: ") ; + Serial.println (gSentCount) ; + } + } + if (can.receive (message)) { + gReceivedCount += 1 ; + Serial.print ("Received: ") ; + Serial.println (gReceivedCount) ; + } +} +``` +`CANFDMessage` is the class that defines a CAN FD message. The `message` object is fully initialized by the default constructor. Here, we set the `id` to `0x542` for sending a standard data frame, without data, with this identifier. + +The `can.tryToSend` tries to send the message. It returns `true` if the message has been sucessfully added to the driver transmit buffer. + +The `gSendDate` variable handles sending a CAN message every 2000 ms. + +`can.receive` returns `true` if a message has been received, and assigned to the `message`argument. + +### Use of Optional Reception Filtering + +The MCP2517 CAN Controller implements 32 acceptance masks and 32 acceptance filters. The driver API enables you to fully manage these registers. + +For example (`LoopBackDemoTeensy3xWithFilters` sketch): + +```cpp + ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, 125 * 1000) ; + settings.mRequestedMode = ACAN2517FDSettings::InternalLoopBack ; // Select loopback mode + ACAN2517Filters filters ; +// Filter #0: receive standard frame with identifier 0x123 + filters.appendFrameFilter (kStandard, 0x123, receiveFromFilter0) ; +// Filter #1: receive extended frame with identifier 0x12345678 + filters.appendFrameFilter (kExtended, 0x12345678, receiveFromFilter1) ; +// Filter #2: receive standard frame with identifier 0x3n4 + filters.appendFilter (kStandard, 0x70F, 0x304, receiveFromFilter2) ; + const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }, filters) ; +``` + +These settings enable the acceptance of standard frames whose identifier is 0x123, extended frames whose identifier is 0x12345678, and data frames whose identifier is 0x304, 0x314, ..., 0x3E4, 0x3F4. + +The `receiveFromFilter0`, `receiveFromFilter1`, `receiveFromFilter2` functions are call back functions, handled by the `can.dispatchReceivedMessage` function: + + +```cpp +void loop () { + can.dispatchReceivedMessage () ; // Do not use can.receive any more + ... +} +``` From 9ec08823292dca8a6e6c52c4849cbf44c270d2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20=C3=96ster?= Date: Mon, 8 Apr 2024 21:28:17 +0300 Subject: [PATCH 10/10] Update version number for release --- Software/Software.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/Software.ino b/Software/Software.ino index 7d3284d7..a9fddf1d 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -29,7 +29,7 @@ Preferences settings; // Store user settings // The current software version, shown on webserver -const char* version_number = "5.7.dev"; +const char* version_number = "5.7.0"; // Interval settings uint16_t intervalUpdateValues = INTERVAL_5_S; // Interval at which to update inverter values / Modbus registers