mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-04 18:29:48 +02:00
Refactor CAN inverter handling
This commit is contained in:
parent
6f4831f4cd
commit
3aa5704d74
15 changed files with 68 additions and 165 deletions
|
@ -135,7 +135,7 @@ void setup() {
|
|||
|
||||
init_serialDataLink();
|
||||
|
||||
inform_user_on_inverter();
|
||||
init_inverter();
|
||||
|
||||
init_battery();
|
||||
|
||||
|
@ -443,50 +443,11 @@ void init_modbus() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void inform_user_on_inverter() {
|
||||
// Inform user what Inverter is used
|
||||
#ifdef BYD_CAN
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BYD CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BYD_MODBUS
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("BYD Modbus RTU protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef LUNA2000_MODBUS
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Luna2000 Modbus RTU protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef PYLON_CAN
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("PYLON CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SMA_CAN
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("SMA CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("SMA Tripower CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("SOFAR CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
void init_inverter() {
|
||||
|
||||
#ifdef SOLAX_CAN
|
||||
datalayer.system.status.inverter_allows_contactor_closing =
|
||||
false; // The inverter needs to allow first on this protocol
|
||||
datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first
|
||||
intervalUpdateValues = 800; // This protocol also requires the values to be updated faster
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("SOLAX CAN protocol selected");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -510,58 +471,30 @@ void receive_can() { // This section checks if we have a complete CAN message i
|
|||
// Depending on which battery/inverter is selected, we forward this to their respective CAN routines
|
||||
CAN_frame_t rx_frame;
|
||||
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 0) == pdTRUE) {
|
||||
if (rx_frame.FIR.B.FF == CAN_frame_std) { // New standard frame
|
||||
// Battery
|
||||
#ifndef SERIAL_LINK_RECEIVER
|
||||
receive_can_battery(rx_frame);
|
||||
// Battery
|
||||
#ifndef SERIAL_LINK_RECEIVER // Only needs to see inverter
|
||||
receive_can_battery(rx_frame);
|
||||
#endif
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
receive_can_byd(rx_frame);
|
||||
// Inverter
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
receive_can_inverter(rx_frame);
|
||||
#endif
|
||||
#ifdef SMA_CAN
|
||||
receive_can_sma(rx_frame);
|
||||
// Charger
|
||||
#ifdef CHARGER_SELECTED
|
||||
receive_can_charger(rx_frame);
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
receive_can_sma_tripower(rx_frame);
|
||||
#endif
|
||||
// Charger
|
||||
#if defined(CHEVYVOLT_CHARGER) || defined(NISSANLEAF_CHARGER)
|
||||
receive_can_charger(rx_frame);
|
||||
#endif
|
||||
} else { // New extended frame
|
||||
#ifdef PYLON_CAN
|
||||
receive_can_pylon(rx_frame);
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
receive_can_sofar(rx_frame);
|
||||
#endif
|
||||
#ifdef SOLAX_CAN
|
||||
receive_can_solax(rx_frame);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_can() {
|
||||
// Send CAN messages
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
send_can_byd();
|
||||
#endif
|
||||
#ifdef SMA_CAN
|
||||
send_can_sma();
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
send_can_sma_tripower();
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
send_can_sofar();
|
||||
#endif
|
||||
// Battery
|
||||
send_can_battery();
|
||||
// Inverter
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
send_can_inverter();
|
||||
#endif
|
||||
// Charger
|
||||
#if defined(CHEVYVOLT_CHARGER) || defined(NISSANLEAF_CHARGER)
|
||||
#ifdef CHARGER_SELECTED
|
||||
send_can_charger();
|
||||
#endif
|
||||
}
|
||||
|
@ -569,40 +502,30 @@ void send_can() {
|
|||
#ifdef DUAL_CAN
|
||||
void receive_can2() { // This function is similar to receive_can, but just takes care of inverters in the 2nd bus.
|
||||
// Depending on which inverter is selected, we forward this to their respective CAN routines
|
||||
CAN_frame_t rx_frame2; // Struct with ESP32Can library format, compatible with the rest of the program
|
||||
CANMessage MCP2515Frame; // Struct with ACAN2515 library format, needed to use thw MCP2515 library
|
||||
CAN_frame_t rx_frame_can2; // Struct with ESP32Can library format, compatible with the rest of the program
|
||||
CANMessage MCP2515Frame; // Struct with ACAN2515 library format, needed to use thw MCP2515 library
|
||||
|
||||
if (can.available()) {
|
||||
can.receive(MCP2515Frame);
|
||||
|
||||
rx_frame2.MsgID = MCP2515Frame.id;
|
||||
rx_frame2.FIR.B.FF = MCP2515Frame.ext ? CAN_frame_ext : CAN_frame_std;
|
||||
rx_frame2.FIR.B.RTR = MCP2515Frame.rtr ? CAN_RTR : CAN_no_RTR;
|
||||
rx_frame2.FIR.B.DLC = MCP2515Frame.len;
|
||||
rx_frame_can2.MsgID = MCP2515Frame.id;
|
||||
rx_frame_can2.FIR.B.FF = MCP2515Frame.ext ? CAN_frame_ext : CAN_frame_std;
|
||||
rx_frame_can2.FIR.B.RTR = MCP2515Frame.rtr ? CAN_RTR : CAN_no_RTR;
|
||||
rx_frame_can2.FIR.B.DLC = MCP2515Frame.len;
|
||||
for (uint8_t i = 0; i < MCP2515Frame.len; i++) {
|
||||
rx_frame2.data.u8[i] = MCP2515Frame.data[i];
|
||||
rx_frame_can2.data.u8[i] = MCP2515Frame.data[i];
|
||||
}
|
||||
|
||||
if (rx_frame2.FIR.B.FF == CAN_frame_std) { // New standard frame
|
||||
#ifdef BYD_CAN
|
||||
receive_can_byd(rx_frame2);
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
receive_can_inverter(rx_frame_can2);
|
||||
#endif
|
||||
} else { // New extended frame
|
||||
#ifdef PYLON_CAN
|
||||
receive_can_pylon(rx_frame2);
|
||||
#endif
|
||||
#ifdef SOLAX_CAN
|
||||
receive_can_solax(rx_frame2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_can2() {
|
||||
// Send CAN
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
send_can_byd();
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
send_can_inverter(); //Note this will only send to CAN1, unless we use SOLAX
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -734,8 +657,8 @@ void update_values() {
|
|||
// Battery
|
||||
update_values_battery(); // Map the fake values to the correct registers
|
||||
// Inverter
|
||||
#ifdef BYD_CAN
|
||||
update_values_can_byd();
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
update_values_can_inverter();
|
||||
#endif
|
||||
#ifdef BYD_MODBUS
|
||||
update_modbus_registers_byd();
|
||||
|
@ -743,21 +666,6 @@ void update_values() {
|
|||
#ifdef LUNA2000_MODBUS
|
||||
update_modbus_registers_luna2000();
|
||||
#endif
|
||||
#ifdef PYLON_CAN
|
||||
update_values_can_pylon();
|
||||
#endif
|
||||
#ifdef SMA_CAN
|
||||
update_values_can_sma();
|
||||
#endif
|
||||
#ifdef SMA_TRIPOWER_CAN
|
||||
update_values_can_sma_tripower();
|
||||
#endif
|
||||
#ifdef SOFAR_CAN
|
||||
update_values_can_sofar();
|
||||
#endif
|
||||
#ifdef SOLAX_CAN
|
||||
update_values_can_solax();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER)
|
||||
|
|
|
@ -114,7 +114,7 @@ static uint16_t inverter_SOC = 0;
|
|||
static long inverter_timestamp = 0;
|
||||
static bool initialDataSent = 0;
|
||||
|
||||
void update_values_can_byd() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
//Calculate values
|
||||
charge_current =
|
||||
((datalayer.battery.status.max_charge_power_W * 10) /
|
||||
|
@ -199,7 +199,7 @@ void update_values_can_byd() { //This function maps all the values fetched from
|
|||
#endif
|
||||
}
|
||||
|
||||
void receive_can_byd(CAN_frame_t rx_frame) {
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x151: //Message originating from BYD HVS compatible inverter. Reply with CAN identifier!
|
||||
if (rx_frame.data.u8[0] & 0x01) { //Battery requests identification
|
||||
|
@ -229,7 +229,7 @@ void receive_can_byd(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_byd() {
|
||||
void send_can_inverter() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send initial CAN data once on bootup
|
||||
if (!initialDataSent) {
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
#ifndef BYD_CAN_H
|
||||
#define BYD_CAN_H
|
||||
#include <Arduino.h>
|
||||
#include "../include.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
void update_values_can_byd();
|
||||
void send_can_byd();
|
||||
void receive_can_byd(CAN_frame_t rx_frame);
|
||||
void send_intial_data();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,4 +39,11 @@
|
|||
#include "SERIAL-LINK-TRANSMITTER-INVERTER.h"
|
||||
#endif
|
||||
|
||||
#ifdef CAN_INVERTER_SELECTED
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" // This include is annoying, consider defining a frame type in types.h
|
||||
void update_values_can_inverter();
|
||||
void receive_can_inverter(CAN_frame_t rx_frame);
|
||||
void send_can_inverter();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -170,7 +170,7 @@ CAN_frame_t PYLON_4291 = {.FIR = {.B =
|
|||
.MsgID = 0x4291,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
void update_values_can_pylon() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
//There are more mappings that could be added, but this should be enough to use as a starting point
|
||||
// Note we map both 0 and 1 messages
|
||||
|
||||
|
@ -243,7 +243,7 @@ void update_values_can_pylon() { //This function maps all the values fetched fr
|
|||
}
|
||||
}
|
||||
|
||||
void receive_can_pylon(CAN_frame_t rx_frame) {
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x4200: //Message originating from inverter. Depending on which data is required, act accordingly
|
||||
if (rx_frame.data.u8[0] == 0x02) {
|
||||
|
@ -258,6 +258,10 @@ void receive_can_pylon(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_inverter() {
|
||||
// No periodic sending, we only react on received can messages
|
||||
}
|
||||
|
||||
void send_setup_info() { //Ensemble information
|
||||
#ifdef SEND_0
|
||||
ESP32Can.CANWriteFrame(&PYLON_7310);
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
#include "../include.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
void update_values_can_pylon();
|
||||
void receive_can_pylon(CAN_frame_t rx_frame);
|
||||
void send_system_data();
|
||||
void send_setup_info();
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include "../include.h"
|
||||
#include "../lib/mackelec-SerialDataLink/SerialDataLink.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
|
||||
void manageSerialLinkTransmitter();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,7 +103,7 @@ static int16_t charge_current = 0;
|
|||
static int16_t temperature_average = 0;
|
||||
static uint16_t ampere_hours_remaining = 0;
|
||||
|
||||
void update_values_can_sma() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
//Calculate values
|
||||
charge_current =
|
||||
((datalayer.battery.status.max_charge_power_W * 10) /
|
||||
|
@ -226,7 +226,7 @@ void update_values_can_sma() { //This function maps all the values fetched from
|
|||
*/
|
||||
}
|
||||
|
||||
void receive_can_sma(CAN_frame_t rx_frame) {
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x360: //Message originating from SMA inverter - Voltage and current
|
||||
//Frame0-1 Voltage
|
||||
|
@ -246,7 +246,7 @@ void receive_can_sma(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_sma() {
|
||||
void send_can_inverter() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// Send CAN Message every 100ms
|
||||
|
|
|
@ -3,13 +3,9 @@
|
|||
#include "../include.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
#define READY_STATE 0x03
|
||||
#define STOP_STATE 0x02
|
||||
|
||||
void update_values_can_sma();
|
||||
void send_can_sma();
|
||||
void receive_can_sma(CAN_frame_t rx_frame);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -161,7 +161,7 @@ Command2Battery command2Battery = RUN;
|
|||
enum InvInitState { SYSTEM_FREQUENCY, XPHASE_SYSTEM, BLACKSTART_OPERATION };
|
||||
InvInitState invInitState = SYSTEM_FREQUENCY;
|
||||
|
||||
void update_values_can_sma_tripower() { //This function maps all the values fetched from battery CAN to the inverter CAN
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the inverter CAN
|
||||
//Calculate values
|
||||
charge_current =
|
||||
((datalayer.battery.status.max_charge_power_W * 10) /
|
||||
|
@ -328,7 +328,7 @@ void update_values_can_sma_tripower() { //This function maps all the values fet
|
|||
//SMA_018.data.u8[7] = BatteryName;
|
||||
}
|
||||
|
||||
void receive_can_sma_tripower(CAN_frame_t rx_frame) {
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) {
|
||||
case 0x00D: //Inverter Measurements
|
||||
break;
|
||||
|
@ -347,7 +347,7 @@ void receive_can_sma_tripower(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_sma_tripower() {
|
||||
void send_can_inverter() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// Send CAN Message every 500ms
|
||||
|
|
|
@ -3,11 +3,8 @@
|
|||
#include "../include.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
void update_values_can_sma_tripower();
|
||||
void send_can_sma_tripower();
|
||||
void receive_can_sma_tripower(CAN_frame_t rx_frame);
|
||||
void send_tripower_init();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -280,7 +280,7 @@ CAN_frame_t SOFAR_7C0 = {.FIR = {.B =
|
|||
.MsgID = 0x7C0,
|
||||
.data = {0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x80, 0x00}};
|
||||
|
||||
void update_values_can_sofar() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
|
||||
//Maxvoltage (eg 400.0V = 4000 , 16bits long) Charge Cutoff Voltage
|
||||
SOFAR_351.data.u8[0] = (datalayer.battery.info.max_design_voltage_dV >> 8);
|
||||
|
@ -308,7 +308,7 @@ void update_values_can_sofar() { //This function maps all the values fetched fr
|
|||
SOFAR_356.data.u8[3] = (datalayer.battery.status.temperature_max_dC & 0x00FF);
|
||||
}
|
||||
|
||||
void receive_can_sofar(CAN_frame_t rx_frame) {
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
switch (rx_frame.MsgID) { //In here we need to respond to the inverter. TODO: make logic
|
||||
case 0x605:
|
||||
//frame1_605 = rx_frame.data.u8[1];
|
||||
|
@ -323,7 +323,7 @@ void receive_can_sofar(CAN_frame_t rx_frame) {
|
|||
}
|
||||
}
|
||||
|
||||
void send_can_sofar() {
|
||||
void send_can_inverter() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 100ms CAN Message
|
||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
#include "../include.h"
|
||||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
|
||||
void update_values_can_sofar();
|
||||
void send_can_sofar();
|
||||
void receive_can_sofar(CAN_frame_t rx_frame);
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
#endif
|
||||
|
|
|
@ -121,7 +121,7 @@ void CAN_WriteFrame(CAN_frame_t* tx_frame) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void update_values_can_solax() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the correct CAN messages
|
||||
// If not receiveing any communication from the inverter, open contactors and return to battery announce state
|
||||
if (millis() - LastFrameTime >= SolaxTimeout) {
|
||||
datalayer.system.status.inverter_allows_contactor_closing = false;
|
||||
|
@ -237,7 +237,11 @@ void update_values_can_solax() { //This function maps all the values fetched fr
|
|||
SOLAX_1801.data.u8[4] = 1;
|
||||
}
|
||||
|
||||
void receive_can_solax(CAN_frame_t rx_frame) {
|
||||
void send_can_inverter() {
|
||||
// No periodic sending used on this protocol, we react only on incoming CAN messages!
|
||||
}
|
||||
|
||||
void receive_can_inverter(CAN_frame_t rx_frame) {
|
||||
if (rx_frame.MsgID == 0x1871 && rx_frame.data.u8[0] == (0x01) ||
|
||||
rx_frame.MsgID == 0x1871 && rx_frame.data.u8[0] == (0x02)) {
|
||||
LastFrameTime = millis();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h"
|
||||
#include "../lib/pierremolinaro-acan2515/ACAN2515.h"
|
||||
|
||||
#define INVERTER_SELECTED
|
||||
#define CAN_INVERTER_SELECTED
|
||||
|
||||
extern ACAN2515 can;
|
||||
|
||||
|
@ -18,6 +18,5 @@ extern ACAN2515 can;
|
|||
#define FAULT_SOLAX 3
|
||||
#define UPDATING_FW 4
|
||||
|
||||
void update_values_can_solax();
|
||||
void receive_can_solax(CAN_frame_t rx_frame);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue