Refactoring: Scalability and performance (#252)

Refactoring v5.7 step 1
This commit is contained in:
Cabooman 2024-04-14 14:41:01 +02:00 committed by GitHub
parent 5a5cfc433b
commit ffa7a54f20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 926 additions and 286 deletions

6
.gitignore vendored
View file

@ -14,4 +14,8 @@
.clang_complete .clang_complete
.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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -0,0 +1,4 @@
#include "datalayer.h"
#include "../include.h"
DataLayer datalayer;

View 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

View file

@ -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

View 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

View 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

View file

@ -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)

View file

@ -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

View file

@ -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

View 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);
}

View 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

View 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;
}
}

View 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

View 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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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;

View file

@ -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;

View file

@ -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"