3535 */
3636public 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