New DIYish battery build

Due to a rather stupid impulse buy, I need to time shift about 10kWh of average excess production to the evenings…

This lead me to scouring web sites for the cheapest batteries, and this is the best I came up with:


at R3700/kWh. It seems to be a branded Vestwoods cell, and Vestwoods claims they are 1st life BYD cells, so they should be OK.

The batteries have bluetooth monitoring, but still need to add inter-pack balancing and inverter comms.

So the basic plan is to use an ESP32 board to poll the bluetooth status of the 4 batteries, produce aggregate data over CAN for the inverter, and drive something like this:

4 Channel Relay Board

With some hefty resistors to control discharge of each battery for some crude balancing.

So I bought some batteries… And could not talk to them. I assumed they would use JBD or JK protocol, which seems to be near universal in these types of battery. But sadly not.

I contacted Vestwoods, and surprisingly, they responded almost immediately, but refused to provide a protocol document.

Fortunately, their mobile app is extremely well written, with the core logic in a JS file, with well named variables and function names. So reverse engineering the protocol was trivial, and I have basic comms up already. (I will publish the protocol when I have cleaned things up a bit.)

Next steps will be to get this running on an ESP32 board, and see how well it runs polling 4 batteries simultaneously. And build another *%&^$& battery rack (which always seems to be the most time-consuming part).

I will document the various bits and pieces here as I go, and document how well this sort of crude balancing and inverter comms works in production, in case anybody else wants to give it a bash (and/or give me a bash for anything stupid I end up doing).

1 Like

It might be easier to just open those boxes, and wire them up with a 48V BMS. The voltages are heavily dependent on the direction of the current and I doubt you will be able to balance them in any satisfactory way. You could leave the 12V BMS in place and simply not use the terminals


I did consider that, but I would like to see how well a cheapie solution can actually work in the real world.

1 Like

Sounds like an intresting take on things. A bit too much work for me :slight_smile:

To be fair for that price I would buy few name brand batteries (Pylontech) and move on. Once you add all the “requirements” you will be very close on price and have none of the benefits of warranty etc.

My 2c :wink:

Well, the batteries cost R37k for 10kWh. The extra electronics ~R150, rack ~R300. The 10 year warranty on the batteries remains in place, as long as I do not replace the BMS.

Pylontech will come in about R15k more than that.

Of course, if I had to charge my commercial rates on the software and hardware dev, that would add about R100k - but we won’t count that :stuck_out_tongue_winking_eye:

I built my 10KWh battery from 2nd life DIY Cells and the in the end I spent about R37K. I do not count my time, money is simply a tool for buying someone’s time, but what most people discount is the knowledge gained. Some people pay for a university degree and then stop learning, some people go to university and they figure out how to learn, and simply never stop


It’s the same reason I wrote my battery driver.
But now because of that I don’t have much time for other items. The projects are piling up and the wife just want to spingclean everything :woozy_face:

Here is a github project for notes and tests regarding the Vestwoods BMS protocol:


Not practically usable as-is, but may be useful anyone else who has these batteries…


You can consider using a RPi or other Nettop type thing with bluetooth just to get going before going ESP, depending on what you’re most comfortable with. Node and serialport work well together over a Bluetooth connection. I’ve used a RPi to poll 2x Bluetooth OBD adapters when the cars pull into the driveway in the past.

But this reminds me, I reversed the Sherlotronics protocol for one of their USB receivers to allow unlimited remotes, custom timeslots and so-on. Must still release that…

Edit: See you’re a Python guy, that works too.

The testing so far was done on a NUC (which is the Node-Red box for inverter and load management).

But for real time control I prefer an embedded board.

@justinschoeman from a time perspective would it not be easier initially to just use a HA02 battery balancer?
It would only add about R800 to your build cost and perhaps speed things along?
This could be a very promising build especially for UPS setups.

I still need the battery status to feed to the inverter…

Aside from balancing the battery, it will also get the battery stats, merge them with the Daly BMS stats from my other battery, and spit out a stream of CAN messages emulating one big battery…

Mechanical work mostly done:

Software is getting there. Taking longer than expected as I decided to build a library of drivers so that this whole thing can be easily reused for protocol conversions and/or paralleling arbitrary batteries.

And to top it off, when I put all 4 batteries on last night for the first time, only 3 would connect. It turns out the Arduino ESP32 module has a hard limit of 3 devices compiled in, so I need to move this over to Espressif IDE to finish the development (although I will use their Arduino wrapper, so the reusable libraries should remain Arduino compatible).

1 Like

1 Like

You may appreciate this comment from some sql I was writing yesterday:

-- ?
--select * from jfs_retl_customer where bpv2_end_date='2999-12-31';

(using an impossibly distant future date as a marker for current active periods)

I am reasonably certain that the code will not actually be running any more in 2999-12-31, but by hard coding an impossible limit like this, it might well be…

1 Like

I have my own version of this story. Back in 2012, in a product I was maintaining, there was an error about an invalid date while loading a particular spreadsheet. This was somewhat weird, as Excel itself is unlikely to do that (dates are stored as a floating point number since 1 January 1900), and a visual inspection also found no invalid dates. So we put a breakpoint around the point where it was breaking, and discovered that it was complaining about 29 February 2002, which was indeed an invalid date.

It turns out that there was a safeguard in the code that rejected data that was “impossibly old”, anything older than ten years. The way this date was determined was by splitting the date into components, subtracting ten from the year, and reassembling it. As it turns out, we did have data for 29 February 2012, which was triggering this bug.

So now the question was how to fix it. One way is to subtract 8 years instead. That way, the calculated date is always a multiple of 4 years from the current date, and in theory it will also be a leap year when it matters… EXCEPT… in 2108.

We figured that it is exceedingly unlikely that this code will still be in production by then, but because I just could not bring myself to keep the terrible existing implementation, and because in python you can simply subtract a timedelta of 3652 days from, which should be close enough, that is what we did… thereby guaranteeing that this code will be retired long before 2108.

To the poor developers I saved from this horrible ordeal… you’re most welcome.

Oh I hate dates in sourcecode :woozy_face:
There is always something that will bite you in the butt.

Don’t forget about time zones…Something I learnt very quickly was to also always convert all times to UTC.


Does that also come with NTP synchronisation built in??