Skip to content

Commit

Permalink
Merge pull request #276 from dalathegreat/refactor/inverter-can-send
Browse files Browse the repository at this point in the history
Refactor: Inverter handling
  • Loading branch information
dalathegreat authored Apr 30, 2024
2 parents 73c46a7 + a6ec991 commit a58c570
Show file tree
Hide file tree
Showing 20 changed files with 81 additions and 182 deletions.
166 changes: 35 additions & 131 deletions Software/Software.ino
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ ACAN2517FD canfd(MCP2517_CS, SPI, MCP2517_INT);
#endif

// ModbusRTU parameters
#if defined(BYD_MODBUS) || defined(LUNA2000_MODBUS)
#ifdef MODBUS_INVERTER_SELECTED
#define MB_RTU_NUM_VALUES 30000
uint16_t mbPV[MB_RTU_NUM_VALUES]; // Process variable memory
// Create a ModbusRTU server instance listening on Serial2 with 2000ms timeout
Expand Down Expand Up @@ -135,7 +135,7 @@ void setup() {

init_serialDataLink();

inform_user_on_inverter();
init_inverter();

init_battery();

Expand Down Expand Up @@ -416,7 +416,7 @@ void init_contactors() {
}

void init_modbus() {
#if defined(BYD_MODBUS) || defined(LUNA2000_MODBUS)
#ifdef MODBUS_INVERTER_SELECTED
// Set up Modbus RTU Server
pinMode(RS485_EN_PIN, OUTPUT);
digitalWrite(RS485_EN_PIN, HIGH);
Expand All @@ -443,50 +443,10 @@ 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
}

Expand All @@ -510,99 +470,61 @@ 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);
#endif
// Inverter
#ifdef BYD_CAN
receive_can_byd(rx_frame);
// Battery
#ifndef SERIAL_LINK_RECEIVER // Only needs to see inverter
receive_can_battery(rx_frame);
#endif
#ifdef SMA_CAN
receive_can_sma(rx_frame);
// Inverter
#ifdef CAN_INVERTER_SELECTED
receive_can_inverter(rx_frame);
#endif
#ifdef SMA_TRIPOWER_CAN
receive_can_sma_tripower(rx_frame);
// Charger
#ifdef CHARGER_SELECTED
receive_can_charger(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
}

#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
Expand Down Expand Up @@ -732,31 +654,13 @@ void update_SOC() {

void update_values() {
// Battery
update_values_battery(); // Map the fake values to the correct registers
update_values_battery();
// Inverter
#ifdef BYD_CAN
update_values_can_byd();
#endif
#ifdef BYD_MODBUS
update_modbus_registers_byd();
#ifdef CAN_INVERTER_SELECTED
update_values_can_inverter();
#endif
#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();
#ifdef MODBUS_INVERTER_SELECTED
update_modbus_registers_inverter();
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion Software/src/include.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#error CAN-FD AND DUAL-CAN CANNOT BE USED SIMULTANEOUSLY
#endif

#if defined(BYD_MODBUS) || defined(LUNA2000_MODBUS)
#ifdef MODBUS_INVERTER_SELECTED
#if defined(SERIAL_LINK_RECEIVER) || defined(SERIAL_LINK_TRANSMITTER)
// Check that Dual LilyGo via RS485 option isn't enabled, this collides with Modbus!
#error MODBUS CANNOT BE USED IN DOUBLE LILYGO SETUPS! CHECK USER SETTINGS!
Expand Down
6 changes: 3 additions & 3 deletions Software/src/inverter/BYD-CAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) /
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 1 addition & 5 deletions Software/src/inverter/BYD-CAN.h
Original file line number Diff line number Diff line change
@@ -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
3 changes: 1 addition & 2 deletions Software/src/inverter/BYD-MODBUS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
#include "../datalayer/datalayer.h"
#include "BYD-MODBUS.h"

void update_modbus_registers_byd() {
//Updata for ModbusRTU Server for BYD
void update_modbus_registers_inverter() {
verify_temperature_modbus();
handle_update_data_modbusp201_byd();
handle_update_data_modbusp301_byd();
Expand Down
3 changes: 1 addition & 2 deletions Software/src/inverter/BYD-MODBUS.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define BYD_MODBUS_H
#include "../include.h"

#define INVERTER_SELECTED
#define MODBUS_INVERTER_SELECTED

#define MB_RTU_NUM_VALUES 30000
#define MAX_POWER 40960 //BYD Modbus specific value
Expand All @@ -13,5 +13,4 @@ void handle_static_data_modbus_byd();
void verify_temperature_modbus();
void handle_update_data_modbusp201_byd();
void handle_update_data_modbusp301_byd();
void update_modbus_registers_byd();
#endif
11 changes: 11 additions & 0 deletions Software/src/inverter/INVERTERS.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,15 @@
#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

#ifdef MODBUS_INVERTER_SELECTED
void update_modbus_registers_inverter();
#endif

#endif
3 changes: 1 addition & 2 deletions Software/src/inverter/LUNA2000-MODBUS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
#include "../datalayer/datalayer.h"
#include "LUNA2000-MODBUS.h"

void update_modbus_registers_luna2000() {
//Updata for ModbusRTU Server for Luna2000
void update_modbus_registers_inverter() {
handle_update_data_modbus32051();
handle_update_data_modbus39500();
}
Expand Down
3 changes: 1 addition & 2 deletions Software/src/inverter/LUNA2000-MODBUS.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
#define LUNA2000_MODBUS_H
#include "../include.h"

#define INVERTER_SELECTED
#define MODBUS_INVERTER_SELECTED

#define MB_RTU_NUM_VALUES 30000

extern uint16_t mbPV[MB_RTU_NUM_VALUES];

void update_modbus_registers_luna2000();
void handle_update_data_modbus32051();
void handle_update_data_modbus39500();
#endif
8 changes: 6 additions & 2 deletions Software/src/inverter/PYLON-CAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down
Loading

0 comments on commit a58c570

Please sign in to comment.