Skip to content

Commit 5d0783d

Browse files
committed
Treat Pylon battery packs on one BMS as one battery pack
1 parent 6ad044f commit 5d0783d

1 file changed

Lines changed: 135 additions & 102 deletions

File tree

bms-pylon-rs485/src/main/java/com/airepublic/bmstoinverter/bms/pylon/rs485/PylonBmsRS485Processor.java

Lines changed: 135 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
*/
3636
public class PylonBmsRS485Processor extends BMS {
3737
private final static Logger LOG = LoggerFactory.getLogger(PylonBmsRS485Processor.class);
38+
private static final int BATTERY_PACK_ID = 0;
3839
private final Predicate<ByteBuffer> validator = buffer -> {
3940
// check if null
4041
if (buffer == null) {
@@ -62,15 +63,15 @@ public class PylonBmsRS485Processor extends BMS {
6263

6364
@Override
6465
protected void collectData(final Port port) throws TooManyInvalidFramesException, NoDataAvailableException, IOException {
65-
final int address = 0x10 + getBmsId();
66+
final int address = 0x12;
6667
for (int packId = 0; packId < getBatteryPacks().size(); packId++) {
6768
sendMessage(port, address, (byte) 0x46, (byte) 0x44, convertByteToAsciiBytes((byte) (packId + 1))); // warnings
6869
}
6970

7071
sendMessage(port, address, (byte) 0x46, (byte) 0x4F); // protocol version
7172
sendMessage(port, address, (byte) 0x46, (byte) 0x51); // manufacturer code
7273
sendMessage(port, address, (byte) 0x46, (byte) 0x92); // charge/discharge management
73-
sendMessage(port, address, (byte) 0x46, (byte) 0x42); // cell information
74+
sendMessage(port, address, (byte) 0x46, (byte) 0x42, convertByteToAsciiBytes((byte) 0xFF)); // cell information
7475
sendMessage(port, address, (byte) 0x46, (byte) 0x47); // max/min voltage/current limits
7576
sendMessage(port, address, (byte) 0x46, (byte) 0x60); // system information
7677
sendMessage(port, address, (byte) 0x46, (byte) 0x61); // battery information
@@ -79,13 +80,13 @@ protected void collectData(final Port port) throws TooManyInvalidFramesException
7980
}
8081

8182

82-
private List<ByteBuffer> sendMessage(final Port port, final int bmsId, final byte cid1, final byte cid2) throws TooManyInvalidFramesException, NoDataAvailableException, IOException {
83-
return sendMessage(port, bmsId, cid1, cid2, new byte[] {});
83+
private List<ByteBuffer> sendMessage(final Port port, final int address, final byte cid1, final byte cid2) throws TooManyInvalidFramesException, NoDataAvailableException, IOException {
84+
return sendMessage(port, address, cid1, cid2, new byte[] {});
8485
}
8586

8687

87-
private List<ByteBuffer> sendMessage(final Port port, final int bmsId, final byte cid1, final byte cid2, final byte[] msg) throws TooManyInvalidFramesException, NoDataAvailableException, IOException {
88-
final ByteBuffer sendBuffer = prepareSendFrame((byte) bmsId, cid1, cid2, msg);
88+
private List<ByteBuffer> sendMessage(final Port port, final int address, final byte cid1, final byte cid2, final byte[] msg) throws TooManyInvalidFramesException, NoDataAvailableException, IOException {
89+
final ByteBuffer sendBuffer = prepareSendFrame((byte) address, cid1, cid2, msg);
8990
final List<ByteBuffer> readBuffers = new ArrayList<>();
9091
int failureCount = 0;
9192
int noDataReceived = 0;
@@ -121,8 +122,8 @@ private List<ByteBuffer> sendMessage(final Port port, final int bmsId, final byt
121122
final byte[] addressAscii = new byte[2];
122123
receiveBuffer.position(3);
123124
receiveBuffer.get(addressAscii);
124-
final int address = convertAsciiBytesToByte(addressAscii[0], addressAscii[1]);
125-
final BatteryPack pack = getBatteryPack(address);
125+
final int responseAddress = convertAsciiBytesToByte(addressAscii[0], addressAscii[1]);
126+
final BatteryPack pack = getBatteryPack(BATTERY_PACK_ID);
126127

127128
// extract command
128129
final byte[] cmdAscii = new byte[2];
@@ -275,145 +276,177 @@ private void readChargeDischargeManagementInfo(final BatteryPack pack, final Byt
275276

276277
// 0x42
277278
private void readCellInformation(final BatteryPack pack, final ByteBuffer data) {
278-
final int bmsId = convertAsciiBytesToByte(data.get(), data.get());
279+
// if there are multiple packs, read them all and aggregate the data
280+
final int packCount = convertAsciiBytesToByte(data.get(), data.get());
279281

280-
if (bmsId < 1) {
281-
LOG.warn("Received invalid BMS ID {} in cell information!", bmsId);
282+
if (packCount < 1) {
283+
LOG.warn("Received invalid amount of packs {} in cell information!", packCount);
282284
return;
283285
}
284286

285-
if (pack != getBatteryPack(bmsId - 1)) {
286-
LOG.warn("Received cell information for BMS ID {} but not matching ADR!", bmsId);
287-
}
287+
int totalNumberOfCells = 0;
288+
int maxCellmV = Integer.MIN_VALUE;
289+
int minCellmV = Integer.MAX_VALUE;
290+
int maxCellVNum = -1;
291+
int minCellVNum = -1;
292+
final int totalNumberOfTempSensors = 0;
293+
int tempAvg = 0;
294+
int tempMin = Integer.MAX_VALUE;
295+
int tempMax = Integer.MIN_VALUE;
296+
int packVoltage = 0;
297+
int packCurrent = 0;
298+
int remainingCapacitymAh = 0;
299+
int ratedCapacitymAh = 0;
300+
301+
for (int packId = 0; packId < packCount; packId++) {
302+
303+
final int packNumberOfCells = convertAsciiBytesToByte(data.get(), data.get());
304+
305+
for (int cellNo = 0; cellNo < packNumberOfCells; cellNo++) {
306+
pack.cellVmV[totalNumberOfCells++] = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
307+
308+
if (pack.cellVmV[totalNumberOfCells - 1] > maxCellmV) {
309+
maxCellmV = pack.cellVmV[totalNumberOfCells - 1];
310+
maxCellVNum = totalNumberOfCells;
311+
}
312+
313+
if (pack.cellVmV[totalNumberOfCells - 1] < minCellmV) {
314+
minCellmV = pack.cellVmV[totalNumberOfCells - 1];
315+
minCellVNum = totalNumberOfCells;
316+
}
317+
}
288318

289-
final BatteryPack packToUse = getBatteryPack(bmsId - 1);
290-
packToUse.numberOfCells = convertAsciiBytesToByte(data.get(), data.get());
319+
final int numOfTempSensors = convertAsciiBytesToByte(data.get(), data.get());
291320

292-
for (int cellNo = 0; cellNo < packToUse.numberOfCells; cellNo++) {
293-
packToUse.cellVmV[cellNo] = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
294-
}
321+
if (numOfTempSensors > 0) {
322+
for (int tempNo = 0; tempNo < numOfTempSensors; tempNo++) {
323+
pack.cellTemperature[tempNo] = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) - 2731;
324+
tempAvg += pack.cellTemperature[tempNo];
295325

296-
packToUse.numOfTempSensors = convertAsciiBytesToByte(data.get(), data.get());
326+
if (pack.cellTemperature[tempNo] < tempMin) {
327+
tempMin = pack.cellTemperature[tempNo];
328+
}
329+
if (pack.cellTemperature[tempNo] > tempMax) {
330+
tempMax = pack.cellTemperature[tempNo];
331+
}
332+
}
333+
334+
}
297335

298-
for (int tempNo = 0; tempNo < packToUse.numOfTempSensors; tempNo++) {
299-
packToUse.cellTemperature[tempNo] = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) - 2731;
336+
packCurrent += convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
337+
packVoltage += convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
338+
remainingCapacitymAh += convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) * 100;
339+
data.getShort(); // user defined items
340+
ratedCapacitymAh += convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) * 100;
300341
}
301342

302-
packToUse.packCurrent = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
303-
packToUse.packVoltage = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() });
304-
packToUse.remainingCapacitymAh = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) * 100;
305-
data.getShort(); // user defined items
306-
packToUse.ratedCapacitymAh = convertAsciiBytesToShort(new byte[] { data.get(), data.get(), data.get(), data.get() }) * 100;
343+
pack.numberOfCells = totalNumberOfCells;
344+
pack.maxCellmV = maxCellmV;
345+
pack.maxCellVNum = maxCellVNum;
346+
pack.minCellmV = minCellmV;
347+
pack.minCellVNum = minCellVNum;
348+
pack.numOfTempSensors = totalNumberOfTempSensors;
349+
pack.tempAverage = tempAvg / totalNumberOfTempSensors;
350+
pack.tempMin = tempMin;
351+
pack.tempMax = tempMax;
352+
pack.packCurrent = packCurrent; // sum of pack currents
353+
pack.packVoltage = packVoltage / packCount; // average pack voltage
354+
pack.remainingCapacitymAh = remainingCapacitymAh / packCount; // average remaining capacity
355+
pack.ratedCapacitymAh = ratedCapacitymAh / packCount; // average rated capacity
307356
}
308357

309358

310359
// 0x44
311360
private void readWarnings(final BatteryPack pack, final ByteBuffer data) {
312-
final int bmsId = convertAsciiBytesToByte(data.get(), data.get());
361+
final int packCount = convertAsciiBytesToByte(data.get(), data.get());
313362

314-
if (bmsId < 1) {
315-
LOG.warn("Received invalid BMS ID {} in cell information!", bmsId);
363+
if (packCount < 1) {
364+
LOG.warn("Received invalid pack count {} in cell information!", packCount);
316365
return;
317366
}
318367

319-
if (pack != getBatteryPack(bmsId - 1)) {
320-
LOG.warn("Received cell information for BMS ID {} but not matching ADR!", bmsId);
321-
}
322-
323-
final BatteryPack packToUse = getBatteryPack(bmsId - 1);
368+
// reset min/max values
369+
pack.alarms.clear();
370+
371+
for (int packId = 0; packId < packCount; packId++) {
372+
// find highest and lowest cell voltage and error status
373+
final int numberOfCells = convertAsciiBytesToByte(data.get(), data.get());
374+
375+
byte status = 0;
376+
boolean cellLowStatus = false;
377+
boolean cellHighStatus = false;
378+
379+
for (int cellNo = 0; cellNo < numberOfCells; cellNo++) {
380+
status = convertAsciiBytesToByte(data.get(), data.get());
381+
382+
switch (status) {
383+
case 1:
384+
cellLowStatus = true;
385+
break;
386+
case 2:
387+
cellHighStatus = true;
388+
break;
389+
}
390+
}
324391

325-
// find highest and lowest cell voltage and error status
326-
packToUse.numberOfCells = convertAsciiBytesToByte(data.get(), data.get());
392+
if (cellLowStatus) {
393+
pack.setAlarm(Alarm.CELL_VOLTAGE_LOW, AlarmLevel.ALARM);
394+
}
327395

328-
byte status = 0;
329-
boolean cellLowStatus = false;
330-
boolean cellHighStatus = false;
396+
if (cellHighStatus) {
397+
pack.setAlarm(Alarm.CELL_VOLTAGE_HIGH, AlarmLevel.ALARM);
398+
}
331399

332-
// reset min/max values
333-
packToUse.maxCellmV = Integer.MIN_VALUE;
334-
packToUse.minCellmV = Integer.MAX_VALUE;
335-
packToUse.setAlarm(Alarm.CELL_VOLTAGE_LOW, AlarmLevel.NONE);
336-
packToUse.setAlarm(Alarm.CELL_VOLTAGE_HIGH, AlarmLevel.NONE);
400+
// find highest and lowest temperature and error status
401+
final int numOfTempSensors = convertAsciiBytesToByte(data.get(), data.get());
337402

338-
for (int cellNo = 0; cellNo < packToUse.numberOfCells; cellNo++) {
403+
// read status of the BMS temperature
339404
status = convertAsciiBytesToByte(data.get(), data.get());
340-
341405
switch (status) {
342406
case 1:
343-
if (packToUse.cellVmV[cellNo] < packToUse.minCellmV) {
344-
packToUse.minCellmV = packToUse.cellVmV[cellNo];
345-
packToUse.minCellVNum = cellNo + 1;
346-
}
347-
cellLowStatus = true;
407+
pack.setAlarm(Alarm.PACK_TEMPERATURE_LOW, AlarmLevel.ALARM);
348408
break;
349409
case 2:
350-
if (packToUse.cellVmV[cellNo] > packToUse.maxCellmV) {
351-
packToUse.maxCellmV = packToUse.cellVmV[cellNo];
352-
packToUse.maxCellVNum = cellNo + 1;
353-
}
354-
cellHighStatus = true;
410+
pack.setAlarm(Alarm.PACK_TEMPERATURE_HIGH, AlarmLevel.ALARM);
355411
break;
356412
}
357-
}
358-
359-
if (cellLowStatus) {
360-
packToUse.setAlarm(Alarm.CELL_VOLTAGE_LOW, AlarmLevel.ALARM);
361-
}
362413

363-
if (cellHighStatus) {
364-
packToUse.setAlarm(Alarm.CELL_VOLTAGE_HIGH, AlarmLevel.ALARM);
365-
}
414+
boolean tempLowStatus = false;
415+
boolean tempHighStatus = false;
366416

367-
// find highest and lowest temperature and error status
368-
packToUse.numOfTempSensors = convertAsciiBytesToByte(data.get(), data.get());
417+
for (int tempNo = 0; tempNo < numOfTempSensors; tempNo++) {
418+
status = convertAsciiBytesToByte(data.get(), data.get());
369419

370-
// read status of the BMS temperature
371-
status = convertAsciiBytesToByte(data.get(), data.get());
372-
packToUse.setAlarm(Alarm.PACK_TEMPERATURE_LOW, status == 1 ? AlarmLevel.ALARM : AlarmLevel.NONE);
373-
packToUse.setAlarm(Alarm.PACK_TEMPERATURE_HIGH, status == 2 ? AlarmLevel.ALARM : AlarmLevel.NONE);
420+
switch (status) {
421+
case 1:
422+
tempLowStatus = true;
423+
break;
424+
case 2:
425+
tempHighStatus = true;
426+
break;
427+
}
428+
}
374429

375-
boolean tempLowStatus = false;
376-
boolean tempHighStatus = false;
430+
if (tempLowStatus) {
431+
pack.setAlarm(Alarm.CELL_TEMPERATURE_LOW, AlarmLevel.ALARM);
432+
}
377433

378-
// reset min/max values
379-
packToUse.tempMax = Integer.MIN_VALUE;
380-
packToUse.tempMin = Integer.MAX_VALUE;
381-
packToUse.setAlarm(Alarm.CELL_TEMPERATURE_LOW, AlarmLevel.NONE);
382-
packToUse.setAlarm(Alarm.CELL_TEMPERATURE_HIGH, AlarmLevel.NONE);
434+
if (tempHighStatus) {
435+
pack.setAlarm(Alarm.CELL_TEMPERATURE_HIGH, AlarmLevel.ALARM);
436+
}
383437

384-
for (int tempNo = 0; tempNo < packToUse.numOfTempSensors; tempNo++) {
438+
// read mosfet temperature status
385439
status = convertAsciiBytesToByte(data.get(), data.get());
386440

387441
switch (status) {
388442
case 1:
389-
if (packToUse.cellTemperature[tempNo] < packToUse.tempMin) {
390-
packToUse.tempMin = packToUse.cellTemperature[tempNo];
391-
packToUse.tempMinCellNum = tempNo * 4 + 1;
392-
tempLowStatus = true;
393-
}
443+
pack.setAlarm(Alarm.CHARGE_TEMPERATURE_LOW, AlarmLevel.ALARM);
394444
break;
395445
case 2:
396-
if (packToUse.cellTemperature[tempNo] > packToUse.tempMax) {
397-
packToUse.tempMax = packToUse.cellTemperature[tempNo];
398-
packToUse.tempMaxCellNum = tempNo * 4 + 1;
399-
tempHighStatus = true;
400-
}
446+
pack.setAlarm(Alarm.CHARGE_TEMPERATURE_HIGH, AlarmLevel.ALARM);
401447
break;
402448
}
403449
}
404-
405-
if (tempLowStatus) {
406-
packToUse.setAlarm(Alarm.CELL_TEMPERATURE_LOW, AlarmLevel.ALARM);
407-
}
408-
409-
if (tempHighStatus) {
410-
packToUse.setAlarm(Alarm.CELL_TEMPERATURE_HIGH, AlarmLevel.ALARM);
411-
}
412-
413-
// read mosfet temperature status
414-
status = convertAsciiBytesToByte(data.get(), data.get());
415-
packToUse.setAlarm(Alarm.CHARGE_TEMPERATURE_LOW, status == 1 ? AlarmLevel.ALARM : AlarmLevel.NONE);
416-
packToUse.setAlarm(Alarm.CHARGE_TEMPERATURE_HIGH, status == 2 ? AlarmLevel.ALARM : AlarmLevel.NONE);
417450
}
418451

419452

0 commit comments

Comments
 (0)