mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 09:49:32 +02:00
Merge pull request #1208 from kyberias/can-receive
Generalize comm 'transmit' and introduce common class for shunts
This commit is contained in:
commit
30fc0f002a
32 changed files with 317 additions and 262 deletions
3
.github/workflows/compile-all-batteries.yml
vendored
3
.github/workflows/compile-all-batteries.yml
vendored
|
@ -115,4 +115,5 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
@ -288,4 +288,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
|
@ -90,4 +90,5 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -DDOUBLE_BATTERY -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -DDOUBLE_BATTERY -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
||||
|
|
2
.github/workflows/compile-all-hardware.yml
vendored
2
.github/workflows/compile-all-hardware.yml
vendored
|
@ -90,4 +90,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
2
.github/workflows/compile-all-inverters.yml
vendored
2
.github/workflows/compile-all-inverters.yml
vendored
|
@ -105,4 +105,4 @@ jobs:
|
|||
# in the build matrix, and using build flags to define the
|
||||
# battery and inverter set in the build matrix.
|
||||
- name: Compile Sketch
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property build.partitions=min_spiffs --build-property upload.maximum_size=1966080 --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "src/communication/Transmitter.h"
|
||||
#include "src/communication/can/comm_can.h"
|
||||
#include "src/communication/contactorcontrol/comm_contactorcontrol.h"
|
||||
#include "src/communication/equipmentstopbutton/comm_equipmentstopbutton.h"
|
||||
|
@ -88,11 +89,6 @@ void setup() {
|
|||
&logging_loop_task, WIFI_CORE);
|
||||
#endif
|
||||
|
||||
#ifdef MQTT
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
||||
WIFI_CORE);
|
||||
#endif
|
||||
|
||||
init_CAN();
|
||||
|
||||
init_contactors();
|
||||
|
@ -110,9 +106,8 @@ void setup() {
|
|||
#ifdef EQUIPMENT_STOP_BUTTON
|
||||
init_equipment_stop_button();
|
||||
#endif
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
|
||||
setup_can_shunt();
|
||||
#endif
|
||||
// BOOT button at runtime is used as an input for various things
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
|
||||
|
@ -126,6 +121,12 @@ void setup() {
|
|||
};
|
||||
|
||||
// Start tasks
|
||||
|
||||
#ifdef MQTT
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
|
||||
WIFI_CORE);
|
||||
#endif
|
||||
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
|
||||
CORE_FUNCTION_CORE);
|
||||
#ifdef PERIODIC_BMS_RESET_AT
|
||||
|
@ -202,6 +203,12 @@ void mqtt_loop(void*) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static std::list<Transmitter*> transmitters;
|
||||
|
||||
void register_transmitter(Transmitter* transmitter) {
|
||||
transmitters.push_back(transmitter);
|
||||
}
|
||||
|
||||
void core_loop(void*) {
|
||||
esp_task_wdt_add(NULL); // Register this task with WDT
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
|
@ -254,14 +261,24 @@ void core_loop(void*) {
|
|||
START_TIME_MEASUREMENT(time_values);
|
||||
#endif
|
||||
update_pause_state(); // Check if we are OK to send CAN or need to pause
|
||||
update_values_battery(); // Fetch battery values
|
||||
#ifdef DOUBLE_BATTERY
|
||||
update_values_battery2();
|
||||
|
||||
// Fetch battery values
|
||||
if (battery) {
|
||||
battery->update_values();
|
||||
}
|
||||
|
||||
if (battery2) {
|
||||
battery2->update_values();
|
||||
check_interconnect_available();
|
||||
#endif // DOUBLE_BATTERY
|
||||
}
|
||||
update_calculated_values();
|
||||
update_machineryprotection(); // Check safeties
|
||||
update_values_inverter(); // Update values heading towards inverter
|
||||
|
||||
// Update values heading towards inverter
|
||||
if (inverter) {
|
||||
inverter->update_values();
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||
END_TIME_MEASUREMENT_MAX(time_values, datalayer.system.status.time_values_us);
|
||||
#endif
|
||||
|
@ -269,12 +286,12 @@ void core_loop(void*) {
|
|||
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||
START_TIME_MEASUREMENT(cantx);
|
||||
#endif
|
||||
// Output
|
||||
transmit_can(currentMillis); // Send CAN messages to all components
|
||||
|
||||
#ifdef RS485_BATTERY_SELECTED
|
||||
transmit_rs485(currentMillis);
|
||||
#endif // RS485_BATTERY_SELECTED
|
||||
// Let all transmitter objects send their messages
|
||||
for (auto& transmitter : transmitters) {
|
||||
transmitter->transmit(currentMillis);
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_TIME_MEASUREMENT
|
||||
END_TIME_MEASUREMENT_MAX(cantx, datalayer.system.status.time_cantx_us);
|
||||
END_TIME_MEASUREMENT_MAX(all, datalayer.system.status.core_task_10s_max_us);
|
||||
|
@ -506,12 +523,6 @@ void update_calculated_values() {
|
|||
lastMillisOverflowCheck = currentMillis;
|
||||
}
|
||||
|
||||
void update_values_inverter() {
|
||||
if (inverter) {
|
||||
inverter->update_values();
|
||||
}
|
||||
}
|
||||
|
||||
void check_reset_reason() {
|
||||
esp_reset_reason_t reason = esp_reset_reason();
|
||||
switch (reason) {
|
||||
|
|
|
@ -41,43 +41,21 @@ void setup_battery() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void update_values_battery() {
|
||||
battery->update_values();
|
||||
}
|
||||
|
||||
// transmit_can_battery is called once and we need to
|
||||
// call both batteries.
|
||||
void transmit_can_battery(unsigned long currentMillis) {
|
||||
((CanBattery*)battery)->transmit_can(currentMillis);
|
||||
|
||||
#ifdef DOUBLE_BATTERY
|
||||
((CanBattery*)battery2)->transmit_can(currentMillis);
|
||||
#endif
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||
((CanBattery*)battery)->handle_incoming_can_frame(rx_frame);
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_BATTERY
|
||||
void update_values_battery2() {
|
||||
battery2->update_values();
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||
((CanBattery*)battery2)->handle_incoming_can_frame(rx_frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RS485_BATTERY_SELECTED
|
||||
void transmit_rs485(unsigned long currentMillis) {
|
||||
((RS485Battery*)battery)->transmit_rs485(currentMillis);
|
||||
}
|
||||
|
||||
void receive_RS485() {
|
||||
((RS485Battery*)battery)->receive_RS485();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,11 +9,11 @@ class Battery;
|
|||
extern Battery* battery;
|
||||
extern Battery* battery2;
|
||||
|
||||
void setup_can_shunt();
|
||||
|
||||
#ifdef BMW_SBOX
|
||||
#include "BMW-SBOX.h"
|
||||
void handle_incoming_can_frame_shunt(CAN_frame rx_frame);
|
||||
void transmit_can_shunt(unsigned long currentMillis);
|
||||
void setup_can_shunt();
|
||||
#endif
|
||||
|
||||
#ifdef BMW_I3_BATTERY
|
||||
|
@ -159,7 +159,6 @@ void setup_can_shunt();
|
|||
#endif
|
||||
|
||||
void setup_battery(void);
|
||||
void update_values_battery();
|
||||
|
||||
#ifdef RS485_BATTERY_SELECTED
|
||||
void transmit_rs485(unsigned long currentMillis);
|
||||
|
@ -169,7 +168,6 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame);
|
|||
void transmit_can_battery(unsigned long currentMillis);
|
||||
#endif
|
||||
|
||||
void update_values_battery2();
|
||||
void handle_incoming_can_frame_battery2(CAN_frame rx_frame);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,41 +1,9 @@
|
|||
#include "../include.h"
|
||||
#ifdef BMW_SBOX
|
||||
#include "../communication/can/comm_can.h"
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "BMW-SBOX.h"
|
||||
|
||||
#define MAX_ALLOWED_FAULT_TICKS 1000
|
||||
|
||||
enum SboxState { DISCONNECTED, PRECHARGE, NEGATIVE, POSITIVE, PRECHARGE_OFF, COMPLETED, SHUTDOWN_REQUESTED };
|
||||
SboxState contactorStatus = DISCONNECTED;
|
||||
|
||||
unsigned long prechargeStartTime = 0;
|
||||
unsigned long negativeStartTime = 0;
|
||||
unsigned long positiveStartTime = 0;
|
||||
unsigned long timeSpentInFaultedMode = 0;
|
||||
unsigned long LastMsgTime = 0; // will store last time a 20ms CAN Message was send
|
||||
unsigned long LastAvgTime = 0; // Last current storage time
|
||||
unsigned long ShuntLastSeen = 0;
|
||||
|
||||
uint32_t avg_mA_array[10];
|
||||
uint32_t avg_sum;
|
||||
|
||||
uint8_t k; //avg array pointer
|
||||
|
||||
uint8_t CAN100_cnt = 0;
|
||||
|
||||
CAN_frame SBOX_100 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 4,
|
||||
.ID = 0x100,
|
||||
.data = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}; // Byte 0: relay control, Byte 1: counter 0-E, Byte 4: CRC
|
||||
|
||||
CAN_frame SBOX_300 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 4,
|
||||
.ID = 0x300,
|
||||
.data = {0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}}; // Static frame
|
||||
|
||||
uint8_t reverse_bits(uint8_t byte) {
|
||||
uint8_t reversed = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
|
@ -64,7 +32,7 @@ uint8_t calculateCRC(CAN_frame CAN) {
|
|||
return crc;
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_shunt(CAN_frame rx_frame) {
|
||||
void BmwSbox::handle_incoming_can_frame(CAN_frame rx_frame) {
|
||||
unsigned long currentTime = millis();
|
||||
if (rx_frame.ID == 0x200) {
|
||||
ShuntLastSeen = currentTime;
|
||||
|
@ -100,7 +68,7 @@ void handle_incoming_can_frame_shunt(CAN_frame rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void transmit_can_shunt(unsigned long currentMillis) {
|
||||
void BmwSbox::transmit_can(unsigned long currentMillis) {
|
||||
|
||||
/** Shunt can frames seen? **/
|
||||
if (ShuntLastSeen + 1000 < currentMillis) {
|
||||
|
@ -210,7 +178,7 @@ void transmit_can_shunt(unsigned long currentMillis) {
|
|||
}
|
||||
}
|
||||
|
||||
void setup_can_shunt() {
|
||||
void BmwSbox::setup() {
|
||||
strncpy(datalayer.system.info.shunt_protocol, "BMW SBOX", 63);
|
||||
datalayer.system.info.shunt_protocol[63] = '\0';
|
||||
}
|
||||
|
|
|
@ -1,22 +1,67 @@
|
|||
#ifndef BMW_SBOX_CONTROL_H
|
||||
#define BMW_SBOX_CONTROL_H
|
||||
#include "../include.h"
|
||||
|
||||
#define CAN_SHUNT_SELECTED
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
#define SELECTED_SHUNT_CLASS BmwSbox
|
||||
|
||||
/** Minimum input voltage required to enable relay control **/
|
||||
#define MINIMUM_INPUT_VOLTAGE 250
|
||||
#include "Shunt.h"
|
||||
|
||||
/** Minimum required percentage of input voltage at the output port to engage the positive relay. **/
|
||||
/** Prevents engagement of the positive contactor if the precharge resistor is faulty. **/
|
||||
#define MAX_PRECHARGE_RESISTOR_VOLTAGE_PERCENT 0.99
|
||||
class BmwSbox : public CanShunt {
|
||||
public:
|
||||
void setup();
|
||||
void transmit_can(unsigned long currentMillis);
|
||||
void handle_incoming_can_frame(CAN_frame rx_frame);
|
||||
|
||||
/* NOTE: modify the T2 time constant below to account for the resistance and capacitance of the target system.
|
||||
private:
|
||||
/** Minimum input voltage required to enable relay control **/
|
||||
static const int MINIMUM_INPUT_VOLTAGE = 250;
|
||||
|
||||
/** Minimum required percentage of input voltage at the output port to engage the positive relay. **/
|
||||
/** Prevents engagement of the positive contactor if the precharge resistor is faulty. **/
|
||||
static constexpr const double MAX_PRECHARGE_RESISTOR_VOLTAGE_PERCENT = 0.99;
|
||||
|
||||
/* NOTE: modify the T2 time constant below to account for the resistance and capacitance of the target system.
|
||||
* t=3RC at minimum, t=5RC ideally
|
||||
*/
|
||||
|
||||
#define CONTACTOR_CONTROL_T1 5000 // Time before negative contactor engages and precharging starts
|
||||
#define CONTACTOR_CONTROL_T2 5000 // Precharge time before precharge resistor is bypassed by positive contactor
|
||||
#define CONTACTOR_CONTROL_T3 2000 // Precharge relay lead time after positive contactor has been engaged
|
||||
static const int CONTACTOR_CONTROL_T1 = 5000; // Time before negative contactor engages and precharging starts
|
||||
static const int CONTACTOR_CONTROL_T2 =
|
||||
5000; // Precharge time before precharge resistor is bypassed by positive contactor
|
||||
static const int CONTACTOR_CONTROL_T3 = 2000; // Precharge relay lead time after positive contactor has been engaged
|
||||
|
||||
static const int MAX_ALLOWED_FAULT_TICKS = 1000;
|
||||
|
||||
enum SboxState { DISCONNECTED, PRECHARGE, NEGATIVE, POSITIVE, PRECHARGE_OFF, COMPLETED, SHUTDOWN_REQUESTED };
|
||||
SboxState contactorStatus = DISCONNECTED;
|
||||
|
||||
unsigned long prechargeStartTime = 0;
|
||||
unsigned long negativeStartTime = 0;
|
||||
unsigned long positiveStartTime = 0;
|
||||
unsigned long timeSpentInFaultedMode = 0;
|
||||
unsigned long LastMsgTime = 0; // will store last time a 20ms CAN Message was send
|
||||
unsigned long LastAvgTime = 0; // Last current storage time
|
||||
unsigned long ShuntLastSeen = 0;
|
||||
|
||||
uint32_t avg_mA_array[10];
|
||||
uint32_t avg_sum;
|
||||
|
||||
uint8_t k; //avg array pointer
|
||||
|
||||
uint8_t CAN100_cnt = 0;
|
||||
|
||||
CAN_frame SBOX_100 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 4,
|
||||
.ID = 0x100,
|
||||
.data = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00}}; // Byte 0: relay control, Byte 1: counter 0-E, Byte 4: CRC
|
||||
|
||||
CAN_frame SBOX_300 = {.FD = false,
|
||||
.ext_ID = false,
|
||||
.DLC = 4,
|
||||
.ID = 0x300,
|
||||
.data = {0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}}; // Static frame
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,9 @@ class Battery {
|
|||
// This allows for battery specific SOC plausibility calculations to be performed.
|
||||
virtual bool soc_plausible() { return true; }
|
||||
|
||||
// Battery reports total_charged_battery_Wh and total_discharged_battery_Wh
|
||||
virtual bool supports_charged_energy() { return false; }
|
||||
|
||||
virtual BatteryHtmlRenderer& get_status_renderer() { return defaultRenderer; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -3,22 +3,31 @@
|
|||
|
||||
#include "Battery.h"
|
||||
|
||||
#include "src/communication/Transmitter.h"
|
||||
#include "src/devboard/utils/types.h"
|
||||
|
||||
// Abstract base class for batteries using the CAN bus
|
||||
class CanBattery : public Battery {
|
||||
class CanBattery : public Battery, Transmitter {
|
||||
public:
|
||||
virtual void handle_incoming_can_frame(CAN_frame rx_frame) = 0;
|
||||
virtual void transmit_can(unsigned long currentMillis) = 0;
|
||||
|
||||
String interface_name() { return getCANInterfaceName(can_interface); }
|
||||
|
||||
void transmit(unsigned long currentMillis) { transmit_can(currentMillis); }
|
||||
|
||||
protected:
|
||||
CAN_Interface can_interface;
|
||||
|
||||
CanBattery() { can_interface = can_config.battery; }
|
||||
CanBattery() {
|
||||
can_interface = can_config.battery;
|
||||
register_transmitter(this);
|
||||
}
|
||||
|
||||
CanBattery(CAN_Interface interface) { can_interface = interface; }
|
||||
CanBattery(CAN_Interface interface) {
|
||||
can_interface = interface;
|
||||
register_transmitter(this);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@ class MebBattery : public CanBattery {
|
|||
virtual void update_values();
|
||||
virtual void transmit_can(unsigned long currentMillis);
|
||||
bool supports_real_BMS_status() { return true; }
|
||||
bool supports_charged_energy() { return true; }
|
||||
|
||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||
|
||||
|
|
|
@ -43,9 +43,14 @@ class NissanLeafBattery : public CanBattery {
|
|||
virtual void transmit_can(unsigned long currentMillis);
|
||||
|
||||
bool supports_reset_SOH();
|
||||
|
||||
void reset_SOH() { datalayer_extended.nissanleaf.UserRequestSOHreset = true; }
|
||||
|
||||
bool soc_plausible() {
|
||||
// When pack voltage is close to max, and SOC% is still low, SOC is not plausible
|
||||
return !((datalayer.battery.status.voltage_dV > (datalayer.battery.info.max_design_voltage_dV - 100)) &&
|
||||
(datalayer.battery.status.real_soc < 6500));
|
||||
}
|
||||
|
||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -3,14 +3,20 @@
|
|||
|
||||
#include "Battery.h"
|
||||
|
||||
#include "src/communication/Transmitter.h"
|
||||
#include "src/devboard/utils/types.h"
|
||||
|
||||
// Abstract base class for batteries using the RS485 interface
|
||||
class RS485Battery : public Battery {
|
||||
class RS485Battery : public Battery, Transmitter {
|
||||
public:
|
||||
virtual void receive_RS485() = 0;
|
||||
virtual void transmit_rs485(unsigned long currentMillis) = 0;
|
||||
|
||||
String interface_name() { return "RS485"; }
|
||||
|
||||
void transmit(unsigned long currentMillis) { transmit_rs485(currentMillis); }
|
||||
|
||||
RS485Battery() { register_transmitter(this); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
31
Software/src/battery/Shunt.h
Normal file
31
Software/src/battery/Shunt.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _SHUNT_H
|
||||
#define _SHUNT_H
|
||||
|
||||
#include "../communication/can/comm_can.h"
|
||||
#include "src/communication/Transmitter.h"
|
||||
#include "src/devboard/utils/types.h"
|
||||
|
||||
class CanShunt : public Transmitter {
|
||||
public:
|
||||
virtual void setup() = 0;
|
||||
virtual void transmit_can(unsigned long currentMillis) = 0;
|
||||
virtual void handle_incoming_can_frame(CAN_frame rx_frame) = 0;
|
||||
|
||||
void transmit(unsigned long currentMillis) {
|
||||
if (allowed_to_send_CAN) {
|
||||
transmit_can(currentMillis);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
CAN_Interface can_interface;
|
||||
|
||||
CanShunt() {
|
||||
can_interface = can_config.battery;
|
||||
register_transmitter(this);
|
||||
}
|
||||
};
|
||||
|
||||
extern CanShunt* shunt;
|
||||
|
||||
#endif
|
19
Software/src/battery/Shunts.cpp
Normal file
19
Software/src/battery/Shunts.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "../include.h"
|
||||
#include "Shunt.h"
|
||||
|
||||
CanShunt* shunt = nullptr;
|
||||
|
||||
void setup_can_shunt() {
|
||||
#if defined(CAN_SHUNT_SELECTED) && defined(SELECTED_SHUNT_CLASS)
|
||||
shunt = new SELECTED_SHUNT_CLASS();
|
||||
if (shunt) {
|
||||
shunt->setup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void handle_incoming_can_frame_shunt(CAN_frame rx_frame) {
|
||||
if (shunt) {
|
||||
shunt->handle_incoming_can_frame(rx_frame);
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ class TeslaBattery : public CanBattery {
|
|||
bool supports_reset_BMS() { return true; }
|
||||
void reset_BMS() { datalayer.battery.settings.user_requests_tesla_bms_reset = true; }
|
||||
|
||||
bool supports_charged_energy() { return true; }
|
||||
|
||||
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "src/devboard/utils/types.h"
|
||||
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "src/communication/Transmitter.h"
|
||||
|
||||
enum class ChargerType { NissanLeaf, ChevyVolt };
|
||||
|
||||
|
@ -36,13 +37,19 @@ class Charger {
|
|||
};
|
||||
|
||||
// Base class for chargers on a CAN bus
|
||||
class CanCharger : public Charger {
|
||||
class CanCharger : public Charger, Transmitter {
|
||||
public:
|
||||
virtual void map_can_frame_to_variable(CAN_frame rx_frame) = 0;
|
||||
virtual void transmit_can(unsigned long currentMillis) = 0;
|
||||
|
||||
void transmit(unsigned long currentMillis) {
|
||||
if (allowed_to_send_CAN) {
|
||||
transmit_can(currentMillis);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
CanCharger(ChargerType type) : Charger(type) {}
|
||||
CanCharger(ChargerType type) : Charger(type) { register_transmitter(this); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
11
Software/src/communication/Transmitter.h
Normal file
11
Software/src/communication/Transmitter.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _TRANSMITTER_H
|
||||
#define _TRANSMITTER_H
|
||||
|
||||
class Transmitter {
|
||||
public:
|
||||
virtual void transmit(unsigned long currentMillis) = 0;
|
||||
};
|
||||
|
||||
void register_transmitter(Transmitter* transmitter);
|
||||
|
||||
#endif
|
|
@ -104,30 +104,6 @@ void init_CAN() {
|
|||
#endif // CANFD_ADDON
|
||||
}
|
||||
|
||||
// Transmit functions
|
||||
void transmit_can(unsigned long currentMillis) {
|
||||
|
||||
if (!allowed_to_send_CAN) {
|
||||
return; //Global block of CAN messages
|
||||
}
|
||||
|
||||
#ifndef RS485_BATTERY_SELECTED
|
||||
transmit_can_battery(currentMillis);
|
||||
#endif
|
||||
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
transmit_can_inverter(currentMillis);
|
||||
#endif // CAN_INVERTER_SELECTED
|
||||
|
||||
if (charger) {
|
||||
charger->transmit_can(currentMillis);
|
||||
}
|
||||
|
||||
#ifdef CAN_SHUNT_SELECTED
|
||||
transmit_can_shunt(currentMillis);
|
||||
#endif // CAN_SHUNT_SELECTED
|
||||
}
|
||||
|
||||
void transmit_can_frame(CAN_frame* tx_frame, int interface) {
|
||||
if (!allowed_to_send_CAN) {
|
||||
return;
|
||||
|
@ -325,10 +301,8 @@ void map_can_frame_to_variable(CAN_frame* rx_frame, int interface) {
|
|||
map_can_frame_to_variable_inverter(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.battery_double) {
|
||||
#ifdef DOUBLE_BATTERY
|
||||
if (interface == can_config.battery_double && battery2) {
|
||||
handle_incoming_can_frame_battery2(*rx_frame);
|
||||
#endif
|
||||
}
|
||||
if (interface == can_config.charger && charger) {
|
||||
charger->map_can_frame_to_variable(*rx_frame);
|
||||
|
|
|
@ -37,16 +37,6 @@ void init_CAN();
|
|||
*/
|
||||
void transmit_can_frame();
|
||||
|
||||
/**
|
||||
* @brief Send CAN messages to all components
|
||||
*
|
||||
* @param[in] void
|
||||
* @param[in] unsigned long currentMillis
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void transmit_can(unsigned long currentMillis);
|
||||
|
||||
/**
|
||||
* @brief Receive CAN messages from all interfaces
|
||||
*
|
||||
|
|
|
@ -79,12 +79,8 @@
|
|||
#define EQUIPMENT_STOP_PIN 35
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
|
|
|
@ -67,12 +67,8 @@ The pin layout below supports the following:
|
|||
#define INVERTER_DISCONNECT_CONTACTOR_PIN GPIO_NUM_5
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
|
|
|
@ -74,12 +74,8 @@
|
|||
#define EQUIPMENT_STOP_PIN 35
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
|
|
|
@ -66,12 +66,8 @@ GPIOs on extra header
|
|||
#define EQUIPMENT_STOP_PIN 2
|
||||
|
||||
// BMW_I3_BATTERY wake up pin
|
||||
#ifdef BMW_I3_BATTERY
|
||||
#define WUP_PIN1 GPIO_NUM_25 // Wake up pin for battery 1
|
||||
#ifdef DOUBLE_BATTERY
|
||||
#define WUP_PIN2 GPIO_NUM_32 // Wake up pin for battery 2
|
||||
#endif // DOUBLE_BATTERY
|
||||
#endif // BMW_I3_BATTERY
|
||||
|
||||
/* ----- Error checks below, don't change (can't be moved to separate file) ----- */
|
||||
#ifndef HW_CONFIGURED
|
||||
|
|
|
@ -62,46 +62,53 @@ struct SensorConfig {
|
|||
const char* value_template;
|
||||
const char* unit;
|
||||
const char* device_class;
|
||||
|
||||
// A function that returns true for the battery if it supports this config
|
||||
std::function<bool(Battery*)> condition;
|
||||
};
|
||||
|
||||
static std::function<bool(Battery*)> always = [](Battery* b) {
|
||||
return true;
|
||||
};
|
||||
static std::function<bool(Battery*)> supports_charged = [](Battery* b) {
|
||||
return b->supports_charged_energy();
|
||||
};
|
||||
|
||||
SensorConfig sensorConfigTemplate[] = {
|
||||
{"SOC", "SOC (Scaled)", "", "%", "battery"},
|
||||
{"SOC_real", "SOC (real)", "", "%", "battery"},
|
||||
{"state_of_health", "State Of Health", "", "%", "battery"},
|
||||
{"temperature_min", "Temperature Min", "", "°C", "temperature"},
|
||||
{"temperature_max", "Temperature Max", "", "°C", "temperature"},
|
||||
{"cpu_temp", "CPU Temperature", "", "°C", "temperature"},
|
||||
{"stat_batt_power", "Stat Batt Power", "", "W", "power"},
|
||||
{"battery_current", "Battery Current", "", "A", "current"},
|
||||
{"cell_max_voltage", "Cell Max Voltage", "", "V", "voltage"},
|
||||
{"cell_min_voltage", "Cell Min Voltage", "", "V", "voltage"},
|
||||
{"cell_voltage_delta", "Cell Voltage Delta", "", "mV", "voltage"},
|
||||
{"battery_voltage", "Battery Voltage", "", "V", "voltage"},
|
||||
{"total_capacity", "Battery Total Capacity", "", "Wh", "energy"},
|
||||
{"remaining_capacity", "Battery Remaining Capacity (scaled)", "", "Wh", "energy"},
|
||||
{"remaining_capacity_real", "Battery Remaining Capacity (real)", "", "Wh", "energy"},
|
||||
{"max_discharge_power", "Battery Max Discharge Power", "", "W", "power"},
|
||||
{"max_charge_power", "Battery Max Charge Power", "", "W", "power"},
|
||||
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
|
||||
{"charged_energy", "Battery Charged Energy", "", "Wh", "energy"},
|
||||
{"discharged_energy", "Battery Discharged Energy", "", "Wh", "energy"},
|
||||
#endif
|
||||
{"bms_status", "BMS Status", "", "", ""},
|
||||
{"pause_status", "Pause Status", "", "", ""}};
|
||||
{"SOC", "SOC (Scaled)", "", "%", "battery", always},
|
||||
{"SOC_real", "SOC (real)", "", "%", "battery", always},
|
||||
{"state_of_health", "State Of Health", "", "%", "battery", always},
|
||||
{"temperature_min", "Temperature Min", "", "°C", "temperature", always},
|
||||
{"temperature_max", "Temperature Max", "", "°C", "temperature", always},
|
||||
{"cpu_temp", "CPU Temperature", "", "°C", "temperature", always},
|
||||
{"stat_batt_power", "Stat Batt Power", "", "W", "power", always},
|
||||
{"battery_current", "Battery Current", "", "A", "current", always},
|
||||
{"cell_max_voltage", "Cell Max Voltage", "", "V", "voltage", always},
|
||||
{"cell_min_voltage", "Cell Min Voltage", "", "V", "voltage", always},
|
||||
{"cell_voltage_delta", "Cell Voltage Delta", "", "mV", "voltage", always},
|
||||
{"battery_voltage", "Battery Voltage", "", "V", "voltage", always},
|
||||
{"total_capacity", "Battery Total Capacity", "", "Wh", "energy", always},
|
||||
{"remaining_capacity", "Battery Remaining Capacity (scaled)", "", "Wh", "energy", always},
|
||||
{"remaining_capacity_real", "Battery Remaining Capacity (real)", "", "Wh", "energy", always},
|
||||
{"max_discharge_power", "Battery Max Discharge Power", "", "W", "power", always},
|
||||
{"max_charge_power", "Battery Max Charge Power", "", "W", "power", always},
|
||||
{"charged_energy", "Battery Charged Energy", "", "Wh", "energy", supports_charged},
|
||||
{"discharged_energy", "Battery Discharged Energy", "", "Wh", "energy", supports_charged},
|
||||
{"bms_status", "BMS Status", "", "", "", always},
|
||||
{"pause_status", "Pause Status", "", "", "", always}};
|
||||
|
||||
#ifdef DOUBLE_BATTERY
|
||||
// Enough space for two batteries
|
||||
SensorConfig sensorConfigs[((sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0])) * 2) - 2];
|
||||
#else
|
||||
SensorConfig sensorConfigs[sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0])];
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
void create_sensor_configs() {
|
||||
int number_of_templates = sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0]);
|
||||
|
||||
for (int i = 0; i < number_of_templates; i++) {
|
||||
SensorConfig config = sensorConfigTemplate[i];
|
||||
config.value_template = strdup(("{{ value_json." + std::string(config.object_id) + " }}").c_str());
|
||||
sensorConfigs[i] = config;
|
||||
#ifdef DOUBLE_BATTERY
|
||||
|
||||
if (battery2) {
|
||||
if (config.object_id == "pause_status" || config.object_id == "bms_status") {
|
||||
continue;
|
||||
}
|
||||
|
@ -110,7 +117,7 @@ void create_sensor_configs() {
|
|||
sensorConfigs[i + number_of_templates].object_id = strdup(String(config.object_id + String("_2")).c_str());
|
||||
sensorConfigs[i + number_of_templates].value_template =
|
||||
strdup(("{{ value_json." + std::string(config.object_id) + "_2 }}").c_str());
|
||||
#endif // DOUBLE_BATTERY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +171,8 @@ static String generateButtonTopic(const char* subtype) {
|
|||
return topic_name + "/command/" + String(subtype);
|
||||
}
|
||||
|
||||
void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& battery, const String& suffix) {
|
||||
void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& battery, const String& suffix,
|
||||
bool supports_charged) {
|
||||
doc["SOC" + suffix] = ((float)battery.status.reported_soc) / 100.0;
|
||||
doc["SOC_real" + suffix] = ((float)battery.status.real_soc) / 100.0;
|
||||
doc["state_of_health" + suffix] = ((float)battery.status.soh_pptt) / 100.0;
|
||||
|
@ -185,13 +193,14 @@ void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& bat
|
|||
doc["remaining_capacity" + suffix] = ((float)battery.status.reported_remaining_capacity_Wh);
|
||||
doc["max_discharge_power" + suffix] = ((float)battery.status.max_discharge_power_W);
|
||||
doc["max_charge_power" + suffix] = ((float)battery.status.max_charge_power_W);
|
||||
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
|
||||
|
||||
if (supports_charged) {
|
||||
if (datalayer.battery.status.total_charged_battery_Wh != 0 &&
|
||||
datalayer.battery.status.total_discharged_battery_Wh != 0) {
|
||||
doc["charged_energy" + suffix] = ((float)datalayer.battery.status.total_charged_battery_Wh);
|
||||
doc["discharged_energy" + suffix] = ((float)datalayer.battery.status.total_discharged_battery_Wh);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<EventData> order_events;
|
||||
|
@ -203,13 +212,19 @@ static bool publish_common_info(void) {
|
|||
if (ha_common_info_published == false) {
|
||||
for (int i = 0; i < sizeof(sensorConfigs) / sizeof(sensorConfigs[0]); i++) {
|
||||
SensorConfig& config = sensorConfigs[i];
|
||||
|
||||
if (!config.condition(battery)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
doc["name"] = config.name;
|
||||
doc["state_topic"] = state_topic;
|
||||
doc["unique_id"] = topic_name + "_" + String(config.object_id);
|
||||
doc["object_id"] = object_id_prefix + String(config.object_id);
|
||||
doc["value_template"] = config.value_template;
|
||||
if (config.unit != nullptr && strlen(config.unit) > 0)
|
||||
if (config.unit != nullptr && strlen(config.unit) > 0) {
|
||||
doc["unit_of_measurement"] = config.unit;
|
||||
}
|
||||
if (config.device_class != nullptr && strlen(config.device_class) > 0) {
|
||||
doc["device_class"] = config.device_class;
|
||||
doc["state_class"] = "measurement";
|
||||
|
@ -231,14 +246,15 @@ static bool publish_common_info(void) {
|
|||
|
||||
//only publish these values if BMS is active and we are comunication with the battery (can send CAN messages to the battery)
|
||||
if (datalayer.battery.status.CAN_battery_still_alive && allowed_to_send_CAN && millis() > BOOTUP_TIME) {
|
||||
set_battery_attributes(doc, datalayer.battery, "");
|
||||
set_battery_attributes(doc, datalayer.battery, "", battery->supports_charged_energy());
|
||||
}
|
||||
#ifdef DOUBLE_BATTERY
|
||||
|
||||
if (battery2) {
|
||||
//only publish these values if BMS is active and we are comunication with the battery (can send CAN messages to the battery)
|
||||
if (datalayer.battery2.status.CAN_battery_still_alive && allowed_to_send_CAN && millis() > BOOTUP_TIME) {
|
||||
set_battery_attributes(doc, datalayer.battery2, "_2");
|
||||
set_battery_attributes(doc, datalayer.battery2, "_2", battery2->supports_charged_energy());
|
||||
}
|
||||
}
|
||||
#endif // DOUBLE_BATTERY
|
||||
serializeJson(doc, mqtt_msg);
|
||||
if (mqtt_publish(state_topic.c_str(), mqtt_msg, false) == false) {
|
||||
#ifdef DEBUG_LOG
|
||||
|
@ -256,9 +272,7 @@ static bool publish_common_info(void) {
|
|||
static bool publish_cell_voltages(void) {
|
||||
static JsonDocument doc;
|
||||
static String state_topic = topic_name + "/spec_data";
|
||||
#ifdef DOUBLE_BATTERY
|
||||
static String state_topic_2 = topic_name + "/spec_data_2";
|
||||
#endif // DOUBLE_BATTERY
|
||||
|
||||
#ifdef HA_AUTODISCOVERY
|
||||
bool failed_to_publish = false;
|
||||
|
@ -280,7 +294,9 @@ static bool publish_cell_voltages(void) {
|
|||
}
|
||||
doc.clear(); // clear after sending autoconfig
|
||||
}
|
||||
#ifdef DOUBLE_BATTERY
|
||||
|
||||
if (battery2) {
|
||||
// TODO: Combine this identical block with the previous one.
|
||||
// If the cell voltage number isn't initialized...
|
||||
if (datalayer.battery2.info.number_of_cells != 0u) {
|
||||
|
||||
|
@ -297,7 +313,7 @@ static bool publish_cell_voltages(void) {
|
|||
}
|
||||
doc.clear(); // clear after sending autoconfig
|
||||
}
|
||||
#endif // DOUBLE_BATTERY
|
||||
}
|
||||
}
|
||||
if (failed_to_publish == false) {
|
||||
ha_cell_voltages_published = true;
|
||||
|
@ -324,7 +340,7 @@ static bool publish_cell_voltages(void) {
|
|||
doc.clear();
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_BATTERY
|
||||
if (battery2) {
|
||||
// If cell voltages have been populated...
|
||||
if (datalayer.battery2.info.number_of_cells != 0u &&
|
||||
datalayer.battery2.status.cell_voltages_mV[datalayer.battery2.info.number_of_cells - 1] != 0u) {
|
||||
|
@ -344,7 +360,7 @@ static bool publish_cell_voltages(void) {
|
|||
}
|
||||
doc.clear();
|
||||
}
|
||||
#endif // DOUBLE_BATTERY
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,18 +156,9 @@ void update_machineryprotection() {
|
|||
clear_event(EVENT_SOH_LOW);
|
||||
}
|
||||
|
||||
#ifdef NISSAN_LEAF_BATTERY
|
||||
// Check if SOC% is plausible
|
||||
if (datalayer.battery.status.voltage_dV >
|
||||
(datalayer.battery.info.max_design_voltage_dV -
|
||||
100)) { // When pack voltage is close to max, and SOC% is still low, raise event
|
||||
if (datalayer.battery.status.real_soc < 6500) { // 65.00%
|
||||
if (!battery->soc_plausible()) {
|
||||
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, datalayer.battery.status.real_soc);
|
||||
} else {
|
||||
clear_event(EVENT_SOC_PLAUSIBILITY_ERROR);
|
||||
}
|
||||
}
|
||||
#endif //NISSAN_LEAF_BATTERY
|
||||
|
||||
// Check diff between highest and lowest cell
|
||||
cell_deviation_mV =
|
||||
|
|
|
@ -5,11 +5,20 @@
|
|||
|
||||
#include "src/devboard/utils/types.h"
|
||||
|
||||
class CanInverterProtocol : public InverterProtocol {
|
||||
class CanInverterProtocol : public InverterProtocol, Transmitter {
|
||||
public:
|
||||
virtual const char* interface_name() { return getCANInterfaceName(can_config.inverter); }
|
||||
virtual void transmit_can(unsigned long currentMillis) = 0;
|
||||
virtual void map_can_frame_to_variable(CAN_frame rx_frame) = 0;
|
||||
|
||||
void transmit(unsigned long currentMillis) {
|
||||
if (allowed_to_send_CAN) {
|
||||
transmit_can(currentMillis);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
CanInverterProtocol() { register_transmitter(this); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,17 +34,10 @@ void setup_inverter() {
|
|||
}
|
||||
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
void update_values_can_inverter() {
|
||||
can_inverter->update_values();
|
||||
}
|
||||
|
||||
void map_can_frame_to_variable_inverter(CAN_frame rx_frame) {
|
||||
can_inverter->map_can_frame_to_variable(rx_frame);
|
||||
}
|
||||
|
||||
void transmit_can_inverter(unsigned long currentMillis) {
|
||||
can_inverter->transmit_can(currentMillis);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RS485_INVERTER_SELECTED
|
||||
|
|
|
@ -34,7 +34,6 @@ extern InverterProtocol* inverter;
|
|||
void setup_inverter();
|
||||
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
void update_values_can_inverter();
|
||||
void map_can_frame_to_variable_inverter(CAN_frame rx_frame);
|
||||
void transmit_can_inverter(unsigned long currentMillis);
|
||||
#endif
|
||||
|
|
|
@ -251,7 +251,10 @@ void KostalInverterProtocol::receive_RS485() // Runs as fast as possible to han
|
|||
int code = RS485_RXFRAME[6] + RS485_RXFRAME[7] * 0x100;
|
||||
if (code == 0x44a) {
|
||||
//Send cyclic data
|
||||
update_values_battery();
|
||||
// TODO: Probably not a good idea to use the battery object here like this.
|
||||
if (battery) {
|
||||
battery->update_values();
|
||||
}
|
||||
update_values();
|
||||
if (f2_startup_count < 15) {
|
||||
f2_startup_count++;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue