Louisvdw / dbus-serialbattery

Battery Monitor driver for serial battery in VenusOS GX systems
MIT License
541 stars 165 forks source link

Tian Power (Revov) BMS Integration #14

Closed NicholasHerbst closed 1 year ago

NicholasHerbst commented 3 years ago

Integrate the Tian Power BMS via RS485 to Victron Venus OS-equipped devices.

It uses CRC-16-ANSI function

def calc_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos 
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc
Louisvdw commented 3 years ago

@NicholasHerbst are the communications protocol available for these BMS? I do not see anything on Tian Power's website.

NicholasHerbst commented 3 years ago

@Louisvdw yes, I have access to the communication protocol. Where would be the most appropriate place to share this document?

Louisvdw commented 3 years ago

@NicholasHerbst You should be able to attach the doc to a comment here.

NicholasHerbst commented 3 years ago

REVOV Modbus communication protocol v1.pdf

csloz commented 2 years ago

I've started some work on this myself. The protocol pdf appears to be completely incorrect for the TianPower BMS - at least from what i'm seeing so far.

Added some progress here - https://powerforum.co.za/topic/4044-the-dreaded-revovs-on-sale/page/3/

I need to work out where some of the variables sit tomorrow.
Have identified 4 commands so far.

Louisvdw commented 2 years ago

Nice work @csloz Once you have something that can read the basics, create a branch and do a pull request.

csloz commented 2 years ago

Will do.

It's progressing fast. Can read the battery voltage, and individual cells now, although some of the details are still MIA. Having fun working it out though.

Take a look at the thread on powerforum for progress. (linked above)

Ideally I need someone else to do some testing to make sure params are correct. @NicholasHerbst are you up for some beta testing?

csloz commented 2 years ago

Ok, have forked it, and made a pull request.

It's a BETA version. Will still make some updates as I'm missing some data still (need to work out where it sits). It's also extremely chatty.

Example logs below;

2022-05-03 17:41:50.031904500 WARNING:SerialBattery:Modbus Address: 124 2022-05-03 17:41:50.032398500 WARNING:SerialBattery:Modbus Type : 1 2022-05-03 17:41:50.032860500 WARNING:SerialBattery:Modbus Command: 1 2022-05-03 17:41:50.033304500 WARNING:SerialBattery:Modbus PackLen: 118 2022-05-03 17:41:50.033791500 WARNING:SerialBattery:Modbus Packet : [7C:01:01:76:01:10:0C:F2:0C:F4:0C:F4:0C:F5:8C:F4:0C:F3:8C:F5:0C:F5:0C:F4:0C:F4:0C:F6:8C:FB:0C:F3:0C:F4:0C:F5:0C:F7:02:01:77:A2:03:01:24:7E:04:01:46:50:05:03:00:48:00:48:20:49:06:05:00:00:00:02:00:00:00:00:00:00:07:01:00:85:08:01:14:BA:09:01:27:10:0A:01:00:00:0B:01:00:00:83:00:0C:01:00:00:37:AE:0D:01:00:40:00:00:0E:01:00:40:00:00:0F:01:00:1A:3A:1B:10:01:00:09:57:AD:DE:0D] 2022-05-03 17:41:50.034225500 WARNING:SerialBattery:== Modbus packet good == 2022-05-03 17:41:50.034727500 WARNING:SerialBattery:Voltage Data: [53.06v] 2022-05-03 17:41:50.035194500 WARNING:SerialBattery:Battery Cycles: [133] 2022-05-03 17:41:50.035660500 WARNING:SerialBattery:Battery Capacity: [180.0Ah] 2022-05-03 17:41:50.036118500 WARNING:SerialBattery:Cell count: [16] 2022-05-03 17:41:50.036595500 WARNING:SerialBattery:Raw Cell Data: [0C:F2:0C:F4:0C:F4:0C:F5:8C:F4:0C:F3:8C:F5:0C:F5:0C:F4:0C:F4:0C:F6:8C:FB:0C:F3:0C:F4:0C:F5:0C:F7] 2022-05-03 17:41:50.037137500 WARNING:SerialBattery:Cell [01] 3.314v 0x0CF2 0b110011110010 2022-05-03 17:41:50.037652500 WARNING:SerialBattery:Cell [02] 3.316v 0x0CF4 0b110011110100 2022-05-03 17:41:50.038165500 WARNING:SerialBattery:Cell [03] 3.316v 0x0CF4 0b110011110100 2022-05-03 17:41:50.038666500 WARNING:SerialBattery:Cell [04] 3.317v 0x0CF5 0b110011110101 2022-05-03 17:41:50.039182500 WARNING:SerialBattery:Cell [05] 3.608v 0x8CF4 0b1000110011110100 2022-05-03 17:41:50.039686500 WARNING:SerialBattery:Cell [06] 3.315v 0x0CF3 0b110011110011 2022-05-03 17:41:50.040260500 WARNING:SerialBattery:Cell [07] 3.608v 0x8CF5 0b1000110011110101 2022-05-03 17:41:50.040769500 WARNING:SerialBattery:Cell [08] 3.317v 0x0CF5 0b110011110101 2022-05-03 17:41:50.041383500 WARNING:SerialBattery:Cell [09] 3.316v 0x0CF4 0b110011110100 2022-05-03 17:41:50.041904500 WARNING:SerialBattery:Cell [10] 3.316v 0x0CF4 0b110011110100 2022-05-03 17:41:50.042409500 WARNING:SerialBattery:Cell [11] 3.318v 0x0CF6 0b110011110110 2022-05-03 17:41:50.042922500 WARNING:SerialBattery:Cell [12] 3.609v 0x8CFB 0b1000110011111011 2022-05-03 17:41:50.043424500 WARNING:SerialBattery:Cell [13] 3.315v 0x0CF3 0b110011110011 2022-05-03 17:41:50.043990500 WARNING:SerialBattery:Cell [14] 3.316v 0x0CF4 0b110011110100 2022-05-03 17:41:50.044473500 WARNING:SerialBattery:Cell [15] 3.317v 0x0CF5 0b110011110101 2022-05-03 17:41:50.044978500 WARNING:SerialBattery:Cell [16] 3.319v 0x0CF7 0b110011110111 2022-05-03 17:41:50.045448500 WARNING:SerialBattery:Cell Total: 53.94v

csloz commented 2 years ago

I realised I'm a bit dof just now.

Their data format is quite straightforward - I just didn't notice that till now.

Sample info packet:

[7C:01:01:76:01:10:8D:20:0D:17:8D:21:0D:2F:8D:3B:0D:32:CD:E3:0D:B3:8D:23:0D:0D:8D:24:0D:24:0D:11:8D:21:0D:18:8D:21:02:01:75:30:03:01:27:10:04:01:46:50:05:03:00:49:00:48:20:4B:06:05:00:00:10:10:00:00:00:00:00:01:07:01:00:85:08:01:15:24:09:01:27:10:0A:01:00:01:0B:01:00:00:83:00:0C:01:00:00:37:AE:0D:01:00:40:00:00:0E:01:00:40:00:00:0F:01:00:1A:3A:04:10:01:00:09:57:AD:BA:0D]

Once I spotted that they seperate out the packet info with byte/length pairs suddenly the data makes much more sense.

7C:01:01:76 (bus/cmd/req/length) Then from there its simply 01:10 with length 16 (10 in HEX) is our battery cell info 02:01 75:30 = 3000 -> 30 03:01 27:10 = 10000 ->100 04:01 46:50 = 18000 ->180 05:03 00:49 00:49 20:4A = 3 pairs? 73/73/8266 ?? 06:05 00:00 10:10 00:00 00:00 00:01 Alarm bits 07:01 00:85 = 133 -> Cycles 08:01 15:3C = 5436 -> Volts (54.36) 09:01 27:10 = 10000 -> 100 0A:01 00:01 = 1 0B:01 00:00 83:66 = 0, 33670 (3.367?) 0C:01 00:00 37:AE = 0, 14254 (0.14254?) 0D:01 00:40 00:00 = 64, 0 0E:01 00:40 00:00 = 64, 0 0F:01 00:1A 4A:3F = 26, 190007 (unsigned? signed, tbd...) 10:01 00:09 57:AD = 9, 22445 (22.445?)

I'll have a play looking at the byte pair values in word/float signed/unsigned etc to see if the weirder values make more sense, but, by George, I think he's got it!

NicholasHerbst commented 2 years ago

This is awesome work!

I am sorry that I have not been able to respond sooner – have had a very busy work week schedule.

I will gladly assist with any testing or other from next week as required.

Keep up the great work!

Regards,

From: csloz @.> Sent: Wednesday, 04 May 2022 12:09 To: Louisvdw/dbus-serialbattery @.> Cc: NicholasHerbst @.>; Mention @.> Subject: Re: [Louisvdw/dbus-serialbattery] Tian Power (Revov) BMS Integration (#14)

I realised I'm a bit dof just now.

Their data format is quite straightforward - I just didn't notice that till now.

Sample info packet:

[7C:01:01:76:01:10:8D:20:0D:17:8D:21:0D:2F:8D:3B:0D:32:CD:E3:0D:B3:8D:23:0D:0D:8D:24:0D:24:0D:11:8D:21:0D:18:8D:21:02:01:75:30:03:01:27:10:04:01:46:50:05:03:00:49:00:48:20:4B:06:05:00:00:10:10:00:00:00:00:00:01:07:01:00:85:08:01:15:24:09:01:27:10:0A:01:00:01:0B:01:00:00:83:00:0C:01:00:00:37:AE:0D:01:00:40:00:00:0E:01:00:40:00:00:0F:01:00:1A:3A:04:10:01:00:09:57:AD:BA:0D]

Once I spotted that they seperate out the packet info with byte/length pairs suddenly the data makes much more sense.

7C:01:01:76 (bus/cmd/req/length) Then from there its simply 01:10 with length 16 (10 in HEX) is our battery cell info 02:01 75:30 = 3000 -> 30 03:01 27:10 = 10000 ->100 04:01 46:50 = 18000 ->180 05:03 00:49 00:49 20:4A = 3 pairs? 73/73/8266 ?? 06:05 00:00 10:10 00:00 00:00 00:01 Alarm bits 07:01 00:85 = 133 -> Cycles 08:01 15:3C = 5436 -> Volts (54.36) 09:01 27:10 = 10000 -> 100 0A:01 00:01 = 1 0B:01 00:00 83:66 = 0, 33670 (3.367?) 0C:01 00:00 37:AE = 0, 14254 (0.14254?) 0D:01 00:40 00:00 = 64, 0 0E:01 00:40 00:00 = 64, 0 0F:01 00:1A 4A:3F = 26, 190007 (unsigned? signed, tbd...) 10:01 00:09 57:AD = 9, 22445 (22.445?)

I'll have a play looking at the byte pair values in word/float signed/unsigned etc to see if the weirder values make more sense, but, by George, I think he's got it!

— Reply to this email directly, view it on GitHub https://github.com/Louisvdw/dbus-serialbattery/issues/14#issuecomment-1117141039 , or unsubscribe https://github.com/notifications/unsubscribe-auth/APGAYMKFWY2OEGJ5H3EHL4TVIJEFPANCNFSM43S3RYWA . You are receiving this because you were mentioned. https://github.com/notifications/beacon/APGAYMJ72SJAIN673367IWLVIJEFPA5CNFSM43S3RYWKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOIKLDQLY.gif Message ID: @. @.> >

csloz commented 2 years ago

Haven't had a chance to do any code changes since i noticed the packet format, but the code is up at the revov branch in my github if you want to pull it to test.

I need to rewrite the parser code to correctly interpret each data size. Will hopefully get time next week. Its usable as is, and seems pretty stable, even if missing some values still. I've had it running on mine for almost a week now.

https://github.com/csloz/dbus-serialbattery/tree/revov

ghost commented 2 years ago

I also have a Revov battery with the BMS supplied by them and wish to, specifically, get the SoC data fed into the Victron Cerbo GX. If there is anything I can help with, kindly let me know. I have a Raspberry Pi with a 2-CH_RS485_HAT mounted on it. So, if I get the right Python script, I can perhaps use that to “extract” the right protocol.

ghost commented 2 years ago

I am trying to find answers to an issue I picked up since the installation of the dbus-serialbattery system and upgrading the Cerbo GX Firmware to get the former to work.

Yesterday, due to the cloud cover and low charging rate through the MPPT and the looming load shedding, I wanted to charge the batteries (Rovov) through the inverter and thus started the Scheduled Charge. I immediately noticed that the charging rate was very low compared to what I witnessed before. I unplugged the USB cable from the battery’s BMS hoping that would solve the issue, without any success. I then upgraded the inverter’s firmware, again with no success.

This morning, I decided to look for reasons and the first I came across was the “charge current control management” under the features. In there it is said that the “CCCM limits the current when the battery is close to full or close to empty. When your battery is full, the reduced charge current will give the balancers in your BMS time to work When your battery is close to empty the reduced discharge current will limit that a sudden large load will pull your battery cells below their protection values. The CCCM limits the charge/discharge current depending on the SOC - between 99% - 100% => 5A charge - between 95% - 98% => 1/4 Max charge - between 91% - 95% => 1/2 Max charge”.

With the Revov battery SoC remaining at 100%, I am wondering if that is the reason for poor rate of charge?

Louisvdw commented 2 years ago

It would be limiting your charge yes. In your utils.py go change CCCM_ENABLE = False around line 25 and restart to see if that helps. That setting in still experimental.

ghost commented 2 years ago

I made the changes in the utils.py and restarted the system through by running “sh /data/etc/dbus-serialbattery/installrelease.sh” and rebooted the Cerbo GX. The charging then worked as expected until I plugged the USB back in. I then got a low voltage alarm on the inverter which I had to clear before restarting the entire system (inverter and Cerbo GX) for it to work. So, now the USB cable is unplugged wating for the new revov.py script.

I want to repeat my offer. If there is anything I can help with, let me know.

Louisvdw commented 2 years ago

Anyone want to test a new beta please https://github.com/Louisvdw/dbus-serialbattery/releases/tag/v0.12b4 We've added a new battery driver that seem to be the same BMS as the Revov batteries. In this beta above the revov driver is disabled and the LifePower enabled. Please give it a test with the Revov batteries and check if it works and if more data is available . @bertiebez @csloz

TianPower commented 1 year ago

Hello, I’m the online sales manager of Tian Power, if you need, I can call our technical experts to help you. and if you have any questions about our products, please feel free to contact me!

Louisvdw commented 1 year ago

@TianPower what could really help would be if you have a BMS that you could send that I can test with. It's not easy solving problems virtually. It does not need to be big or new. It just need to run the same protocols. You can send me a PM at energytalk.co.za and we can chat.

pchiquit commented 1 year ago

@TianPower I guess having the documented BMS protocol would also help. The current implementation is based on the reverse engineering (as documented here #212 ). Having the official protocol would help us to improve the implementation and add more features.

mike-marcacci commented 1 year ago

@TianPower I've been working on a prometheus exporter for your BMS, largely using the work done here and on related projects to help reverse engineer the communication protocol. So far, I haven't been able to figure out the checksum algorithm, and have resorted to hardcoding messages. To second @pchiquit's request: if you could publish the communication protocol, this would be immensely helpful.

Thanks in advance (and also to everybody here whose work has given me a place to start)!

TianPower commented 1 year ago

I'm very sorry not to reply your message in time, now I will follow up your questions ,Can you provide the model of the BMS? @mike-marcacci Do you mean Upper computer?

mike-marcacci commented 1 year ago

Thanks @TianPower! "Upper computer" may be what I mean by checksum, I'm not entirely sure; @slim-bean put together what is probably the most useful document I've found here, from his reverse-engineering efforts.

When observing requests made by the Windows tool supplied by EG4, the second-to-last byte contains a value that I haven't been able to predict, and I assumed was some form of checksum, despite it not matching any CRC algorithm I've tried.

For example, requests for current battery metrics appear to be the following, based on the address of the queried battery:

Start Byte Address Command Length? Checksum? End Byte
7E 00 01 00 FC OD
7E 01 01 00 FE OD
7E 02 01 00 FC OD
7E 03 01 00 FE OD
7E 04 01 00 F8 OD
7E 05 01 00 FE OD

I'm not entirely sure what the specific model of the BMS is – it's the one used in the EG4 LifePower4 batteries. A video showing the battery teardown reveals some numbers on the main board that didn't mean anything to me, but might to you:

S/N:
RoHS
05J11
QT_PBMS_EPBMS_48100_16S100Z0-V2.0.7

EDIT: the below questions appear to be somewhat answered by this post.

I do have a number of other questions that I'm struggling to answer via reverse-engineering, but which would probably be covered in a communication protocol documentation. For example, group 4 of the response appears to return the battery's "full capacity" in cAh, but this differs from what the UI displays. (In my case the message on one of my batteries reports 101.32Ah while the UI reports what I believe is a truncated 100.00Ah.) It makes sense that the UI might try and make some "friendlier" numbers, but is my inference that this is "full capacity" even correct?

Similarly, group 3 appears to contain either the state-of-charge in percentage * 100, or the "remaining capacity" in cAh – both of which report identically on the UI. If the former assertion about "full capacity" is correct, though, then these numbers shouldn't actually be the same, and it's unclear which value this group actually represents.


Apologies for hijacking this thread a bit, but thanks so much for your time @TianPower – you all are making some great products, and I'm looking forward to getting better visibility into our battery performance!

cybertza commented 3 months ago

Hey Gents,

What was the max amount of batteries you guys were able to integrate with this mod?

And i furthermore assume no additional hardware is required besides the USB-RS485?

LilDucky commented 2 months ago

I have a couple of different Tian Power BMS and can assist with testing / data collection. The BMS are both 48V 15/16S, one is 50AH and other is 100Ah. They seem to have a charge / discharge limiting board installed on them. I have used the Lifepower driver with some success; mainly the temperature group is har coded for 6 values and the 50Ah model only has 4. The protocol reflects this correctly, sand I kludged my copy to work correctly. The next issue is that when a cell OV warning comes up it displays as 19-20V ish because only the top bit is masked for alarms. AFAIK the two top bits need to be masked, I think that the top bit is OV alarm, and the next bit is warning. I am in the process of rebuilding the 100Ah battery and can test with that soon. I may be able to put together a 50Ah unit with less cells in parallel for testing.

Please let me know if this has been of assistance and if I can do anything else. Simon

ETA Just found my earlier work on decoding the protocol.

LiPo Protocol.pdf

I also have a few different copies of the OEM windows software