-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eb5eeb6
commit 2fafe32
Showing
10 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/target/ | ||
/.classpath | ||
/.project | ||
/.settings/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>com.ai-republic.bms-to-inverter</groupId> | ||
<artifactId>bms-to-inverter-parent</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>bms-narada-modbus</artifactId> | ||
|
||
<name>${project.artifactId}-${project.version}</name> | ||
<description>Module for the Narada BMS ModBus support</description> | ||
|
||
<properties> | ||
<encoding>UTF-8</encoding> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.ai-republic.bms-to-inverter</groupId> | ||
<artifactId>protocol-modbus</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
47 changes: 47 additions & 0 deletions
47
...c/main/java/com/airepublic/bmstoinverter/bms/narada/modbus/NaradaBmsModbusDescriptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* This software is free to use and to distribute in its unchanged form for private use. | ||
* Commercial use is prohibited without an explicit license agreement of the copyright holder. | ||
* Any changes to this software must be made solely in the project repository at https://github.com/ai-republic/bms-to-inverter. | ||
* The copyright holder is not liable for any damages in whatever form that may occur by using this software. | ||
* | ||
* (c) Copyright 2022 and onwards - Torsten Oltmanns | ||
* | ||
* @author Torsten Oltmanns - bms-to-inverter''AT''gmail.com | ||
*/ | ||
package com.airepublic.bmstoinverter.bms.narada.modbus; | ||
|
||
import com.airepublic.bmstoinverter.core.BMS; | ||
import com.airepublic.bmstoinverter.core.BMSConfig; | ||
import com.airepublic.bmstoinverter.core.BMSDescriptor; | ||
import com.airepublic.bmstoinverter.core.Port; | ||
import com.airepublic.bmstoinverter.protocol.modbus.J2ModMasterPort; | ||
|
||
/** | ||
* The {@link BMSDescriptor} for the Narada BMS using the Modbus protocol. | ||
*/ | ||
public class NaradaBmsModbusDescriptor implements BMSDescriptor { | ||
@Override | ||
public String getName() { | ||
return "NARADA_MODBUS"; | ||
} | ||
|
||
|
||
@Override | ||
public int getDefaultBaudRate() { | ||
return 9600; | ||
} | ||
|
||
|
||
@Override | ||
public Class<? extends BMS> getBMSClass() { | ||
return NaradaBmsModbusProcessor.class; | ||
} | ||
|
||
|
||
@Override | ||
public Port createPort(final BMSConfig config) { | ||
final Port port = new J2ModMasterPort(config.getPortLocator(), config.getBaudRate()); | ||
return port; | ||
} | ||
|
||
} |
152 changes: 152 additions & 0 deletions
152
...rc/main/java/com/airepublic/bmstoinverter/bms/narada/modbus/NaradaBmsModbusProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/** | ||
* This software is free to use and to distribute in its unchanged form for private use. | ||
* Commercial use is prohibited without an explicit license agreement of the copyright holder. | ||
* Any changes to this software must be made solely in the project repository at https://github.com/ai-republic/bms-to-inverter. | ||
* The copyright holder is not liable for any damages in whatever form that may occur by using this software. | ||
* | ||
* (c) Copyright 2022 and onwards - Torsten Oltmanns | ||
* | ||
* @author Torsten Oltmanns - bms-to-inverter''AT''gmail.com | ||
*/ | ||
package com.airepublic.bmstoinverter.bms.narada.modbus; | ||
|
||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.util.function.Consumer; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.airepublic.bmstoinverter.core.AlarmLevel; | ||
import com.airepublic.bmstoinverter.core.BMS; | ||
import com.airepublic.bmstoinverter.core.Port; | ||
import com.airepublic.bmstoinverter.core.bms.data.Alarm; | ||
import com.airepublic.bmstoinverter.core.bms.data.BatteryPack; | ||
import com.airepublic.bmstoinverter.core.bms.data.EnergyStorage; | ||
import com.airepublic.bmstoinverter.core.util.Util; | ||
import com.airepublic.bmstoinverter.protocol.modbus.ModbusUtil; | ||
import com.airepublic.bmstoinverter.protocol.modbus.ModbusUtil.RegisterCode; | ||
|
||
import jakarta.inject.Inject; | ||
|
||
/** | ||
* The class to handle Modbus messages from a Narada {@link BMS}. | ||
*/ | ||
public class NaradaBmsModbusProcessor extends BMS { | ||
private final static Logger LOG = LoggerFactory.getLogger(NaradaBmsModbusProcessor.class); | ||
@Inject | ||
private EnergyStorage energyStorage; | ||
|
||
@Override | ||
protected void collectData(final Port port) { | ||
try { | ||
sendMessage(port, RegisterCode.READ_INPUT_REGISTERS, 0x0FFF, 50, getBmsId(), this::readBatteryStatus); | ||
} catch (final IOException e) { | ||
LOG.error("Error reading from modbus!", e); | ||
} | ||
} | ||
|
||
|
||
protected void sendMessage(final Port port, final RegisterCode functionCode, final int startAddress, final int numRegisters, final int unitId, final Consumer<ByteBuffer> handler) throws IOException { | ||
port.sendFrame(ModbusUtil.createRequestBuffer(functionCode, startAddress, numRegisters, unitId)); | ||
handler.accept(port.receiveFrame()); | ||
} | ||
|
||
|
||
protected void readBatteryStatus(final ByteBuffer frame) { | ||
frame.getInt(); // functionCode | ||
frame.getInt(); // numRegisters | ||
final int unitId = frame.getInt(); | ||
final BatteryPack pack = energyStorage.getBatteryPack(unitId); | ||
|
||
pack.packVoltage = frame.getShort() / 10; // 0.01V | ||
pack.packCurrent = frame.getShort() - 10000; // 0.1A | ||
pack.remainingCapacitymAh = frame.getShort() * 100; // 0.1A | ||
pack.tempAverage = frame.getShort() - 400; // 0.1C - 400 | ||
frame.getShort(); // env temp 0.1C - 400 | ||
final int warningFlag = frame.getChar(); | ||
final int protectionFlag = frame.getShort(); | ||
final int statusFlag = frame.getShort(); | ||
pack.packSOC = frame.getShort() / 10; // 0.01% | ||
pack.bmsCycles = frame.getShort(); | ||
pack.packSOH = frame.getShort() / 10; // 0.01% | ||
frame.getShort(); // history discharge capacity 10A | ||
pack.numberOfCells = frame.getShort(); | ||
|
||
// determine min/max cell voltages | ||
for (int i = 0; i < 16; i++) { | ||
if (i < pack.numberOfCells) { | ||
pack.cellVmV[i] = frame.getShort(); | ||
|
||
if (pack.cellVmV[i] > pack.maxCellmV) { | ||
pack.maxCellmV = pack.cellVmV[i]; | ||
pack.maxCellVNum = i; | ||
} else if (pack.cellVmV[i] < pack.minCellmV) { | ||
pack.minCellmV = pack.cellVmV[i]; | ||
pack.minCellVNum = i; | ||
} | ||
} else { | ||
frame.getShort(); | ||
} | ||
} | ||
|
||
// calculate cell voltage difference | ||
pack.cellDiffmV = pack.maxCellmV - pack.minCellmV; | ||
|
||
pack.numOfTempSensors = frame.getShort(); | ||
|
||
for (int i = 0; i < 16; i++) { | ||
if (i < pack.numOfTempSensors) { | ||
pack.cellTemperature[i] = frame.getShort() - 400; // 0.1C - 400 | ||
} else { | ||
frame.getShort(); | ||
} | ||
} | ||
|
||
pack.ratedCapacitymAh = frame.getShort() * 100; // 0.1A | ||
frame.getShort(); // remaining charge time 1min | ||
frame.getShort(); // remaining discharge time 1min | ||
final int cellUVStatus = frame.getShort(); // Cell undervoltage state | ||
|
||
readAlarms(pack, warningFlag, protectionFlag, statusFlag, cellUVStatus); | ||
} | ||
|
||
|
||
private void readAlarms(final BatteryPack pack, final int warningFlag, final int protectionFlag, final int faultStatus, final int cellUVStatus) { | ||
// warnings | ||
pack.alarms.put(Alarm.CELL_VOLTAGE_HIGH, Util.bit(warningFlag, 0) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CELL_VOLTAGE_LOW, Util.bit(warningFlag, 1) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.PACK_VOLTAGE_HIGH, Util.bit(warningFlag, 2) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.PACK_VOLTAGE_LOW, Util.bit(warningFlag, 3) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CHARGE_CURRENT_HIGH, Util.bit(warningFlag, 4) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.DISCHARGE_CURRENT_HIGH, Util.bit(warningFlag, 5) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CELL_TEMPERATURE_HIGH, Util.bit(warningFlag, 6) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CELL_TEMPERATURE_LOW, Util.bit(warningFlag, 7) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.ENCASING_TEMPERATURE_HIGH, Util.bit(warningFlag, 8) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
|
||
pack.alarms.put(Alarm.CHARGE_MODULE_TEMPERATURE_HIGH, Util.bit(warningFlag, 10) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.SOC_LOW, Util.bit(warningFlag, 11) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CELL_VOLTAGE_DIFFERENCE_HIGH, Util.bit(warningFlag, 12) ? AlarmLevel.WARNING : AlarmLevel.NONE); | ||
|
||
// alarms | ||
pack.alarms.put(Alarm.CELL_VOLTAGE_HIGH, Util.bit(protectionFlag, 0) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CELL_VOLTAGE_LOW, Util.bit(protectionFlag, 1) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.PACK_VOLTAGE_HIGH, Util.bit(protectionFlag, 2) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.PACK_VOLTAGE_LOW, Util.bit(protectionFlag, 3) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.FAILURE_SHORT_CIRCUIT_PROTECTION, Util.bit(protectionFlag, 4) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
|
||
pack.alarms.put(Alarm.CHARGE_TEMPERATURE_HIGH, Util.bit(protectionFlag, 6) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.CHARGE_TEMPERATURE_LOW, Util.bit(protectionFlag, 7) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.DISCHARGE_TEMPERATURE_HIGH, Util.bit(protectionFlag, 8) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.DISCHARGE_TEMPERATURE_LOW, Util.bit(protectionFlag, 9) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
|
||
// fault | ||
pack.alarms.put(Alarm.FAILURE_COMMUNICATION_INTERNAL, Util.bit(faultStatus, 0) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
pack.alarms.put(Alarm.FAILURE_SENSOR_PACK_TEMPERATURE, Util.bit(faultStatus, 1) ? AlarmLevel.ALARM : AlarmLevel.NONE); | ||
|
||
pack.chargeDischargeStatus = Util.bit(faultStatus, 8) ? 1 : Util.bit(faultStatus, 9) ? 2 : 0; | ||
pack.chargeMOSState = Util.bit(faultStatus, 9); | ||
pack.dischargeMOSState = Util.bit(faultStatus, 10); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" | ||
bean-discovery-mode="all" version="4.0"> | ||
|
||
</beans> |
1 change: 1 addition & 0 deletions
1
...dbus/src/main/resources/META-INF/services/com.airepublic.bmstoinverter.core.BMSDescriptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
com.airepublic.bmstoinverter.bms.narada.modbus.NaradaBmsModbusDescriptor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters