mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 19:42:08 +02:00
Battery and inverter can bus can be selected in the UI
This commit is contained in:
parent
c63ae6eb23
commit
e3de4e546c
29 changed files with 224 additions and 65 deletions
|
@ -72,10 +72,6 @@ Logging logging;
|
||||||
void setup() {
|
void setup() {
|
||||||
init_hal();
|
init_hal();
|
||||||
|
|
||||||
if (!led_init()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_serial();
|
init_serial();
|
||||||
|
|
||||||
// We print this after setting up serial, such that is also printed to serial with DEBUG_VIA_USB set.
|
// We print this after setting up serial, such that is also printed to serial with DEBUG_VIA_USB set.
|
||||||
|
@ -87,18 +83,18 @@ void setup() {
|
||||||
|
|
||||||
#ifdef WIFI
|
#ifdef WIFI
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&connectivity_loop, "connectivity_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
xTaskCreatePinnedToCore((TaskFunction_t)&connectivity_loop, "connectivity_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
||||||
&connectivity_loop_task, WIFI_CORE);
|
&connectivity_loop_task, esp32hal->WIFICORE());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!led_init()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(LOG_CAN_TO_SD) || defined(LOG_TO_SD)
|
#if defined(LOG_CAN_TO_SD) || defined(LOG_TO_SD)
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
xTaskCreatePinnedToCore((TaskFunction_t)&logging_loop, "logging_loop", 4096, NULL, TASK_CONNECTIVITY_PRIO,
|
||||||
&logging_loop_task, WIFI_CORE);
|
&logging_loop_task, esp32hal->WIFICORE());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!init_CAN()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!init_contactors()) {
|
if (!init_contactors()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +110,12 @@ void setup() {
|
||||||
}
|
}
|
||||||
setup_battery();
|
setup_battery();
|
||||||
|
|
||||||
|
setup_can_shunt();
|
||||||
|
|
||||||
|
if (!init_CAN()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!init_rs485()) {
|
if (!init_rs485()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +124,6 @@ void setup() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_can_shunt();
|
|
||||||
// BOOT button at runtime is used as an input for various things
|
// BOOT button at runtime is used as an input for various things
|
||||||
pinMode(0, INPUT_PULLUP);
|
pinMode(0, INPUT_PULLUP);
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ void setup() {
|
||||||
// Initialize Task Watchdog for subscribed tasks
|
// Initialize Task Watchdog for subscribed tasks
|
||||||
esp_task_wdt_config_t wdt_config = {
|
esp_task_wdt_config_t wdt_config = {
|
||||||
.timeout_ms = INTERVAL_5_S, // If task hangs for longer than this, reboot
|
.timeout_ms = INTERVAL_5_S, // If task hangs for longer than this, reboot
|
||||||
.idle_core_mask = (1 << esp32hal->CORE_FUNCTION_CORE()) | (1 << esp32hal->WIFI_CORE()), // Watch both cores
|
.idle_core_mask = (1 << esp32hal->CORE_FUNCTION_CORE()) | (1 << esp32hal->WIFICORE()), // Watch both cores
|
||||||
.trigger_panic = true // Enable panic reset on timeout
|
.trigger_panic = true // Enable panic reset on timeout
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ void setup() {
|
||||||
init_mqtt();
|
init_mqtt();
|
||||||
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
||||||
esp32hal->WIFI_CORE());
|
esp32hal->WIFICORE());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
|
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "RS485Battery.h"
|
#include "RS485Battery.h"
|
||||||
|
|
||||||
#if !defined(COMMON_IMAGE) && !defined(SELECTED_BATTERY_CLASS)
|
#if !defined(COMMON_IMAGE) && !defined(SELECTED_BATTERY_CLASS)
|
||||||
#error No battery selected! Choose one from the USER_SETTINGS.h file
|
#error No battery selected! Choose one from the USER_SETTINGS.h file or build COMMON_IMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Battery* battery = nullptr;
|
Battery* battery = nullptr;
|
||||||
|
@ -21,7 +21,7 @@ std::vector<BatteryType> supported_battery_types() {
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const char* name_for_chemistry(battery_chemistry_enum chem) {
|
const char* name_for_chemistry(battery_chemistry_enum chem) {
|
||||||
switch (chem) {
|
switch (chem) {
|
||||||
case battery_chemistry_enum::LFP:
|
case battery_chemistry_enum::LFP:
|
||||||
return "LFP";
|
return "LFP";
|
||||||
|
@ -34,7 +34,26 @@ extern const char* name_for_chemistry(battery_chemistry_enum chem) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const char* name_for_battery_type(BatteryType type) {
|
const char* name_for_comm_interface(comm_interface comm) {
|
||||||
|
switch (comm) {
|
||||||
|
case comm_interface::Modbus:
|
||||||
|
return "Modbus";
|
||||||
|
case comm_interface::RS485:
|
||||||
|
return "RS485";
|
||||||
|
case comm_interface::CanNative:
|
||||||
|
return "Native CAN";
|
||||||
|
case comm_interface::CanFdNative:
|
||||||
|
return "Native CAN FD";
|
||||||
|
case comm_interface::CanAddonMcp2515:
|
||||||
|
return "CAN MCP 2515 add-on";
|
||||||
|
case comm_interface::CanFdAddonMcp2518:
|
||||||
|
return "CAN FD MCP 2518 add-on";
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name_for_battery_type(BatteryType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BatteryType::None:
|
case BatteryType::None:
|
||||||
return "None";
|
return "None";
|
||||||
|
@ -119,7 +138,7 @@ const battery_chemistry_enum battery_chemistry_default = battery_chemistry_enum:
|
||||||
const battery_chemistry_enum battery_chemistry_default = battery_chemistry_enum::NMC;
|
const battery_chemistry_enum battery_chemistry_default = battery_chemistry_enum::NMC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern battery_chemistry_enum user_selected_battery_chemistry;
|
battery_chemistry_enum user_selected_battery_chemistry = battery_chemistry_default;
|
||||||
|
|
||||||
#ifdef COMMON_IMAGE
|
#ifdef COMMON_IMAGE
|
||||||
#ifdef SELECTED_BATTERY_CLASS
|
#ifdef SELECTED_BATTERY_CLASS
|
||||||
|
|
|
@ -188,12 +188,12 @@ void BmwPhevBattery::wake_battery_via_canbus() {
|
||||||
// Followed by a Recessive interval of at least ~3 µs (min) and at most ~10 µs (max)
|
// Followed by a Recessive interval of at least ~3 µs (min) and at most ~10 µs (max)
|
||||||
// Then a second dominant pulse of similar timing.
|
// Then a second dominant pulse of similar timing.
|
||||||
|
|
||||||
CAN_cfg.speed = CAN_SPEED_100KBPS; //Slow down canbus to achieve wakeup timings
|
slow_down_can();
|
||||||
ESP32Can.CANInit(); // ReInit native CAN module at new speed
|
|
||||||
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
|
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
|
||||||
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
|
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
|
||||||
CAN_cfg.speed = CAN_SPEED_500KBPS; //Resume fullspeed
|
|
||||||
ESP32Can.CANInit(); // ReInit native CAN module at new speed
|
resume_full_speed();
|
||||||
|
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
logging.println("Sent magic wakeup packet to SME at 100kbps...");
|
logging.println("Sent magic wakeup packet to SME at 100kbps...");
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define BATTERY_H
|
#define BATTERY_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "src/devboard/utils/types.h"
|
||||||
#include "src/devboard/webserver/BatteryHtmlRenderer.h"
|
#include "src/devboard/webserver/BatteryHtmlRenderer.h"
|
||||||
|
|
||||||
enum class BatteryType {
|
enum class BatteryType {
|
||||||
|
@ -48,6 +49,7 @@ enum class BatteryType {
|
||||||
extern std::vector<BatteryType> supported_battery_types();
|
extern std::vector<BatteryType> supported_battery_types();
|
||||||
extern const char* name_for_battery_type(BatteryType type);
|
extern const char* name_for_battery_type(BatteryType type);
|
||||||
extern const char* name_for_chemistry(battery_chemistry_enum chem);
|
extern const char* name_for_chemistry(battery_chemistry_enum chem);
|
||||||
|
extern const char* name_for_comm_interface(comm_interface comm);
|
||||||
|
|
||||||
extern BatteryType user_selected_battery_type;
|
extern BatteryType user_selected_battery_type;
|
||||||
extern bool user_selected_second_battery;
|
extern bool user_selected_second_battery;
|
||||||
|
|
|
@ -75,7 +75,7 @@ void ChademoBattery::process_vehicle_charging_session(CAN_frame rx_frame) {
|
||||||
|
|
||||||
vehicle_can_initialized = true;
|
vehicle_can_initialized = true;
|
||||||
|
|
||||||
vehicle_permission = digitalRead(CHADEMO_PIN_4);
|
vehicle_permission = digitalRead(pin4);
|
||||||
|
|
||||||
x102_chg_session.ControlProtocolNumberEV = rx_frame.data.u8[0];
|
x102_chg_session.ControlProtocolNumberEV = rx_frame.data.u8[0];
|
||||||
|
|
||||||
|
@ -936,7 +936,7 @@ void ChademoBattery::handle_chademo_sequence() {
|
||||||
|
|
||||||
void ChademoBattery::setup(void) { // Performs one time setup at startup
|
void ChademoBattery::setup(void) { // Performs one time setup at startup
|
||||||
|
|
||||||
if (!esp32hal->alloc_pins("CHADEMO", pin2, pin10, pin4, pin7, pin_lock)) {
|
if (!esp32hal->alloc_pins(Name, pin2, pin10, pin4, pin7, pin_lock)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,11 @@ CanBattery::CanBattery() {
|
||||||
register_transmitter(this);
|
register_transmitter(this);
|
||||||
register_can_receiver(this, can_interface);
|
register_can_receiver(this, can_interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanBattery::slow_down_can() {
|
||||||
|
::slow_down_can(can_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanBattery::resume_full_speed() {
|
||||||
|
::resume_full_speed(can_interface);
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "src/communication/Transmitter.h"
|
#include "src/communication/Transmitter.h"
|
||||||
#include "src/communication/can/CanReceiver.h"
|
#include "src/communication/can/CanReceiver.h"
|
||||||
|
#include "src/communication/can/comm_can.h"
|
||||||
#include "src/devboard/utils/types.h"
|
#include "src/devboard/utils/types.h"
|
||||||
|
|
||||||
// Abstract base class for batteries using the CAN bus
|
// Abstract base class for batteries using the CAN bus
|
||||||
|
@ -29,6 +30,9 @@ class CanBattery : public Battery, Transmitter, CanReceiver {
|
||||||
register_transmitter(this);
|
register_transmitter(this);
|
||||||
register_can_receiver(this, can_interface);
|
register_can_receiver(this, can_interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void slow_down_can();
|
||||||
|
void resume_full_speed();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../devboard/utils/events.h"
|
#include "../devboard/utils/events.h"
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
|
||||||
|
|
||||||
const unsigned char crc8_table[256] =
|
const unsigned char crc8_table[256] =
|
||||||
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
{ // CRC8_SAE_J1850_ZER0 formula,0x1D Poly,initial value 0x3F,Final XOR value varies
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
#define KIA_E_GMP_BATTERY_H
|
#define KIA_E_GMP_BATTERY_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "../include.h"
|
#include "../include.h"
|
||||||
#include "../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
|
||||||
#include "CanBattery.h"
|
#include "CanBattery.h"
|
||||||
|
|
||||||
extern ACAN2517FD canfd;
|
|
||||||
|
|
||||||
#define ESTIMATE_SOC_FROM_CELLVOLTAGE
|
#define ESTIMATE_SOC_FROM_CELLVOLTAGE
|
||||||
|
|
||||||
#ifdef KIA_E_GMP_BATTERY
|
#ifdef KIA_E_GMP_BATTERY
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "comm_can.h"
|
#include "comm_can.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "../../include.h"
|
#include "../../include.h"
|
||||||
|
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||||
#include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
#include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
|
||||||
#include "../../lib/pierremolinaro-acan2515/ACAN2515.h"
|
#include "../../lib/pierremolinaro-acan2515/ACAN2515.h"
|
||||||
#include "src/devboard/sdcard/sdcard.h"
|
#include "src/devboard/sdcard/sdcard.h"
|
||||||
|
@ -295,7 +297,7 @@ void receive_frame_canfd_addon() { // This section checks if we have a complete
|
||||||
rx_frame.ID = MCP2518frame.id;
|
rx_frame.ID = MCP2518frame.id;
|
||||||
rx_frame.ext_ID = MCP2518frame.ext;
|
rx_frame.ext_ID = MCP2518frame.ext;
|
||||||
rx_frame.DLC = MCP2518frame.len;
|
rx_frame.DLC = MCP2518frame.len;
|
||||||
memcpy(rx_frame.data.u8, MCP2518frame.data, MIN(rx_frame.DLC, 64));
|
memcpy(rx_frame.data.u8, MCP2518frame.data, std::min(rx_frame.DLC, (uint8_t)64));
|
||||||
//message incoming, pass it on to the handler
|
//message incoming, pass it on to the handler
|
||||||
map_can_frame_to_variable(&rx_frame, CANFD_ADDON_MCP2518);
|
map_can_frame_to_variable(&rx_frame, CANFD_ADDON_MCP2518);
|
||||||
map_can_frame_to_variable(&rx_frame, CANFD_NATIVE);
|
map_can_frame_to_variable(&rx_frame, CANFD_NATIVE);
|
||||||
|
@ -416,3 +418,17 @@ void restart_can() {
|
||||||
canfd->begin(*settings2517, [] { can2515->isr(); });
|
canfd->begin(*settings2517, [] { can2515->isr(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void slow_down_can(CAN_Interface interface) {
|
||||||
|
if (interface == CAN_Interface::CAN_NATIVE) {
|
||||||
|
CAN_cfg.speed = CAN_SPEED_100KBPS; //Slow down canbus to achieve wakeup timings
|
||||||
|
ESP32Can.CANInit(); // ReInit native CAN module at new speed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resume_full_speed(CAN_Interface interface) {
|
||||||
|
if (interface == CAN_Interface::CAN_NATIVE) {
|
||||||
|
CAN_cfg.speed = CAN_SPEED_500KBPS; //Resume fullspeed
|
||||||
|
ESP32Can.CANInit(); // ReInit native CAN module at new speed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
#ifndef _COMM_CAN_H_
|
#ifndef _COMM_CAN_H_
|
||||||
#define _COMM_CAN_H_
|
#define _COMM_CAN_H_
|
||||||
|
|
||||||
#include "../../include.h"
|
#include "../../devboard/utils/types.h"
|
||||||
|
|
||||||
#include "../../datalayer/datalayer.h"
|
|
||||||
#include "../../devboard/utils/events.h"
|
|
||||||
#include "../../devboard/utils/value_mapping.h"
|
|
||||||
#include "../../lib/ESP32Async-ESPAsyncWebServer/src/ESPAsyncWebServer.h"
|
|
||||||
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
|
||||||
|
|
||||||
extern bool use_canfd_as_can;
|
extern bool use_canfd_as_can;
|
||||||
|
|
||||||
|
@ -79,4 +73,7 @@ void stop_can();
|
||||||
// Restart CAN communication for all interfaces
|
// Restart CAN communication for all interfaces
|
||||||
void restart_can();
|
void restart_can();
|
||||||
|
|
||||||
|
void slow_down_can(CAN_Interface interface);
|
||||||
|
void resume_full_speed(CAN_Interface interface);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,7 @@ bool init_equipment_stop_button();
|
||||||
*/
|
*/
|
||||||
void monitor_equipment_stop_button();
|
void monitor_equipment_stop_button();
|
||||||
|
|
||||||
enum class STOP_BUTTON_BEHAVIOR { NOT_CONNECTED = 0, LATCHING_SWITCH = 1, MOMENTARY_SWITCH = 2 };
|
enum class STOP_BUTTON_BEHAVIOR { NOT_CONNECTED = 0, LATCHING_SWITCH = 1, MOMENTARY_SWITCH = 2, Highest };
|
||||||
|
|
||||||
extern STOP_BUTTON_BEHAVIOR equipment_stop_behavior;
|
extern STOP_BUTTON_BEHAVIOR equipment_stop_behavior;
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,28 @@ void init_stored_settings() {
|
||||||
user_selected_inverter_protocol = (InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None);
|
user_selected_inverter_protocol = (InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None);
|
||||||
user_selected_charger_type = (ChargerType)settings.getUInt("CHGTYPE", (int)ChargerType::None);
|
user_selected_charger_type = (ChargerType)settings.getUInt("CHGTYPE", (int)ChargerType::None);
|
||||||
|
|
||||||
|
auto readIf = [](const char* settingName) {
|
||||||
|
auto batt1If = (comm_interface)settings.getUInt(settingName, (int)comm_interface::CanNative);
|
||||||
|
switch (batt1If) {
|
||||||
|
case comm_interface::CanNative:
|
||||||
|
return CAN_Interface::CAN_NATIVE;
|
||||||
|
case comm_interface::CanFdNative:
|
||||||
|
return CAN_Interface::CANFD_NATIVE;
|
||||||
|
case comm_interface::CanAddonMcp2515:
|
||||||
|
return CAN_Interface::CAN_ADDON_MCP2515;
|
||||||
|
case comm_interface::CanFdAddonMcp2518:
|
||||||
|
return CAN_Interface::CANFD_ADDON_MCP2518;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CAN_Interface::CAN_NATIVE;
|
||||||
|
};
|
||||||
|
|
||||||
|
can_config.battery = readIf("BATTCOMM");
|
||||||
|
can_config.battery_double = readIf("BATT2COMM");
|
||||||
|
can_config.inverter = readIf("INVCOMM");
|
||||||
|
can_config.charger = readIf("CHGCOMM");
|
||||||
|
can_config.shunt = readIf("SHUNTCOMM");
|
||||||
|
|
||||||
equipment_stop_behavior = (STOP_BUTTON_BEHAVIOR)settings.getUInt("EQSTOP", (int)STOP_BUTTON_BEHAVIOR::NOT_CONNECTED);
|
equipment_stop_behavior = (STOP_BUTTON_BEHAVIOR)settings.getUInt("EQSTOP", (int)STOP_BUTTON_BEHAVIOR::NOT_CONNECTED);
|
||||||
user_selected_second_battery = settings.getBool("DBLBTR", false);
|
user_selected_second_battery = settings.getBool("DBLBTR", false);
|
||||||
contactor_control_enabled = settings.getBool("CNTCTRL", false);
|
contactor_control_enabled = settings.getBool("CNTCTRL", false);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "hw_lilygo.h"
|
#include "hw_lilygo.h"
|
||||||
#include "hw_stark.h"
|
#include "hw_stark.h"
|
||||||
|
|
||||||
extern Esp32Hal* esp32hal;
|
Esp32Hal* esp32hal = nullptr;
|
||||||
|
|
||||||
void init_hal() {
|
void init_hal() {
|
||||||
#if defined(HW_LILYGO)
|
#if defined(HW_LILYGO)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <soc/gpio_num.h>
|
#include <soc/gpio_num.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "../../../src/devboard/utils/events.h"
|
||||||
#include "../../../src/devboard/utils/types.h"
|
#include "../../../src/devboard/utils/types.h"
|
||||||
|
|
||||||
// Hardware Abstraction Layer base class.
|
// Hardware Abstraction Layer base class.
|
||||||
|
@ -19,7 +21,7 @@ class Esp32Hal {
|
||||||
// Core assignment
|
// Core assignment
|
||||||
virtual int CORE_FUNCTION_CORE() { return 1; }
|
virtual int CORE_FUNCTION_CORE() { return 1; }
|
||||||
virtual int MODBUS_CORE() { return 0; }
|
virtual int MODBUS_CORE() { return 0; }
|
||||||
virtual int WIFI_CORE() { return 0; }
|
virtual int WIFICORE() { return 0; }
|
||||||
|
|
||||||
template <typename... Pins>
|
template <typename... Pins>
|
||||||
bool alloc_pins(const char* name, Pins... pins) {
|
bool alloc_pins(const char* name, Pins... pins) {
|
||||||
|
@ -27,6 +29,7 @@ class Esp32Hal {
|
||||||
|
|
||||||
for (gpio_num_t pin : requested_pins) {
|
for (gpio_num_t pin : requested_pins) {
|
||||||
if (pin < 0) {
|
if (pin < 0) {
|
||||||
|
set_event(EVENT_GPIO_NOT_DEFINED, (int)pin);
|
||||||
// Event: {name} attempted to allocate pin that wasn't defined for the selected HW.
|
// Event: {name} attempted to allocate pin that wasn't defined for the selected HW.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +38,7 @@ class Esp32Hal {
|
||||||
if (it != allocated_pins.end()) {
|
if (it != allocated_pins.end()) {
|
||||||
// Event: GPIO conflict for pin {pin} between name and it->second.
|
// Event: GPIO conflict for pin {pin} between name and it->second.
|
||||||
//std::cerr << "Pin " << pin << " already allocated to \"" << it->second << "\".\n";
|
//std::cerr << "Pin " << pin << " already allocated to \"" << it->second << "\".\n";
|
||||||
|
set_event(EVENT_GPIO_CONFLICT, (int)pin);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,12 +140,18 @@ class Esp32Hal {
|
||||||
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_NC; }
|
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_NC; }
|
||||||
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_NC; }
|
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_NC; }
|
||||||
|
|
||||||
|
// Returns the available comm interfaces on this HW
|
||||||
|
virtual std::vector<comm_interface> available_interfaces() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<gpio_num_t, std::string> allocated_pins;
|
std::unordered_map<gpio_num_t, std::string> allocated_pins;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Esp32Hal* esp32hal;
|
extern Esp32Hal* esp32hal;
|
||||||
|
|
||||||
|
// Needed for AsyncTCPSock library.
|
||||||
|
#define WIFI_CORE (esp32hal->WIFICORE())
|
||||||
|
|
||||||
void init_hal();
|
void init_hal();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,6 +72,10 @@ class ThreeLBHal : public Esp32Hal {
|
||||||
// Battery wake up pins
|
// Battery wake up pins
|
||||||
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
||||||
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
||||||
|
|
||||||
|
std::vector<comm_interface> available_interfaces() {
|
||||||
|
return {comm_interface::Modbus, comm_interface::RS485, comm_interface::CanNative};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -66,6 +66,14 @@ class DevKitHal : public Esp32Hal {
|
||||||
// Battery wake up pins
|
// Battery wake up pins
|
||||||
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
||||||
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
||||||
|
|
||||||
|
std::vector<comm_interface> available_interfaces() {
|
||||||
|
return {
|
||||||
|
comm_interface::Modbus,
|
||||||
|
comm_interface::RS485,
|
||||||
|
comm_interface::CanNative,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __HW_DEVKIT_H__
|
#endif // __HW_DEVKIT_H__
|
||||||
|
|
|
@ -76,6 +76,11 @@ class LilyGoHal : public Esp32Hal {
|
||||||
// Battery wake up pins
|
// Battery wake up pins
|
||||||
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
||||||
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
||||||
|
|
||||||
|
std::vector<comm_interface> available_interfaces() {
|
||||||
|
return {comm_interface::Modbus, comm_interface::RS485, comm_interface::CanNative, comm_interface::CanAddonMcp2515,
|
||||||
|
comm_interface::CanFdAddonMcp2518};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HalClass LilyGoHal
|
#define HalClass LilyGoHal
|
||||||
|
|
|
@ -69,6 +69,10 @@ class StarkHal : public Esp32Hal {
|
||||||
// Battery wake up pins
|
// Battery wake up pins
|
||||||
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
virtual gpio_num_t WUP_PIN1() { return GPIO_NUM_25; }
|
||||||
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
virtual gpio_num_t WUP_PIN2() { return GPIO_NUM_32; }
|
||||||
|
|
||||||
|
std::vector<comm_interface> available_interfaces() {
|
||||||
|
return {comm_interface::Modbus, comm_interface::RS485, comm_interface::CanNative, comm_interface::CanFdNative};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __HW_STARK_H__
|
#endif // __HW_STARK_H__
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#include "safety.h"
|
||||||
#include "../../datalayer/datalayer.h"
|
#include "../../datalayer/datalayer.h"
|
||||||
|
#include "../../include.h"
|
||||||
#include "../utils/events.h"
|
#include "../utils/events.h"
|
||||||
|
|
||||||
static uint16_t cell_deviation_mV = 0;
|
static uint16_t cell_deviation_mV = 0;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef SAFETY_H
|
#ifndef SAFETY_H
|
||||||
#define SAFETY_H
|
#define SAFETY_H
|
||||||
#include <Arduino.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
|
||||||
|
|
||||||
#define MAX_CAN_FAILURES 50
|
#define MAX_CAN_FAILURES 50
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "sdcard.h"
|
#include "sdcard.h"
|
||||||
|
#include "../../include.h"
|
||||||
#include "freertos/ringbuf.h"
|
#include "freertos/ringbuf.h"
|
||||||
|
|
||||||
File can_log_file;
|
File can_log_file;
|
||||||
|
@ -183,13 +184,11 @@ void init_logging_buffers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init_sdcard() {
|
bool init_sdcard() {
|
||||||
|
|
||||||
auto miso_pin = esp32hal->SD_MISO_PIN();
|
auto miso_pin = esp32hal->SD_MISO_PIN();
|
||||||
auto mosi_pin = esp32hal->SD_MOSI_PIN();
|
auto mosi_pin = esp32hal->SD_MOSI_PIN();
|
||||||
auto miso_pin = esp32hal->SD_MISO_PIN();
|
|
||||||
auto sclk_pin = esp32hal->SD_SCLK_PIN();
|
auto sclk_pin = esp32hal->SD_SCLK_PIN();
|
||||||
|
|
||||||
if (!esp32hal->alloc_pins("SD Card", miso_pin, mosi_pin)) {
|
if (!esp32hal->alloc_pins("SD Card", miso_pin, mosi_pin, sclk_pin)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +200,7 @@ bool init_sdcard() {
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
logging.println("SD Card initialization failed!");
|
logging.println("SD Card initialization failed!");
|
||||||
#endif // DEBUG_LOG
|
#endif // DEBUG_LOG
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_event(EVENT_SD_INIT_FAILED);
|
clear_event(EVENT_SD_INIT_FAILED);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "../../datalayer/datalayer.h"
|
#include "../../datalayer/datalayer.h"
|
||||||
|
#include "../../include.h"
|
||||||
|
|
||||||
#include "../../../USER_SETTINGS.h"
|
#include "../../../USER_SETTINGS.h"
|
||||||
|
|
||||||
|
@ -132,6 +133,9 @@ void init_events(void) {
|
||||||
events.entries[EVENT_PERIODIC_BMS_RESET_AT_INIT_SUCCESS].level = EVENT_LEVEL_INFO;
|
events.entries[EVENT_PERIODIC_BMS_RESET_AT_INIT_SUCCESS].level = EVENT_LEVEL_INFO;
|
||||||
events.entries[EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED].level = EVENT_LEVEL_WARNING;
|
events.entries[EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED].level = EVENT_LEVEL_WARNING;
|
||||||
events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
|
events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
|
||||||
|
events.entries[EVENT_GPIO_CONFLICT].level = EVENT_LEVEL_ERROR;
|
||||||
|
events.entries[EVENT_GPIO_NOT_DEFINED].level = EVENT_LEVEL_ERROR;
|
||||||
|
events.entries[EVENT_BATTERY_TEMP_DEVIATION_HIGH].level = EVENT_LEVEL_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_event(EVENTS_ENUM_TYPE event, uint8_t data) {
|
void set_event(EVENTS_ENUM_TYPE event, uint8_t data) {
|
||||||
|
@ -373,6 +377,10 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
|
||||||
case EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED:
|
case EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED:
|
||||||
return "Failed to syncronise with the NTP Server. BMS will reset every 24 hours from when the emulator was "
|
return "Failed to syncronise with the NTP Server. BMS will reset every 24 hours from when the emulator was "
|
||||||
"powered on";
|
"powered on";
|
||||||
|
case EVENT_GPIO_CONFLICT:
|
||||||
|
return "There is a GPIO pin conflict between SW components.";
|
||||||
|
case EVENT_GPIO_NOT_DEFINED:
|
||||||
|
return "SW module requires GPIO that is not defined for this hardware.";
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef __EVENTS_H__
|
#ifndef __EVENTS_H__
|
||||||
#define __EVENTS_H__
|
#define __EVENTS_H__
|
||||||
#ifndef UNIT_TEST
|
|
||||||
#include "../../include.h"
|
#include <stdint.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GENERATE_ENUM(ENUM) ENUM,
|
#define GENERATE_ENUM(ENUM) ENUM,
|
||||||
#define GENERATE_STRING(STRING) #STRING,
|
#define GENERATE_STRING(STRING) #STRING,
|
||||||
|
@ -107,6 +106,8 @@
|
||||||
XX(EVENT_PERIODIC_BMS_RESET_AT_INIT_SUCCESS) \
|
XX(EVENT_PERIODIC_BMS_RESET_AT_INIT_SUCCESS) \
|
||||||
XX(EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED) \
|
XX(EVENT_PERIODIC_BMS_RESET_AT_INIT_FAILED) \
|
||||||
XX(EVENT_BATTERY_TEMP_DEVIATION_HIGH) \
|
XX(EVENT_BATTERY_TEMP_DEVIATION_HIGH) \
|
||||||
|
XX(EVENT_GPIO_NOT_DEFINED) \
|
||||||
|
XX(EVENT_GPIO_CONFLICT) \
|
||||||
XX(EVENT_NOF_EVENTS)
|
XX(EVENT_NOF_EVENTS)
|
||||||
|
|
||||||
typedef enum { EVENTS_ENUM_TYPE(GENERATE_ENUM) } EVENTS_ENUM_TYPE;
|
typedef enum { EVENTS_ENUM_TYPE(GENERATE_ENUM) } EVENTS_ENUM_TYPE;
|
||||||
|
|
|
@ -9,7 +9,18 @@ using duration = std::chrono::duration<unsigned long, std::ratio<1, 1000>>;
|
||||||
|
|
||||||
enum bms_status_enum { STANDBY = 0, INACTIVE = 1, DARKSTART = 2, ACTIVE = 3, FAULT = 4, UPDATING = 5 };
|
enum bms_status_enum { STANDBY = 0, INACTIVE = 1, DARKSTART = 2, ACTIVE = 3, FAULT = 4, UPDATING = 5 };
|
||||||
enum real_bms_status_enum { BMS_DISCONNECTED = 0, BMS_STANDBY = 1, BMS_ACTIVE = 2, BMS_FAULT = 3 };
|
enum real_bms_status_enum { BMS_DISCONNECTED = 0, BMS_STANDBY = 1, BMS_ACTIVE = 2, BMS_FAULT = 3 };
|
||||||
enum battery_chemistry_enum { NCA, NMC, LFP };
|
enum battery_chemistry_enum { NCA = 1, NMC = 2, LFP = 3, Highest };
|
||||||
|
|
||||||
|
enum class comm_interface {
|
||||||
|
Modbus = 1,
|
||||||
|
RS485 = 2,
|
||||||
|
CanNative = 3,
|
||||||
|
CanFdNative = 4,
|
||||||
|
CanAddonMcp2515 = 5,
|
||||||
|
CanFdAddonMcp2518 = 6,
|
||||||
|
Highest
|
||||||
|
};
|
||||||
|
|
||||||
enum led_color { GREEN, YELLOW, RED, BLUE };
|
enum led_color { GREEN, YELLOW, RED, BLUE };
|
||||||
enum led_mode_enum { CLASSIC, FLOW, HEARTBEAT };
|
enum led_mode_enum { CLASSIC, FLOW, HEARTBEAT };
|
||||||
enum PrechargeState {
|
enum PrechargeState {
|
||||||
|
|
|
@ -27,7 +27,8 @@ std::vector<EnumType> enum_values() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename EnumType, typename Func>
|
template <typename EnumType, typename Func>
|
||||||
std::vector<std::pair<String, EnumType>> enum_values_and_names(Func name_for_type) {
|
std::vector<std::pair<String, EnumType>> enum_values_and_names(Func name_for_type,
|
||||||
|
const EnumType* noneValue = nullptr) {
|
||||||
auto values = enum_values<EnumType>();
|
auto values = enum_values<EnumType>();
|
||||||
|
|
||||||
std::vector<std::pair<String, EnumType>> pairs;
|
std::vector<std::pair<String, EnumType>> pairs;
|
||||||
|
@ -41,15 +42,31 @@ std::vector<std::pair<String, EnumType>> enum_values_and_names(Func name_for_typ
|
||||||
|
|
||||||
std::sort(pairs.begin(), pairs.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
std::sort(pairs.begin(), pairs.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||||
|
|
||||||
pairs.insert(pairs.begin(), std::pair(name_for_type(EnumType::None), EnumType::None));
|
if (noneValue) {
|
||||||
|
pairs.insert(pairs.begin(), std::pair(name_for_type(*noneValue), *noneValue));
|
||||||
|
}
|
||||||
|
|
||||||
return pairs;
|
return pairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TEnum, typename Func>
|
||||||
|
String options_for_enum_with_none(TEnum selected, Func name_for_type, TEnum noneValue) {
|
||||||
|
String options;
|
||||||
|
TEnum none = noneValue;
|
||||||
|
auto values = enum_values_and_names<TEnum>(name_for_type, &none);
|
||||||
|
for (const auto& [name, type] : values) {
|
||||||
|
options +=
|
||||||
|
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? " selected" : "") + ">");
|
||||||
|
options += name;
|
||||||
|
options += "</option>";
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TEnum, typename Func>
|
template <typename TEnum, typename Func>
|
||||||
String options_for_enum(TEnum selected, Func name_for_type) {
|
String options_for_enum(TEnum selected, Func name_for_type) {
|
||||||
String options;
|
String options;
|
||||||
auto values = enum_values_and_names<TEnum>(name_for_type);
|
auto values = enum_values_and_names<TEnum>(name_for_type, nullptr);
|
||||||
for (const auto& [name, type] : values) {
|
for (const auto& [name, type] : values) {
|
||||||
options +=
|
options +=
|
||||||
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? " selected" : "") + ">");
|
("<option value=\"" + String(static_cast<int>(type)) + "\"" + (selected == type ? " selected" : "") + ">");
|
||||||
|
@ -106,7 +123,7 @@ String settings_processor(const String& var) {
|
||||||
"onclick='editPassword()'>Edit</button></h4>";
|
"onclick='editPassword()'>Edit</button></h4>";
|
||||||
|
|
||||||
#ifdef COMMON_IMAGE
|
#ifdef COMMON_IMAGE
|
||||||
BatteryEmulatorSettingsStore settings;
|
BatteryEmulatorSettingsStore settings(true);
|
||||||
|
|
||||||
// It's important that we read/write settings directly to settings store instead of the run-time values
|
// It's important that we read/write settings directly to settings store instead of the run-time values
|
||||||
// since the run-time values may have direct effect on operation.
|
// since the run-time values may have direct effect on operation.
|
||||||
|
@ -118,29 +135,40 @@ String settings_processor(const String& var) {
|
||||||
"align-items: center;'>";
|
"align-items: center;'>";
|
||||||
|
|
||||||
content += "<label>Battery: </label><select style='max-width: 250px;' name='battery'>";
|
content += "<label>Battery: </label><select style='max-width: 250px;' name='battery'>";
|
||||||
content +=
|
content += options_for_enum_with_none((BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None),
|
||||||
options_for_enum((BatteryType)settings.getUInt("BATTTYPE", (int)BatteryType::None), name_for_battery_type);
|
name_for_battery_type, BatteryType::None);
|
||||||
content += "</select>";
|
content += "</select>";
|
||||||
|
|
||||||
content += "<label>Battery chemistry: </label><select style='max-width: 250px;' name='battery'>";
|
content += "<label>Battery comm I/F: </label><select style='max-width: 250px;' name='BATTCOMM'>";
|
||||||
|
content += options_for_enum((comm_interface)settings.getUInt("BATTCOMM", (int)comm_interface::CanNative),
|
||||||
|
name_for_comm_interface);
|
||||||
|
content += "</select>";
|
||||||
|
|
||||||
|
content += "<label>Battery chemistry: </label><select style='max-width: 250px;' name='BATTCHEM'>";
|
||||||
content += options_for_enum((battery_chemistry_enum)settings.getUInt("BATTCHEM", (int)battery_chemistry_enum::NCA),
|
content += options_for_enum((battery_chemistry_enum)settings.getUInt("BATTCHEM", (int)battery_chemistry_enum::NCA),
|
||||||
name_for_chemistry);
|
name_for_chemistry);
|
||||||
content += "</select>";
|
content += "</select>";
|
||||||
|
|
||||||
content += "<label>Inverter protocol: </label><select style='max-width: 250px;' name='inverter'>";
|
content += "<label>Inverter protocol: </label><select style='max-width: 250px;' name='inverter'>";
|
||||||
content += options_for_enum((InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None),
|
content +=
|
||||||
name_for_inverter_type);
|
options_for_enum_with_none((InverterProtocolType)settings.getUInt("INVTYPE", (int)InverterProtocolType::None),
|
||||||
|
name_for_inverter_type, InverterProtocolType::None);
|
||||||
|
content += "</select>";
|
||||||
|
|
||||||
|
content += "<label>Inverter comm I/F: </label><select style='max-width: 250px;' name='INVCOMM'>";
|
||||||
|
content += options_for_enum((comm_interface)settings.getUInt("INVCOMM", (int)comm_interface::CanNative),
|
||||||
|
name_for_comm_interface);
|
||||||
content += "</select>";
|
content += "</select>";
|
||||||
|
|
||||||
content += "<label>Charger: </label><select style='max-width: 250px;' name='charger'>";
|
content += "<label>Charger: </label><select style='max-width: 250px;' name='charger'>";
|
||||||
content +=
|
content += options_for_enum_with_none((ChargerType)settings.getUInt("CHGTYPE", (int)ChargerType::None),
|
||||||
options_for_enum((ChargerType)settings.getUInt("CHGTYPE", (int)ChargerType::None), name_for_charger_type);
|
name_for_charger_type, ChargerType::None);
|
||||||
content += "</select>";
|
content += "</select>";
|
||||||
|
|
||||||
content += "<label>Equipment stop button: </label><select style='max-width: 250px;' name='EQSTOP'>";
|
content += "<label>Equipment stop button: </label><select style='max-width: 250px;' name='EQSTOP'>";
|
||||||
content +=
|
content += options_for_enum_with_none(
|
||||||
options_for_enum((STOP_BUTTON_BEHAVIOR)settings.getUInt("EQSTOP", (int)STOP_BUTTON_BEHAVIOR::NOT_CONNECTED),
|
(STOP_BUTTON_BEHAVIOR)settings.getUInt("EQSTOP", (int)STOP_BUTTON_BEHAVIOR::NOT_CONNECTED),
|
||||||
name_for_button_type);
|
name_for_button_type, STOP_BUTTON_BEHAVIOR::NOT_CONNECTED);
|
||||||
content += "</select>";
|
content += "</select>";
|
||||||
|
|
||||||
// TODO: Generalize settings: define settings in one place and use the definitions to render
|
// TODO: Generalize settings: define settings in one place and use the definitions to render
|
||||||
|
|
|
@ -417,12 +417,30 @@ void init_webserver() {
|
||||||
} else if (p->name() == "battery") {
|
} else if (p->name() == "battery") {
|
||||||
auto type = static_cast<BatteryType>(atoi(p->value().c_str()));
|
auto type = static_cast<BatteryType>(atoi(p->value().c_str()));
|
||||||
settings.saveUInt("BATTTYPE", (int)type);
|
settings.saveUInt("BATTTYPE", (int)type);
|
||||||
|
} else if (p->name() == "BATTCHEM") {
|
||||||
|
auto type = static_cast<battery_chemistry_enum>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("BATTCHEM", (int)type);
|
||||||
} else if (p->name() == "charger") {
|
} else if (p->name() == "charger") {
|
||||||
auto type = static_cast<ChargerType>(atoi(p->value().c_str()));
|
auto type = static_cast<ChargerType>(atoi(p->value().c_str()));
|
||||||
settings.saveUInt("CHGTYPE", (int)type);
|
settings.saveUInt("CHGTYPE", (int)type);
|
||||||
} else if (p->name() == "EQSTOP") {
|
} else if (p->name() == "EQSTOP") {
|
||||||
auto type = static_cast<STOP_BUTTON_BEHAVIOR>(atoi(p->value().c_str()));
|
auto type = static_cast<STOP_BUTTON_BEHAVIOR>(atoi(p->value().c_str()));
|
||||||
settings.saveUInt("EQSTOP", (int)type);
|
settings.saveUInt("EQSTOP", (int)type);
|
||||||
|
} else if (p->name() == "BATTCOMM") {
|
||||||
|
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("BATTCOMM", (int)type);
|
||||||
|
} else if (p->name() == "BATT2COMM") {
|
||||||
|
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("BATT2COMM", (int)type);
|
||||||
|
} else if (p->name() == "INVCOMM") {
|
||||||
|
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("INVCOMM", (int)type);
|
||||||
|
} else if (p->name() == "CHGCOMM") {
|
||||||
|
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("CHGCOMM", (int)type);
|
||||||
|
} else if (p->name() == "SHUNTCOMM") {
|
||||||
|
auto type = static_cast<comm_interface>(atoi(p->value().c_str()));
|
||||||
|
settings.saveUInt("SHUNTCOMM", (int)type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& boolSetting : boolSettings) {
|
for (auto& boolSetting : boolSettings) {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
/* - ERROR CHECKS BELOW, DON'T TOUCH - */
|
/* - ERROR CHECKS BELOW, DON'T TOUCH - */
|
||||||
|
|
||||||
#if !defined(HW_LILYGO) || !defined(HW_STARK) || !defined(HW_3LB) || !defined(HW_DEVKIT)
|
#if !defined(HW_LILYGO) && !defined(HW_STARK) && !defined(HW_3LB) && !defined(HW_DEVKIT)
|
||||||
#error You must select a target hardware in the USER_SETTINGS.h file!
|
#error You must select a target hardware in the USER_SETTINGS.h file!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
class SmaBydHInverter : public SmaInverterBase {
|
class SmaBydHInverter : public SmaInverterBase {
|
||||||
public:
|
public:
|
||||||
SmaBydHInverter();
|
|
||||||
|
|
||||||
const char* name() override { return Name; }
|
const char* name() override { return Name; }
|
||||||
void update_values();
|
void update_values();
|
||||||
void transmit_can(unsigned long currentMillis);
|
void transmit_can(unsigned long currentMillis);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue