Can receivers can register with half speed

This commit is contained in:
Jaakko Haakana 2025-07-02 16:39:45 +03:00
parent e57f2ce324
commit d3f6577ebc
13 changed files with 66 additions and 31 deletions

View file

@ -89,10 +89,6 @@ void setup() {
&logging_loop_task, WIFI_CORE);
#endif
init_CAN();
init_contactors();
#ifdef PRECHARGE_CONTROL
init_precharge_control();
#endif // PRECHARGE_CONTROL
@ -100,6 +96,12 @@ void setup() {
setup_charger();
setup_inverter();
setup_battery();
setup_can_shunt();
// Init CAN only after any CAN receivers have had a chance to register.
init_CAN();
init_contactors();
init_rs485();
@ -107,7 +109,6 @@ void setup() {
init_equipment_stop_button();
#endif
setup_can_shunt();
// BOOT button at runtime is used as an input for various things
pinMode(0, INPUT_PULLUP);
@ -139,6 +140,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
@ -207,6 +210,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;
@ -101,6 +102,7 @@ extern const char* name_for_battery_type(BatteryType type) {
return nullptr;
}
}
#endif
#ifdef COMMON_IMAGE
#ifdef SELECTED_BATTERY_CLASS

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

@ -11,6 +11,8 @@
class CellPowerBms : public CanBattery {
public:
CellPowerBms() : CanBattery(true) {}
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
@ -132,7 +134,4 @@ class CellPowerBms : public CanBattery {
bool error_state = false;
};
/* Do not modify any rows below*/
#define NATIVECAN_250KBPS
#endif

View file

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

View file

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

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"
@ -205,6 +206,8 @@ void NissanLeafBattery::
}
void NissanLeafBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
DEBUG_PRINTF("Leaf frame %x", rx_frame.ID);
switch (rx_frame.ID) {
case 0x1DB:
if (is_message_corrupt(rx_frame)) {

View file

@ -11,6 +11,8 @@
class RjxzsBms : public CanBattery {
public:
RjxzsBms() : CanBattery(true) {}
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
@ -103,7 +105,4 @@ class RjxzsBms : public CanBattery {
bool discharging_active = false;
};
/* Do not modify any rows below*/
#define NATIVECAN_250KBPS
#endif

View file

@ -102,8 +102,6 @@ void VolvoSpaBattery::
logging.println(MAX_U);
logging.print("Battery minimum voltage limit: ");
logging.println(MIN_U);
logging.print("Remaining Energy: ");
logging.println(remaining_capacity);
logging.print("Discharge limit: ");
logging.println(HvBattPwrLimDchaSoft);
logging.print("Battery Error Indication: ");

View file

@ -9,6 +9,6 @@ class CanReceiver {
};
// Register a receiver object for a given CAN interface
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface);
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool halfSpeed = false);
#endif

View file

@ -2,6 +2,24 @@
#include <map>
#include "../../include.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;
bool hasHalfSpeedReceivers(const CAN_Interface& iface) {
auto range = can_receivers.equal_range(iface);
for (auto it = range.first; it != range.second; ++it) {
if (it->second.halfSpeed) {
return true;
}
}
return false;
}
// Parameters
CAN_device_t CAN_cfg; // CAN Config
@ -27,21 +45,25 @@ ACAN2517FD canfd(MCP2517_CS, SPI2517, MCP2517_INT);
// Initialization functions
void init_CAN() {
DEBUG_PRINTF("init_CAN called\n");
// CAN pins
#ifdef CAN_SE_PIN
pinMode(CAN_SE_PIN, OUTPUT);
digitalWrite(CAN_SE_PIN, LOW);
#endif // CAN_SE_PIN
CAN_cfg.speed = CAN_SPEED_500KBPS;
#ifdef NATIVECAN_250KBPS // Some component is requesting lower CAN speed
CAN_cfg.speed = CAN_SPEED_250KBPS;
#endif // NATIVECAN_250KBPS
// Half-speed currently only supported for CAN_NATIVE
auto anyHalfSpeedNative = hasHalfSpeedReceivers(CAN_Interface::CAN_NATIVE);
CAN_cfg.speed = anyHalfSpeedNative ? CAN_SPEED_250KBPS : CAN_SPEED_500KBPS;
CAN_cfg.tx_pin_id = CAN_TX_PIN;
CAN_cfg.rx_pin_id = CAN_RX_PIN;
CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));
// Init CAN Module
ESP32Can.CANInit();
DEBUG_PRINTF("init_CAN performed\n");
#ifdef CAN_ADDON
#ifdef DEBUG_LOG
logging.println("Dual CAN Bus (ESP32+MCP2515) selected");
@ -108,6 +130,7 @@ void init_CAN() {
}
void transmit_can_frame(CAN_frame* tx_frame, int interface) {
DEBUG_PRINTF("transmit can %d", interface);
if (!allowed_to_send_CAN) {
return;
}
@ -119,6 +142,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;
@ -276,13 +300,13 @@ void print_can_frame(CAN_frame frame, frameDirection msgDir) {
}
}
static std::multimap<CAN_Interface, CanReceiver*> can_receivers;
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface) {
can_receivers.insert({interface, receiver});
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());
}
void map_can_frame_to_variable(CAN_frame* rx_frame, CAN_Interface interface) {
DEBUG_PRINTF("map_can_frame_to_variable %d\n", interface);
if (interface !=
CANFD_NATIVE) { //Avoid printing twice due to receive_frame_canfd_addon sending to both FD interfaces
//TODO: This check can be removed later when refactored to use inline functions for logging
@ -302,7 +326,7 @@ void map_can_frame_to_variable(CAN_frame* rx_frame, CAN_Interface interface) {
for (auto it = receivers.first; it != receivers.second; ++it) {
auto& receiver = it->second;
receiver->receive_can_frame(rx_frame);
receiver.receiver->receive_can_frame(rx_frame);
}
}

View file

@ -17,4 +17,11 @@ class Logging : public Print {
};
extern Logging logging;
#ifdef DEBUG_LOG
#define DEBUG_PRINTF(fmt, ...) logging.printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...) ((void)0)
#endif
#endif // __LOGGING_H__

View file

@ -1258,7 +1258,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>";