mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Refactoring: Scalability and performance (#252)
Refactoring v5.7 step 1
This commit is contained in:
parent
5a5cfc433b
commit
ffa7a54f20
77 changed files with 926 additions and 286 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -15,3 +15,7 @@
|
||||||
.gcc-flags.json
|
.gcc-flags.json
|
||||||
.pio
|
.pio
|
||||||
logs
|
logs
|
||||||
|
|
||||||
|
# Ignore upload command (removes the need to re-compile after Verify when running Download, in e.g. VS Code)
|
||||||
|
upload.bat
|
||||||
|
compile.bat
|
|
@ -1,20 +1,19 @@
|
||||||
/* Do not change any code below this line unless you are sure what you are doing */
|
/* Do not change any code below this line unless you are sure what you are doing */
|
||||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include "src/include.h"
|
||||||
#include <Preferences.h>
|
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "USER_SETTINGS.h"
|
#include "USER_SETTINGS.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "src/battery/BATTERIES.h"
|
|
||||||
#include "src/charger/CHARGERS.h"
|
#include "src/charger/CHARGERS.h"
|
||||||
#include "src/devboard/config.h"
|
|
||||||
#include "src/devboard/utils/events.h"
|
#include "src/devboard/utils/events.h"
|
||||||
#include "src/inverter/INVERTERS.h"
|
#include "src/devboard/utils/led_handler.h"
|
||||||
#include "src/lib/adafruit-Adafruit_NeoPixel/Adafruit_NeoPixel.h"
|
#include "src/devboard/utils/value_mapping.h"
|
||||||
#include "src/lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
#include "src/lib/bblanchon-ArduinoJson/ArduinoJson.h"
|
||||||
#include "src/lib/eModbus-eModbus/Logging.h"
|
#include "src/lib/eModbus-eModbus/Logging.h"
|
||||||
#include "src/lib/eModbus-eModbus/ModbusServerRTU.h"
|
#include "src/lib/eModbus-eModbus/ModbusServerRTU.h"
|
||||||
|
@ -22,6 +21,8 @@
|
||||||
#include "src/lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "src/lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "src/lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "src/lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#include "src/datalayer/datalayer.h"
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
#ifdef WEBSERVER
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include "src/devboard/webserver/webserver.h"
|
#include "src/devboard/webserver/webserver.h"
|
||||||
|
@ -96,12 +97,12 @@ float charger_stat_ACvol = 0;
|
||||||
float charger_stat_LVcur = 0;
|
float charger_stat_LVcur = 0;
|
||||||
float charger_stat_LVvol = 0;
|
float charger_stat_LVvol = 0;
|
||||||
|
|
||||||
// LED parameters
|
// Task time measurement for debugging and for setting CPU load events
|
||||||
Adafruit_NeoPixel pixels(1, WS2812_PIN, NEO_GRB + NEO_KHZ800);
|
int64_t core_task_time_us;
|
||||||
static uint8_t brightness = 0;
|
MyTimer core_task_timer_10s(INTERVAL_10_S);
|
||||||
static bool rampUp = true;
|
|
||||||
const uint8_t maxBrightness = 100;
|
int64_t mqtt_task_time_us;
|
||||||
uint8_t LEDcolor = GREEN;
|
MyTimer mqtt_task_timer_10s(INTERVAL_10_S);
|
||||||
|
|
||||||
// Contactor parameters
|
// Contactor parameters
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
|
@ -126,7 +127,8 @@ unsigned long timeSpentInFaultedMode = 0;
|
||||||
bool batteryAllowsContactorClosing = false;
|
bool batteryAllowsContactorClosing = false;
|
||||||
bool inverterAllowsContactorClosing = true;
|
bool inverterAllowsContactorClosing = true;
|
||||||
|
|
||||||
TaskHandle_t mainLoopTask;
|
TaskHandle_t main_loop_task;
|
||||||
|
TaskHandle_t wifi_loop_task;
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
void setup() {
|
void setup() {
|
||||||
|
@ -136,16 +138,17 @@ void setup() {
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
#ifdef WEBSERVER
|
||||||
init_webserver();
|
init_webserver();
|
||||||
|
|
||||||
init_mDNS();
|
init_mDNS();
|
||||||
|
#ifdef MQTT
|
||||||
|
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, &mqtt_task_time_us, TASK_WIFI_PRIO,
|
||||||
|
&main_loop_task, WIFI_CORE);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_events();
|
init_events();
|
||||||
|
|
||||||
init_CAN();
|
init_CAN();
|
||||||
|
|
||||||
init_LED();
|
|
||||||
|
|
||||||
init_contactors();
|
init_contactors();
|
||||||
|
|
||||||
init_modbus();
|
init_modbus();
|
||||||
|
@ -161,26 +164,45 @@ void setup() {
|
||||||
|
|
||||||
esp_task_wdt_deinit(); // Disable watchdog
|
esp_task_wdt_deinit(); // Disable watchdog
|
||||||
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&mainLoop, "mainLoop", 4096, NULL, 8, &mainLoopTask, 1);
|
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, &core_task_time_us, TASK_CORE_PRIO,
|
||||||
|
&main_loop_task, CORE_FUNCTION_CORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform main program functions
|
// Perform main program functions
|
||||||
void loop() {
|
void loop() {}
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mainLoop(void* pvParameters) {
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
|
||||||
// Over-the-air updates by ElegantOTA
|
|
||||||
wifi_monitor();
|
|
||||||
ElegantOTA.loop();
|
|
||||||
#ifdef MQTT
|
#ifdef MQTT
|
||||||
|
void mqtt_loop(void* task_time_us) {
|
||||||
|
// Init MQTT
|
||||||
|
init_mqtt();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
START_TIME_MEASUREMENT(mqtt);
|
||||||
mqtt_loop();
|
mqtt_loop();
|
||||||
|
END_TIME_MEASUREMENT_MAX(mqtt, datalayer.system.status.time_mqtt_us);
|
||||||
|
|
||||||
|
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||||
|
if (mqtt_task_timer_10s.elapsed()) {
|
||||||
|
datalayer.system.status.time_mqtt_us = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void core_loop(void* task_time_us) {
|
||||||
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
|
const TickType_t xFrequency = pdMS_TO_TICKS(1); // Convert 1ms to ticks
|
||||||
|
led_init();
|
||||||
|
int64_t prev_wake;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int64_t now = esp_timer_get_time();
|
||||||
|
int64_t wake_period = now - prev_wake;
|
||||||
|
prev_wake = now;
|
||||||
|
START_TIME_MEASUREMENT(all);
|
||||||
|
START_TIME_MEASUREMENT(comm);
|
||||||
// Input
|
// Input
|
||||||
receive_can(); // Receive CAN messages. Runs as fast as possible
|
receive_can(); // Receive CAN messages. Runs as fast as possible
|
||||||
#ifdef CAN_FD
|
#ifdef CAN_FD
|
||||||
|
@ -192,16 +214,26 @@ void mainLoop(void* pvParameters) {
|
||||||
#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER)
|
#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER)
|
||||||
runSerialDataLink();
|
runSerialDataLink();
|
||||||
#endif
|
#endif
|
||||||
|
END_TIME_MEASUREMENT_MAX(comm, datalayer.system.status.time_comm_us);
|
||||||
|
#ifdef WEBSERVER
|
||||||
|
START_TIME_MEASUREMENT(wifi_ota);
|
||||||
|
wifi_monitor();
|
||||||
|
ElegantOTA.loop();
|
||||||
|
END_TIME_MEASUREMENT(wifi_ota, datalayer.system.status.time_wifi_us);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
START_TIME_MEASUREMENT(time_10ms);
|
||||||
// Process
|
// Process
|
||||||
if (millis() - previousMillis10ms >= INTERVAL_10_MS) {
|
if (millis() - previousMillis10ms >= INTERVAL_10_MS) {
|
||||||
previousMillis10ms = millis();
|
previousMillis10ms = millis();
|
||||||
handle_LED_state(); // Set the LED color according to state
|
led_exe();
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
handle_contactors(); // Take care of startup precharge/contactor closing
|
handle_contactors(); // Take care of startup precharge/contactor closing
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
END_TIME_MEASUREMENT_MAX(time_10ms, datalayer.system.status.time_10ms_us);
|
||||||
|
|
||||||
|
START_TIME_MEASUREMENT(time_5s);
|
||||||
if (millis() - previousMillisUpdateVal >= intervalUpdateValues) // Every 5s normally
|
if (millis() - previousMillisUpdateVal >= intervalUpdateValues) // Every 5s normally
|
||||||
{
|
{
|
||||||
previousMillisUpdateVal = millis();
|
previousMillisUpdateVal = millis();
|
||||||
|
@ -211,15 +243,33 @@ void mainLoop(void* pvParameters) {
|
||||||
set_event(EVENT_DUMMY_ERROR, (uint8_t)millis());
|
set_event(EVENT_DUMMY_ERROR, (uint8_t)millis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
END_TIME_MEASUREMENT_MAX(time_5s, datalayer.system.status.time_5s_us);
|
||||||
|
|
||||||
|
START_TIME_MEASUREMENT(cantx);
|
||||||
// Output
|
// Output
|
||||||
send_can(); // Send CAN messages
|
send_can(); // Send CAN messages
|
||||||
#ifdef DUAL_CAN
|
#ifdef DUAL_CAN
|
||||||
send_can2();
|
send_can2();
|
||||||
#endif
|
#endif
|
||||||
run_event_handling();
|
END_TIME_MEASUREMENT_MAX(cantx, datalayer.system.status.time_cantx_us);
|
||||||
|
|
||||||
delay(1); // Allow the scheduler to start other tasks on other cores
|
START_TIME_MEASUREMENT(events);
|
||||||
|
run_event_handling();
|
||||||
|
END_TIME_MEASUREMENT_MAX(events, datalayer.system.status.time_events_us);
|
||||||
|
END_TIME_MEASUREMENT_MAX(all, datalayer.system.status.main_task_10s_max_us);
|
||||||
|
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||||
|
datalayer.system.status.main_task_max_us =
|
||||||
|
MAX(datalayer.system.status.main_task_10s_max_us, datalayer.system.status.main_task_max_us);
|
||||||
|
if (core_task_timer_10s.elapsed()) {
|
||||||
|
datalayer.system.status.time_comm_us = 0;
|
||||||
|
datalayer.system.status.time_10ms_us = 0;
|
||||||
|
datalayer.system.status.time_5s_us = 0;
|
||||||
|
datalayer.system.status.time_cantx_us = 0;
|
||||||
|
datalayer.system.status.time_events_us = 0;
|
||||||
|
datalayer.system.status.main_task_10s_max_us = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,11 +398,6 @@ void init_CAN() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_LED() {
|
|
||||||
// Init LED control
|
|
||||||
pixels.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_contactors() {
|
void init_contactors() {
|
||||||
// Init contactor pins
|
// Init contactor pins
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
|
@ -397,7 +442,7 @@ void init_modbus() {
|
||||||
MBserver.registerWorker(MBTCP_ID, WRITE_MULT_REGISTERS, &FC16);
|
MBserver.registerWorker(MBTCP_ID, WRITE_MULT_REGISTERS, &FC16);
|
||||||
MBserver.registerWorker(MBTCP_ID, R_W_MULT_REGISTERS, &FC23);
|
MBserver.registerWorker(MBTCP_ID, R_W_MULT_REGISTERS, &FC23);
|
||||||
// Start ModbusRTU background task
|
// Start ModbusRTU background task
|
||||||
MBserver.begin(Serial2, 0);
|
MBserver.begin(Serial2, MODBUS_CORE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,10 +495,6 @@ void inform_user_on_inverter() {
|
||||||
void init_battery() {
|
void init_battery() {
|
||||||
// Inform user what battery is used and perform setup
|
// Inform user what battery is used and perform setup
|
||||||
setup_battery();
|
setup_battery();
|
||||||
|
|
||||||
#ifndef BATTERY_SELECTED
|
|
||||||
#error No battery selected! Choose one from the USER_SETTINGS.h file
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CAN_FD
|
#ifdef CAN_FD
|
||||||
|
@ -470,7 +511,7 @@ void receive_canfd() { // This section checks if we have a complete CAN-FD mess
|
||||||
void receive_can() { // This section checks if we have a complete CAN message incoming
|
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
|
// Depending on which battery/inverter is selected, we forward this to their respective CAN routines
|
||||||
CAN_frame_t rx_frame;
|
CAN_frame_t rx_frame;
|
||||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) {
|
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 0) == pdTRUE) {
|
||||||
if (rx_frame.FIR.B.FF == CAN_frame_std) { // New standard frame
|
if (rx_frame.FIR.B.FF == CAN_frame_std) { // New standard frame
|
||||||
// Battery
|
// Battery
|
||||||
#ifndef SERIAL_LINK_RECEIVER
|
#ifndef SERIAL_LINK_RECEIVER
|
||||||
|
@ -574,48 +615,6 @@ void send_can2() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handle_LED_state() {
|
|
||||||
// Determine how bright the LED should be
|
|
||||||
if (rampUp && brightness < maxBrightness) {
|
|
||||||
brightness++;
|
|
||||||
} else if (rampUp && brightness == maxBrightness) {
|
|
||||||
rampUp = false;
|
|
||||||
} else if (!rampUp && brightness > 0) {
|
|
||||||
brightness--;
|
|
||||||
} else if (!rampUp && brightness == 0) {
|
|
||||||
rampUp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (get_event_level()) {
|
|
||||||
case EVENT_LEVEL_INFO:
|
|
||||||
LEDcolor = GREEN;
|
|
||||||
pixels.setPixelColor(0, pixels.Color(0, brightness, 0)); // Green pulsing LED
|
|
||||||
break;
|
|
||||||
case EVENT_LEVEL_WARNING:
|
|
||||||
LEDcolor = YELLOW;
|
|
||||||
pixels.setPixelColor(0, pixels.Color(brightness, brightness, 0)); // Yellow pulsing LED
|
|
||||||
break;
|
|
||||||
case EVENT_LEVEL_DEBUG:
|
|
||||||
case EVENT_LEVEL_UPDATE:
|
|
||||||
LEDcolor = BLUE;
|
|
||||||
pixels.setPixelColor(0, pixels.Color(0, 0, brightness)); // Blue pulsing LED
|
|
||||||
break;
|
|
||||||
case EVENT_LEVEL_ERROR:
|
|
||||||
LEDcolor = RED;
|
|
||||||
pixels.setPixelColor(0, pixels.Color(150, 0, 0)); // Red LED full brightness
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if button is being held down. If so, test all colors
|
|
||||||
if (digitalRead(0) == LOW) {
|
|
||||||
pixels.setPixelColor(0, pixels.Color(brightness, abs((100 - brightness)), abs((50 - brightness)))); // RGB
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels.show(); // This sends the updated pixel color to the hardware.
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
void handle_contactors() {
|
void handle_contactors() {
|
||||||
// First check if we have any active errors, incase we do, turn off the battery
|
// First check if we have any active errors, incase we do, turn off the battery
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
//#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery)
|
//#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.
|
#define WEBSERVER //Enable this line to enable WiFi, and to run the webserver. See USER_SETTINGS.cpp for the Wifi settings.
|
||||||
//#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot (overrides any battery settings set in USER_SETTINGS.cpp)
|
//#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot (overrides any battery settings set in USER_SETTINGS.cpp)
|
||||||
|
//#define FUNCTION_TIME_MEASUREMENT // Enable this to record execution times and present them in the web UI (WARNING, raises CPU load, do not use for production)
|
||||||
|
|
||||||
/* MQTT options */
|
/* MQTT options */
|
||||||
// #define MQTT // Enable this line to enable MQTT
|
// #define MQTT // Enable this line to enable MQTT
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
|
|
||||||
#ifdef KIA_E_GMP_BATTERY
|
#ifdef KIA_E_GMP_BATTERY
|
||||||
#include "KIA-E-GMP-BATTERY.h" //See this file for more GMP battery settings
|
#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
|
#endif
|
||||||
|
|
||||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||||
|
@ -61,11 +58,13 @@
|
||||||
#ifdef SERIAL_LINK_RECEIVER // The serial thing does its thing
|
#ifdef SERIAL_LINK_RECEIVER // The serial thing does its thing
|
||||||
void receive_can_battery();
|
void receive_can_battery();
|
||||||
#else
|
#else
|
||||||
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // This include is annoying, consider defining a frame type in types.h
|
||||||
void receive_can_battery(CAN_frame_t rx_frame);
|
void receive_can_battery(CAN_frame_t rx_frame);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CAN_FD
|
#ifdef CAN_FD
|
||||||
void receive_canfd_battery(CANFDMessage frame);
|
void receive_canfd_battery(CANFDMessage frame);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void update_values_battery();
|
void update_values_battery();
|
||||||
void send_can_battery();
|
void send_can_battery();
|
||||||
void setup_battery(void);
|
void setup_battery(void);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef BMW_I3_BATTERY
|
#ifdef BMW_I3_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#ifndef BMW_I3_BATTERY_H
|
#ifndef BMW_I3_BATTERY_H
|
||||||
#define BMW_I3_BATTERY_H
|
#define BMW_I3_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
||||||
|
#define WUP_PIN 25
|
||||||
|
|
||||||
// These parameters need to be mapped for the inverter
|
// These parameters need to be mapped for the inverter
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef CHADEMO_BATTERY
|
#ifdef CHADEMO_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef CHADEMO_BATTERY_H
|
#ifndef CHADEMO_BATTERY_H
|
||||||
#define CHADEMO_BATTERY_H
|
#define CHADEMO_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef IMIEV_CZERO_ION_BATTERY
|
#ifdef IMIEV_CZERO_ION_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef IMIEV_CZERO_ION_BATTERY_H
|
#ifndef IMIEV_CZERO_ION_BATTERY_H
|
||||||
#define IMIEV_CZERO_ION_BATTERY_H
|
#define IMIEV_CZERO_ION_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef KIA_E_GMP_BATTERY
|
#ifdef KIA_E_GMP_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef KIA_E_GMP_BATTERY_H
|
#ifndef KIA_E_GMP_BATTERY_H
|
||||||
#define KIA_E_GMP_BATTERY_H
|
#define KIA_E_GMP_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef KIA_HYUNDAI_64_BATTERY
|
#ifdef KIA_HYUNDAI_64_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef KIA_HYUNDAI_64_BATTERY_H
|
#ifndef KIA_HYUNDAI_64_BATTERY_H
|
||||||
#define KIA_HYUNDAI_64_BATTERY_H
|
#define KIA_HYUNDAI_64_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef NISSAN_LEAF_BATTERY
|
#ifdef NISSAN_LEAF_BATTERY
|
||||||
#include "NISSAN-LEAF-BATTERY.h"
|
#include "NISSAN-LEAF-BATTERY.h"
|
||||||
#ifdef MQTT
|
#ifdef MQTT
|
||||||
#include "../devboard/mqtt/mqtt.h"
|
#include "../devboard/mqtt/mqtt.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef NISSAN_LEAF_BATTERY_H
|
#ifndef NISSAN_LEAF_BATTERY_H
|
||||||
#define NISSAN_LEAF_BATTERY_H
|
#define NISSAN_LEAF_BATTERY_H
|
||||||
#include <Arduino.h>
|
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef RENAULT_KANGOO_BATTERY
|
#ifdef RENAULT_KANGOO_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef RENAULT_KANGOO_BATTERY_H
|
#ifndef RENAULT_KANGOO_BATTERY_H
|
||||||
#define RENAULT_KANGOO_BATTERY_H
|
#define RENAULT_KANGOO_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef RENAULT_ZOE_BATTERY
|
#ifdef RENAULT_ZOE_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef RENAULT_ZOE_BATTERY_H
|
#ifndef RENAULT_ZOE_BATTERY_H
|
||||||
#define RENAULT_ZOE_BATTERY_H
|
#define RENAULT_ZOE_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef SANTA_FE_PHEV_BATTERY
|
#ifdef SANTA_FE_PHEV_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef SANTA_FE_PHEV_BATTERY_H
|
#ifndef SANTA_FE_PHEV_BATTERY_H
|
||||||
#define SANTA_FE_PHEV_BATTERY_H
|
#define SANTA_FE_PHEV_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef SERIAL_LINK_RECEIVER
|
#ifdef SERIAL_LINK_RECEIVER
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
||||||
|
|
||||||
// https://github.com/mackelec/SerialDataLink
|
// https://github.com/mackelec/SerialDataLink
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef TESLA_MODEL_3_BATTERY
|
#ifdef TESLA_MODEL_3_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef TESLA_MODEL_3_BATTERY_H
|
#ifndef TESLA_MODEL_3_BATTERY_H
|
||||||
#define TESLA_MODEL_3_BATTERY_H
|
#define TESLA_MODEL_3_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef TEST_FAKE_BATTERY
|
#ifdef TEST_FAKE_BATTERY
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "TEST-FAKE-BATTERY.h"
|
#include "TEST-FAKE-BATTERY.h"
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#ifndef TEST_FAKE_BATTERY_H
|
#ifndef TEST_FAKE_BATTERY_H
|
||||||
#define TEST_FAKE_BATTERY_H
|
#define TEST_FAKE_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include "../include.h"
|
||||||
#include "../../USER_SETTINGS.h"
|
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "BATTERIES.h"
|
#include "../include.h"
|
||||||
#ifdef VOLVO_SPA_BATTERY
|
#ifdef VOLVO_SPA_BATTERY
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef VOLVO_SPA_BATTERY_H
|
#ifndef VOLVO_SPA_BATTERY_H
|
||||||
#define VOLVO_SPA_BATTERY_H
|
#define VOLVO_SPA_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
#define BATTERY_SELECTED
|
#define BATTERY_SELECTED
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef CHARGERS_H
|
#ifndef CHARGERS_H
|
||||||
#define CHARGERS_H
|
#define CHARGERS_H
|
||||||
|
|
||||||
|
#include "../../USER_SETTINGS.h"
|
||||||
|
|
||||||
#ifdef CHEVYVOLT_CHARGER
|
#ifdef CHEVYVOLT_CHARGER
|
||||||
#include "CHEVY-VOLT-CHARGER.h"
|
#include "CHEVY-VOLT-CHARGER.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "CHEVY-VOLT-CHARGER.h"
|
#include "../include.h"
|
||||||
|
#ifdef CHEVYVOLT_CHARGER
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "CHEVY-VOLT-CHARGER.h"
|
||||||
|
|
||||||
/* This implements Chevy Volt / Ampera charger support (2011-2015 model years).
|
/* This implements Chevy Volt / Ampera charger support (2011-2015 model years).
|
||||||
*
|
*
|
||||||
|
@ -193,3 +195,4 @@ void send_can_chevyvolt_charger() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef CHEVYVOLT_CHARGER_H
|
#ifndef CHEVYVOLT_CHARGER_H
|
||||||
#define CHEVYVOLT_CHARGER_H
|
#define CHEVYVOLT_CHARGER_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
/* Charger hardware limits
|
/* Charger hardware limits
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "NISSAN-LEAF-CHARGER.h"
|
#include "../include.h"
|
||||||
|
#ifdef NISSAN_LEAF_CHARGER
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "NISSAN-LEAF-CHARGER.h"
|
||||||
|
|
||||||
/* This implements Nissan LEAF PDM charger support. 2013-2024 Gen2/3 PDMs are supported
|
/* This implements Nissan LEAF PDM charger support. 2013-2024 Gen2/3 PDMs are supported
|
||||||
*
|
*
|
||||||
|
@ -271,3 +273,4 @@ void send_can_nissanleaf_charger() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef NISSANLEAF_CHARGER_H
|
#ifndef NISSANLEAF_CHARGER_H
|
||||||
#define NISSANLEAF_CHARGER_H
|
#define NISSANLEAF_CHARGER_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000)
|
extern uint16_t system_battery_voltage_dV; //V+1, 0-1000.0 (0-10000)
|
||||||
|
|
4
Software/src/datalayer/datalayer.cpp
Normal file
4
Software/src/datalayer/datalayer.cpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#include "datalayer.h"
|
||||||
|
#include "../include.h"
|
||||||
|
|
||||||
|
DataLayer datalayer;
|
85
Software/src/datalayer/datalayer.h
Normal file
85
Software/src/datalayer/datalayer.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#ifndef _DATALAYER_H_
|
||||||
|
#define _DATALAYER_H_
|
||||||
|
|
||||||
|
#include "../devboard/utils/soc_scaling.h"
|
||||||
|
#include "../include.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/** float */
|
||||||
|
float max_design_voltage_V;
|
||||||
|
float min_design_voltage_V;
|
||||||
|
|
||||||
|
/** uint32_t */
|
||||||
|
uint32_t total_capacity;
|
||||||
|
|
||||||
|
/** uint16_t */
|
||||||
|
uint16_t number_of_cells;
|
||||||
|
|
||||||
|
/** Other */
|
||||||
|
battery_chemistry_enum chemistry;
|
||||||
|
} DATALAYER_BATTERY_DATA_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/** float */
|
||||||
|
float temperature_max_C;
|
||||||
|
float temperature_min_C;
|
||||||
|
float current_A;
|
||||||
|
float voltage_V;
|
||||||
|
float soh_pct;
|
||||||
|
|
||||||
|
/** uint32_t */
|
||||||
|
int32_t active_power_W;
|
||||||
|
uint32_t remaining_capacity;
|
||||||
|
|
||||||
|
/** int16_t */
|
||||||
|
|
||||||
|
/** uint16_t */
|
||||||
|
uint32_t max_discharge_power_W;
|
||||||
|
uint32_t max_charge_power_W;
|
||||||
|
uint16_t cell_max_voltage_mV;
|
||||||
|
uint16_t cell_min_voltage_mV;
|
||||||
|
uint16_t cell_voltages_mV[MAX_AMOUNT_CELLS];
|
||||||
|
|
||||||
|
/** Other */
|
||||||
|
// bms_status_enum bms_status; // Not ready yet
|
||||||
|
ScaledSoc soc;
|
||||||
|
} DATALAYER_BATTERY_STATUS_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DATALAYER_BATTERY_DATA_TYPE data;
|
||||||
|
DATALAYER_BATTERY_STATUS_TYPE status;
|
||||||
|
} DATALAYER_BATTERY_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||||
|
int64_t main_task_max_us = 0;
|
||||||
|
int64_t main_task_10s_max_us = 0;
|
||||||
|
int64_t time_wifi_us = 0;
|
||||||
|
int64_t time_mqtt_us = 0;
|
||||||
|
int64_t time_comm_us = 0;
|
||||||
|
int64_t time_10ms_us = 0;
|
||||||
|
int64_t time_5s_us = 0;
|
||||||
|
int64_t time_cantx_us = 0;
|
||||||
|
int64_t time_events_us = 0;
|
||||||
|
#endif
|
||||||
|
} DATALAYER_SYSTEM_STATUS_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DATALAYER_SYSTEM_STATUS_TYPE status;
|
||||||
|
} DATALAYER_SYSTEM_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool batteryAllowsContactorClosing = false;
|
||||||
|
bool inverterAllowsContactorClosing = true;
|
||||||
|
} DATALAYER_SETTINGS_TYPE;
|
||||||
|
|
||||||
|
class DataLayer {
|
||||||
|
public:
|
||||||
|
DATALAYER_BATTERY_TYPE battery;
|
||||||
|
DATALAYER_SYSTEM_TYPE system;
|
||||||
|
DATALAYER_SETTINGS_TYPE settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DataLayer datalayer;
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,101 +0,0 @@
|
||||||
#ifndef __CONFIG_H__
|
|
||||||
#define __CONFIG_H__
|
|
||||||
|
|
||||||
// PIN mappings, do not change these unless you are adding on extra hardware to the PCB
|
|
||||||
#define PIN_5V_EN 16
|
|
||||||
#define CAN_TX_PIN 27
|
|
||||||
#define CAN_RX_PIN 26
|
|
||||||
#define CAN_SE_PIN 23
|
|
||||||
|
|
||||||
#define RS485_EN_PIN 17 // 17 /RE
|
|
||||||
#define RS485_TX_PIN 22 // 21
|
|
||||||
#define RS485_RX_PIN 21 // 22
|
|
||||||
#define RS485_SE_PIN 19 // 22 /SHDN
|
|
||||||
|
|
||||||
#ifdef DUAL_CAN
|
|
||||||
#define MCP2515_SCK 12 // SCK input of MCP2515
|
|
||||||
#define MCP2515_MOSI 5 // SDI input of MCP2515
|
|
||||||
#define MCP2515_MISO 34 // SDO output of MCP2515 | Pin 34 is input only, without pullup/down resistors
|
|
||||||
#define MCP2515_CS 18 // CS input of MCP2515
|
|
||||||
#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
|
|
||||||
#define PRECHARGE_PIN 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BMW_I3_BATTERY
|
|
||||||
#define WUP_PIN 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SD_MISO_PIN 2
|
|
||||||
#define SD_MOSI_PIN 15
|
|
||||||
#define SD_SCLK_PIN 14
|
|
||||||
#define SD_CS_PIN 13
|
|
||||||
#define WS2812_PIN 4
|
|
||||||
|
|
||||||
// LED definitions for the board, in order of "priority", DONT CHANGE!
|
|
||||||
#define GREEN 0
|
|
||||||
#define YELLOW 1
|
|
||||||
#define BLUE 2
|
|
||||||
#define RED 3
|
|
||||||
#define TEST_ALL_COLORS 10
|
|
||||||
|
|
||||||
// Inverter definitions
|
|
||||||
#define STANDBY 0
|
|
||||||
#define INACTIVE 1
|
|
||||||
#define DARKSTART 2
|
|
||||||
#define ACTIVE 3
|
|
||||||
#define FAULT 4
|
|
||||||
#define UPDATING 5
|
|
||||||
#define DISCHARGING 1
|
|
||||||
#define CHARGING 2
|
|
||||||
|
|
||||||
// Common definitions
|
|
||||||
#define MAX_AMOUNT_CELLS 192
|
|
||||||
#define MAX_CAN_FAILURES 500 // Amount of malformed CAN messages to allow before raising a warning
|
|
||||||
|
|
||||||
#define INTERVAL_10_MS 10
|
|
||||||
#define INTERVAL_20_MS 20
|
|
||||||
#define INTERVAL_30_MS 30
|
|
||||||
#define INTERVAL_50_MS 50
|
|
||||||
#define INTERVAL_100_MS 100
|
|
||||||
#define INTERVAL_200_MS 200
|
|
||||||
#define INTERVAL_500_MS 500
|
|
||||||
#define INTERVAL_640_MS 640
|
|
||||||
#define INTERVAL_1_S 1000
|
|
||||||
#define INTERVAL_2_S 2000
|
|
||||||
#define INTERVAL_5_S 5000
|
|
||||||
#define INTERVAL_10_S 10000
|
|
||||||
#define INTERVAL_60_S 60000
|
|
||||||
|
|
||||||
#define INTERVAL_10_MS_DELAYED 15
|
|
||||||
#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
|
|
15
Software/src/devboard/hal/hal.h
Normal file
15
Software/src/devboard/hal/hal.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef _HAL_H_
|
||||||
|
#define _HAL_H_
|
||||||
|
|
||||||
|
#include "../../../USER_SETTINGS.h"
|
||||||
|
|
||||||
|
/* Select HW - DONT TOUCH */
|
||||||
|
#define HW_LILYGO
|
||||||
|
|
||||||
|
#if defined(HW_LILYGO)
|
||||||
|
#include "hw_lilygo.h"
|
||||||
|
#elif defined(HW_SJB_V1)
|
||||||
|
#include "hw_sjb_v1.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
65
Software/src/devboard/hal/hw_lilygo.h
Normal file
65
Software/src/devboard/hal/hw_lilygo.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef __HW_LILYGO_H__
|
||||||
|
#define __HW_LILYGO_H__
|
||||||
|
|
||||||
|
// Board boot-up time
|
||||||
|
#define BOOTUP_TIME 1000 // Time in ms it takes before system is considered fully started up
|
||||||
|
|
||||||
|
// Core assignment
|
||||||
|
#define CORE_FUNCTION_CORE 1
|
||||||
|
#define MODBUS_CORE 0
|
||||||
|
#define WIFI_CORE 0
|
||||||
|
|
||||||
|
// RS485
|
||||||
|
#define PIN_5V_EN 16
|
||||||
|
#define RS485_EN_PIN 17 // 17 /RE
|
||||||
|
#define RS485_TX_PIN 22 // 21
|
||||||
|
#define RS485_RX_PIN 21 // 22
|
||||||
|
#define RS485_SE_PIN 19 // 22 /SHDN
|
||||||
|
|
||||||
|
// CAN settings. CAN_2 is not defined as it can be either MCP2515 or MCP2517, defined by the user settings
|
||||||
|
#define CAN_1_TYPE ESP32CAN
|
||||||
|
|
||||||
|
// CAN1 PIN mappings, do not change these unless you are adding on extra hardware to the PCB
|
||||||
|
#define CAN_TX_PIN GPIO_NUM_27
|
||||||
|
#define CAN_RX_PIN GPIO_NUM_26
|
||||||
|
#define CAN_SE_PIN 23
|
||||||
|
|
||||||
|
// CAN2 defines below
|
||||||
|
|
||||||
|
// DUAL_CAN defines
|
||||||
|
#define MCP2515_SCK 12 // SCK input of MCP2515
|
||||||
|
#define MCP2515_MOSI 5 // SDI input of MCP2515
|
||||||
|
#define MCP2515_MISO 34 // SDO output of MCP2515 | Pin 34 is input only, without pullup/down resistors
|
||||||
|
#define MCP2515_CS 18 // CS input of MCP2515
|
||||||
|
#define MCP2515_INT 35 // INT output of MCP2515 | | Pin 35 is input only, without pullup/down resistors
|
||||||
|
|
||||||
|
// CAN_FD defines
|
||||||
|
#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
|
||||||
|
|
||||||
|
// Contactor handling
|
||||||
|
#define POSITIVE_CONTACTOR_PIN 32
|
||||||
|
#define NEGATIVE_CONTACTOR_PIN 33
|
||||||
|
#define PRECHARGE_PIN 25
|
||||||
|
|
||||||
|
// SD card
|
||||||
|
#define SD_MISO_PIN 2
|
||||||
|
#define SD_MOSI_PIN 15
|
||||||
|
#define SD_SCLK_PIN 14
|
||||||
|
#define SD_CS_PIN 13
|
||||||
|
|
||||||
|
// LED
|
||||||
|
#define LED_PIN 4
|
||||||
|
#define LED_MAX_BRIGHTNESS 40
|
||||||
|
|
||||||
|
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||||
|
#ifndef HW_CONFIGURED
|
||||||
|
#define HW_CONFIGURED
|
||||||
|
#else
|
||||||
|
#error Multiple HW defined! Please select a single HW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -35,8 +35,7 @@
|
||||||
#define __MQTT_H__
|
#define __MQTT_H__
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../../USER_SETTINGS.h"
|
#include "../../include.h"
|
||||||
#include "../config.h" // Needed for defines
|
|
||||||
|
|
||||||
#define MQTT_MSG_BUFFER_SIZE (1024)
|
#define MQTT_MSG_BUFFER_SIZE (1024)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../USER_SETTINGS.h"
|
#include "../../../USER_SETTINGS.h"
|
||||||
#include "../config.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#define EE_NOF_EVENT_ENTRIES 30
|
#define EE_NOF_EVENT_ENTRIES 30
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef __EVENTS_H__
|
#ifndef __EVENTS_H__
|
||||||
#define __EVENTS_H__
|
#define __EVENTS_H__
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef UNIT_TEST
|
#ifndef UNIT_TEST
|
||||||
#include <Arduino.h>
|
#include "../../include.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #define INCLUDE_EVENTS_TEST // Enable to run an event test loop, see events_test_on_target.cpp
|
// #define INCLUDE_EVENTS_TEST // Enable to run an event test loop, see events_test_on_target.cpp
|
||||||
|
|
197
Software/src/devboard/utils/led_handler.cpp
Normal file
197
Software/src/devboard/utils/led_handler.cpp
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
#include "led_handler.h"
|
||||||
|
#include "../../datalayer/datalayer.h"
|
||||||
|
#include "../../include.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "value_mapping.h"
|
||||||
|
|
||||||
|
#define COLOR_GREEN(x) (((uint32_t)0 << 16) | ((uint32_t)x << 8) | 0)
|
||||||
|
#define COLOR_YELLOW(x) (((uint32_t)x << 16) | ((uint32_t)x << 8) | 0)
|
||||||
|
#define COLOR_RED(x) (((uint32_t)x << 16) | ((uint32_t)0 << 8) | 0)
|
||||||
|
#define COLOR_BLUE(x) (((uint32_t)0 << 16) | ((uint32_t)0 << 8) | x)
|
||||||
|
|
||||||
|
#define BPM_TO_MS(x) ((uint16_t)((60.0f / ((float)x)) * 1000))
|
||||||
|
|
||||||
|
static const float heartbeat_base = 0.15;
|
||||||
|
static const float heartbeat_peak1 = 0.80;
|
||||||
|
static const float heartbeat_peak2 = 0.55;
|
||||||
|
static const float heartbeat_deviation = 0.05;
|
||||||
|
|
||||||
|
static LED led(LED_MODE_DEFAULT);
|
||||||
|
|
||||||
|
void led_init(void) {
|
||||||
|
led.init();
|
||||||
|
}
|
||||||
|
void led_exe(void) {
|
||||||
|
led.exe();
|
||||||
|
}
|
||||||
|
led_color led_get_color() {
|
||||||
|
return led.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LED::exe(void) {
|
||||||
|
static bool test_all_colors = true;
|
||||||
|
// Don't run too often
|
||||||
|
if (!timer.elapsed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
default:
|
||||||
|
case LED_NORMAL:
|
||||||
|
// Update brightness
|
||||||
|
switch (mode) {
|
||||||
|
case led_mode::FLOW:
|
||||||
|
flow_run();
|
||||||
|
break;
|
||||||
|
case led_mode::HEARTBEAT:
|
||||||
|
heartbeat_run();
|
||||||
|
break;
|
||||||
|
case led_mode::CLASSIC:
|
||||||
|
default:
|
||||||
|
classic_run();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set color
|
||||||
|
switch (get_event_level()) {
|
||||||
|
case EVENT_LEVEL_INFO:
|
||||||
|
color = led_color::GREEN;
|
||||||
|
pixels.setPixelColor(0, COLOR_GREEN(brightness)); // Green pulsing LED
|
||||||
|
break;
|
||||||
|
case EVENT_LEVEL_WARNING:
|
||||||
|
color = led_color::YELLOW;
|
||||||
|
pixels.setPixelColor(0, COLOR_YELLOW(brightness)); // Yellow pulsing LED
|
||||||
|
break;
|
||||||
|
case EVENT_LEVEL_DEBUG:
|
||||||
|
case EVENT_LEVEL_UPDATE:
|
||||||
|
color = led_color::BLUE;
|
||||||
|
pixels.setPixelColor(0, COLOR_BLUE(brightness)); // Blue pulsing LED
|
||||||
|
break;
|
||||||
|
case EVENT_LEVEL_ERROR:
|
||||||
|
color = led_color::RED;
|
||||||
|
pixels.setPixelColor(0, COLOR_RED(brightness)); // Red LED full brightness
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_COMMAND:
|
||||||
|
break;
|
||||||
|
case LED_RGB:
|
||||||
|
rainbow_run();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show(); // This sends the updated pixel color to the hardware.
|
||||||
|
}
|
||||||
|
|
||||||
|
void LED::classic_run(void) {
|
||||||
|
// Determine how bright the LED should be
|
||||||
|
brightness = up_down(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LED::flow_run(void) {
|
||||||
|
// Determine how bright the LED should be
|
||||||
|
bool power_positive;
|
||||||
|
int16_t power_W = datalayer.battery.status.active_power_W;
|
||||||
|
if (power_W < -50) {
|
||||||
|
// Discharging
|
||||||
|
brightness = max_brightness - up_down(0.95);
|
||||||
|
} else if (power_W > 50) {
|
||||||
|
// Charging
|
||||||
|
brightness = up_down(0.95);
|
||||||
|
} else {
|
||||||
|
brightness = up_down(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LED::heartbeat_run(void) {
|
||||||
|
uint16_t period;
|
||||||
|
switch (get_event_level()) {
|
||||||
|
case EVENT_LEVEL_WARNING:
|
||||||
|
// phew, starting to sweat here
|
||||||
|
period = BPM_TO_MS(70);
|
||||||
|
break;
|
||||||
|
case EVENT_LEVEL_ERROR:
|
||||||
|
// omg omg OMG OMGG
|
||||||
|
period = BPM_TO_MS(100);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Keep default chill bpm (ba-dunk... ba-dunk... ba-dunk...)
|
||||||
|
period = BPM_TO_MS(35);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ms = (uint16_t)(millis() % period);
|
||||||
|
|
||||||
|
float period_pct = ((float)ms) / period;
|
||||||
|
float brightness_f;
|
||||||
|
|
||||||
|
if (period_pct < 0.10) {
|
||||||
|
brightness_f = map_float(period_pct, 0.00f, 0.10f, heartbeat_base, heartbeat_base - heartbeat_deviation);
|
||||||
|
} else if (period_pct < 0.20) {
|
||||||
|
brightness_f = map_float(period_pct, 0.10f, 0.20f, heartbeat_base - heartbeat_deviation,
|
||||||
|
heartbeat_base - heartbeat_deviation * 2);
|
||||||
|
} else if (period_pct < 0.25) {
|
||||||
|
brightness_f = map_float(period_pct, 0.20f, 0.25f, heartbeat_base - heartbeat_deviation * 2, heartbeat_peak1);
|
||||||
|
} else if (period_pct < 0.30) {
|
||||||
|
brightness_f = map_float(period_pct, 0.25f, 0.30f, heartbeat_peak1, heartbeat_base - heartbeat_deviation);
|
||||||
|
} else if (period_pct < 0.40) {
|
||||||
|
brightness_f = map_float(period_pct, 0.30f, 0.40f, heartbeat_base - heartbeat_deviation, heartbeat_peak2);
|
||||||
|
} else if (period_pct < 0.55) {
|
||||||
|
brightness_f = map_float(period_pct, 0.40f, 0.55f, heartbeat_peak2, heartbeat_base + heartbeat_deviation * 2);
|
||||||
|
} else {
|
||||||
|
brightness_f = map_float(period_pct, 0.55f, 1.00f, heartbeat_base + heartbeat_deviation * 2, heartbeat_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
brightness = (uint8_t)(brightness_f * LED_MAX_BRIGHTNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LED::rainbow_run(void) {
|
||||||
|
brightness = LED_MAX_BRIGHTNESS / 2;
|
||||||
|
|
||||||
|
uint16_t ms = (uint16_t)(millis() % LED_PERIOD_MS);
|
||||||
|
float value = ((float)ms) / LED_PERIOD_MS;
|
||||||
|
|
||||||
|
// Clamp the input value to the range [0.0, 1.0]
|
||||||
|
value = value < 0.0f ? 0.0f : value;
|
||||||
|
value = value > 1.0f ? 1.0f : value;
|
||||||
|
|
||||||
|
uint8_t r = 0, g = 0, b = 0;
|
||||||
|
|
||||||
|
// Scale the value to the range [0, 3), which will be used to transition through the colors
|
||||||
|
float scaledValue = value * 3.0f;
|
||||||
|
|
||||||
|
if (scaledValue < 1.0f) {
|
||||||
|
// From red to green
|
||||||
|
r = static_cast<uint8_t>((1.0f - scaledValue) * brightness);
|
||||||
|
g = static_cast<uint8_t>((scaledValue - 0.0f) * brightness);
|
||||||
|
} else if (scaledValue < 2.0f) {
|
||||||
|
// From green to blue
|
||||||
|
g = static_cast<uint8_t>((2.0f - scaledValue) * brightness);
|
||||||
|
b = static_cast<uint8_t>((scaledValue - 1.0f) * brightness);
|
||||||
|
} else {
|
||||||
|
// From blue back to red
|
||||||
|
b = static_cast<uint8_t>((3.0f - scaledValue) * brightness);
|
||||||
|
r = static_cast<uint8_t>((scaledValue - 2.0f) * brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble the color
|
||||||
|
uint32_t color = (static_cast<uint32_t>(r) << 16) | (static_cast<uint32_t>(g) << 8) | b;
|
||||||
|
pixels.setPixelColor(0, pixels.Color(r, g, b)); // RGB
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t LED::up_down(float middle_point_f) {
|
||||||
|
// Determine how bright the LED should be
|
||||||
|
middle_point_f = CONSTRAIN(middle_point_f, 0.0f, 1.0f);
|
||||||
|
uint16_t middle_point = (uint16_t)(middle_point_f * LED_PERIOD_MS);
|
||||||
|
uint16_t ms = (uint16_t)(millis() % LED_PERIOD_MS);
|
||||||
|
brightness = map_uint16(ms, 0, middle_point, 0, max_brightness);
|
||||||
|
if (ms < middle_point) {
|
||||||
|
brightness = map_uint16(ms, 0, middle_point, 0, max_brightness);
|
||||||
|
} else {
|
||||||
|
brightness = LED_MAX_BRIGHTNESS - map_uint16(ms, middle_point, LED_PERIOD_MS, 0, max_brightness);
|
||||||
|
}
|
||||||
|
return CONSTRAIN(brightness, 0, max_brightness);
|
||||||
|
}
|
49
Software/src/devboard/utils/led_handler.h
Normal file
49
Software/src/devboard/utils/led_handler.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef LED_H_
|
||||||
|
#define LED_H_
|
||||||
|
|
||||||
|
#include "../../include.h"
|
||||||
|
#include "../../lib/adafruit-Adafruit_NeoPixel/Adafruit_NeoPixel.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
enum led_mode { CLASSIC, FLOW, HEARTBEAT };
|
||||||
|
enum led_state { LED_NORMAL, LED_COMMAND, LED_RGB };
|
||||||
|
|
||||||
|
class LED {
|
||||||
|
public:
|
||||||
|
led_color color = led_color::GREEN;
|
||||||
|
|
||||||
|
LED()
|
||||||
|
: mode(led_mode::CLASSIC),
|
||||||
|
max_brightness(LED_MAX_BRIGHTNESS),
|
||||||
|
pixels(1, LED_PIN, NEO_GRB + NEO_KHZ800),
|
||||||
|
timer(LED_EXECUTION_FREQUENCY) {}
|
||||||
|
LED(led_mode mode)
|
||||||
|
: mode(mode),
|
||||||
|
max_brightness(LED_MAX_BRIGHTNESS),
|
||||||
|
pixels(1, LED_PIN, NEO_GRB + NEO_KHZ800),
|
||||||
|
timer(LED_EXECUTION_FREQUENCY) {}
|
||||||
|
|
||||||
|
void exe(void);
|
||||||
|
void init(void) { pixels.begin(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Adafruit_NeoPixel pixels;
|
||||||
|
uint8_t max_brightness;
|
||||||
|
uint8_t brightness;
|
||||||
|
led_mode mode = led_mode::CLASSIC;
|
||||||
|
led_state state = LED_NORMAL;
|
||||||
|
MyTimer timer;
|
||||||
|
|
||||||
|
void classic_run(void);
|
||||||
|
void flow_run(void);
|
||||||
|
void rainbow_run(void);
|
||||||
|
void heartbeat_run(void);
|
||||||
|
|
||||||
|
uint8_t up_down(float middle_point_f);
|
||||||
|
};
|
||||||
|
|
||||||
|
void led_init(void);
|
||||||
|
void led_exe(void);
|
||||||
|
led_color led_get_color(void);
|
||||||
|
|
||||||
|
#endif
|
36
Software/src/devboard/utils/soc_scaling.cpp
Normal file
36
Software/src/devboard/utils/soc_scaling.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include "soc_scaling.h"
|
||||||
|
|
||||||
|
float ScaledSoc::set_real_soc(float soc) {
|
||||||
|
real_soc = soc;
|
||||||
|
scaled_soc = map_float(real_soc, 0.0f, 100.0f, min_real_soc, max_real_soc);
|
||||||
|
real_soc_initialized = true;
|
||||||
|
return scaled_soc;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ScaledSoc::get_scaled_soc(void) {
|
||||||
|
if (real_soc_initialized) {
|
||||||
|
return scaled_soc;
|
||||||
|
} else {
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ScaledSoc::get_real_soc(void) {
|
||||||
|
if (real_soc_initialized) {
|
||||||
|
return real_soc;
|
||||||
|
} else {
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ScaledSoc::get_soc(void) {
|
||||||
|
if (real_soc_initialized) {
|
||||||
|
if (soc_scaling_active) {
|
||||||
|
return scaled_soc;
|
||||||
|
} else {
|
||||||
|
return real_soc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
}
|
29
Software/src/devboard/utils/soc_scaling.h
Normal file
29
Software/src/devboard/utils/soc_scaling.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef __SOC_SCALING_H__
|
||||||
|
#define __SOC_SCALING_H__
|
||||||
|
|
||||||
|
#include "value_mapping.h"
|
||||||
|
|
||||||
|
class ScaledSoc {
|
||||||
|
private:
|
||||||
|
float min_real_soc, max_real_soc, real_soc, scaled_soc;
|
||||||
|
bool soc_scaling_active;
|
||||||
|
bool real_soc_initialized = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScaledSoc() : min_real_soc(20.0f), max_real_soc(80.0f), soc_scaling_active(true) {}
|
||||||
|
ScaledSoc(float min_soc, float max_soc, bool scaling_active) {
|
||||||
|
min_real_soc = min_soc;
|
||||||
|
max_real_soc = max_soc;
|
||||||
|
soc_scaling_active = scaling_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the real soc
|
||||||
|
float set_real_soc(float soc);
|
||||||
|
// Get scaled soc regardless of setting
|
||||||
|
float get_scaled_soc(void);
|
||||||
|
// Get real soc regardless of setting
|
||||||
|
float get_real_soc(void);
|
||||||
|
// Get scaled or real soc based on the scaling setting
|
||||||
|
float get_soc(void);
|
||||||
|
};
|
||||||
|
#endif
|
29
Software/src/devboard/utils/time_meas.h
Normal file
29
Software/src/devboard/utils/time_meas.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef TIME_MEAS_H_
|
||||||
|
#define TIME_MEAS_H_
|
||||||
|
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
/** Start time measurement in microseconds
|
||||||
|
* Input parameter must be a unique "tag", e.g: START_TIME_MEASUREMENT(wifi);
|
||||||
|
*/
|
||||||
|
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||||
|
#define START_TIME_MEASUREMENT(x) int64_t start_time_##x = esp_timer_get_time()
|
||||||
|
/** End time measurement in microseconds
|
||||||
|
* Input parameters are the unique tag and the name of the ALREADY EXISTING
|
||||||
|
* destination variable (int64_t), e.g: END_TIME_MEASUREMENT(wifi, my_wifi_time_int64_t);
|
||||||
|
*/
|
||||||
|
#define END_TIME_MEASUREMENT(x, y) y = esp_timer_get_time() - start_time_##x
|
||||||
|
/** End time measurement in microseconds, log maximum
|
||||||
|
* Input parameters are the unique tag and the name of the ALREADY EXISTING
|
||||||
|
* destination variable (int64_t), e.g: END_TIME_MEASUREMENT_MAX(wifi, my_wifi_time_int64_t);
|
||||||
|
*
|
||||||
|
* This will log the maximum value in the destination variable.
|
||||||
|
*/
|
||||||
|
#define END_TIME_MEASUREMENT_MAX(x, y) y = MAX(y, esp_timer_get_time() - start_time_##x)
|
||||||
|
#else
|
||||||
|
#define START_TIME_MEASUREMENT(x) ;
|
||||||
|
#define END_TIME_MEASUREMENT(x, y) ;
|
||||||
|
#define END_TIME_MEASUREMENT_MAX(x, y) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
40
Software/src/devboard/utils/types.h
Normal file
40
Software/src/devboard/utils/types.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef _TYPES_H_
|
||||||
|
#define _TYPES_H_
|
||||||
|
|
||||||
|
// enum bms_status_enum { STANDBY = 0, INACTIVE = 1, DARKSTART = 2, ACTIVE = 3, FAULT = 4, UPDATING = 5 };
|
||||||
|
enum battery_chemistry_enum { NCA, NMC, LFP };
|
||||||
|
enum led_color { GREEN, YELLOW, RED, BLUE, RGB };
|
||||||
|
|
||||||
|
// Inverter definitions
|
||||||
|
#define STANDBY 0
|
||||||
|
#define INACTIVE 1
|
||||||
|
#define DARKSTART 2
|
||||||
|
#define ACTIVE 3
|
||||||
|
#define FAULT 4
|
||||||
|
#define UPDATING 5
|
||||||
|
|
||||||
|
#define DISCHARGING 1
|
||||||
|
#define CHARGING 2
|
||||||
|
|
||||||
|
#define INTERVAL_10_MS 10
|
||||||
|
#define INTERVAL_20_MS 20
|
||||||
|
#define INTERVAL_30_MS 30
|
||||||
|
#define INTERVAL_50_MS 50
|
||||||
|
#define INTERVAL_100_MS 100
|
||||||
|
#define INTERVAL_200_MS 200
|
||||||
|
#define INTERVAL_500_MS 500
|
||||||
|
#define INTERVAL_640_MS 640
|
||||||
|
#define INTERVAL_1_S 1000
|
||||||
|
#define INTERVAL_2_S 2000
|
||||||
|
#define INTERVAL_5_S 5000
|
||||||
|
#define INTERVAL_10_S 10000
|
||||||
|
#define INTERVAL_60_S 60000
|
||||||
|
|
||||||
|
#define INTERVAL_10_MS_DELAYED 15
|
||||||
|
#define INTERVAL_20_MS_DELAYED 30
|
||||||
|
#define INTERVAL_30_MS_DELAYED 40
|
||||||
|
#define INTERVAL_100_MS_DELAYED 120
|
||||||
|
|
||||||
|
#define MAX_CAN_FAILURES 500 // Amount of malformed CAN messages to allow before raising a warning
|
||||||
|
|
||||||
|
#endif
|
66
Software/src/devboard/utils/value_mapping.h
Normal file
66
Software/src/devboard/utils/value_mapping.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef __MAPPING_H__
|
||||||
|
#define __MAPPING_H__
|
||||||
|
|
||||||
|
#include "../../include.h"
|
||||||
|
|
||||||
|
/** MIN macro, returns the smallest of two values
|
||||||
|
* Warning: Side effects. MUST be called using values and/or variables only, e.g.:
|
||||||
|
* int x = MIN(temp1, temp2);
|
||||||
|
* int x = MIN(reported_temp, 25);
|
||||||
|
* Do NOT use this macro with operators or function calls, e.g.:
|
||||||
|
* int x = MIN(y++, my_func());
|
||||||
|
*/
|
||||||
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
/** MAX macro, returns the largest of two values
|
||||||
|
* Warning: Side effects. MUST be called using values and/or variables only, e.g.:
|
||||||
|
* int x = MAX(temp1, temp2);
|
||||||
|
* int x = MAX(reported_temp, 10);
|
||||||
|
* Do NOT use this macro with operators or function calls, e.g.:
|
||||||
|
* int x = MAX(y++, my_func());
|
||||||
|
*/
|
||||||
|
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
|
/** CONSTRAIN macro, limits a value to a provided range
|
||||||
|
* Warning: Side effects. MUST be called using values and/or variables only, e.g.:
|
||||||
|
* int x = CONSTRAIN(temp, min_temp, max_temp);
|
||||||
|
* int x = CONSTRAIN(reported_temp, 10, 30);
|
||||||
|
* Do NOT use this macro with operators or function calls, e.g.:
|
||||||
|
* int x = CONSTRAIN(y++, my_min_func(), max_value--);
|
||||||
|
*/
|
||||||
|
#define CONSTRAIN(val, min, max) (MIN(max, MAX(min, val)))
|
||||||
|
|
||||||
|
static inline float map_float(float val, float in_min, float in_max, float out_min, float out_max) {
|
||||||
|
if (val <= in_min) {
|
||||||
|
return out_min;
|
||||||
|
} else if (val > in_max) {
|
||||||
|
return out_max;
|
||||||
|
} else {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t map_uint8(uint8_t val, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max) {
|
||||||
|
if (val <= in_min) {
|
||||||
|
return out_min;
|
||||||
|
} else if (val >= in_max) {
|
||||||
|
return out_max;
|
||||||
|
} else {
|
||||||
|
// Ensure the multiplication does not overflow by promoting to a larger type (uint16_t)
|
||||||
|
// And ensure the division happens last to minimize precision loss
|
||||||
|
return static_cast<uint8_t>((static_cast<uint16_t>(val - in_min) * (out_max - out_min)) / (in_max - in_min) +
|
||||||
|
out_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t map_uint16(uint16_t val, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max) {
|
||||||
|
if (val <= in_min) {
|
||||||
|
return out_min;
|
||||||
|
} else if (val >= in_max) {
|
||||||
|
return out_max;
|
||||||
|
} else {
|
||||||
|
// Promote to uint32_t to prevent overflow during multiplication
|
||||||
|
return static_cast<uint16_t>((static_cast<uint32_t>(val - in_min) * (out_max - out_min)) / (in_max - in_min) +
|
||||||
|
out_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef CELLMONITOR_H
|
#ifndef CELLMONITOR_H
|
||||||
#define CELLMONITOR_H
|
#define CELLMONITOR_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include "../../include.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include "../config.h" // Needed for defines
|
|
||||||
|
|
||||||
extern uint16_t system_cell_max_voltage_mV; //mV, 0-5000, Stores the highest cell millivolt value
|
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_cell_min_voltage_mV; //mV, 0-5000, Stores the minimum cell millivolt value
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "webserver.h"
|
#include "webserver.h"
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
|
#include "../../datalayer/datalayer.h"
|
||||||
#include "../utils/events.h"
|
#include "../utils/events.h"
|
||||||
|
#include "../utils/led_handler.h"
|
||||||
#include "../utils/timer.h"
|
#include "../utils/timer.h"
|
||||||
|
|
||||||
// Create AsyncWebServer object on port 80
|
// Create AsyncWebServer object on port 80
|
||||||
|
@ -22,7 +24,7 @@ enum WifiState {
|
||||||
|
|
||||||
WifiState wifi_state = INIT;
|
WifiState wifi_state = INIT;
|
||||||
|
|
||||||
MyTimer ota_timeout_timer = MyTimer(5000);
|
MyTimer ota_timeout_timer = MyTimer(15000);
|
||||||
bool ota_active = false;
|
bool ota_active = false;
|
||||||
|
|
||||||
unsigned const long WIFI_MONITOR_INTERVAL_TIME = 15000;
|
unsigned const long WIFI_MONITOR_INTERVAL_TIME = 15000;
|
||||||
|
@ -368,6 +370,19 @@ String processor(const String& var) {
|
||||||
|
|
||||||
// Show version number
|
// Show version number
|
||||||
content += "<h4>Software: " + String(version_number) + "</h4>";
|
content += "<h4>Software: " + String(version_number) + "</h4>";
|
||||||
|
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||||
|
// Load information
|
||||||
|
content += "<h4>Main task max load: " + String(datalayer.system.status.main_task_max_us) + " us</h4>";
|
||||||
|
content += "<h4>Main task max load last 10 s: " + String(datalayer.system.status.main_task_10s_max_us) + " us</h4>";
|
||||||
|
content += "<h4>MQTT task max load last 10 s: " + String(datalayer.system.status.time_mqtt_us) + " us</h4>";
|
||||||
|
content += "<h4>Max function load last 10 s:</h4>";
|
||||||
|
content += "<h4>Events function timing: " + String(datalayer.system.status.time_events_us) + " us</h4>";
|
||||||
|
content += "<h4>10ms function timing: " + String(datalayer.system.status.time_10ms_us) + " us</h4>";
|
||||||
|
content += "<h4>5s function timing: " + String(datalayer.system.status.time_5s_us) + " us</h4>";
|
||||||
|
content += "<h4>CAN/serial RX function timing: " + String(datalayer.system.status.time_comm_us) + " us</h4>";
|
||||||
|
content += "<h4>CAN TX function timing: " + String(datalayer.system.status.time_cantx_us) + " us</h4>";
|
||||||
|
content += "<h4>Wifi and OTA function timing: " + String(datalayer.system.status.time_wifi_us) + " us</h4>";
|
||||||
|
#endif
|
||||||
|
|
||||||
wl_status_t status = WiFi.status();
|
wl_status_t status = WiFi.status();
|
||||||
// Display ssid of network connected to and, if connected to the WiFi, its own IP
|
// Display ssid of network connected to and, if connected to the WiFi, its own IP
|
||||||
|
@ -469,18 +484,18 @@ String processor(const String& var) {
|
||||||
|
|
||||||
// Start a new block with a specific background color. Color changes depending on BMS status
|
// Start a new block with a specific background color. Color changes depending on BMS status
|
||||||
content += "<div style='background-color: ";
|
content += "<div style='background-color: ";
|
||||||
switch (LEDcolor) {
|
switch (led_get_color()) {
|
||||||
case GREEN:
|
case led_color::GREEN:
|
||||||
content += "#2D3F2F;";
|
content += "#2D3F2F;";
|
||||||
break;
|
break;
|
||||||
case YELLOW:
|
case led_color::YELLOW:
|
||||||
content += "#F5CC00;";
|
content += "#F5CC00;";
|
||||||
break;
|
break;
|
||||||
case BLUE:
|
case led_color::BLUE:
|
||||||
case TEST_ALL_COLORS:
|
case led_color::RGB:
|
||||||
content += "#2B35AF;"; // Blue in test mode
|
content += "#2B35AF;"; // Blue in test mode
|
||||||
break;
|
break;
|
||||||
case RED:
|
case led_color::RED:
|
||||||
content += "#A70107;";
|
content += "#A70107;";
|
||||||
break;
|
break;
|
||||||
default: // Some new color, make background green
|
default: // Some new color, make background green
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include "../../../USER_SETTINGS.h" // Needed for WiFi ssid and password
|
#include "../../include.h"
|
||||||
#include "../../lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h"
|
#include "../../lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h"
|
||||||
#ifdef MQTT
|
#ifdef MQTT
|
||||||
#include "../../lib/knolleary-pubsubclient/PubSubClient.h"
|
#include "../../lib/knolleary-pubsubclient/PubSubClient.h"
|
||||||
|
@ -11,7 +11,6 @@
|
||||||
#include "../../lib/me-no-dev-AsyncTCP/src/AsyncTCP.h"
|
#include "../../lib/me-no-dev-AsyncTCP/src/AsyncTCP.h"
|
||||||
#include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h"
|
#include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h"
|
||||||
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "../config.h" // Needed for LED defines
|
|
||||||
#ifdef MQTT
|
#ifdef MQTT
|
||||||
#include "../mqtt/mqtt.h"
|
#include "../mqtt/mqtt.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,7 +35,6 @@ extern uint16_t system_cell_min_voltage_mV; //mV, 0-5000, Stores
|
||||||
extern uint16_t system_cellvoltages_mV[MAX_AMOUNT_CELLS]; //Array with all cell voltages in mV
|
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_number_of_cells; //Total number of cell voltages, set by each battery
|
||||||
extern uint8_t system_bms_status; //Enum 0-5
|
extern uint8_t system_bms_status; //Enum 0-5
|
||||||
extern uint8_t LEDcolor; //Enum, 0-10
|
|
||||||
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||||
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false
|
||||||
|
|
||||||
|
|
45
Software/src/include.h
Normal file
45
Software/src/include.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef INCLUDE_H_
|
||||||
|
#define INCLUDE_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Preferences.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../USER_SETTINGS.h"
|
||||||
|
#include "system_settings.h"
|
||||||
|
|
||||||
|
#include "devboard/hal/hal.h"
|
||||||
|
#include "devboard/utils/time_meas.h"
|
||||||
|
#include "devboard/utils/types.h"
|
||||||
|
|
||||||
|
#include "battery/BATTERIES.h"
|
||||||
|
#include "inverter/INVERTERS.h"
|
||||||
|
|
||||||
|
/* - ERROR CHECKS BELOW, DON'T TOUCH - */
|
||||||
|
|
||||||
|
#if !defined(HW_CONFIGURED)
|
||||||
|
#error You must select a HW to run on!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#ifndef BATTERY_SELECTED
|
||||||
|
#error No battery selected! Choose one from the USER_SETTINGS.h file
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KIA_E_GMP_BATTERY
|
||||||
|
#ifndef CAN_FD
|
||||||
|
#error KIA HYUNDAI EGMP BATTERIES CANNOT BE USED WITHOUT CAN FD
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,6 +1,8 @@
|
||||||
#include "BYD-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef BYD_CAN
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "BYD-CAN.h"
|
||||||
|
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
static unsigned long previousMillis2s = 0; // will store last time a 2s CAN Message was send
|
static unsigned long previousMillis2s = 0; // will store last time a 2s CAN Message was send
|
||||||
|
@ -259,3 +261,4 @@ void send_intial_data() {
|
||||||
ESP32Can.CANWriteFrame(&BYD_3D0_2);
|
ESP32Can.CANWriteFrame(&BYD_3D0_2);
|
||||||
ESP32Can.CANWriteFrame(&BYD_3D0_3);
|
ESP32Can.CANWriteFrame(&BYD_3D0_3);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef BYD_CAN_H
|
#ifndef BYD_CAN_H
|
||||||
#define BYD_CAN_H
|
#define BYD_CAN_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
// These parameters need to be mapped for the inverter
|
// These parameters need to be mapped for the inverter
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "../include.h"
|
||||||
|
#ifdef BYD_MODBUS
|
||||||
#include "BYD-MODBUS.h"
|
#include "BYD-MODBUS.h"
|
||||||
|
|
||||||
void update_modbus_registers_byd() {
|
void update_modbus_registers_byd() {
|
||||||
|
@ -151,3 +153,4 @@ void verify_temperature_modbus() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef BYD_MODBUS_H
|
#ifndef BYD_MODBUS_H
|
||||||
#define BYD_MODBUS_H
|
#define BYD_MODBUS_H
|
||||||
#include <Arduino.h>
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
#define MB_RTU_NUM_VALUES 30000
|
#define MB_RTU_NUM_VALUES 30000
|
||||||
#define MAX_POWER 40960 //BYD Modbus specific value
|
#define MAX_POWER 40960 //BYD Modbus specific value
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef INVERTERS_H
|
#ifndef INVERTERS_H
|
||||||
#define INVERTERS_H
|
#define INVERTERS_H
|
||||||
|
|
||||||
|
#include "../../USER_SETTINGS.h"
|
||||||
|
|
||||||
#ifdef BYD_CAN
|
#ifdef BYD_CAN
|
||||||
#include "BYD-CAN.h"
|
#include "BYD-CAN.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "../include.h"
|
||||||
|
#ifdef LUNA2000_MODBUS
|
||||||
#include "LUNA2000-MODBUS.h"
|
#include "LUNA2000-MODBUS.h"
|
||||||
|
|
||||||
void update_modbus_registers_luna2000() {
|
void update_modbus_registers_luna2000() {
|
||||||
|
@ -56,3 +58,4 @@ void handle_update_data_modbus39500() {
|
||||||
static uint16_t i = 9500;
|
static uint16_t i = 9500;
|
||||||
memcpy(&mbPV[i], system_data, sizeof(system_data));
|
memcpy(&mbPV[i], system_data, sizeof(system_data));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef LUNA2000_MODBUS_H
|
#ifndef LUNA2000_MODBUS_H
|
||||||
#define LUNA2000_MODBUS_H
|
#define LUNA2000_MODBUS_H
|
||||||
#include <Arduino.h>
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
#define MB_RTU_NUM_VALUES 30000
|
#define MB_RTU_NUM_VALUES 30000
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "PYLON-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef PYLON_CAN
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "PYLON-CAN.h"
|
||||||
|
|
||||||
#define SEND_0 //If defined, the messages will have ID ending with 0 (useful for some inverters)
|
#define SEND_0 //If defined, the messages will have ID ending with 0 (useful for some inverters)
|
||||||
//#define SEND_1 //If defined, the messages will have ID ending with 1 (useful for some inverters)
|
//#define SEND_1 //If defined, the messages will have ID ending with 1 (useful for some inverters)
|
||||||
|
@ -290,3 +292,4 @@ void send_system_data() { //System equipment information
|
||||||
ESP32Can.CANWriteFrame(&PYLON_4291);
|
ESP32Can.CANWriteFrame(&PYLON_4291);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef PYLON_CAN_H
|
#ifndef PYLON_CAN_H
|
||||||
#define PYLON_CAN_H
|
#define PYLON_CAN_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_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_min_dC; //C+1, -50.0 - 50.0
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
//SERIAL-LINK-TRANSMITTER-INVERTER.cpp
|
#include "../include.h"
|
||||||
|
#ifdef SERIAL_LINK_TRANSMITTER
|
||||||
|
|
||||||
#include "SERIAL-LINK-TRANSMITTER-INVERTER.h"
|
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
|
#include "SERIAL-LINK-TRANSMITTER-INVERTER.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SerialDataLink
|
* SerialDataLink
|
||||||
|
@ -186,3 +187,4 @@ void printSendingValues() {
|
||||||
|
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
#define SERIAL_LINK_TRANSMITTER_INVERTER_H
|
#define SERIAL_LINK_TRANSMITTER_INVERTER_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
// These parameters need to be mapped for the inverter
|
// 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_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_SOH_pptt; //SOH%, 0-100.00 (0-10000)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "SMA-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef SMA_CAN
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "SMA-CAN.h"
|
||||||
|
|
||||||
/* TODO: Map error bits in 0x158 */
|
/* TODO: Map error bits in 0x158 */
|
||||||
|
|
||||||
|
@ -258,3 +260,4 @@ void send_can_sma() {
|
||||||
ESP32Can.CANWriteFrame(&SMA_158);
|
ESP32Can.CANWriteFrame(&SMA_158);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef SMA_CAN_H
|
#ifndef SMA_CAN_H
|
||||||
#define SMA_CAN_H
|
#define SMA_CAN_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_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_min_dC; //C+1, -50.0 - 50.0
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "SMA-TRIPOWER-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef SMA_TRIPOWER_CAN
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "SMA-TRIPOWER-CAN.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
- Figure out the manufacturer info needed in send_tripower_init() CAN messages
|
- Figure out the manufacturer info needed in send_tripower_init() CAN messages
|
||||||
|
@ -369,3 +371,4 @@ void send_tripower_init() {
|
||||||
ESP32Can.CANWriteFrame(&SMA_017); // Battery Manufacturer
|
ESP32Can.CANWriteFrame(&SMA_017); // Battery Manufacturer
|
||||||
ESP32Can.CANWriteFrame(&SMA_018); // Battery Name
|
ESP32Can.CANWriteFrame(&SMA_018); // Battery Name
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef SMA_CAN_TRIPOWER_H
|
#ifndef SMA_CAN_TRIPOWER_H
|
||||||
#define SMA_CAN_TRIPOWER_H
|
#define SMA_CAN_TRIPOWER_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_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_min_dC; //C+1, -50.0 - 50.0
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "SOFAR-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef SOFAR_CAN
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/CAN_config.h"
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
#include "SOFAR-CAN.h"
|
||||||
|
|
||||||
/* This implementation of the SOFAR can protocol is halfway done. What's missing is implementing the inverter replies, all the CAN messages are listed, but the can sending is missing. */
|
/* This implementation of the SOFAR can protocol is halfway done. What's missing is implementing the inverter replies, all the CAN messages are listed, but the can sending is missing. */
|
||||||
|
|
||||||
|
@ -336,3 +338,4 @@ void send_can_sofar() {
|
||||||
ESP32Can.CANWriteFrame(&SOFAR_35A);
|
ESP32Can.CANWriteFrame(&SOFAR_35A);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#ifndef SOFAR_CAN_H
|
#ifndef SOFAR_CAN_H
|
||||||
#define SOFAR_CAN_H
|
#define SOFAR_CAN_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
// These parameters need to be mapped for the inverter
|
// These parameters need to be mapped for the inverter
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_remaining_capacity_Wh; //Wh, 0-500000Wh
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "SOLAX-CAN.h"
|
#include "../include.h"
|
||||||
|
#ifdef SOLAX_CAN
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
|
#include "SOLAX-CAN.h"
|
||||||
|
|
||||||
/* Do not change code below unless you are sure what you are doing */
|
/* Do not change code below unless you are sure what you are doing */
|
||||||
static uint16_t max_charge_rate_amp = 0;
|
static uint16_t max_charge_rate_amp = 0;
|
||||||
|
@ -307,3 +309,4 @@ void receive_can_solax(CAN_frame_t rx_frame) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#ifndef SOLAX_CAN_H
|
#ifndef SOLAX_CAN_H
|
||||||
#define SOLAX_CAN_H
|
#define SOLAX_CAN_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../../USER_SETTINGS.h"
|
#include "../include.h"
|
||||||
#include "../devboard/config.h" // Needed for all defines
|
|
||||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
|
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
|
||||||
|
|
||||||
|
#define INVERTER_SELECTED
|
||||||
|
|
||||||
extern ACAN2515 can;
|
extern ACAN2515 can;
|
||||||
|
|
||||||
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
extern uint32_t system_capacity_Wh; //Wh, 0-500000Wh
|
||||||
|
|
43
Software/src/system_settings.h
Normal file
43
Software/src/system_settings.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef SYSTEM_SETTINGS_H_
|
||||||
|
#define SYSTEM_SETTINGS_H_
|
||||||
|
/** TASKS
|
||||||
|
*
|
||||||
|
* Parameter: TASK_CORE_PRIO
|
||||||
|
* Description:
|
||||||
|
* Defines the priority of core functionality (CAN, Modbus, etc)
|
||||||
|
*
|
||||||
|
* Parameter: TASK_CONNECTIVITY_PRIO
|
||||||
|
* Description:
|
||||||
|
* Defines the priority of various wireless functionality (TCP, MQTT, etc)
|
||||||
|
*/
|
||||||
|
#define TASK_CORE_PRIO 4
|
||||||
|
#define TASK_WIFI_PRIO 3
|
||||||
|
#define TASK_MODBUS_PRIO 8
|
||||||
|
|
||||||
|
/** MAX AMOUNT OF CELLS
|
||||||
|
*
|
||||||
|
* Parameter: MAX_AMOUNT_CELLS
|
||||||
|
* Description:
|
||||||
|
* Basically the length of the array used to hold individual cell voltages
|
||||||
|
*/
|
||||||
|
#define MAX_AMOUNT_CELLS 192
|
||||||
|
|
||||||
|
/** LED
|
||||||
|
*
|
||||||
|
* Parameter: LED_MODE_DEFAULT
|
||||||
|
* Description:
|
||||||
|
* The default LED mode. Available modes:
|
||||||
|
* CLASSIC - slow up/down ramp
|
||||||
|
* FLOW - slow ramp up or down depending on flow of energy
|
||||||
|
* HEARTBEAT - Heartbeat-like LED pattern that reacts to the system state with color and BPM
|
||||||
|
*
|
||||||
|
* Parameter: LED_PERIOD_MS
|
||||||
|
* Description:
|
||||||
|
* The period of whatever LED mode is active. If CLASSIC, then a ramp up and ramp down will finish in
|
||||||
|
* LED_PERIOD_MS milliseconds
|
||||||
|
*/
|
||||||
|
#define LED_MODE_DEFAULT FLOW
|
||||||
|
#define LED_PERIOD_MS 3000
|
||||||
|
#define LED_EXECUTION_FREQUENCY 50
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../Software/src/devboard/config.h"
|
|
||||||
|
|
||||||
MySerial Serial;
|
MySerial Serial;
|
||||||
|
|
||||||
unsigned long testlib_millis = 0;
|
unsigned long testlib_millis = 0;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "microtest.h"
|
#include "microtest.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// The test library must be included first!
|
// The test library must be included first!
|
||||||
#include "../test_lib.h"
|
#include "../test_lib.h"
|
||||||
|
|
||||||
#include "../../Software/src/devboard/config.h"
|
#include "../../Software/src/include.h"
|
||||||
#include "../../Software/src/devboard/utils/timer.cpp"
|
#include "../../Software/src/devboard/utils/timer.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue