What BMS protocol to use on a DIY BMS

Hi, I have a custom made BMS with CAN bus. I want to make it communicate with the Cerbo GX. I also want to be able to connect more batteries on the bus. I can program the MCU freely so CAN speed or messages are all no problem.

Options in the Cerbo GX are:

  1. Pylontech LV
    No addressing so parallel does not work. It is the easiest though, I can implement this within a few days.

  2. Pylontech HV
    I can’t get my Cerbo to read the messages I send. This one does support up to 16 batteries on the bus.

  3. VE.Can protocol
    I really like to use this, but it seems like not all VREGs are available in the public document. I see Lynx Ion VREGs but many objects related to DVCC are non existent. For example VREG 0x0FFF is an SoC value, but is listed under settings. Is this the place I want to put my SoC? I do see a max charge voltage (0xEDF7) and max charge current (0xEDF0) but they seem to be listed under other settings, meant to actively set devices. I can’t seem to find exactly what VREGs a battery should have available, other than the Lynx Ion ones.

  4. RV-C
    I won’t go down that rabbit hole. I tried it but it seems to be dated anyways. Unless someone can give me a good reason to use it

I assume that you have access to the pylontech CAN document?
One drawback of this is that the GX device applies some quirks to the CVL , but if you omit 0x350, 0x359 and 0x35c, then the GX device will recognise your battery from the 0x35E frame string.
The BMS-CAN protocol is not designed for multi-master, so your batteries need to have one master BMS, and you BMS chips are then all linked to the one master using the chips proprietary communications. This depends on whose chip you are using. I currently have 4 BMS chips, each looking after 3.3kWh of battery, reporting to a master BMS. That code has several variants, one of which is a CAN interface to the Venus os.

Yes I implemented the Pylon LV at work so no problem there. I don’t have implement the min and max cell voltage, but I guess the cerbo doesn’t even do something with that?

I also came around a thread where someone stated Victron does not support multiple batteries. I hope they fix that when they come around with the HV system. Because the Pylon HV does not use a master BMS but all BMS’s have a different address.

I guess I have to go the Pylon LV way then. And maybe use my own protocol to connect more batteries in parallel.

I have made my own BMS from scratch so I need to write all code myself. Fortunately I do have all freedom now.

All the Cerbo does with min/max cell voltages and Id’s is to log them to VRM.
Action is only taken on CVL / CCL. I hope that this also expands to take action on alarms and warnings.
Victron may support multiple batteries using their own protocol, however, the Pylontech LV protocol which appears to be a Default Chinese standard - lots of battery manufacturers also use the same 3rd party bms board.
The Maxim chips that I use have their own interchip communications - similar to most BMS chips. This means that there only needs to be one master BMS - even if the chips are used for an HV battery, rather than an LV battery. If I add another battery to my system, I add another card with another chip, the chip’s communications are then daisychained with the others. The BMS master has an interface to the chip serial coms, and when another chip is added, the code adapts automatically. The BMS code also looks after the whole system, there is no GX device in my main system. It also has a web server and modbus server. Changing to the CAN interface has been a background project for future use. If you are interested I can make the code available on GIThub - some of it already is there.
Anyway, the only requirement for a GX device to support multiple batteries (other than Victron batteries) is if you have 2 different manufacturer’s batteries connected to one system. This may be possible as the latest Cerbo’s have 2 CAN ports, both of which can be set as CAN-BMS ports.

The action taken on CVL is based on the reported max cell voltage…

charge_voltage = 52.5 - 30 * max(0, bms.maxcellvoltage-3.485)

Where do you get that from Alex?
From what I’ve seen, the CVL is sent to the GX by the BMS, the GX then only applies an offset to this when it is sent to an MPPT, but no offset when sending it to an inverter.
The GX should not relate the CVL to the max cell voltage, as it does not know what the max cell voltage limit is - this depends on cell chemistry…
That equation you quote also assumes a 48V nominal system which may also not be true.

The above piece of code is the Pylontech quirk from dvcc.py script.
And it’s specifically targeted to 48V, 15 cell battery.
It corrects/adjust (downwards) the CVL received from the BMS, based on the max cell voltage, in order to prevent max cell voltage sky rocketing and generate an over voltage alarm.
Reference here (line 88): dbus-systemcalc-py/delegates/dvcc.py at master · victronenergy/dbus-systemcalc-py · GitHub

ok, so yes the quirks related to pylontech are already noted, but not in details. That also removes the chemistry and pack voltage comments.
Normally the CVL calculation should solely be the function of the BMS using the max cell voltage. However, the quirk that you refer to is to overcome the 400mV offset added to enable export, as well as the pylontech board using the absolute cell max voltage to calculate the CVL, rather than a slightly lower voltage, so as to give a little bit of headroom between the max normal voltage and the disconnect on max voltage limits.

You’re right about the CVL that should be only the BMS’es job.
I, for one, besides this voltage quirk, I’ve also implemented in the same place a current quirk, because Pylontech is reporting CCL = 0 on SOC 100, so it can happen for the MPPTs to stop producing when the SOC is 100.
So, it seems that nothing is governed by an uniform standard and each has to improvise in order to make it work… :zany_face:

Setting CCL to 0 purely on 100% SOC is so wrong in my opinion, it requires to stop charging thus balancing when the SOC reaches 100%. Or the SOC should only go to 100% when the battery is balanced and fully charged.

I think the battery should tell the inverter the CCL to keep balancing but not get an over voltage, because the battery is unique and the manufacturer can tune the CCL algorithm to not get overshoots. I mean a big battery can handle more current without overshooting.

Anyways, the balancing algorithm from Victron is also shitty if you ask me. I hit 100% and max charge voltage multiple times a month but that apparently does not count as balancing, it still holds the monthly schedule. It would buy from the grid only to hold the battery for like half an hour at 100% before selling to grid again.

No upper charge limit is a bit garbage too in my opinion. A target SoC window would be the solution for all my problems. But I guess Victron has more to do than listen to hobbyists.

Thanks for your reply, I see what you mean now. You use different slave modules with only AFE’s connected with some sort of isospi or other protocol to a master board which has contactors or FET’s to protect your battery and does all the SOC gauging and controlling balancing etc. My BMS has one AFE connected to one MCU. Kind of like a JK BMS but then my own design. Maxim has really nice chips. Renesas and NXP are there too though.

I’ll come back tomorrow to reply to the rest of your answer

Yes, Victron have a boondogle here - or maybe the Pylontech board does.
Setting CCL to zero does turn off all MPPT’s. so stopping any export.
However, what should happen, as I implement in my BMS, is that as the Max cell voltage approaches 3.55V, the current limit is throttled back, and settles at a point sufficient to drive the inverter loads. This works fine in an off grid system with no export. I then calculate the CVL from the CCL by using the current battery voltage and the battery resistance.
It would help if Victron were to implement shutdown of all charging sources on the appropriate warning,
The return from the Pylontech Quirk:

return (charge_voltage, charge_current, feedback_allowed, True)

the last “True” is whether to shut down the MPPT’s or not if (I think) CCL =0; and even with export, I can’t see any condition where this should not happen. Where this seems to come from is lazy coders of BMS’s that instead of linearly reducing either CVL or CCL or both, do a step cut off in charging.
I think part of the reason this lazy coding happens is the Victron is unique in having MPPT’s with dynamic current limiting, something I consider essential for charging lithium batteries given the rapid rise in cell voltage at max charge %.

Yes, that’s the sort of topography. However, I don’t have any contactors or fet’s in the system, allowing sufficient reserve power to feed the control system, inverter current in off mode, overnight MPPT use and a few dc lights for emergency.
The maxim chips use a balanced serial data signal, with both an up and a down stream data path.
Use of isolator fets in separate parts of a multi-battery system can be problematic, unless there is some form of central control, as switching one or more packs off can lead to insufficient current capacity. This is more problematic when packs are in series, as reverse voltage issues then appear, and bypass diodes are needed. Best to use a single contactor, and efficient coms.

Fully agree. This is why I’ve also implemented a “current” quirk, as said above, besides the “voltage” quirk. :+1:

But there are “discharging” FETs and “charging” FETs, right?
The “discharge” ones still remain active, so no problem in case of sudden need for consumption.
So the battery → inverter sense is active, only the inverter/charger → battery sense is blocked.

True, only ditching a discharge FET would make it more safe while keeping it reliable. Tool batteries often only include a charge FET, disabling the load is done by telling your tool it has to stop (or in case of lamps they just stop on battery voltage). LiFePO4 can handle over voltage pretty well but it degrades fast when kept too high. I think he has a safe setup, but should not be replicated when you don’t know what you’re doing. For commercial use this won’t pass any certification.

Yes for stacking them in series an all in one BMS usually can’t safely protect your system because of the reverse voltage problem. Those LTC chips etc are mainly used for connecting modules in series, but I know some cars use series/parallel configuration. It’s very flexible. Single contactor is indeed needed.
My purpose with multiple all in one BMS’S in parallel is to have multiple different packs. I do have a big stack of old cells I want to cycle to death, and I want to be able to just plug it in and unplug it when I want to service it without interruptions. It could be done your way but seperate FET’s ensure only the bad pack disconnects and if I would get a cell failure the pack disconnects and would not interfere with my good pack.

I got the pylontech LV protocol up and running though, only for DVCC, SOC, voltage and current reporting.

If you set your max charge voltage according to current and internal resistance, you won’t need to set your CCL, right? Because your charger is doing PID regulation on the voltage already. It is a very interesting approach, only setting CCL can give you a hard time avoiding oscillations. A charger should have a near perfect PID on it’s end of charge voltage, so only reducing CVL on a high cell voltage may be more stable.

No Both the CCL and CVL are active, oscillations are prevented by damping the charge rate increase, though decrease is left at full speed. Whilst this does cause a drain on the battery in the instance of a sudden load - like a kettle (2kW), this is usually corrected within 30s.

You can still do this with the maxim interchip coms, there is a register for setting internal loopback of the coms path. Also depends if you can write the controlling code for hot plug type applications.

When I have to service my packs - some over 5 yrs old, and heavily used- then I can bypass the BMS inverter control, turn off the BMS, remove the pack to be worked on, bypass the packs bms card, then power up the BMS again. This takes about 1 minute, and the pack to be serviced is then disconnected from the busbars. I usually do this when the CVL/CCL is inactive, i.e.at max charge.