Teardown & Rebuild of a MuscleGrid LiFePO4 Server Rack Battery

Looks pretty cool for a BMS (compared to everyone else at least):

This is definitely gets in some top ten list for Made In India just by style points alone ha:

Balance leads and temperature sensor connectors:

Dual communication ports, I’m hoping this means I’ll have wired and wireless options:

Firmware and hardware version, with on/off switch:

Telfon coated wires, again with the style factor:

Close-up of the connectors, I don’t think I recognize the exact type they’re using:


3 Likes

Nice looking BMS.

So thats a 20 cell connector/ port but only 16 is used. Any documentation.

How much current can it dispate per cell during balancing, since this is a passive balancer it will bleed it off by heat.

I will also in the not too distant future will add LFP, so will be keeping a eye on your progress.

For people using regular inverters which use lead acid battery where it will trickle charge after reaching the set voltage. Usually about 100ma to 200ma depending on the size of the battery. So in those conditions a LFP battery connected with a BMS it will the bleed those excess energy as heat. Wondering how this will dispate the heat with no fans. In my inverter when it trickle/float charges the current is below what my shunt can register and in a clamp meter its within the margin of error.

1 Like

They have models upto 24S, I’m guessing they’re reusing the basic design, with pricing reflecting the quality of their analogue front-end (1mV accuracy in the X3 series and 5mV for the X1 series) and the number of mosfets, depending on how much current it’s rated for:

The PCB also shows the unused pins for the balance leads for that model, there’s 24 pins in total.

I figure this is the case since all of the X3 100A models are priced the same (Rs 10k) and the cheapest X1 30A model is priced pretty high at Rs 4K, probably because it uses the same design.

It’s a really well-designed product, they just needed to make one PCB and they have over 50 SKUs based on it: LFP, NMC, 30A to 100A, 4S to 24S. Can you tell I’m a fan? haha

The balance current is just 50mA, but interestingly they say their microcontroller does coulombic balancing — I’m excited to see that since I’m mixing two different types of cells in the same battery pack.

I’m guessing they depend on passive dissipation, there’s warning text on the device saying it should not be covered and they have some models with a heatsink.

I cannot state this enough, but this is one of rare products that I’m really proud to see come out of India, right up there with Ashapower. Both of these companies do not design to meet a price target, only to meet an engineering goal.

I’ve lost count how many times I revisit your older posts about your setup. It’s really well done and a source of inspiration.

1 Like

I got a bunch of lugs and a length of 50 sq mm wire from Daystar Solutions, they arrived today:

hex bit for scale, this stuff is super big!

The pin type lug is for the isolator:

The ring type for everything else:

At 1C this battery should be able to provide 5000W easily, but my inverter is ~3000W.

I might get another inverter and connect it to the same battery or I might not.

I’m thinking maybe I should build this battery to handle 100A? I guess the safety factor itself should be worth it (so that nothing overheats or melts or catches fire because of undersized connections).

So far I’ve got a 100A terminal, a 125A NH type fuse, a 100A current shunt and a 125A isolator:

I’ll also have a circuit breaker that’ll arrive next week.

Would having both isolator and circuit breaker be redundant? The circuit breaker is for external loads (inverter), the isolator is for internal loads (monitoring) if I ever need to replace the fuse.

I’m a little confused, maybe the isolator is unnecessary.

I think I want the isolator before the BMS, would that make sense? It wouldn’t be wasted there.

The current shunt sizing is another topic but later.

If you want to switch on or off the load be it to the inverter input or output, AC or DC. You need to use a Circuit breaker. You can use a isolator, only when there is zero current flowing, else expect arcing. The Arc in a DC voltage is even bigger.

1 Like

Thanks, yes I’ll have a MCCB like yours for a circuit breaker, but I’d like to also use an isolator somewhere if only because I already bought it ha.

I thought maybe the isolator to disconnect the BMS for the rare instance I need to change the fuse would be a valid place for it.

You wont need a isolator for the BMS since the balance leads are already connected, so no arcing. Its like the the pre charge relay in EV before the main contactor turns On.

1 Like

That makes sense. I guess I’ll need to find some other use for the isolator elsewhere.

Something I forgot to mention with this photo, I’m considering using busbars as interconnects to save on lugs and to tidy up wiring.

Bus bar are fine just to be safe I would probably put some heat shrink on Non contact area of bus bar. Never know a simple screw driver or spanner may end up touching the other terminal no matter how far it is.

1 Like

I searched for welding cables on maps and found this place using streetview:

I thought it’d be cool to have orange cables like Andy from the Off Grid Garage on YouTube.

But they didn’t have 50mm sq in orange, just yellow, so I got that instead.

It was Rs 280 per meter, about half what I paid for the Daystar cable.

Also the 100A molded case circuit breaker arrived, it’s super big ha:

(regular mcb for size)

Would’ve been nice if the Amici people took pride in their work and designed the laser etch graphic properly and not just stretch/distort to fill the etchable area.

Great information and probably it gave me a much needed boost to do some DIY which I have been postponing for years .

A suggestion - I always keep the inverter and the batteries out of the house and I also have a few fire extinguishers on standby . You should invest in fire fighting equipment as a priority .

1 Like

22 months, and I’ve finally reached Version 0, haha!

Wired up everything together with no safety measures, open air free range:

Connections aren’t great, I’ve measured between 0.7 milliohm to 2.1 milliohm between fasteners, but that’s probably to be expected for stainless steel hardware.

However, it doesn’t work as I wanted it to. As soon as power cuts and the inverter switches to battery, the BMS registers a short-circuit and cuts power. It keeps trying to recover, but something about this inverter won’t let it.

If I turn off the inverter, then turn on the BMS, then turn on the inverter, it works.

But that means I’ll need to be around whenever power cuts, which isn’t practical.

Then I had the idea of paralleling some 7Ah batteries I had from my other UPSs, and that did work:

There’s no current draw from these batteries, they just help during switchover for a split second.

It’s going to be absurdly hilarious if I need lead acid batteries to make this lithium battery work with my inverter.

Anyway, I’ve been doing a rough capacity test, to see if there’s been any degradation since I got these cells. I’ve put on a ~20A continuous load for almost five hours now and all of the cells are still above 3V, it’s doing great. I’ll do a proper capacity test when I’ve finished building this, in a month or three.

To note: My automation flows no longer work, the low battery shutdown and safe startup etc, they relied on the lead acid battery monitors.

I’ll need to work out a way to get communication from this BMS to MQTT and Node-RED, preferably through the can bus interface, or modbus or uart. I’ve done uart to mqtt before, but I’d really like to use the can bus interface because it’ll auto broadcast. But that’ll happen after I regrow some brain cells. I’m just relieved that I can stay online now during extended power outages.

12x 105Ah mismatched C-grade cells paired with 4x top quality 100Ah cells and and this BMS balanced it down to a delta of 29mV

I thought I would’ve needed an active balancer or a more effective passive balancer, so this is a really nice surprise.

1 Like

Replying in this thread so the other doesn’t get derailed.

Yes, that is one of the things I’m going try out.

Yes, that’s the plan, I’ll be doing efficiency calculations to compare before/after.

The BMS is potted/sealed. This BMS is designed to protect against >500A short circuits, the datasheet says response time for short circuits is 8 microseconds.

Also from the datasheet:

I suspect that it’s the magnetic flux in the transformer from float charging after a power cut is triggering the short circuit.

It’s fine if I do a cold start when there’s no power.

Forgot .. the 230v line will be copper . You just need to rewind the out 24v core . If you are good with transformer winding you could probably do it within 1000 rupees .

1 Like

I found this jig on banggood and it came with a step-drill bit + stop collar:

Heh, put something off long enough and someone will make it easier.

Nothing like this available a year ago when I bought the drill press.

It makes my previous setup completely unnecessary!

For posterity:

It’s been a productive night! I started work around midnight and finished at 6 (I work slow).

Here’s a recap. But first a story, as is expected.

With the lead acid batteries, I was able to track/monitor/notify about power outages by the fact that the inverter float charges the batteries at 13.9x4 so when power is cut, that drops immediately down to 13 and lower. Those IoT lead acid battery monitors were pretty helpful:

But that same float voltage works out to be 13.9/4 = 3.475V per lifepo4 cell, which is very close to their resting voltage, so I can’t use that method here.

I could just directly monitor live mains ac but I wanted a safer, non-invasive way so I got the idea of using a current transformer clamp, a ct clamp.

If there’s current flowing, then we have power. If it drops to below 1A, then power went out and we’re on battery power (there’s some leakage by the inverter so it’s never 0).

That’ll be perfect, in theory.

Next, I want my own coulomb counter, something to track voltage, current, state of charge, state of health — independent of the BMS.

The idea is to collect data with Tasmota transmitting to MQTT, receive and process by Node-RED, store in InfluxDB and display in pretty graphs with Grafana.

As with everything I like to do, all logic will be server-side (SoH, SoC, etc).

So for that I got a PZEM017 dc power meter.

Here’s everything laid out:

There’s an arduino protoshield, a nodemcu, the pzem module, level shifters to communicate with the pzem module, the ct clamp, and a 3.5mm breakout board to connect to the ct clamp.

I chose a 15A/1V clamp because the inverter can’t handle more than 3000W.

Here’s everything ready to use:

I like the arduino form factor for my projects because it’s so cool looking. Not very space efficient but it doesn’t have to be.

A closer look at the prepared protoshield:

The ct clamp has two connections, one directly goes to the ADC pin and the other is used to bias the signal to positive with a voltage divider and a capacitor.

Schematic here: ESP32 + CT clamp - Calculations for measuring energy consumption - ESPHome - Home Assistant Community

The 4 pin jst connector is for serial communication while the level shifter is at the back. It’s not absolutely necessary, there are simpler ways, but it was just Rs 13.

I didn’t have any 15 pin female headers so I used 10pin and 4pin.

The underside:

I really would like a stack of this pcb, unpopulated.

I’m not looking for accuracy with the ct clamp, but it is plenty accurate if you make sure it’s closed completely and tightly.

Voltage is hard coded here, I’m only interested in the current value:

I needed to adjust the multiplier value for the ct clamp since the default values are for a 20A/1V transformer. AdcParam is now deprecated in tasmota, replaced by AdcGpio so here’s the command: ADCGPIO 0,1610,0.23,0

Would’ve been simpler to just get a 20A/1V clamp, it took a while to figure out the new value and also that I need to set the ADC gpio to CT POWER and not CT CURRENT.

The logic in the nodered flow is if current > 1 then charge = true and if current < 0 then discharge = true and power status is based on whether we’re charging or discharging

This logic is necessary because the pzem module cannot tell us which way the current is flowing, it’ll just tally up both charging and discharging and give us a total energy reading. It’s a little limited in that way.

The BMS can tell us, but I want an independent system.

Part 2 of this update after some sleeps.

2 Likes

Here we go, five hours of sleep is plenty (I’ll sleep more when I’m dead).

The pzem module communicates through modbus, a mature and well known protocol, but it’s half duplex and since I don’t really need everything modbus offers, I’ll be using serial uart.

Fortunately this means it’s as easy as yeeting the MAX485 chip off the board and connecting the input pads to the output pads:

This still maintains the optical isolation, which is great.

Except it took a while to figure out that the module requires you to provide 5V, which makes sense, how else would you power the optoisolators when there’s no 5V regulator on board?

Except no documentation anywhere tells you that you need to provide 5V, so that was fun.

5V added:

At this point, everything is connected and I’m seeing numbers. Oh and set baudrate 9600 and serialconfig 8n2 and EnergyConfig range 300

But the measurements weren’t accurate, it’s because I took short cuts wiring up the shunt, this is not the right way to do it:

You cannot have the current sense wires at the same point as the voltage sense wires, also don’t use thin 2m long wires.

Measurements were off by as much as 5A compared to both the BMS and a clamp meter.

Doubling up the wire to 1m (still not ideal) and seperating the sense wires brought the difference to just half an amp:

I’ll be replacing the 300A shunt with a 100A one eventually.

Here’s where we are now, the nodemcu is powered by usb temporarily:

Connections aren’t great but it’s working so I’m happy for now.

And we’re monitoring stuff:

With that, Version 1 is done! Ship it, ha!

Next is to work on the server-side logic, but I’m in no rush.

4 Likes

So last night was spent coming up with the logic for State of Charge, State of Health, Cycles — about 90% of that was figuring out how to structure the data and what variable names would sound cool, the other 10% was trying to remember Javascript syntax, ha.

Here’s what I got:

The top level object key is unique name of the battery set in tasmota, for when I have multiple batteries. RM01 is Rack Mount #1 and the rest is self-descriptive, LFP 16S 100Ah.

“charge” is State of Charge, currently zeroed out since I discharged the battery down to 48V

“health” is State of Health, currently measuring 4.25kWH (out of 5.12) or 82%, probably due to less than ideal connections (Current value is between half an amp to 1amp less than what the bms reports) — also I need to fix the rounding on the percentages after I find my brain

“status” is the current battery measurements

“total” is cumulative kWh in and out of the battery along with cycle count. Cycles are calculated against last known State of Health value, for this first discharge it was against the rated capacity, but now onwards it’ll be against this new value of 4.25kWh. I’ll be scheduling/planning a State of Health calibration (discharge down to 48V) about once every month if we don’t get any long outages.

“last” is data I need to be stored for calculations, reading is total energy reported by the pzem module and discharged is how much energy is currently being discharged, uninterrupted. A full discharge down to 48V gives us the current state of health.

The javascript:

const battery = msg.topic.split('/')[3]
const measurements = flow.get(battery) || {
    charge: { Energy: 0, Value: 0 },
    health: { Energy: 0, Value: 0 },
    status: { Voltage: 0, Current: 0, Power:0 },
    total: { Cycles: 0, Charged: 0, Discharged: 0 },
    last: { Reading: 0, Discharged: 0 }
};

const [batteryCells, batteryAh] = battery.match(/\d+/g).slice(1).map(Number);
const lowVoltage = 3 * batteryCells;

const ratedCapacity = 3.2 * batteryCells * batteryAh / 1000;
let actualCapacity = measurements.health.Energy || ratedCapacity;

const { Voltage, Current, Power } = msg.payload.ENERGY;
measurements.status = { Voltage, Current, Power };

const deltaKWH = msg.payload.ENERGY.Total - measurements.last.Reading;
measurements.last.Reading = msg.payload.ENERGY.Total;

const mainsAC = msg.payload.ANALOG.CTEnergy.Current;

if (mainsAC > 1) {
    measurements.charge.Energy += deltaKWH;
    measurements.charge.Value += deltaKWH / actualCapacity * 100;
    measurements.total.Charged += deltaKWH;
    measurements.last.Discharged = 0;
} else {
    measurements.charge.Energy -= deltaKWH;
    measurements.charge.Value -= deltaKWH / actualCapacity * 100;
    measurements.total.Cycles += deltaKWH / actualCapacity;
    measurements.total.Discharged += deltaKWH;
    measurements.last.Discharged += deltaKWH;
}

if (mainsAC > 1 && Current < 1) {
    measurements.charge.Energy = actualCapacity;
    measurements.charge.Value = 100;
} else if (mainsAC < 1 && Voltage < lowVoltage) {
    measurements.health.Energy = measurements.last.Discharged;
    measurements.health.Value = measurements.last.Discharged / ratedCapacity * 100;
    measurements.charge.Energy = 0;
    measurements.charge.Value = 0;
}

measurements.charge.Energy = Math.min(measurements.charge.Energy, actualCapacity);
measurements.charge.Value = Math.min(Math.max(measurements.charge.Value, 0), 100);

flow.set(battery, measurements);

Of note is that the battery name set in tasmota will autoconfigure battery configuration in the code. I’m only going to consider low voltage cutoff at 3V per cell or 48V for this pack even though you do have some energy left over (between 5% and 10%), this will be the trigger point for a safe shutdown of the homelab.

This means state of health will be capped at about 90% to 95% of actual capacity, which I’m fine with. You could think of it as “reserve” in a petrol tank, I guess.

Data retention strategy: tasmota sends data through MQTT every 10 seconds, Node-RED will then record it to InfluxDB every minute, which is then averaged out to every hour after 30 days.

I think that covers the logic bit. As far as I can tell, this is a more useful set of data than what something like a Victron Shunt provides, at least at first glance. If I’m missing something, let me know.

So this is Version 1.1 of the battery, completed. I’ll add per-cell battery monitoring later on, after these cells are in some kind of frame/cage.

1 Like