mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Convert .ino to .cpp file
This commit is contained in:
parent
aba193ca85
commit
1cc4a021c2
1 changed files with 247 additions and 256 deletions
|
@ -1,5 +1,4 @@
|
||||||
/* Do not change any code below this line unless you are sure what you are doing */
|
#include <Arduino.h>
|
||||||
/* Only change battery specific settings in "USER_SETTINGS.h" */
|
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "USER_SETTINGS.h"
|
#include "USER_SETTINGS.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
|
@ -51,130 +50,20 @@ TaskHandle_t connectivity_loop_task;
|
||||||
TaskHandle_t logging_loop_task;
|
TaskHandle_t logging_loop_task;
|
||||||
TaskHandle_t mqtt_loop_task;
|
TaskHandle_t mqtt_loop_task;
|
||||||
|
|
||||||
/* Charger settings (Optional, when using generator charging) */
|
|
||||||
volatile float CHARGER_SET_HV = 384; // Reasonably appropriate 4.0v per cell charging of a 96s pack
|
|
||||||
volatile float CHARGER_MAX_HV = 420; // Max permissible output (VDC) of charger
|
|
||||||
volatile float CHARGER_MIN_HV = 200; // Min permissible output (VDC) of charger
|
|
||||||
volatile float CHARGER_MAX_POWER = 3300; // Max power capable of charger, as a ceiling for validating config
|
|
||||||
volatile float CHARGER_MAX_A = 11.5; // Max current output (amps) of charger
|
|
||||||
volatile float CHARGER_END_A = 1.0; // Current at which charging is considered complete
|
|
||||||
|
|
||||||
Logging logging;
|
Logging logging;
|
||||||
|
|
||||||
// Initialization
|
static std::list<Transmitter*> transmitters;
|
||||||
void setup() {
|
|
||||||
init_hal();
|
|
||||||
|
|
||||||
init_serial();
|
void register_transmitter(Transmitter* transmitter) {
|
||||||
|
transmitters.push_back(transmitter);
|
||||||
// We print this after setting up serial, so that is also printed if configured to do so
|
DEBUG_PRINTF("transmitter registered, total: %d\n", transmitters.size());
|
||||||
logging.printf("Battery emulator %s build " __DATE__ " " __TIME__ "\n", version_number);
|
|
||||||
|
|
||||||
init_events();
|
|
||||||
|
|
||||||
init_stored_settings();
|
|
||||||
|
|
||||||
if (wifi_enabled) {
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&connectivity_loop, "connectivity_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
|
||||||
&connectivity_loop_task, esp32hal->WIFICORE());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!led_init()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalayer.system.info.CAN_SD_logging_active || datalayer.system.info.SD_logging_active) {
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
|
||||||
&logging_loop_task, esp32hal->WIFICORE());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_contactors()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_precharge_control()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_charger();
|
|
||||||
|
|
||||||
if (!setup_inverter()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setup_battery();
|
|
||||||
setup_can_shunt();
|
|
||||||
|
|
||||||
// Init CAN only after any CAN receivers have had a chance to register.
|
|
||||||
if (!init_CAN()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_rs485()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_equipment_stop_button()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOOT button at runtime is used as an input for various things
|
|
||||||
pinMode(0, INPUT_PULLUP);
|
|
||||||
|
|
||||||
check_reset_reason();
|
|
||||||
|
|
||||||
// Initialize Task Watchdog for subscribed tasks
|
|
||||||
esp_task_wdt_config_t wdt_config = {// 5s should be enough for the connectivity tasks (which are all contending
|
|
||||||
// for the same core) to yield to each other and reset their watchdogs.
|
|
||||||
.timeout_ms = INTERVAL_5_S,
|
|
||||||
// We don't benefit from idle task watchdogs, our critical loops have their
|
|
||||||
// own. The idle watchdogs can cause nuisance reboots under heavy load.
|
|
||||||
.idle_core_mask = 0,
|
|
||||||
// Panic (and reboot) on timeout
|
|
||||||
.trigger_panic = true};
|
|
||||||
#ifdef CONFIG_ESP_TASK_WDT
|
|
||||||
// ESP-IDF will have already initialized it, so reconfigure.
|
|
||||||
// Arduino and PlatformIO have different watchdog defaults, so we reconfigure
|
|
||||||
// for consistency.
|
|
||||||
esp_task_wdt_reconfigure(&wdt_config);
|
|
||||||
#else
|
|
||||||
// Otherwise initialize it for the first time.
|
|
||||||
esp_task_wdt_init(&wdt_config);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Start tasks
|
|
||||||
|
|
||||||
if (mqtt_enabled) {
|
|
||||||
if (!init_mqtt()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
|
||||||
esp32hal->WIFICORE());
|
|
||||||
}
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
|
|
||||||
esp32hal->CORE_FUNCTION_CORE());
|
|
||||||
|
|
||||||
DEBUG_PRINTF("setup() complete\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop empty, all functionality runs in tasks
|
// Initialization functions
|
||||||
void loop() {}
|
void init_serial() {
|
||||||
|
// Init Serial monitor
|
||||||
void logging_loop(void*) {
|
Serial.begin(115200);
|
||||||
|
while (!Serial) {}
|
||||||
init_logging_buffers();
|
|
||||||
init_sdcard();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (datalayer.system.info.SD_logging_active) {
|
|
||||||
write_log_to_sdcard();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalayer.system.info.CAN_SD_logging_active) {
|
|
||||||
write_can_frame_to_sdcard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectivity_loop(void*) {
|
void connectivity_loop(void*) {
|
||||||
|
@ -205,146 +94,22 @@ void connectivity_loop(void*) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mqtt_loop(void*) {
|
void logging_loop(void*) {
|
||||||
esp_task_wdt_add(NULL); // Register this task with WDT
|
|
||||||
|
init_logging_buffers();
|
||||||
|
init_sdcard();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
START_TIME_MEASUREMENT(mqtt);
|
if (datalayer.system.info.SD_logging_active) {
|
||||||
mqtt_loop();
|
write_log_to_sdcard();
|
||||||
END_TIME_MEASUREMENT_MAX(mqtt, datalayer.system.status.mqtt_task_10s_max_us);
|
}
|
||||||
esp_task_wdt_reset(); // Reset watchdog
|
|
||||||
delay(1);
|
if (datalayer.system.info.CAN_SD_logging_active) {
|
||||||
|
write_can_frame_to_sdcard();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::list<Transmitter*> transmitters;
|
|
||||||
|
|
||||||
void register_transmitter(Transmitter* transmitter) {
|
|
||||||
transmitters.push_back(transmitter);
|
|
||||||
DEBUG_PRINTF("transmitter registered, total: %d\n", transmitters.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void core_loop(void*) {
|
|
||||||
esp_task_wdt_add(NULL); // Register this task with WDT
|
|
||||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
|
||||||
const TickType_t xFrequency = pdMS_TO_TICKS(1); // Convert 1ms to ticks
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
|
|
||||||
START_TIME_MEASUREMENT(all);
|
|
||||||
START_TIME_MEASUREMENT(comm);
|
|
||||||
|
|
||||||
monitor_equipment_stop_button();
|
|
||||||
|
|
||||||
// Input, Runs as fast as possible
|
|
||||||
receive_can(); // Receive CAN messages
|
|
||||||
receive_rs485(); // Process serial2 RS485 interface
|
|
||||||
|
|
||||||
END_TIME_MEASUREMENT_MAX(comm, datalayer.system.status.time_comm_us);
|
|
||||||
|
|
||||||
if (webserver_enabled) {
|
|
||||||
START_TIME_MEASUREMENT(ota);
|
|
||||||
ElegantOTA.loop();
|
|
||||||
END_TIME_MEASUREMENT_MAX(ota, datalayer.system.status.time_ota_us);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process
|
|
||||||
currentMillis = millis();
|
|
||||||
if (currentMillis - previousMillis10ms >= INTERVAL_10_MS) {
|
|
||||||
if ((currentMillis - previousMillis10ms >= INTERVAL_10_MS_DELAYED) &&
|
|
||||||
(milliseconds(currentMillis) > esp32hal->BOOTUP_TIME())) {
|
|
||||||
set_event(EVENT_TASK_OVERRUN, (currentMillis - previousMillis10ms));
|
|
||||||
}
|
|
||||||
previousMillis10ms = currentMillis;
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
START_TIME_MEASUREMENT(10ms);
|
|
||||||
}
|
|
||||||
led_exe();
|
|
||||||
handle_contactors(); // Take care of startup precharge/contactor closing
|
|
||||||
#ifdef PRECHARGE_CONTROL
|
|
||||||
handle_precharge_control(currentMillis);
|
|
||||||
#endif // PRECHARGE_CONTROL
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
END_TIME_MEASUREMENT_MAX(10ms, datalayer.system.status.time_10ms_us);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentMillis - previousMillisUpdateVal >= INTERVAL_1_S) {
|
|
||||||
previousMillisUpdateVal = currentMillis; // Order matters on the update_loop!
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
START_TIME_MEASUREMENT(values);
|
|
||||||
}
|
|
||||||
update_pause_state(); // Check if we are OK to send CAN or need to pause
|
|
||||||
|
|
||||||
// Fetch battery values
|
|
||||||
if (battery) {
|
|
||||||
battery->update_values();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (battery2) {
|
|
||||||
battery2->update_values();
|
|
||||||
check_interconnect_available();
|
|
||||||
}
|
|
||||||
update_calculated_values();
|
|
||||||
update_machineryprotection(); // Check safeties
|
|
||||||
|
|
||||||
// Update values heading towards inverter
|
|
||||||
if (inverter) {
|
|
||||||
inverter->update_values();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
END_TIME_MEASUREMENT_MAX(values, datalayer.system.status.time_values_us);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
START_TIME_MEASUREMENT(cantx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let all transmitter objects send their messages
|
|
||||||
for (auto& transmitter : transmitters) {
|
|
||||||
transmitter->transmit(currentMillis);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalayer.system.info.performance_measurement_active) {
|
|
||||||
END_TIME_MEASUREMENT_MAX(cantx, datalayer.system.status.time_cantx_us);
|
|
||||||
END_TIME_MEASUREMENT_MAX(all, datalayer.system.status.core_task_10s_max_us);
|
|
||||||
if (datalayer.system.status.core_task_10s_max_us > datalayer.system.status.core_task_max_us) {
|
|
||||||
// Update worst case total time
|
|
||||||
datalayer.system.status.core_task_max_us = datalayer.system.status.core_task_10s_max_us;
|
|
||||||
// Record snapshots of task times
|
|
||||||
datalayer.system.status.time_snap_comm_us = datalayer.system.status.time_comm_us;
|
|
||||||
datalayer.system.status.time_snap_10ms_us = datalayer.system.status.time_10ms_us;
|
|
||||||
datalayer.system.status.time_snap_values_us = datalayer.system.status.time_values_us;
|
|
||||||
datalayer.system.status.time_snap_cantx_us = datalayer.system.status.time_cantx_us;
|
|
||||||
datalayer.system.status.time_snap_ota_us = datalayer.system.status.time_ota_us;
|
|
||||||
}
|
|
||||||
|
|
||||||
datalayer.system.status.core_task_max_us =
|
|
||||||
MAX(datalayer.system.status.core_task_10s_max_us, datalayer.system.status.core_task_max_us);
|
|
||||||
if (core_task_timer_10s.elapsed()) {
|
|
||||||
datalayer.system.status.time_ota_us = 0;
|
|
||||||
datalayer.system.status.time_comm_us = 0;
|
|
||||||
datalayer.system.status.time_10ms_us = 0;
|
|
||||||
datalayer.system.status.time_values_us = 0;
|
|
||||||
datalayer.system.status.time_cantx_us = 0;
|
|
||||||
datalayer.system.status.core_task_10s_max_us = 0;
|
|
||||||
datalayer.system.status.wifi_task_10s_max_us = 0;
|
|
||||||
datalayer.system.status.mqtt_task_10s_max_us = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
esp_task_wdt_reset(); // Reset watchdog to prevent reset
|
|
||||||
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization functions
|
|
||||||
void init_serial() {
|
|
||||||
// Init Serial monitor
|
|
||||||
Serial.begin(115200);
|
|
||||||
while (!Serial) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_interconnect_available() {
|
void check_interconnect_available() {
|
||||||
if (datalayer.battery.status.voltage_dV == 0 || datalayer.battery2.status.voltage_dV == 0) {
|
if (datalayer.battery.status.voltage_dV == 0 || datalayer.battery2.status.voltage_dV == 0) {
|
||||||
return; // Both voltage values need to be available to start check
|
return; // Both voltage values need to be available to start check
|
||||||
|
@ -589,3 +354,229 @@ void check_reset_reason() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void core_loop(void*) {
|
||||||
|
esp_task_wdt_add(NULL); // Register this task with WDT
|
||||||
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
|
const TickType_t xFrequency = pdMS_TO_TICKS(1); // Convert 1ms to ticks
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
START_TIME_MEASUREMENT(all);
|
||||||
|
START_TIME_MEASUREMENT(comm);
|
||||||
|
|
||||||
|
monitor_equipment_stop_button();
|
||||||
|
|
||||||
|
// Input, Runs as fast as possible
|
||||||
|
receive_can(); // Receive CAN messages
|
||||||
|
receive_rs485(); // Process serial2 RS485 interface
|
||||||
|
|
||||||
|
END_TIME_MEASUREMENT_MAX(comm, datalayer.system.status.time_comm_us);
|
||||||
|
|
||||||
|
if (webserver_enabled) {
|
||||||
|
START_TIME_MEASUREMENT(ota);
|
||||||
|
ElegantOTA.loop();
|
||||||
|
END_TIME_MEASUREMENT_MAX(ota, datalayer.system.status.time_ota_us);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process
|
||||||
|
currentMillis = millis();
|
||||||
|
if (currentMillis - previousMillis10ms >= INTERVAL_10_MS) {
|
||||||
|
if ((currentMillis - previousMillis10ms >= INTERVAL_10_MS_DELAYED) &&
|
||||||
|
(milliseconds(currentMillis) > esp32hal->BOOTUP_TIME())) {
|
||||||
|
set_event(EVENT_TASK_OVERRUN, (currentMillis - previousMillis10ms));
|
||||||
|
}
|
||||||
|
previousMillis10ms = currentMillis;
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
START_TIME_MEASUREMENT(10ms);
|
||||||
|
}
|
||||||
|
led_exe();
|
||||||
|
handle_contactors(); // Take care of startup precharge/contactor closing
|
||||||
|
#ifdef PRECHARGE_CONTROL
|
||||||
|
handle_precharge_control(currentMillis);
|
||||||
|
#endif // PRECHARGE_CONTROL
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
END_TIME_MEASUREMENT_MAX(10ms, datalayer.system.status.time_10ms_us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMillis - previousMillisUpdateVal >= INTERVAL_1_S) {
|
||||||
|
previousMillisUpdateVal = currentMillis; // Order matters on the update_loop!
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
START_TIME_MEASUREMENT(values);
|
||||||
|
}
|
||||||
|
update_pause_state(); // Check if we are OK to send CAN or need to pause
|
||||||
|
|
||||||
|
// Fetch battery values
|
||||||
|
if (battery) {
|
||||||
|
battery->update_values();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery2) {
|
||||||
|
battery2->update_values();
|
||||||
|
check_interconnect_available();
|
||||||
|
}
|
||||||
|
update_calculated_values();
|
||||||
|
update_machineryprotection(); // Check safeties
|
||||||
|
|
||||||
|
// Update values heading towards inverter
|
||||||
|
if (inverter) {
|
||||||
|
inverter->update_values();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
END_TIME_MEASUREMENT_MAX(values, datalayer.system.status.time_values_us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
START_TIME_MEASUREMENT(cantx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let all transmitter objects send their messages
|
||||||
|
for (auto& transmitter : transmitters) {
|
||||||
|
transmitter->transmit(currentMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datalayer.system.info.performance_measurement_active) {
|
||||||
|
END_TIME_MEASUREMENT_MAX(cantx, datalayer.system.status.time_cantx_us);
|
||||||
|
END_TIME_MEASUREMENT_MAX(all, datalayer.system.status.core_task_10s_max_us);
|
||||||
|
if (datalayer.system.status.core_task_10s_max_us > datalayer.system.status.core_task_max_us) {
|
||||||
|
// Update worst case total time
|
||||||
|
datalayer.system.status.core_task_max_us = datalayer.system.status.core_task_10s_max_us;
|
||||||
|
// Record snapshots of task times
|
||||||
|
datalayer.system.status.time_snap_comm_us = datalayer.system.status.time_comm_us;
|
||||||
|
datalayer.system.status.time_snap_10ms_us = datalayer.system.status.time_10ms_us;
|
||||||
|
datalayer.system.status.time_snap_values_us = datalayer.system.status.time_values_us;
|
||||||
|
datalayer.system.status.time_snap_cantx_us = datalayer.system.status.time_cantx_us;
|
||||||
|
datalayer.system.status.time_snap_ota_us = datalayer.system.status.time_ota_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
datalayer.system.status.core_task_max_us =
|
||||||
|
MAX(datalayer.system.status.core_task_10s_max_us, datalayer.system.status.core_task_max_us);
|
||||||
|
if (core_task_timer_10s.elapsed()) {
|
||||||
|
datalayer.system.status.time_ota_us = 0;
|
||||||
|
datalayer.system.status.time_comm_us = 0;
|
||||||
|
datalayer.system.status.time_10ms_us = 0;
|
||||||
|
datalayer.system.status.time_values_us = 0;
|
||||||
|
datalayer.system.status.time_cantx_us = 0;
|
||||||
|
datalayer.system.status.core_task_10s_max_us = 0;
|
||||||
|
datalayer.system.status.wifi_task_10s_max_us = 0;
|
||||||
|
datalayer.system.status.mqtt_task_10s_max_us = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esp_task_wdt_reset(); // Reset watchdog to prevent reset
|
||||||
|
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
void setup() {
|
||||||
|
init_hal();
|
||||||
|
|
||||||
|
init_serial();
|
||||||
|
|
||||||
|
// We print this after setting up serial, so that is also printed if configured to do so
|
||||||
|
logging.printf("Battery emulator %s build " __DATE__ " " __TIME__ "\n", version_number);
|
||||||
|
|
||||||
|
init_events();
|
||||||
|
|
||||||
|
init_stored_settings();
|
||||||
|
|
||||||
|
if (wifi_enabled) {
|
||||||
|
xTaskCreatePinnedToCore((TaskFunction_t)&connectivity_loop, "connectivity_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
||||||
|
&connectivity_loop_task, esp32hal->WIFICORE());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!led_init()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datalayer.system.info.CAN_SD_logging_active || datalayer.system.info.SD_logging_active) {
|
||||||
|
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
||||||
|
&logging_loop_task, esp32hal->WIFICORE());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_contactors()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_precharge_control()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_charger();
|
||||||
|
|
||||||
|
if (!setup_inverter()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setup_battery();
|
||||||
|
setup_can_shunt();
|
||||||
|
|
||||||
|
// Init CAN only after any CAN receivers have had a chance to register.
|
||||||
|
if (!init_CAN()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_rs485()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!init_equipment_stop_button()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOOT button at runtime is used as an input for various things
|
||||||
|
pinMode(0, INPUT_PULLUP);
|
||||||
|
|
||||||
|
check_reset_reason();
|
||||||
|
|
||||||
|
// Initialize Task Watchdog for subscribed tasks
|
||||||
|
esp_task_wdt_config_t wdt_config = {// 5s should be enough for the connectivity tasks (which are all contending
|
||||||
|
// for the same core) to yield to each other and reset their watchdogs.
|
||||||
|
.timeout_ms = INTERVAL_5_S,
|
||||||
|
// We don't benefit from idle task watchdogs, our critical loops have their
|
||||||
|
// own. The idle watchdogs can cause nuisance reboots under heavy load.
|
||||||
|
.idle_core_mask = 0,
|
||||||
|
// Panic (and reboot) on timeout
|
||||||
|
.trigger_panic = true};
|
||||||
|
#ifdef CONFIG_ESP_TASK_WDT
|
||||||
|
// ESP-IDF will have already initialized it, so reconfigure.
|
||||||
|
// Arduino and PlatformIO have different watchdog defaults, so we reconfigure
|
||||||
|
// for consistency.
|
||||||
|
esp_task_wdt_reconfigure(&wdt_config);
|
||||||
|
#else
|
||||||
|
// Otherwise initialize it for the first time.
|
||||||
|
esp_task_wdt_init(&wdt_config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start tasks
|
||||||
|
|
||||||
|
if (mqtt_enabled) {
|
||||||
|
if (!init_mqtt()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
||||||
|
esp32hal->WIFICORE());
|
||||||
|
}
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
|
||||||
|
esp32hal->CORE_FUNCTION_CORE());
|
||||||
|
|
||||||
|
DEBUG_PRINTF("setup() complete\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop empty, all functionality runs in tasks
|
||||||
|
void loop() {}
|
||||||
|
|
||||||
|
void mqtt_loop(void*) {
|
||||||
|
esp_task_wdt_add(NULL); // Register this task with WDT
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
START_TIME_MEASUREMENT(mqtt);
|
||||||
|
mqtt_loop();
|
||||||
|
END_TIME_MEASUREMENT_MAX(mqtt, datalayer.system.status.mqtt_task_10s_max_us);
|
||||||
|
esp_task_wdt_reset(); // Reset watchdog
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue