Merge from main

This commit is contained in:
Jaakko Haakana 2025-07-02 19:09:01 +03:00
commit 2602316369
76 changed files with 128 additions and 107 deletions

View file

@ -109,9 +109,9 @@ void setup() {
return;
}
setup_battery();
setup_can_shunt();
// Init CAN only after any CAN receivers have had a chance to register.
if (!init_CAN()) {
return;
}
@ -155,6 +155,8 @@ void setup() {
set_event(EVENT_PERIODIC_BMS_RESET_AT_INIT_SUCCESS, 0);
}
#endif
DEBUG_PRINTF("setup() complete\n");
}
// Loop empty, all functionality runs in tasks
@ -223,6 +225,7 @@ 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*) {

View file

@ -11,6 +11,7 @@
Battery* battery = nullptr;
Battery* battery2 = nullptr;
#ifdef COMMON_IMAGE
std::vector<BatteryType> supported_battery_types() {
std::vector<BatteryType> types;
@ -131,6 +132,7 @@ const char* name_for_battery_type(BatteryType type) {
return nullptr;
}
}
#endif
#ifdef LFP_CHEMISTRY
const battery_chemistry_enum battery_chemistry_default = battery_chemistry_enum::LFP;

View file

@ -1,6 +1,7 @@
#ifndef BATTERIES_H
#define BATTERIES_H
#include "../../USER_SETTINGS.h"
#include "Shunt.h"
class Battery;
@ -18,10 +19,8 @@ void setup_can_shunt();
#include "BOLT-AMPERA-BATTERY.h"
#include "BYD-ATTO-3-BATTERY.h"
#include "CELLPOWER-BMS.h"
#include "CHADEMO-BATTERY.h"
#include "CHADEMO-SHUNTS.h"
#include "CMFA-EV-BATTERY.h"
#include "DALY-BMS.h"
#include "ECMP-BATTERY.h"

View file

@ -38,7 +38,7 @@ class BmwI3Battery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "BMW i3";
static constexpr const char* Name = "BMW i3";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -22,7 +22,7 @@ class BmwIXBattery : public CanBattery {
void request_open_contactors() { datalayer_extended.bmwix.UserRequestContactorOpen = true; }
void request_close_contactors() { datalayer_extended.bmwix.UserRequestContactorClose = true; }
static constexpr char* Name = "BMW iX and i4-7 platform";
static constexpr const char* Name = "BMW iX and i4-7 platform";
private:
BmwIXHtmlRenderer renderer;

View file

@ -13,7 +13,7 @@ class BmwSbox : public CanShunt {
void setup();
void transmit_can(unsigned long currentMillis);
void handle_incoming_can_frame(CAN_frame rx_frame);
static constexpr char* Name = "BMW SBOX";
static constexpr const char* Name = "BMW SBOX";
private:
/** Minimum input voltage required to enable relay control **/

View file

@ -17,7 +17,7 @@ class BoltAmperaBattery : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Chevrolet Bolt EV/Opel Ampera-e";
static constexpr const char* Name = "Chevrolet Bolt EV/Opel Ampera-e";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -44,7 +44,7 @@ class BydAttoBattery : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "BYD Atto 3";
static constexpr const char* Name = "BYD Atto 3";
bool supports_charged_energy() { return true; }
bool supports_reset_crash() { return true; }

View file

@ -18,7 +18,7 @@ class CellPowerBms : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Cellpower BMS";
static constexpr const char* Name = "Cellpower BMS";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -714,7 +714,7 @@ void ChademoBattery::handle_chademo_sequence() {
* with timers to have higher confidence of certain conditions hitting
* a steady state
*/
LOG_PRINTLN("CHADEMO plug is not inserted, cannot connect d2 relay to begin initialization.");
DEBUG_PRINTLN("CHADEMO plug is not inserted, cannot connect d2 relay to begin initialization.");
CHADEMO_Status = CHADEMO_IDLE;
}
break;
@ -723,7 +723,7 @@ void ChademoBattery::handle_chademo_sequence() {
* Used for triggers/error handling elsewhere;
* State change to CHADEMO_NEGOTIATE occurs in handle_incoming_can_frame_battery(..)
*/
LOG_PRINTLN("Awaiting initial vehicle CAN to trigger negotiation");
DEBUG_PRINTLN("Awaiting initial vehicle CAN to trigger negotiation");
evse_init();
break;
case CHADEMO_NEGOTIATE:

View file

@ -30,7 +30,7 @@ class ChademoBattery : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Chademo V2X mode";
static constexpr const char* Name = "Chademo V2X mode";
private:
gpio_num_t pin2, pin10, pin4, pin7, pin_lock, precharge, positive_contactor;

View file

@ -32,7 +32,7 @@ class CmfaEvBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "CMFA platform, 27 kWh battery";
static constexpr const char* Name = "CMFA platform, 27 kWh battery";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -1,10 +1,10 @@
#include "CanBattery.h"
#include "../../src/include.h"
CanBattery::CanBattery(bool low_speed) {
CanBattery::CanBattery(bool halfSpeed) {
can_interface = can_config.battery;
register_transmitter(this);
register_can_receiver(this, can_interface, low_speed);
register_can_receiver(this, can_interface, halfSpeed);
}
void CanBattery::slow_down_can() {

View file

@ -23,12 +23,12 @@ class CanBattery : public Battery, Transmitter, CanReceiver {
protected:
CAN_Interface can_interface;
CanBattery(bool low_speed = false);
CanBattery(bool halfSpeed = false);
CanBattery(CAN_Interface interface, bool low_speed = false) {
CanBattery(CAN_Interface interface, bool halfSpeed = false) {
can_interface = interface;
register_transmitter(this);
register_can_receiver(this, can_interface, low_speed);
register_can_receiver(this, can_interface, halfSpeed);
}
void slow_down_can();

View file

@ -13,7 +13,7 @@ class DalyBms : public RS485Battery {
void update_values();
void transmit_rs485(unsigned long currentMillis);
void receive();
static constexpr char* Name = "DALY RS485";
static constexpr const char* Name = "DALY RS485";
private:
/* Tweak these according to your battery build */

View file

@ -16,7 +16,7 @@ class EcmpBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Stellantis ECMP battery";
static constexpr const char* Name = "Stellantis ECMP battery";
bool supports_clear_isolation() { return true; }
void clear_isolation() { datalayer_extended.stellantisECMP.UserRequestIsolationReset = true; }

View file

@ -15,7 +15,7 @@ class FoxessBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "FoxESS HV2600/ECS4100 OEM battery";
static constexpr const char* Name = "FoxESS HV2600/ECS4100 OEM battery";
private:
static const int MAX_PACK_VOLTAGE_DV = 4672; //467.2V for HS20.8 (used during startup, refined later)

View file

@ -16,7 +16,7 @@ class GeelyGeometryCBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Geely Geometry C";
static constexpr const char* Name = "Geely Geometry C";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -15,7 +15,7 @@ class ImievCZeroIonBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "I-Miev / C-Zero / Ion Triplet";
static constexpr const char* Name = "I-Miev / C-Zero / Ion Triplet";
private:
static const int MAX_PACK_VOLTAGE_DV = 3696; //5000 = 500.0V

View file

@ -13,7 +13,7 @@ class JaguarIpaceBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Jaguar I-PACE";
static constexpr const char* Name = "Jaguar I-PACE";
private:
static const int MAX_PACK_VOLTAGE_DV = 4546; //5000 = 500.0V

View file

@ -16,7 +16,7 @@ class KiaEGmpBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Kia/Hyundai EGMP platform";
static constexpr const char* Name = "Kia/Hyundai EGMP platform";
private:
uint16_t estimateSOC(uint16_t packVoltage, uint16_t cellCount, int16_t currentAmps);

View file

@ -35,7 +35,7 @@ class KiaHyundai64Battery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Kia/Hyundai 64/40kWh battery";
static constexpr const char* Name = "Kia/Hyundai 64/40kWh battery";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -15,7 +15,7 @@ class KiaHyundaiHybridBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Kia/Hyundai Hybrid";
static constexpr const char* Name = "Kia/Hyundai Hybrid";
private:
static const int MAX_PACK_VOLTAGE_DV = 2550; //5000 = 500.0V

View file

@ -17,7 +17,7 @@ class MebBattery : public CanBattery {
virtual void transmit_can(unsigned long currentMillis);
bool supports_real_BMS_status() { return true; }
bool supports_charged_energy() { return true; }
static constexpr char* Name = "Volkswagen Group MEB platform via CAN-FD";
static constexpr const char* Name = "Volkswagen Group MEB platform via CAN-FD";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -15,7 +15,7 @@ class Mg5Battery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "MG 5 battery";
static constexpr const char* Name = "MG 5 battery";
private:
static const int MAX_PACK_VOLTAGE_DV = 4040; //5000 = 500.0V

View file

@ -7,6 +7,7 @@
#include "../datalayer/datalayer.h"
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
#include "../devboard/utils/events.h"
#include "../devboard/utils/logging.h"
#include "../charger/CanCharger.h"

View file

@ -46,7 +46,7 @@ class NissanLeafBattery : public CanBattery {
}
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
static constexpr char* Name = "Nissan LEAF battery";
static constexpr const char* Name = "Nissan LEAF battery";
private:
static const int MAX_PACK_VOLTAGE_DV = 4040; //5000 = 500.0V

View file

@ -15,7 +15,7 @@ class OrionBms : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "DIY battery with Orion BMS (Victron setting)";
static constexpr const char* Name = "DIY battery with Orion BMS (Victron setting)";
private:
/* Change the following to suit your battery */

View file

@ -31,7 +31,7 @@ class PylonBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Pylon compatible battery";
static constexpr const char* Name = "Pylon compatible battery";
private:
/* Change the following to suit your battery */

View file

@ -15,7 +15,7 @@ class RangeRoverPhevBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Range Rover 13kWh PHEV battery (L494/L405)";
static constexpr const char* Name = "Range Rover 13kWh PHEV battery (L494/L405)";
private:
/* Change the following to suit your battery */

View file

@ -15,7 +15,7 @@ class RenaultKangooBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Renault Kangoo";
static constexpr const char* Name = "Renault Kangoo";
private:
static const int MAX_PACK_VOLTAGE_DV = 4150; //5000 = 500.0V

View file

@ -13,7 +13,7 @@ class RenaultTwizyBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Renault Twizy";
static constexpr const char* Name = "Renault Twizy";
private:
static const int MAX_PACK_VOLTAGE_DV = 579; // 57.9V at 100% SOC (with 70% SOH, new one might be higher)

View file

@ -166,7 +166,7 @@ void RenaultZoeGen1Battery::handle_incoming_can_frame(CAN_frame rx_frame) {
switch (frame0) {
case 0x10: //PID HEADER, datarow 0
requested_poll = rx_frame.data.u8[3];
transmit_can_frame(&ZOE_ACK_79B, can_config.battery);
transmit_can_frame(&ZOE_ACK_79B, can_interface);
if (requested_poll == GROUP1_CELLVOLTAGES_1_POLL) {
cellvoltages[0] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
@ -469,7 +469,7 @@ void RenaultZoeGen1Battery::transmit_can(unsigned long currentMillis) {
// Send 100ms CAN Message
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
previousMillis100 = currentMillis;
transmit_can_frame(&ZOE_423, can_config.battery);
transmit_can_frame(&ZOE_423, can_interface);
if ((counter_423 / 5) % 2 == 0) { // Alternate every 5 messages between these two
ZOE_423.data.u8[4] = 0xB2;
@ -508,7 +508,7 @@ void RenaultZoeGen1Battery::transmit_can(unsigned long currentMillis) {
ZOE_POLL_79B.data.u8[2] = current_poll;
transmit_can_frame(&ZOE_POLL_79B, can_config.battery);
transmit_can_frame(&ZOE_POLL_79B, can_interface);
}
}

View file

@ -31,7 +31,7 @@ class RenaultZoeGen1Battery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Renault Zoe Gen1 22/40kWh";
static constexpr const char* Name = "Renault Zoe Gen1 22/40kWh";
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -15,7 +15,7 @@ class RenaultZoeGen2Battery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Renault Zoe Gen2 50kWh";
static constexpr const char* Name = "Renault Zoe Gen2 50kWh";
bool supports_reset_NVROL() { return true; }

View file

@ -17,7 +17,7 @@ class RjxzsBms : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "RJXZS BMS, DIY battery";
static constexpr const char* Name = "RJXZS BMS, DIY battery";
private:
/* Tweak these according to your battery build */

View file

@ -27,7 +27,7 @@ class SantaFePhevBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Santa Fe PHEV";
static constexpr const char* Name = "Santa Fe PHEV";
private:
DATALAYER_BATTERY_TYPE* datalayer_battery;

View file

@ -15,7 +15,7 @@ class SimpBmsBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "SIMPBMS battery";
static constexpr const char* Name = "SIMPBMS battery";
private:
/* DEFAULT VALUES BMS will send configured */

View file

@ -15,7 +15,7 @@ class SonoBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Sono Motors Sion 64kWh LFP ";
static constexpr const char* Name = "Sono Motors Sion 64kWh LFP ";
private:
static const int MAX_PACK_VOLTAGE_DV = 5000; //5000 = 500.0V

View file

@ -3,6 +3,7 @@
#include "src/communication/Transmitter.h"
#include "src/communication/can/CanReceiver.h"
#include "src/communication/can/comm_can.h"
#include "src/devboard/utils/types.h"
class CanShunt : public Transmitter, CanReceiver {

View file

@ -514,14 +514,14 @@ class TeslaModel3YBattery : public TeslaBattery {
operate_contactors = true;
#endif
}
static constexpr char* Name = "Tesla Model 3/Y";
static constexpr const char* Name = "Tesla Model 3/Y";
virtual void setup(void);
};
class TeslaModelSXBattery : public TeslaBattery {
public:
TeslaModelSXBattery() { operate_contactors = true; }
static constexpr char* Name = "Tesla Model S/X";
static constexpr const char* Name = "Tesla Model S/X";
virtual void setup(void);
};

View file

@ -22,7 +22,7 @@ class TestFakeBattery : public CanBattery {
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
}
static constexpr char* Name = "Fake battery for testing purposes";
static constexpr const char* Name = "Fake battery for testing purposes";
virtual void setup();
virtual void handle_incoming_can_frame(CAN_frame rx_frame);

View file

@ -16,7 +16,7 @@ class VolvoSpaBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Volvo / Polestar 69/78kWh SPA battery";
static constexpr const char* Name = "Volvo / Polestar 69/78kWh SPA battery";
bool supports_reset_DTC() { return true; }
void reset_DTC() { datalayer_extended.VolvoPolestar.UserRequestDTCreset = true; }

View file

@ -16,7 +16,7 @@ class VolvoSpaHybridBattery : public CanBattery {
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
static constexpr char* Name = "Volvo PHEV battery";
static constexpr const char* Name = "Volvo PHEV battery";
bool supports_reset_DTC() { return true; }
void reset_DTC() { datalayer_extended.VolvoHybrid.UserRequestDTCreset = true; }

View file

@ -14,7 +14,7 @@ class ChevyVoltCharger : public CanCharger {
ChevyVoltCharger() : CanCharger(ChargerType::ChevyVolt) {}
const char* name() { return Name; }
static constexpr char* Name = "Chevy Volt Gen1 Charger";
static constexpr const char* Name = "Chevy Volt Gen1 Charger";
void map_can_frame_to_variable(CAN_frame rx_frame);
void transmit_can(unsigned long currentMillis);

View file

@ -14,7 +14,7 @@ class NissanLeafCharger : public CanCharger {
NissanLeafCharger() : CanCharger(ChargerType::NissanLeaf) {}
const char* name() { return Name; }
static constexpr char* Name = "Nissan LEAF 2013-2024 PDM charger";
static constexpr const char* Name = "Nissan LEAF 2013-2024 PDM charger";
void map_can_frame_to_variable(CAN_frame rx_frame);
void transmit_can(unsigned long currentMillis);

View file

@ -6,6 +6,14 @@
#include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
#include "../../lib/pierremolinaro-acan2515/ACAN2515.h"
#include "src/devboard/sdcard/sdcard.h"
#include "src/devboard/utils/logging.h"
struct CanReceiverRegistration {
CanReceiver* receiver;
bool halfSpeed;
};
static std::multimap<CAN_Interface, CanReceiverRegistration> can_receivers;
// Parameters
CAN_device_t CAN_cfg; // CAN Config
@ -22,17 +30,11 @@ const bool use_canfd_as_can_default = false;
#endif
bool use_canfd_as_can = use_canfd_as_can_default;
struct CanInterfaceRegistration {
CanReceiver* receiver;
bool lowSpeed;
};
void map_can_frame_to_variable(CAN_frame* rx_frame, CAN_Interface interface);
static std::multimap<CAN_Interface, CanInterfaceRegistration> can_receivers;
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool low_speed) {
can_receivers.insert({interface, {receiver, low_speed}});
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool halfSpeed) {
can_receivers.insert({interface, {receiver, halfSpeed}});
DEBUG_PRINTF("CAN receiver registered, total: %d\n", can_receivers.size());
}
static const uint32_t QUARTZ_FREQUENCY = CRYSTAL_FREQUENCY_MHZ * 1000000UL; //MHZ configured in USER_SETTINGS.h
@ -65,7 +67,7 @@ bool init_CAN() {
digitalWrite(se_pin, LOW);
}
if (nativeIt->second.lowSpeed) {
if (nativeIt->second.halfSpeed) {
CAN_cfg.speed = CAN_SPEED_250KBPS;
} else {
CAN_cfg.speed = CAN_SPEED_500KBPS;
@ -104,7 +106,7 @@ bool init_CAN() {
SPI2515.begin(sck_pin, miso_pin, mosi_pin);
// CAN bit rate 250 or 500 kb/s
auto bitRate = addonIt->second.lowSpeed ? 250UL * 1000UL : 500UL * 1000UL;
auto bitRate = addonIt->second.halfSpeed ? 250UL * 1000UL : 500UL * 1000UL;
settings2515 = new ACAN2515Settings(QUARTZ_FREQUENCY, bitRate);
settings2515->mRequestedMode = ACAN2515Settings::NormalMode;
@ -128,8 +130,8 @@ bool init_CAN() {
if (fdNativeIt != can_receivers.end() || fdAddonIt != can_receivers.end()) {
auto slow = (fdNativeIt != can_receivers.end() && fdNativeIt->second.lowSpeed) ||
(fdAddonIt != can_receivers.end() && fdAddonIt->second.lowSpeed);
auto slow = (fdNativeIt != can_receivers.end() && fdNativeIt->second.halfSpeed) ||
(fdAddonIt != can_receivers.end() && fdAddonIt->second.halfSpeed);
auto cs_pin = esp32hal->MCP2517_CS();
auto int_pin = esp32hal->MCP2517_INT();
@ -201,6 +203,7 @@ void transmit_can_frame(CAN_frame* tx_frame, int interface) {
switch (interface) {
case CAN_NATIVE:
CAN_frame_t frame;
frame.MsgID = tx_frame->ID;
frame.FIR.B.FF = tx_frame->ext_ID ? CAN_frame_ext : CAN_frame_std;

View file

@ -12,8 +12,8 @@ class CanReceiver;
// Register a receiver object for a given CAN interface.
// By default receivers expect the CAN interface to be operated at "fast" speed.
// If low_speed is true, half speed is used.
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool low_speed = false);
// If halfSpeed is true, half speed is used.
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool halfSpeed = false);
/**
* @brief Initializes all CAN interfaces requested earlier by other modules (see register_can_receiver)

View file

@ -16,6 +16,7 @@ void init_stored_settings() {
// Always get the equipment stop status
datalayer.system.settings.equipment_stop_active = settings.getBool("EQUIPMENT_STOP", false);
if (datalayer.system.settings.equipment_stop_active) {
DEBUG_PRINTF("Equipment stop status set in boot.");
set_event(EVENT_EQUIPMENT_STOP, 1);
}

View file

@ -30,6 +30,8 @@ bool init_rs485() {
// Inverters and batteries are expected to initialize their serial port in their setup-function
// for RS485 or Modbus comms.
return true;
}
static std::list<Rs485Receiver*> receivers;

View file

@ -31,13 +31,16 @@ class Esp32Hal {
for (gpio_num_t pin : requested_pins) {
if (pin < 0) {
set_event(EVENT_GPIO_NOT_DEFINED, (int)pin);
LOG_PRINT("%s attempted to allocate pin %d that wasn't defined for the selected HW.\n", name, (int)pin);
allocator_name = name;
DEBUG_PRINTF("%s attempted to allocate pin %d that wasn't defined for the selected HW.\n", name, (int)pin);
return false;
}
auto it = allocated_pins.find(pin);
if (it != allocated_pins.end()) {
LOG_PRINT("GPIO conflict for pin %d between %s and %s.\n", (int)pin, name, it->second.c_str());
allocator_name = name;
allocated_name = it->second.c_str();
DEBUG_PRINTF("GPIO conflict for pin %d between %s and %s.\n", (int)pin, name, it->second.c_str());
set_event(EVENT_GPIO_CONFLICT, (int)pin);
return false;
}
@ -143,8 +146,16 @@ class Esp32Hal {
// Returns the available comm interfaces on this HW
virtual std::vector<comm_interface> available_interfaces() = 0;
String failed_allocator() { return allocator_name; }
String conflicting_allocator() { return allocated_name; }
private:
std::unordered_map<gpio_num_t, std::string> allocated_pins;
// For event logging, store the name of the allocator/allocated
// for failed gpio allocations.
String allocator_name;
String allocated_name;
};
extern Esp32Hal* esp32hal;

View file

@ -415,7 +415,7 @@ bool publish_events() {
doc["severity"] = String(get_event_level_string(event_handle));
doc["count"] = String(event_pointer->occurences);
doc["data"] = String(event_pointer->data);
doc["message"] = String(get_event_message_string(event_handle));
doc["message"] = get_event_message_string(event_handle);
doc["millis"] = String(event_pointer->timestamp);
serializeJson(doc, mqtt_msg);

View file

@ -330,6 +330,7 @@ void update_machineryprotection() {
//battery pause status begin
void setBatteryPause(bool pause_battery, bool pause_CAN, bool equipment_stop, bool store_settings) {
DEBUG_PRINTF("Battery pause begin %d %d %d %d\n", pause_battery, pause_CAN, equipment_stop, store_settings);
// First handle equipment stop / resume
if (equipment_stop && !datalayer.system.settings.equipment_stop_active) {
@ -396,12 +397,12 @@ void update_pause_state() {
allowed_to_send_CAN = (!emulator_pause_CAN_send_ON || emulator_pause_status == NORMAL);
if (previous_allowed_to_send_CAN && !allowed_to_send_CAN) {
LOG_PRINT("Safety: Pausing CAN sending\n");
DEBUG_PRINTF("Safety: Pausing CAN sending\n");
//completely force stop the CAN communication
stop_can();
} else if (!previous_allowed_to_send_CAN && allowed_to_send_CAN) {
//resume CAN communication
LOG_PRINT("Safety: Resuming CAN sending\n");
DEBUG_PRINTF("Safety: Resuming CAN sending\n");
restart_can();
}
}

View file

@ -174,7 +174,7 @@ void set_event_MQTTpublished(EVENTS_ENUM_TYPE event) {
events.entries[event].MQTTpublished = true;
}
const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
String get_event_message_string(EVENTS_ENUM_TYPE event) {
switch (event) {
case EVENT_CANMCP2517FD_INIT_FAILURE:
return "CAN-FD initialization failed. Check hardware or bitrate settings";
@ -378,9 +378,10 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
return "Failed to syncronise with the NTP Server. BMS will reset every 24 hours from when the emulator was "
"powered on";
case EVENT_GPIO_CONFLICT:
return "There is a GPIO pin conflict between SW components.";
return "There is a GPIO pin conflict between SW components: " + esp32hal->failed_allocator() + " / " +
esp32hal->conflicting_allocator();
case EVENT_GPIO_NOT_DEFINED:
return "SW module requires GPIO that is not defined for this hardware.";
return "SW module requires GPIO that is not defined for this hardware: " + esp32hal->failed_allocator();
default:
return "";
}
@ -417,10 +418,8 @@ static void set_event(EVENTS_ENUM_TYPE event, uint8_t data, bool latched) {
(events.entries[event].state != EVENT_STATE_ACTIVE_LATCHED)) {
events.entries[event].occurences++;
events.entries[event].MQTTpublished = false;
#ifdef DEBUG_LOG
logging.print("Event: ");
logging.println(get_event_message_string(event));
#endif
DEBUG_PRINTF("Event: %s\n", get_event_message_string(event).c_str());
}
// We should set the event, update event info

View file

@ -1,6 +1,8 @@
#ifndef __EVENTS_H__
#define __EVENTS_H__
#include <WString.h>
#include <src/devboard/utils/types.h>
#include <stdint.h>
#define GENERATE_ENUM(ENUM) ENUM,
@ -146,7 +148,7 @@ struct EventData {
};
const char* get_event_enum_string(EVENTS_ENUM_TYPE event);
const char* get_event_message_string(EVENTS_ENUM_TYPE event);
String get_event_message_string(EVENTS_ENUM_TYPE event);
const char* get_event_level_string(EVENTS_ENUM_TYPE event);
EVENTS_LEVEL_TYPE get_event_level(void);

View file

@ -19,15 +19,11 @@ class Logging : public Print {
extern Logging logging;
#ifdef DEBUG_LOG
#define LOG_PRINT(fmt, ...) logging.printf(fmt, ##__VA_ARGS__)
#define LOG_PRINTLN(str) logging.println(str)
#define DEBUG_PRINTF(fmt, ...) logging.printf(fmt, ##__VA_ARGS__)
#define DEBUG_PRINTLN(str) logging.println(str)
#else
#define LOG_PRINT(fmt, ...) \
do { \
} while (0)
#define LOG_PRINTLN(str) \
do { \
} while (0)
#define DEBUG_PRINTF(fmt, ...) ((void)0)
#define DEBUG_PRINTLN(fmt, ...) ((void)0)
#endif
#endif // __LOGGING_H__

View file

@ -54,7 +54,7 @@ String events_processor(const String& var) {
String(timestamp_now - event_pointer->timestamp) + "</div>");
content.concat("<div>" + String(event_pointer->occurences) + "</div>");
content.concat("<div>" + String(event_pointer->data) + "</div>");
content.concat("<div>" + String(get_event_message_string(event_handle)) + "</div>");
content.concat("<div>" + get_event_message_string(event_handle) + "</div>");
content.concat("</div>"); // End of event row
}

View file

@ -1257,7 +1257,7 @@ String processor(const String& var) {
if (contactor_control_enabled) {
content += "<h4>Contactors controlled by emulator, state: ";
if (datalayer.system.status.contactors_battery2_engaged) {
if (datalayer.system.status.contactors_engaged) {
content += "<span style='color: green;'>ON</span>";
} else {
content += "<span style='color: red;'>OFF</span>";

View file

@ -14,7 +14,7 @@ class AforeCanInverter : public CanInverterProtocol {
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
void update_values();
static constexpr char* Name = "Afore battery over CAN";
static constexpr const char* Name = "Afore battery over CAN";
private:
/* The code is following the Afore 2.3 CAN standard, little-endian, 500kbps, from 2023.08.07 */

View file

@ -14,7 +14,7 @@ class BydCanInverter : public CanInverterProtocol {
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
void update_values();
static constexpr char* Name = "BYD Battery-Box Premium HVS over CAN Bus";
static constexpr const char* Name = "BYD Battery-Box Premium HVS over CAN Bus";
private:
void send_initial_data();

View file

@ -13,7 +13,7 @@ class BydModbusInverter : public ModbusInverterProtocol {
const char* name() override { return Name; }
bool setup() override;
void update_values();
static constexpr char* Name = "BYD 11kWh HVM battery over Modbus RTU";
static constexpr const char* Name = "BYD 11kWh HVM battery over Modbus RTU";
private:
void handle_static_data();

View file

@ -15,7 +15,7 @@ class FerroampCanInverter : public CanInverterProtocol {
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Ferroamp Pylon battery over CAN bus";
static constexpr const char* Name = "Ferroamp Pylon battery over CAN bus";
private:
void send_system_data();

View file

@ -14,7 +14,7 @@ class FoxessCanInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "FoxESS compatible HV2600/ECS4100 battery";
static constexpr const char* Name = "FoxESS compatible HV2600/ECS4100 battery";
private:
int16_t temperature_average = 0;

View file

@ -14,7 +14,7 @@ class GrowattHvInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Growatt High Voltage protocol via CAN";
static constexpr const char* Name = "Growatt High Voltage protocol via CAN";
private:
//Total number of Cells (1-512)

View file

@ -14,7 +14,7 @@ class GrowattLvInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Growatt Low Voltage (48V) protocol via CAN";
static constexpr const char* Name = "Growatt Low Voltage (48V) protocol via CAN";
private:
//Actual content messages

View file

@ -23,7 +23,7 @@ class KostalInverterProtocol : public Rs485InverterProtocol {
bool setup() override;
void receive();
void update_values();
static constexpr char* Name = "BYD battery via Kostal RS485";
static constexpr const char* Name = "BYD battery via Kostal RS485";
private:
int baud_rate() { return 57600; }

View file

@ -14,7 +14,7 @@ class PylonInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Pylontech battery over CAN bus";
static constexpr const char* Name = "Pylontech battery over CAN bus";
private:
void send_system_data();

View file

@ -14,7 +14,7 @@ class PylonLvInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Pylontech LV battery over CAN bus";
static constexpr const char* Name = "Pylontech LV battery over CAN bus";
private:
void send_system_data();

View file

@ -14,7 +14,7 @@ class SchneiderInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Schneider V2 SE BMS CAN";
static constexpr const char* Name = "Schneider V2 SE BMS CAN";
private:
static const int STATE_OFFLINE = 0;

View file

@ -15,7 +15,7 @@ class SmaBydHInverter : public SmaInverterBase {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "BYD over SMA CAN";
static constexpr const char* Name = "BYD over SMA CAN";
virtual bool controls_contactor() { return true; }

View file

@ -15,7 +15,7 @@ class SmaBydHvsInverter : public SmaInverterBase {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "BYD Battery-Box HVS over SMA CAN";
static constexpr const char* Name = "BYD Battery-Box HVS over SMA CAN";
virtual bool controls_contactor() { return true; }

View file

@ -14,7 +14,7 @@ class SmaLvInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "SMA Low Voltage (48V) protocol via CAN";
static constexpr const char* Name = "SMA Low Voltage (48V) protocol via CAN";
private:
static const int READY_STATE = 0x03;

View file

@ -15,7 +15,7 @@ class SmaTripowerInverter : public SmaInverterBase {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "SMA Tripower CAN";
static constexpr const char* Name = "SMA Tripower CAN";
virtual bool controls_contactor() { return true; }

View file

@ -14,7 +14,7 @@ class SofarInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Sofar BMS (Extended Frame) over CAN bus";
static constexpr const char* Name = "Sofar BMS (Extended Frame) over CAN bus";
private:
unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was send

View file

@ -15,7 +15,7 @@ class SolaxInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "SolaX Triple Power LFP over CAN bus";
static constexpr const char* Name = "SolaX Triple Power LFP over CAN bus";
private:
// Timeout in milliseconds

View file

@ -14,7 +14,7 @@ class SungrowInverter : public CanInverterProtocol {
void update_values();
void transmit_can(unsigned long currentMillis);
void map_can_frame_to_variable(CAN_frame rx_frame);
static constexpr char* Name = "Sungrow SBR064 battery over CAN bus";
static constexpr const char* Name = "Sungrow SBR064 battery over CAN bus";
private:
unsigned long previousMillis500ms = 0;