Skip to content

Commit

Permalink
JK Inverter BMS (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
shining-man committed Jul 2, 2024
1 parent 74409c7 commit fd63b1b
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 45 deletions.
61 changes: 31 additions & 30 deletions include/BmsData.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,36 @@

struct bmsData_s
{
// N | J | J | S | J | D | S | J | G | G | S | B | S |
// E | b | K | e | K | A | Y | K | O | O | M | P | e |
// E | d | | p | | L | L | | B | B | A | N | p |
// Y | | | l | B | Y | C | V | E | E | R | | l |
// 4 | | | o | T | | I | 1 | L | L | T | | o |
// A | | | s | | | N | 3 | | | S | | s |
// | | | | | | | | R | P | H | | |
// | | | | | | | | N | C | U | | v |
// | | | | | | | | 1 | 2 | N | | 3 |
// | | | | | | | | 5 | 0 | T | | |
// | | | | | | | | 0 | 0 | | | |
//---|---|---|---|---|---|---|---|---|---|---|---|---|
uint16_t bmsCellVoltage[BMSDATA_NUMBER_ALLDEVICES][24]; // x | x | x | x | | x | x | x | x | x | | | x |
//float bmsCellResistance[BMSDATA_NUMBER_ALLDEVICES][24]; // x | | | | | | | | | | | | |
int16_t bmsTotalVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | x | | x |
uint16_t bmsMaxCellDifferenceVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | | | x |
uint16_t bmsAvgVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | | | x |
int16_t bmsTotalCurrent[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | | x | x | - | x | x | x | | x |
uint16_t bmsMaxCellVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | c | x | x | | | x |
uint16_t bmsMinCellVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | c | x | x | | | x |
uint8_t bmsMaxVoltageCellNumber[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | c | x | x | | | x |
uint8_t bmsMinVoltageCellNumber[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | c | x | x | | | x |
uint8_t bmsIsBalancingActive[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | x | | | | | x |
int16_t bmsBalancingCurrent[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | | | x | | | | | |
int16_t bmsTempature[BMSDATA_NUMBER_ALLDEVICES][3]; // 2 | 3 | 3 | 3 | | 3 | 3 | x | 3 | 3 | | | x |
uint8_t bmsChargePercentage[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | | x | x | - | x | x | x | | x |
uint32_t bmsErrors[BMSDATA_NUMBER_ALLDEVICES]; // * | x | x | | | | x | * | x | x | | | x |
uint32_t bmsWarnings[BMSDATA_NUMBER_ALLDEVICES]; // | | | x | | | | | | | | | |
uint8_t bmsStateFETs[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | x | x | x | - | - | - | | | x | bit 0=FET charge, bit 1=FET discharge
unsigned long bmsLastDataMillis[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | x | | x | x | x | x | | | x |
// N | J | J | S | J | D | S | J | G | G | S | B | S | J |
// E | b | K | e | K | A | Y | K | O | O | M | P | e | K |
// E | d | | p | | L | L | | B | B | A | N | p | |
// Y | | | l | B | Y | C | V | E | E | R | | l | I |
// 4 | | | o | T | | I | 1 | L | L | T | | o | N |
// A | | | s | | | N | 3 | | | S | | s | V |
// | | | | | | | | R | P | H | | | . |
// | | | | | | | | N | C | U | | v | |
// | | | | | | | | 1 | 2 | N | | 3 | |
// | | | | | | | | 5 | 0 | T | | | |
// | | | | | | | | 0 | 0 | | | | |
//---|---|---|---|---|---|---|---|---|---|---|---|---|---|
uint16_t bmsCellVoltage[BMSDATA_NUMBER_ALLDEVICES][24]; // x | x | x | x | | x | x | x | x | x | | | x | x |
//float bmsCellResistance[BMSDATA_NUMBER_ALLDEVICES][24]; // x | | | | | | | | | | | | | |
int16_t bmsTotalVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | x | | x | x |
uint16_t bmsMaxCellDifferenceVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | | | x | x |
uint16_t bmsAvgVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | x | x | x | | | x | x |
int16_t bmsTotalCurrent[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | | x | x | - | x | x | x | | x | x |
uint16_t bmsMaxCellVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | c | x | x | | | x | x |
uint16_t bmsMinCellVoltage[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | | x | x | c | x | x | | | x | x |
uint8_t bmsMaxVoltageCellNumber[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | c | x | x | | | x | x |
uint8_t bmsMinVoltageCellNumber[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | c | x | x | | | x | x |
uint8_t bmsIsBalancingActive[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | x | | x | | | | | x | x |
int16_t bmsBalancingCurrent[BMSDATA_NUMBER_ALLDEVICES]; // x | | | | | | | x | | | | | | x |
int16_t bmsTempature[BMSDATA_NUMBER_ALLDEVICES][3]; // 2 | 3 | 3 | 3 | | 3 | 3 | x | 3 | 3 | | | x | x |
uint8_t bmsChargePercentage[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | | x | x | - | x | x | x | | x | x |
uint32_t bmsErrors[BMSDATA_NUMBER_ALLDEVICES]; // * | x | x | | | | x | * | x | x | | | x | |
uint32_t bmsWarnings[BMSDATA_NUMBER_ALLDEVICES]; // | | | x | | | | | | | | | | |
uint8_t bmsStateFETs[BMSDATA_NUMBER_ALLDEVICES]; // - | x | x | x | x | x | x | - | - | - | | | x | | bit 0=FET charge, bit 1=FET discharge
unsigned long bmsLastDataMillis[BMSDATA_NUMBER_ALLDEVICES]; // x | x | x | x | x | | x | x | x | x | | | x | |
uint16_t bmsCellVoltageCrc[BMSDATA_NUMBER_ALLDEVICES]; // Wird nach dem Holen Daten vom BMS berechnet
uint8_t bmsLastChangeCellVoltageCrc[BMSDATA_NUMBER_ALLDEVICES]; // Wird nach dem Holen Daten vom BMS berechnet
// // *=Teilweise; -=Nicht verfügbar; c=wird berechnet
Expand Down Expand Up @@ -93,6 +93,7 @@ void setBmsIsBalancingActive(uint8_t devNr, uint8_t value);

float getBmsBalancingCurrent(uint8_t devNr);
void setBmsBalancingCurrent(uint8_t devNr, float value);
void setBmsBalancingCurrentI16(uint8_t devNr, int16_t value);

float getBmsTempature(uint8_t devNr, uint8_t sensorNr);
void setBmsTempature(uint8_t devNr, uint8_t sensorNr, float value);
Expand Down
6 changes: 6 additions & 0 deletions include/ModbusRTU.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ namespace modbusrtu
uint16_t getU16Value(uint16_t address);
int16_t getI16Value(uint16_t address);

uint8_t getU8ValueByOffset(uint16_t offset);
int8_t getI8ValueByOffset(uint16_t offset);
uint16_t getU16ValueByOffset(uint16_t offset);
int16_t getI16ValueByOffset(uint16_t offset);
uint32_t getU32ValueByOffset(uint16_t offset);
int32_t getI32ValueByOffset(uint16_t offset);


private:
Stream *mPort;
Expand Down
29 changes: 16 additions & 13 deletions include/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static const char COMPILE_DATE_TIME[] = "";
//#define WEBSET_DEBUG
//#define MAIN_DEBUG
//#define LOG_BMS_DATA
//#define JK_INV_DEBUG
#endif

#ifdef DEBUG_ON_HW_SERIAL
Expand All @@ -68,6 +69,7 @@ static const char COMPILE_DATE_TIME[] = "";
//#define WEBSET_DEBUG
#define MAIN_DEBUG
//#define LOG_BMS_DATA
//#define JK_INV_DEBUG
#endif

//Tests
Expand Down Expand Up @@ -436,20 +438,21 @@ enum serialDataRwTyp_e {BPN_NO_DATA, BPN_READ_SETTINGS, BPN_WRITE_READ_SETTINGS,
#define ID_BT_DEVICE_NEEY8A 4

//Auswahl Serial Geräte
#define ID_SERIAL_DEVICE_NB 0
#define ID_SERIAL_DEVICE_JBDBMS 1
#define ID_SERIAL_DEVICE_JKBMS 2
#define ID_SERIAL_DEVICE_SEPLOSBMS 3
#define ID_SERIAL_DEVICE_DALYBMS 4
#define ID_SERIAL_DEVICE_SYLCINBMS 5
#define ID_SERIAL_DEVICE_JKBMS_V13 6
#define ID_SERIAL_DEVICE_GOBELBMS 7
#define ID_SERIAL_DEVICE_JKBMS_CAN 8
#define ID_SERIAL_DEVICE_BPN 9
#define ID_SERIAL_DEVICE_NB 0
#define ID_SERIAL_DEVICE_JBDBMS 1
#define ID_SERIAL_DEVICE_JKBMS 2
#define ID_SERIAL_DEVICE_SEPLOSBMS 3
#define ID_SERIAL_DEVICE_DALYBMS 4
#define ID_SERIAL_DEVICE_SYLCINBMS 5
#define ID_SERIAL_DEVICE_JKBMS_V13 6
#define ID_SERIAL_DEVICE_GOBELBMS 7
#define ID_SERIAL_DEVICE_JKBMS_CAN 8
#define ID_SERIAL_DEVICE_BPN 9
#define ID_SERIAL_DEVICE_SMARTSHUNT_VEDIRECT 10
#define ID_SERIAL_DEVICE_GOBEL_PC200 11
#define ID_SERIAL_DEVICE_SEPLOSBMS_V3 12
#define ID_SERIAL_DEVICE_NEEY_4A 13
#define ID_SERIAL_DEVICE_GOBEL_PC200 11
#define ID_SERIAL_DEVICE_SEPLOSBMS_V3 12
#define ID_SERIAL_DEVICE_NEEY_4A 13
#define ID_SERIAL_DEVICE_JKINVERTERBMS 14

//Auswahl CAN Geräte
#define ID_CAN_DEVICE_NB 0
Expand Down
18 changes: 18 additions & 0 deletions include/devices/JkInverterBms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2024 tobias
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

#ifndef JK_INVERTER_BMS_H
#define JK_INVERTER_BMS_H

#include "Arduino.h"
#include "defines.h"
#include "devices/serialDevData.h"

#define JK_INVERTER_BMS_MAX_ANSWER_LEN 280


bool JkInverterBms_readBmsData(Stream *port, uint8_t devNr, void (*callback)(uint8_t, uint8_t), serialDevData_s *devData);

#endif
5 changes: 3 additions & 2 deletions include/params_py.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,15 @@ const String paramSerial PROGMEM = "{'page':["
"{'v':'"+String(ID_SERIAL_DEVICE_BPN)+"','l':'BPN (not use)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JBDBMS)+"','l':'JBD BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKBMS)+"','l':'JK BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKBMS_V13)+"','l':'JK BMS V1.3 (only monitoring)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKBMS_CAN)+"','l':'JK BMS - CAN (Test; only monitoring)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKINVERTERBMS)+"','l':'JK Inverter BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_SEPLOSBMS)+"','l':'Seplos BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_SEPLOSBMS_V3)+"','l':'Seplos V3 BMS (Test)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_DALYBMS)+"','l':'DALY BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_SYLCINBMS)+"','l':'Sylcin BMS'},"
"{'v':'"+String(ID_SERIAL_DEVICE_GOBELBMS)+"','l':'Gobel RN150 BMS (Test)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_GOBEL_PC200)+"','l':'Gobel PC200 BMS (Test)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKBMS_V13)+"','l':'JK BMS V1.3 (only monitoring)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_JKBMS_CAN)+"','l':'JK BMS - CAN (Test; only monitoring)'},"
// "{'v':'"+String(ID_SERIAL_DEVICE_NEEY_4A)+"','l':'NEEY 4A Balancer (Test)'},"
"{'v':'"+String(ID_SERIAL_DEVICE_SMARTSHUNT_VEDIRECT)+"','l':'Victron SmartShunt'}"
"],"
Expand Down
6 changes: 6 additions & 0 deletions src/BmsData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,12 @@ void setBmsBalancingCurrent(uint8_t devNr, float value)
bmsData.bmsBalancingCurrent[devNr] = (int16_t)(value*100);
xSemaphoreGive(mBmsDataMutex);
}
void setBmsBalancingCurrentI16(uint8_t devNr, int16_t value)
{
xSemaphoreTake(mBmsDataMutex, portMAX_DELAY);
bmsData.bmsBalancingCurrent[devNr] = value;
xSemaphoreGive(mBmsDataMutex);
}


float getBmsTempature(uint8_t devNr, uint8_t sensorNr)
Expand Down
6 changes: 6 additions & 0 deletions src/BscSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ void BscSerial::setReadBmsFunktion(uint8_t u8_devNr, uint8_t funktionsTyp)
serialDeviceData[u8_devNr].readBms = &NeeySerial_readBmsData;
break;

case ID_SERIAL_DEVICE_JKINVERTERBMS:
BSC_LOGI(TAG,"setReadBmsFunktion JK Inverter");
setSerialBaudrate(u8_devNr, 115200);
serialDeviceData[u8_devNr].readBms = &SeplosBmsV3_readBmsData;
break;

default:
serialDeviceData[u8_devNr].readBms = 0;
}
Expand Down
26 changes: 26 additions & 0 deletions src/ModbusRTU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,35 @@ int16_t ModbusRTU::getI16Value(uint16_t address)
}



uint8_t ModbusRTU::getU8ValueByOffset(uint16_t offset)
{
return mRetData[offset];
}

int8_t ModbusRTU::getI8ValueByOffset(uint16_t offset)
{
return (int8_t)getU8ValueByOffset(offset);
}

uint16_t ModbusRTU::getU16ValueByOffset(uint16_t offset)
{
return (mRetData[offset]<<8) | mRetData[offset+1];
}

int16_t ModbusRTU::getI16ValueByOffset(uint16_t offset)
{
return (int16_t)getU16ValueByOffset(offset);
}

uint32_t ModbusRTU::getU32ValueByOffset(uint16_t offset)
{
return (mRetData[offset]<<24) | (mRetData[offset+1]<<16) | (mRetData[offset+2]<<8) | mRetData[offset+3];
}

int32_t ModbusRTU::getI32ValueByOffset(uint16_t offset)
{
return (int32_t)getU32ValueByOffset(offset);
}

} // namespace modbusrtu
121 changes: 121 additions & 0 deletions src/devices/JkInverterBms.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2022 tobias
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

#include "devices/JkInverterBms.h"
#include "BmsData.h"
#include "mqtt_t.h"
#include "log.h"
#include "ModbusRTU.hpp"

static const char *TAG = "JK_INV_BMS";

static void parsePackInfo(modbusrtu::ModbusRTU *modbus, uint8_t devNr);

//static void message2Log(uint8_t * t_message, uint8_t len, uint8_t address);

static serialDevData_s *mDevData;

bool JkInverterBms_readBmsData(Stream *port, uint8_t devNr, void (*callback)(uint8_t, uint8_t), serialDevData_s *devData)
{
mDevData = devData;
uint8_t u8_mCountOfPacks = devData->u8_NumberOfDevices;
uint8_t response[JK_INVERTER_BMS_MAX_ANSWER_LEN];

uint8_t jkInvBmsAdr = devData->u8_deviceNr;
uint8_t jkInvBmsAdrBmsData = devData->u8_BmsDataAdr + BT_DEVICES_COUNT;

if(u8_mCountOfPacks>1) jkInvBmsAdr += 1;

#ifdef JK_INV_DEBUG
BSC_LOGI(TAG,"JkInverterBms_readBmsData() devNr=%i, readFromAdr=%i, BmsDataAdr=%i, CountOfPacks=%i",u8_mDevNr,jkInvBmsAdr,jkInvBmsAdrBmsData,u8_mCountOfPacks);
#endif

modbusrtu::ModbusRTU modbus(port,callback,devNr);

if(modbus.readData(jkInvBmsAdr, modbusrtu::ModbusRTU::fCode::READ_CMD_JK, 0x1200, 268, response))
{
//message2Log(response, 36, 0);
parsePackInfo(&modbus, jkInvBmsAdrBmsData);

// MQTT
mqttPublish(MQTT_TOPIC_BMS_BT, jkInvBmsAdrBmsData, MQTT_TOPIC2_TOTAL_VOLTAGE, -1, getBmsTotalVoltage(jkInvBmsAdrBmsData));
mqttPublish(MQTT_TOPIC_BMS_BT, jkInvBmsAdrBmsData, MQTT_TOPIC2_TOTAL_CURRENT, -1, getBmsTotalCurrent(jkInvBmsAdrBmsData));

vTaskDelay(pdMS_TO_TICKS(25));
}
else return false;


return true;
}


static void parsePackInfo(modbusrtu::ModbusRTU *modbus, uint8_t devNr)
{
// Cellvoltage
for(uint8_t i;i<24;i++) setBmsCellVoltage(devNr, i, modbus->getU16ValueByOffset(i*2));

// Avg. Voltage
setBmsAvgVoltage(devNr, modbus->getU16ValueByOffset(68));

// Max. Cell Dif.
setBmsMaxCellDifferenceVoltage(devNr, modbus->getU16ValueByOffset(70));

// Max. Cellvoltage
setBmsMaxVoltageCellNumber(devNr, modbus->getU8ValueByOffset(72));
setBmsMaxCellVoltage(devNr, getBmsCellVoltage(devNr, modbus->getU8ValueByOffset(72)));

// Min. Cellvoltage
setBmsMinVoltageCellNumber(devNr, modbus->getU8ValueByOffset(73));
setBmsMinCellVoltage(devNr, getBmsCellVoltage(devNr, modbus->getU8ValueByOffset(73)));

// Total Voltage
setBmsTotalVoltage_int(devNr, modbus->getU32ValueByOffset(144)/10);

// Total Current
setBmsTotalCurrent_int(devNr, modbus->getI32ValueByOffset(152)/10);

// Temperature
setBmsTempatureI16(devNr, 0, modbus->getI16ValueByOffset(156)*10);
setBmsTempatureI16(devNr, 1, modbus->getI16ValueByOffset(158)*10);

// Alarm
// ToDo

// Bal. Current
setBmsBalancingCurrentI16(devNr, modbus->getI16ValueByOffset(164)/10);

// Bal. State
setBmsIsBalancingActive(devNr, modbus->getU8ValueByOffset(166));

// SoC
setBmsChargePercentage(devNr, modbus->getU8ValueByOffset(167));

}




/*static void message2Log(uint8_t * t_message, uint8_t len, uint8_t address)
{
String recvBytes="";
uint8_t u8_logByteCount=0;
BSC_LOGI(TAG,"Dev=%i, RecvBytes=%i",address, len);
for(uint8_t x=0;x<len;x++)
{
u8_logByteCount++;
recvBytes+="0x";
recvBytes+=String(t_message[x],16);
recvBytes+=" ";
if(u8_logByteCount==20)
{
BSC_LOGI(TAG,"%s",recvBytes.c_str());
recvBytes="";
u8_logByteCount=0;
}
}
BSC_LOGI(TAG,"%s",recvBytes.c_str());
//log_print_buf(p_lRecvBytes, u8_lRecvBytesCnt);
}*/

0 comments on commit fd63b1b

Please sign in to comment.