Let batteries select CAN speed

This commit is contained in:
Jaakko Haakana 2025-07-13 09:35:11 +03:00
parent d5ac3cf300
commit 5b55197c5e
7 changed files with 40 additions and 42 deletions

View file

@ -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)
// Then a second dominant pulse of similar timing.
slow_down_can();
auto original_speed = change_can_speed(CAN_Speed::CAN_SPEED_250KBPS);
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
transmit_can_frame(&BMW_PHEV_BUS_WAKEUP_REQUEST, can_config.battery);
resume_full_speed();
change_can_speed(original_speed);
#ifdef DEBUG_LOG
logging.println("Sent magic wakeup packet to SME at 100kbps...");

View file

@ -11,7 +11,7 @@
class CellPowerBms : public CanBattery {
public:
CellPowerBms() : CanBattery(true) {}
CellPowerBms() : CanBattery(CAN_Speed::CAN_SPEED_250KBPS) {}
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);

View file

@ -1,16 +1,12 @@
#include "CanBattery.h"
#include "../../src/include.h"
CanBattery::CanBattery(bool halfSpeed) {
CanBattery::CanBattery(CAN_Speed speed) {
can_interface = can_config.battery;
register_transmitter(this);
register_can_receiver(this, can_interface, halfSpeed);
register_can_receiver(this, can_interface, speed);
}
void CanBattery::slow_down_can() {
::slow_down_can(can_interface);
}
void CanBattery::resume_full_speed() {
::resume_full_speed(can_interface);
CAN_Speed CanBattery::change_can_speed(CAN_Speed speed) {
return ::change_can_speed(can_interface, speed);
}

View file

@ -23,16 +23,15 @@ class CanBattery : public Battery, Transmitter, CanReceiver {
protected:
CAN_Interface can_interface;
CanBattery(bool halfSpeed = false);
CanBattery(CAN_Speed speed = CAN_Speed::CAN_SPEED_500KBPS);
CanBattery(CAN_Interface interface, bool halfSpeed = false) {
CanBattery(CAN_Interface interface, CAN_Speed speed = CAN_Speed::CAN_SPEED_500KBPS) {
can_interface = interface;
register_transmitter(this);
register_can_receiver(this, can_interface, halfSpeed);
register_can_receiver(this, can_interface, speed);
}
void slow_down_can();
void resume_full_speed();
CAN_Speed change_can_speed(CAN_Speed speed);
};
#endif

View file

@ -11,7 +11,7 @@
class RjxzsBms : public CanBattery {
public:
RjxzsBms() : CanBattery(true) {}
RjxzsBms() : CanBattery(CAN_Speed::CAN_SPEED_250KBPS) {}
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);

View file

@ -5,12 +5,13 @@
#include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
#include "../../lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h"
#include "../../lib/pierremolinaro-acan2515/ACAN2515.h"
#include "comm_can.h"
#include "src/devboard/sdcard/sdcard.h"
#include "src/devboard/utils/logging.h"
struct CanReceiverRegistration {
CanReceiver* receiver;
bool halfSpeed;
CAN_Speed speed;
};
static std::multimap<CAN_Interface, CanReceiverRegistration> can_receivers;
@ -32,8 +33,8 @@ bool use_canfd_as_can = use_canfd_as_can_default;
void map_can_frame_to_variable(CAN_frame* rx_frame, CAN_Interface interface);
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool halfSpeed) {
can_receivers.insert({interface, {receiver, halfSpeed}});
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, CAN_Speed speed) {
can_receivers.insert({interface, {receiver, speed}});
DEBUG_PRINTF("CAN receiver registered, total: %d\n", can_receivers.size());
}
@ -69,11 +70,7 @@ bool init_CAN() {
digitalWrite(se_pin, LOW);
}
if (nativeIt->second.halfSpeed) {
CAN_cfg.speed = CAN_SPEED_250KBPS;
} else {
CAN_cfg.speed = CAN_SPEED_500KBPS;
}
CAN_cfg.speed = (CAN_speed_t)nativeIt->second.speed;
if (!esp32hal->alloc_pins("CAN", tx_pin, rx_pin)) {
return false;
@ -109,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.halfSpeed ? 250UL * 1000UL : 500UL * 1000UL;
auto bitRate = (int)addonIt->second.speed * 1000UL;
settings2515 = new ACAN2515Settings(QUARTZ_FREQUENCY, bitRate);
settings2515->mRequestedMode = ACAN2515Settings::NormalMode;
@ -133,8 +130,7 @@ bool init_CAN() {
if (fdNativeIt != can_receivers.end() || fdAddonIt != can_receivers.end()) {
auto slow = (fdNativeIt != can_receivers.end() && fdNativeIt->second.halfSpeed) ||
(fdAddonIt != can_receivers.end() && fdAddonIt->second.halfSpeed);
auto speed = (fdNativeIt != can_receivers.end()) ? fdNativeIt->second.speed : fdAddonIt->second.speed;
auto cs_pin = esp32hal->MCP2517_CS();
auto int_pin = esp32hal->MCP2517_INT();
@ -152,7 +148,7 @@ bool init_CAN() {
logging.println("CAN FD add-on (ESP32+MCP2517) selected");
#endif // DEBUG_LOG
SPI2517.begin(sck_pin, sdo_pin, sdi_pin);
auto bitRate = slow ? 250UL * 1000UL : 500UL * 1000UL;
auto bitRate = (int)speed * 1000UL;
settings2517 = new ACAN2517FDSettings(
CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ, bitRate,
DataBitRateFactor::x4); // Arbitration bit rate: 250/500 kbit/s, data bit rate: 1/2 Mbit/s
@ -446,16 +442,12 @@ void restart_can() {
}
}
void slow_down_can(CAN_Interface interface) {
CAN_Speed change_can_speed(CAN_Interface interface, CAN_Speed speed) {
auto oldSpeed = (CAN_Speed)CAN_cfg.speed;
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
CAN_cfg.speed = (CAN_speed_t)speed;
// ReInit native CAN module at new speed
ESP32Can.CANInit();
}
return oldSpeed;
}

View file

@ -10,10 +10,21 @@ void transmit_can_frame(CAN_frame* tx_frame, int interface);
class CanReceiver;
enum class CAN_Speed {
CAN_SPEED_100KBPS = 100,
CAN_SPEED_125KBPS = 125,
CAN_SPEED_200KBPS = 200,
CAN_SPEED_250KBPS = 250,
CAN_SPEED_500KBPS = 500,
CAN_SPEED_800KBPS = 800,
CAN_SPEED_1000KBPS = 1000
};
// Register a receiver object for a given CAN interface.
// By default receivers expect the CAN interface to be operated at "fast" speed.
// If halfSpeed is true, half speed is used.
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface, bool halfSpeed = false);
void register_can_receiver(CanReceiver* receiver, CAN_Interface interface,
CAN_Speed speed = CAN_Speed::CAN_SPEED_500KBPS);
/**
* @brief Initializes all CAN interfaces requested earlier by other modules (see register_can_receiver)
@ -75,7 +86,7 @@ void stop_can();
// Restart CAN communication for all interfaces
void restart_can();
void slow_down_can(CAN_Interface interface);
void resume_full_speed(CAN_Interface interface);
// Change the speed of the CAN interface and return the old speed.
CAN_Speed change_can_speed(CAN_Interface interface, CAN_Speed speed);
#endif