mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
Squashed commit of the following:
commita81133c6c0
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Tue Feb 6 07:59:22 2024 +0100 Update timer_test.cpp commitaca520c506
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Tue Feb 6 07:55:00 2024 +0100 Added a test, new structure commit1d09dacccb
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:36:25 2024 +0100 Event setting commit5edfd6cdec
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:16:46 2024 +0100 Restore to working order, success! commit7f6eddca76
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:15:54 2024 +0100 Testing for failed unit tests commitdcd8dcade9
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:13:25 2024 +0100 Name change commitf1bff798c4
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:11:57 2024 +0100 Moved test files commit933d11f932
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:03:34 2024 +0100 More UT commit92fd0ac31b
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 23:01:44 2024 +0100 Update unit-tests.yml commit5785eeb111
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 22:57:35 2024 +0100 Update unit-tests.yml commitf4fa1115c1
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 22:55:27 2024 +0100 UT debugging commit396f41ed77
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 22:53:10 2024 +0100 Moved test folder previous location caused issues with building the main SW commitda8421dcff
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 22:42:13 2024 +0100 Unit test attempt commit44c02745bf
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 14:10:12 2024 +0100 Improvements and unit tests commit4d95fcfc31
Author: Cabooman <81711263+Cabooman@users.noreply.github.com> Date: Mon Feb 5 01:19:37 2024 +0100 First commit
This commit is contained in:
parent
440e010a71
commit
cb935e4cf8
25 changed files with 657 additions and 7 deletions
23
.github/workflows/unit-tests.yml
vendored
Normal file
23
.github/workflows/unit-tests.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: Run Unit Tests
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Configure and build with CMake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd build/test
|
||||
find . -type f -executable -exec {} \;
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -3,3 +3,9 @@
|
|||
|
||||
# Ignore any files in the build folder
|
||||
Software/build/
|
||||
|
||||
# Ignore CMake build folder
|
||||
build/
|
||||
|
||||
# Ignore unit tests
|
||||
*.exe
|
6
CMakeLists.txt
Normal file
6
CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(BatteryEmulator)
|
||||
|
||||
# add_subdirectory(Software/src/devboard/utils)
|
||||
add_subdirectory(test)
|
|
@ -8,6 +8,7 @@
|
|||
#include "src/battery/BATTERIES.h"
|
||||
#include "src/charger/CHARGERS.h"
|
||||
#include "src/devboard/config.h"
|
||||
#include "src/devboard/utils/events.h"
|
||||
#include "src/inverter/INVERTERS.h"
|
||||
#include "src/lib/adafruit-Adafruit_NeoPixel/Adafruit_NeoPixel.h"
|
||||
#include "src/lib/eModbus-eModbus/Logging.h"
|
||||
|
@ -129,6 +130,8 @@ void setup() {
|
|||
init_webserver();
|
||||
#endif
|
||||
|
||||
init_events();
|
||||
|
||||
init_CAN();
|
||||
|
||||
init_LED();
|
||||
|
@ -183,6 +186,7 @@ void loop() {
|
|||
{
|
||||
previousMillisUpdateVal = millis();
|
||||
update_values(); // Update values heading towards inverter. Prepare for sending on CAN, or write directly to Modbus.
|
||||
set_event(EVENT_DUMMY, (uint8_t)millis());
|
||||
}
|
||||
|
||||
// Output
|
||||
|
@ -190,6 +194,7 @@ void loop() {
|
|||
#ifdef DUAL_CAN
|
||||
send_can2();
|
||||
#endif
|
||||
update_event_timestamps();
|
||||
}
|
||||
|
||||
// Initialization functions
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//#define CHADEMO_BATTERY
|
||||
//#define IMIEV_CZERO_ION_BATTERY
|
||||
//#define KIA_HYUNDAI_64_BATTERY
|
||||
//#define NISSAN_LEAF_BATTERY
|
||||
#define NISSAN_LEAF_BATTERY
|
||||
//#define RENAULT_KANGOO_BATTERY
|
||||
//#define RENAULT_ZOE_BATTERY
|
||||
//#define SANTA_FE_PHEV_BATTERY
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
/* Select inverter communication protocol. See Wiki for which to use with your inverter: https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/wiki */
|
||||
//#define BYD_CAN //Enable this line to emulate a "BYD Battery-Box Premium HVS" over CAN Bus
|
||||
//#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||
#define BYD_MODBUS //Enable this line to emulate a "BYD 11kWh HVM battery" over Modbus RTU
|
||||
//#define LUNA2000_MODBUS //Enable this line to emulate a "Luna2000 battery" over Modbus RTU
|
||||
//#define PYLON_CAN //Enable this line to emulate a "Pylontech battery" over CAN bus
|
||||
//#define SMA_CAN //Enable this line to emulate a "BYD Battery-Box H 8.9kWh, 7 mod" over CAN bus
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "BMW-I3-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -103,6 +104,7 @@ void update_values_i3_battery() { //This function maps all the values fetched v
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "CHADEMO-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -107,6 +108,7 @@ void update_values_chademo_battery() { //This function maps all the values fetc
|
|||
bms_status = FAULT;
|
||||
errorCode = 7;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "IMIEV-CZERO-ION-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -109,6 +110,7 @@ void update_values_imiev_battery() { //This function maps all the values fetche
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "KIA-HYUNDAI-64-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -200,6 +201,7 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
@ -207,11 +209,13 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value
|
|||
if (waterleakageSensor == 0) {
|
||||
Serial.println("Water leakage inside battery detected. Operation halted. Inspect battery!");
|
||||
bms_status = FAULT;
|
||||
set_event(EVENT_WATER_INGRESS, 0);
|
||||
}
|
||||
|
||||
if (leadAcidBatteryVoltage < 110) {
|
||||
Serial.println("12V battery source below required voltage to safely close contactors. Inspect the supply/battery!");
|
||||
LEDcolor = YELLOW;
|
||||
set_event(EVENT_12V_LOW, leadAcidBatteryVoltage);
|
||||
}
|
||||
|
||||
// Check if cell voltages are within allowed range
|
||||
|
@ -220,14 +224,17 @@ void update_values_kiaHyundai_64_battery() { //This function maps all the value
|
|||
if (cell_max_voltage >= MAX_CELL_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_min_voltage <= MIN_CELL_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_deviation_mV > MAX_CELL_DEVIATION) {
|
||||
LEDcolor = YELLOW;
|
||||
Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!");
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
|
||||
if (bms_status == FAULT) { //Incase we enter a critical fault state, zero out the allowed limits
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#ifdef MQTT
|
||||
#include "../devboard/mqtt/mqtt.h"
|
||||
#endif
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -262,6 +263,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ERROR: SOC% reported by battery not plausible. Restart battery!");
|
||||
#endif
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, LB_SOC / 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +313,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ERROR: Battery raised caution indicator AND requested discharge stop. Inspect battery status!");
|
||||
#endif
|
||||
set_event(EVENT_BATTERY_DISCHG_STOP_REQ, 0);
|
||||
break;
|
||||
case (6):
|
||||
//Caution Lamp Request & Charging Mode Stop Request
|
||||
|
@ -319,6 +322,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ERROR: Battery raised caution indicator AND requested charge stop. Inspect battery status!");
|
||||
#endif
|
||||
set_event(EVENT_BATTERY_CHG_STOP_REQ, 0);
|
||||
break;
|
||||
case (7):
|
||||
//Caution Lamp Request & Charging Mode Stop Request & Normal Stop Request
|
||||
|
@ -328,6 +332,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
Serial.println(
|
||||
"ERROR: Battery raised caution indicator AND requested charge/discharge stop. Inspect battery status!");
|
||||
#endif
|
||||
set_event(EVENT_BATTERY_CHG_DISCHG_STOP_REQ, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -342,6 +347,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#endif
|
||||
bms_status = FAULT;
|
||||
errorCode = 5;
|
||||
set_event(EVENT_LOW_SOH, LB_StateOfHealth);
|
||||
max_target_discharge_power = 0;
|
||||
max_target_charge_power = 0;
|
||||
}
|
||||
|
@ -355,6 +361,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
"disabled!");
|
||||
#endif
|
||||
bms_status = FAULT;
|
||||
set_event(EVENT_HVIL_FAILURE, 0);
|
||||
errorCode = 6;
|
||||
SOC = 0;
|
||||
max_target_discharge_power = 0;
|
||||
|
@ -369,6 +376,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ERROR: No CAN communication detected for 60s. Shutting down battery control.");
|
||||
#endif
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
@ -380,6 +388,7 @@ void update_values_leaf_battery() { /* This function maps all the values fetched
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("ERROR: High amount of corrupted CAN messages detected. Check CAN wire shielding!");
|
||||
#endif
|
||||
set_event(EVENT_CAN_WARNING, 0);
|
||||
}
|
||||
|
||||
/*Finally print out values to serial if configured to do so*/
|
||||
|
@ -615,6 +624,7 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("HIGH CELL DEVIATION!!! Inspect battery!");
|
||||
#endif
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
|
||||
if (min_max_voltage[1] >= MAX_CELL_VOLTAGE) {
|
||||
|
@ -623,6 +633,7 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
#endif
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (min_max_voltage[0] <= MIN_CELL_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
|
@ -630,6 +641,7 @@ void receive_can_leaf_battery(CAN_frame_t rx_frame) {
|
|||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
#endif
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "RENAULT-KANGOO-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -126,6 +127,7 @@ void update_values_kangoo_battery() { //This function maps all the values fetch
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
@ -133,14 +135,17 @@ void update_values_kangoo_battery() { //This function maps all the values fetch
|
|||
if (LB_Cell_Max_Voltage >= ABSOLUTE_CELL_MAX_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (LB_Cell_Min_Voltage <= ABSOLUTE_CELL_MIN_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) {
|
||||
LEDcolor = YELLOW;
|
||||
Serial.println("ERROR: HIGH CELL mV DEVIATION!!! Inspect battery!");
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "RENAULT-ZOE-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -87,6 +88,7 @@ void update_values_zoe_battery() { //This function maps all the values fetched
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
@ -94,14 +96,17 @@ void update_values_zoe_battery() { //This function maps all the values fetched
|
|||
if (LB_Cell_Max_Voltage >= ABSOLUTE_CELL_MAX_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (LB_Cell_Min_Voltage <= ABSOLUTE_CELL_MIN_VOLTAGE) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_deviation_mV > MAX_CELL_DEVIATION_MV) {
|
||||
LEDcolor = YELLOW;
|
||||
Serial.println("ERROR: HIGH CELL mV DEVIATION!!! Inspect battery!");
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VIA_USB
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "SANTA-FE-PHEV-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -84,6 +85,7 @@ void update_values_santafe_phev_battery() { //This function maps all the values
|
|||
if (!CANstillAlive) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
CANstillAlive--;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "TESLA-MODEL-3-BATTERY.h"
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
|
@ -231,6 +232,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
if (!stillAliveCAN) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: No CAN communication detected for 60s. Shutting down battery control.");
|
||||
set_event(EVENT_CAN_FAILURE, 0);
|
||||
} else {
|
||||
stillAliveCAN--;
|
||||
}
|
||||
|
@ -238,6 +240,7 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
if (hvil_status == 3) { //INTERNAL_OPEN_FAULT - Someone disconnected a high voltage cable while battery was in use
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: High voltage cable removed while battery running. Opening contactors!");
|
||||
set_event(EVENT_INTERNAL_OPEN_FAULT, 0);
|
||||
}
|
||||
|
||||
cell_deviation_mV = (cell_max_v - cell_min_v);
|
||||
|
@ -258,12 +261,14 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
if (SOC < 6500) { //When SOC is less than 65.00% when approaching max voltage
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: SOC% reported by battery not plausible. Restart battery!");
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, SOC / 100);
|
||||
}
|
||||
}
|
||||
|
||||
//Check if BMS is in need of recalibration
|
||||
if (nominal_full_pack_energy < REASONABLE_ENERGYAMOUNT) {
|
||||
Serial.println("Warning: kWh remaining reported by battery not plausible. Battery needs cycling.");
|
||||
set_event(EVENT_KWH_PLAUSIBILITY_ERROR, nominal_full_pack_energy);
|
||||
LEDcolor = YELLOW;
|
||||
}
|
||||
|
||||
|
@ -271,27 +276,33 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
|
|||
if (cell_max_v >= MAX_CELL_VOLTAGE_LFP) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_min_v <= MIN_CELL_VOLTAGE_LFP) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_deviation_mV > MAX_CELL_DEVIATION_LFP) {
|
||||
LEDcolor = YELLOW;
|
||||
Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!");
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
} else { //NCA/NCM limits used
|
||||
if (cell_max_v >= MAX_CELL_VOLTAGE_NCA_NCM) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_min_v <= MIN_CELL_VOLTAGE_NCA_NCM) {
|
||||
bms_status = FAULT;
|
||||
Serial.println("ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
set_event(EVENT_CELL_UNDER_VOLTAGE, 0);
|
||||
}
|
||||
if (cell_deviation_mV > MAX_CELL_DEVIATION_NCA_NCM) {
|
||||
LEDcolor = YELLOW;
|
||||
Serial.println("ERROR: HIGH CELL DEVIATION!!! Inspect battery!");
|
||||
set_event(EVENT_CELL_DEVIATION_HIGH, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
136
Software/src/devboard/utils/events.cpp
Normal file
136
Software/src/devboard/utils/events.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
#include "events.h"
|
||||
|
||||
#include "../../../USER_SETTINGS.h"
|
||||
#include "../config.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t timestamp; // Time in seconds since startup when the event occurred
|
||||
uint8_t data; // Custom data passed when setting the event, for example cell number for under voltage
|
||||
uint8_t occurences; // Number of occurrences since startup
|
||||
uint8_t led_color; // Weirdly indented comment
|
||||
} EVENTS_STRUCT_TYPE;
|
||||
|
||||
static EVENTS_STRUCT_TYPE entries[EVENT_NOF_EVENTS];
|
||||
static unsigned long previous_millis = 0;
|
||||
static uint32_t time_seconds = 0;
|
||||
static uint8_t total_led_color = GREEN;
|
||||
static char event_message[256];
|
||||
|
||||
/* Local function prototypes */
|
||||
static void set_event_message(EVENTS_ENUM_TYPE event);
|
||||
static void update_led_color(EVENTS_ENUM_TYPE event);
|
||||
|
||||
/* Exported functions */
|
||||
void init_events(void) {
|
||||
for (uint8_t i = 0; i < EVENT_NOF_EVENTS; i++) {
|
||||
entries[i].timestamp = 0;
|
||||
entries[i].data = 0;
|
||||
entries[i].occurences = 0;
|
||||
entries[i].led_color = RED; // Most events are RED
|
||||
}
|
||||
|
||||
// YELLOW events below
|
||||
entries[EVENT_12V_LOW].led_color = YELLOW;
|
||||
entries[EVENT_CAN_WARNING].led_color = YELLOW;
|
||||
entries[EVENT_CELL_DEVIATION_HIGH].led_color = YELLOW;
|
||||
entries[EVENT_KWH_PLAUSIBILITY_ERROR].led_color = YELLOW;
|
||||
}
|
||||
|
||||
void set_event(EVENTS_ENUM_TYPE event, uint8_t data) {
|
||||
if (event >= EVENT_NOF_EVENTS) {
|
||||
event = EVENT_UNKNOWN_EVENT_SET;
|
||||
}
|
||||
entries[event].timestamp = time_seconds;
|
||||
entries[event].data = data;
|
||||
entries[event].occurences++;
|
||||
set_event_message(event);
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println(event_message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void update_event_timestamps(void) {
|
||||
unsigned long new_millis = millis();
|
||||
if (new_millis - previous_millis >= 1000) {
|
||||
time_seconds++;
|
||||
previous_millis = new_millis;
|
||||
}
|
||||
}
|
||||
|
||||
/* Local functions */
|
||||
static void update_led_color(EVENTS_ENUM_TYPE event) {
|
||||
total_led_color = (total_led_color == RED) ? RED : entries[event].led_color;
|
||||
}
|
||||
|
||||
static void set_event_message(EVENTS_ENUM_TYPE event) {
|
||||
switch (event) {
|
||||
case EVENT_CAN_FAILURE:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"No CAN communication detected for 60s. Shutting down battery control.");
|
||||
break;
|
||||
case EVENT_CAN_WARNING:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: High amount of corrupted CAN messages detected. Check CAN wire shielding!");
|
||||
break;
|
||||
case EVENT_WATER_INGRESS:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"Water leakage inside battery detected. Operation halted. Inspect battery!");
|
||||
break;
|
||||
case EVENT_12V_LOW:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"12V battery source below required voltage to safely close contactors. Inspect the supply/battery!");
|
||||
break;
|
||||
case EVENT_SOC_PLAUSIBILITY_ERROR:
|
||||
snprintf(event_message, sizeof(event_message), "ERROR: SOC% reported by battery not plausible. Restart battery!");
|
||||
break;
|
||||
case EVENT_KWH_PLAUSIBILITY_ERROR:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"Warning: kWh remaining reported by battery not plausible. Battery needs cycling.");
|
||||
break;
|
||||
case EVENT_BATTERY_CHG_STOP_REQ:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: Battery raised caution indicator AND requested charge stop. Inspect battery status!");
|
||||
break;
|
||||
case EVENT_BATTERY_DISCHG_STOP_REQ:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: Battery raised caution indicator AND requested discharge stop. Inspect battery status!");
|
||||
break;
|
||||
case EVENT_BATTERY_CHG_DISCHG_STOP_REQ:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: Battery raised caution indicator AND requested charge/discharge stop. Inspect battery status!");
|
||||
break;
|
||||
case EVENT_LOW_SOH:
|
||||
snprintf(
|
||||
event_message, sizeof(event_message),
|
||||
"ERROR: State of health critically low. Battery internal resistance too high to continue. Recycle battery.");
|
||||
break;
|
||||
case EVENT_HVIL_FAILURE:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: Battery interlock loop broken. Check that high voltage connectors are seated. Battery will be "
|
||||
"disabled!");
|
||||
break;
|
||||
case EVENT_INTERNAL_OPEN_FAULT:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: High voltage cable removed while battery running. Opening contactors!");
|
||||
break;
|
||||
case EVENT_CELL_UNDER_VOLTAGE:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
break;
|
||||
case EVENT_CELL_OVER_VOLTAGE:
|
||||
snprintf(event_message, sizeof(event_message),
|
||||
"ERROR: CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!");
|
||||
break;
|
||||
case EVENT_CELL_DEVIATION_HIGH:
|
||||
snprintf(event_message, sizeof(event_message), "ERROR: HIGH CELL DEVIATION!!! Inspect battery!");
|
||||
break;
|
||||
case EVENT_UNKNOWN_EVENT_SET:
|
||||
snprintf(event_message, sizeof(event_message), "An unknown event was set! Review your code!");
|
||||
break;
|
||||
case EVENT_DUMMY:
|
||||
snprintf(event_message, sizeof(event_message), "The dummy event was set!"); // Don't change this event message!
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
35
Software/src/devboard/utils/events.h
Normal file
35
Software/src/devboard/utils/events.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef __EVENTS_H__
|
||||
#define __EVENTS_H__
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
EVENT_CAN_FAILURE = 0u,
|
||||
EVENT_CAN_WARNING,
|
||||
EVENT_WATER_INGRESS,
|
||||
EVENT_12V_LOW,
|
||||
EVENT_SOC_PLAUSIBILITY_ERROR,
|
||||
EVENT_KWH_PLAUSIBILITY_ERROR,
|
||||
EVENT_BATTERY_CHG_STOP_REQ,
|
||||
EVENT_BATTERY_DISCHG_STOP_REQ,
|
||||
EVENT_BATTERY_CHG_DISCHG_STOP_REQ,
|
||||
EVENT_LOW_SOH,
|
||||
EVENT_HVIL_FAILURE,
|
||||
EVENT_INTERNAL_OPEN_FAULT,
|
||||
EVENT_CELL_UNDER_VOLTAGE,
|
||||
EVENT_CELL_OVER_VOLTAGE,
|
||||
EVENT_CELL_DEVIATION_HIGH,
|
||||
EVENT_UNKNOWN_EVENT_SET,
|
||||
EVENT_DUMMY,
|
||||
EVENT_NOF_EVENTS
|
||||
} EVENTS_ENUM_TYPE;
|
||||
|
||||
void init_events(void);
|
||||
void set_event(EVENTS_ENUM_TYPE event, uint8_t data);
|
||||
void update_event_timestamps(void);
|
||||
|
||||
#endif // __MYTIMER_H__
|
1
Software/src/devboard/utils/test_commands.txt
Normal file
1
Software/src/devboard/utils/test_commands.txt
Normal file
|
@ -0,0 +1 @@
|
|||
g++ events_test.cpp ../../../test/test_lib.cpp -o events_test.exe -DUNIT_TEST -I.
|
|
@ -1,11 +1,13 @@
|
|||
#include "timer.h"
|
||||
|
||||
MyTimer::MyTimer(unsigned long interval) : interval(interval), previousMillis(0) {}
|
||||
MyTimer::MyTimer(unsigned long interval) : interval(interval) {
|
||||
previous_millis = millis();
|
||||
}
|
||||
|
||||
bool MyTimer::elapsed() {
|
||||
unsigned long currentMillis = millis();
|
||||
if (currentMillis - previousMillis >= interval) {
|
||||
previousMillis = currentMillis;
|
||||
unsigned long current_millis = millis();
|
||||
if (current_millis - previous_millis >= interval) {
|
||||
previous_millis = current_millis;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef __MYTIMER_H__
|
||||
#define __MYTIMER_H__
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
class MyTimer {
|
||||
public:
|
||||
|
@ -12,7 +14,7 @@ class MyTimer {
|
|||
|
||||
private:
|
||||
unsigned long interval;
|
||||
unsigned long previousMillis;
|
||||
unsigned long previous_millis;
|
||||
};
|
||||
|
||||
#endif // __MYTIMER_H__
|
||||
|
|
18
test/CMakeLists.txt
Normal file
18
test/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Include the directory with your source files
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Software/src/devboard/utils .)
|
||||
|
||||
# Create a variable to store the list of test files
|
||||
file(GLOB TEST_SOURCES utils/*.cpp)
|
||||
|
||||
# Loop through each test source file and create an executable
|
||||
foreach(TEST_SOURCE ${TEST_SOURCES})
|
||||
# Extract the test name without extension
|
||||
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
|
||||
|
||||
# Create an executable for the test
|
||||
add_executable(${TEST_NAME} ${TEST_SOURCE} test_lib.cpp)
|
||||
|
||||
# Apply the target_compile_definitions for the test
|
||||
target_compile_definitions(${TEST_NAME} PRIVATE UNIT_TEST)
|
||||
|
||||
endforeach()
|
209
test/microtest.h
Normal file
209
test/microtest.h
Normal file
|
@ -0,0 +1,209 @@
|
|||
//
|
||||
// microtest.h
|
||||
//
|
||||
// URL: https://github.com/torpedro/microtest.h
|
||||
// Author: Pedro Flemming (http://torpedro.com/)
|
||||
// License: MIT License (https://github.com/torpedro/microtest.h/blob/master/LICENSE)
|
||||
// Copyright (c) 2017 Pedro Flemming
|
||||
//
|
||||
// This is a small header-only C++ unit testing framework.
|
||||
// It allows to define small unit tests with set of assertions available.
|
||||
//
|
||||
#ifndef __MICROTEST_H__
|
||||
#define __MICROTEST_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
////////////////
|
||||
// Assertions //
|
||||
////////////////
|
||||
|
||||
#define ASSERT(cond) ASSERT_TRUE(cond);
|
||||
|
||||
#define ASSERT_TRUE(cond) \
|
||||
if (!(cond)) \
|
||||
throw mt::AssertFailedException(#cond, __FILE__, __LINE__);
|
||||
|
||||
#define ASSERT_FALSE(cond) \
|
||||
if (cond) \
|
||||
throw mt::AssertFailedException(#cond, __FILE__, __LINE__);
|
||||
|
||||
#define ASSERT_NULL(value) ASSERT_TRUE(value == NULL);
|
||||
|
||||
#define ASSERT_NOTNULL(value) ASSERT_TRUE(value != NULL);
|
||||
|
||||
#define ASSERT_STREQ(a, b) \
|
||||
if (std::string(a).compare(std::string(b)) != 0) { \
|
||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
||||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
||||
throw mt::AssertFailedException(#a " == " #b, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
#define ASSERT_STRNEQ(a, b) \
|
||||
if (std::string(a).compare(std::string(b)) != = 0) { \
|
||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
||||
std::cout << "Actual values: " << a << " == " << b << std::endl; \
|
||||
throw mt::AssertFailedException(#a " != " #b, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
#define ASSERT_EQ(a, b) \
|
||||
if (a != b) { \
|
||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
||||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
||||
} \
|
||||
ASSERT(a == b);
|
||||
|
||||
#define ASSERT_NEQ(a, b) \
|
||||
if (a == b) { \
|
||||
printf("%s{ info} %s", mt::yellow(), mt::def()); \
|
||||
std::cout << "Actual values: " << a << " == " << b << std::endl; \
|
||||
} \
|
||||
ASSERT(a != b);
|
||||
|
||||
////////////////
|
||||
// Unit Tests //
|
||||
////////////////
|
||||
|
||||
#define TEST(name) \
|
||||
void name(); \
|
||||
namespace { \
|
||||
bool __##name = mt::TestsManager::AddTest(name, #name); \
|
||||
} \
|
||||
void name()
|
||||
|
||||
///////////////
|
||||
// Framework //
|
||||
///////////////
|
||||
|
||||
namespace mt {
|
||||
|
||||
inline const char* red() {
|
||||
return "\033[1;31m";
|
||||
}
|
||||
|
||||
inline const char* green() {
|
||||
return "\033[0;32m";
|
||||
}
|
||||
|
||||
inline const char* yellow() {
|
||||
return "\033[0;33m";
|
||||
}
|
||||
|
||||
inline const char* def() {
|
||||
return "\033[0m";
|
||||
}
|
||||
|
||||
inline void printRunning(const char* message, FILE* file = stdout) {
|
||||
fprintf(file, "%s{ running}%s %s\n", green(), def(), message);
|
||||
}
|
||||
|
||||
inline void printOk(const char* message, FILE* file = stdout) {
|
||||
fprintf(file, "%s{ ok}%s %s\n", green(), def(), message);
|
||||
}
|
||||
|
||||
inline void printFailed(const char* message, FILE* file = stdout) {
|
||||
fprintf(file, "%s{ failed} %s%s\n", red(), message, def());
|
||||
}
|
||||
|
||||
// Exception that is thrown when an assertion fails.
|
||||
class AssertFailedException : public std::exception {
|
||||
public:
|
||||
AssertFailedException(std::string description, std::string filepath, int line)
|
||||
: std::exception(), description_(description), filepath_(filepath), line_(line){};
|
||||
|
||||
virtual const char* what() const throw() { return description_.c_str(); }
|
||||
|
||||
inline const char* getFilepath() { return filepath_.c_str(); }
|
||||
|
||||
inline int getLine() { return line_; }
|
||||
|
||||
protected:
|
||||
std::string description_;
|
||||
std::string filepath_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
class TestsManager {
|
||||
// Note: static initialization fiasco
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order.html
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html
|
||||
public:
|
||||
struct Test {
|
||||
const char* name;
|
||||
void (*fn)(void);
|
||||
};
|
||||
|
||||
static std::vector<Test>& tests() {
|
||||
static std::vector<Test> tests_;
|
||||
return tests_;
|
||||
}
|
||||
|
||||
// Adds a new test to the current set of tests.
|
||||
// Returns false if a test with the same name already exists.
|
||||
inline static bool AddTest(void (*fn)(void), const char* name) {
|
||||
tests().push_back({name, fn});
|
||||
return true;
|
||||
}
|
||||
|
||||
// Run all tests that are registered.
|
||||
// Returns the number of tests that failed.
|
||||
inline static size_t RunAllTests(FILE* file = stdout) {
|
||||
size_t num_failed = 0;
|
||||
|
||||
for (const Test& test : tests()) {
|
||||
// Run the test.
|
||||
// If an AsserFailedException is thrown, the test has failed.
|
||||
try {
|
||||
printRunning(test.name, file);
|
||||
|
||||
(*test.fn)();
|
||||
|
||||
printOk(test.name, file);
|
||||
|
||||
} catch (AssertFailedException& e) {
|
||||
printFailed(test.name, file);
|
||||
fprintf(file, " %sAssertion failed: %s%s\n", red(), e.what(), def());
|
||||
fprintf(file, " %s%s:%d%s\n", red(), e.getFilepath(), e.getLine(), def());
|
||||
++num_failed;
|
||||
}
|
||||
}
|
||||
|
||||
int return_code = (num_failed > 0) ? 1 : 0;
|
||||
return return_code;
|
||||
}
|
||||
};
|
||||
|
||||
// Class that will capture the arguments passed to the program.
|
||||
class Runtime {
|
||||
public:
|
||||
static const std::vector<std::string>& args(int argc = -1, char** argv = NULL) {
|
||||
static std::vector<std::string> args_;
|
||||
if (argc >= 0) {
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
args_.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
return args_;
|
||||
}
|
||||
};
|
||||
} // namespace mt
|
||||
|
||||
#define TEST_MAIN() \
|
||||
int main(int argc, char* argv[]) { \
|
||||
mt::Runtime::args(argc, argv); \
|
||||
\
|
||||
size_t num_failed = mt::TestsManager::RunAllTests(stdout); \
|
||||
if (num_failed == 0) { \
|
||||
fprintf(stdout, "%s{ summary} All tests succeeded!%s\n", mt::green(), mt::def()); \
|
||||
return 0; \
|
||||
} else { \
|
||||
double percentage = 100.0 * num_failed / mt::TestsManager::tests().size(); \
|
||||
fprintf(stderr, "%s{ summary} %lu tests failed (%.2f%%)%s\n", mt::red(), num_failed, percentage, mt::def()); \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // __MICROTEST_H__
|
6
test/test_lib.cpp
Normal file
6
test/test_lib.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "test_lib.h"
|
||||
#include <cstdint>
|
||||
|
||||
MySerial Serial;
|
||||
|
||||
unsigned long testlib_millis = 0;
|
43
test/test_lib.h
Normal file
43
test/test_lib.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef __TEST_LIB_H__
|
||||
#define __TEST_LIB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include "microtest.h"
|
||||
|
||||
class MySerial;
|
||||
|
||||
extern unsigned long testlib_millis;
|
||||
|
||||
/* Mock millis() */
|
||||
static inline unsigned long millis(void) {
|
||||
return testlib_millis;
|
||||
}
|
||||
|
||||
/* Mock Serial class */
|
||||
class MySerial {
|
||||
public:
|
||||
size_t println(const char* s) {
|
||||
return print(s, true); // Call print with newline argument true
|
||||
}
|
||||
|
||||
size_t print(const char* s) {
|
||||
return print(s, false); // Call print with newline argument false
|
||||
}
|
||||
|
||||
private:
|
||||
size_t print(const char* s, bool newline) {
|
||||
size_t length = printf("%s", s); // Print the string without newline
|
||||
if (newline) {
|
||||
printf("\n"); // Add a newline if specified
|
||||
length++; // Increment length to account for the added newline character
|
||||
}
|
||||
return length; // Return the total length printed
|
||||
}
|
||||
};
|
||||
|
||||
extern MySerial Serial;
|
||||
|
||||
#endif
|
78
test/utils/events_test.cpp
Normal file
78
test/utils/events_test.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
// The test library must be included first!
|
||||
#include "test_lib.h"
|
||||
|
||||
#include "events.cpp"
|
||||
|
||||
/* Helper functions */
|
||||
static void reset_event_msg(void) {
|
||||
snprintf(event_message, sizeof(event_message), "");
|
||||
}
|
||||
|
||||
TEST(init_events_test) {
|
||||
init_events();
|
||||
|
||||
for (uint8_t i = 0; i < EVENT_NOF_EVENTS; i++) {
|
||||
ASSERT_EQ(entries[i].occurences, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(update_event_timestamps_test) {
|
||||
// Reset
|
||||
init_events();
|
||||
time_seconds = 0;
|
||||
|
||||
// No delta, so time shouldn't increase
|
||||
testlib_millis = 0;
|
||||
update_event_timestamps();
|
||||
ASSERT_EQ(time_seconds, 0);
|
||||
|
||||
// Almost time to bump the seconds
|
||||
testlib_millis = 999;
|
||||
update_event_timestamps();
|
||||
ASSERT_EQ(time_seconds, 0);
|
||||
ASSERT_EQ(previous_millis, 0);
|
||||
|
||||
// millis == 1000, so we should add a second
|
||||
testlib_millis = 1000;
|
||||
update_event_timestamps();
|
||||
ASSERT_EQ(time_seconds, 1);
|
||||
ASSERT_EQ(previous_millis, 1000);
|
||||
|
||||
// We shouldn't add more seconds until 2000 now
|
||||
testlib_millis = 1999;
|
||||
update_event_timestamps();
|
||||
ASSERT_EQ(time_seconds, 1);
|
||||
ASSERT_EQ(previous_millis, 1000);
|
||||
testlib_millis = 2000;
|
||||
update_event_timestamps();
|
||||
ASSERT_EQ(time_seconds, 2);
|
||||
ASSERT_EQ(previous_millis, 2000);
|
||||
}
|
||||
|
||||
TEST(set_event_test) {
|
||||
// Reset
|
||||
init_events();
|
||||
time_seconds = 0;
|
||||
|
||||
// Initially, the event should not have any data or occurences
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].data, 0);
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].occurences, 0);
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].timestamp, 0);
|
||||
// Set current time and overvoltage event for cell 23
|
||||
time_seconds = 345;
|
||||
set_event(EVENT_CELL_OVER_VOLTAGE, 123);
|
||||
// Ensure proper event data
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].data, 123);
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].occurences, 1);
|
||||
ASSERT_EQ(entries[EVENT_CELL_OVER_VOLTAGE].timestamp, 345);
|
||||
}
|
||||
|
||||
TEST(event_message_test) {
|
||||
reset_event_msg();
|
||||
|
||||
set_event(EVENT_DUMMY, 0); // Set dummy event with no data
|
||||
|
||||
ASSERT_STREQ("The dummy event was set!", event_message);
|
||||
}
|
||||
|
||||
TEST_MAIN();
|
32
test/utils/timer_test.cpp
Normal file
32
test/utils/timer_test.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
// The test library must be included first!
|
||||
#include "../test_lib.h"
|
||||
|
||||
#include "timer.cpp"
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/* Test functions */
|
||||
|
||||
TEST(timer_test) {
|
||||
unsigned long test_interval = 10;
|
||||
|
||||
testlib_millis = 0;
|
||||
MyTimer timer(test_interval);
|
||||
ASSERT_EQ(timer.elapsed(), false);
|
||||
|
||||
testlib_millis = test_interval - 1;
|
||||
ASSERT_EQ(timer.elapsed(), false);
|
||||
|
||||
testlib_millis = test_interval;
|
||||
ASSERT_EQ(timer.elapsed(), true);
|
||||
ASSERT_EQ(timer.elapsed(), false);
|
||||
|
||||
testlib_millis = 2 * test_interval - 1;
|
||||
ASSERT_EQ(timer.elapsed(), false);
|
||||
|
||||
testlib_millis = 2 * test_interval;
|
||||
ASSERT_EQ(timer.elapsed(), true);
|
||||
ASSERT_EQ(timer.elapsed(), false);
|
||||
}
|
||||
|
||||
TEST_MAIN();
|
Loading…
Add table
Add a link
Reference in a new issue