The Coulomb Castle is the "second unit" working on the BMS. At present, I have two BMUs arranged in a (very small) "network":
Note the wire between the top and bottom boards; when the boards are "right way up" (with the components down and the bypass resistors up), these links will be next to each other, so the wires can be a bit shorter. (Not too short, perhaps, or it's too hard to work on them).
[Edit: the 1/4 watt resistors are 75k pullups (here 68K) on the reset line. We assumed the processor would have these internally, but no. It was frustrating debugging this problem, since the processor would reset any time I wasn't debugging (the JTAG interface has a pullup on it). Pullups are squeezed onto the latest PCB layout.]
[Edit: the RS232 interface, and Jaycar USB to RS232 dongle, can be seen fuzzily at the right of the photo.]
The "end of row only" circuitry (top of the bottom board in the photo) has only just been completed, and hasn't been tested just yet. It will allow both the BMUs to be fully floating. Note that Farnell were out of stock of the SMD 3.3 V regulators, so we bought a TO-92 version instead. It looks rather huge on there.
There is a tiny dual inverter chip hidden by this regulator. I had 25 x 15 mil pads there, as suggested by a datasheet somewhere. But that just barely covers the lead footprint, and it was a pig to solder by hand, so I've extended the pads to 35 x 15 mils. Still tiny, but hopefully more manageable.
The software for in-place updating of the firmware works fine with two boards. I've implemented software to give each board a unique ID. In theory, this will only take about 350 ms for 228 cells.
[Edit: the software for updating IDs is a bit tricky, because each BMU echoes everything it receives immediately to all upstream neighbours.]
It probes the serial line for a start bit; if found within 1.5 byte transmit times, it reads and echoes that byte, which will be the ID for one of the upstream BMUs, [edit: and one less than the tentative ID for this cell]. Each BMU sees that byte after only 1/2 a byte time, since they are 1 byte time delayed compared to their immediate up-stream neighbour. If the time expires (it's just a busy wait loop), the current tentative ID is accepted as permanent, it is sent to the downstream neighbours, and written to info-flash. (Info-flash is separate from the main flash, and doesn't get overwritten when the main firmware is updated).
I've also gotten the beginnings of voltage measurement working. I get the hardware to do 6 successive reads, and busy wait for the results (about 30 μS). I find two outliers (minimum and maximum), and zero these. I add the remaining four samples, to get a 12-bit result that is the measurement in millivolts (0 to 4095 mV).
We have hardware on the BMUs (two resistors) to expand the scale to read 2.048 to 4.095 volts with 2 mV resolution. If that works, I'll shift the result (sum of 4 samples) right 1 bit and add 2^11, so again the result will be readable in millivolts.
I still need to implement a "comment to end of line" character, so the results can be sent upstream without all the upstream BMUs wasting power pushing and dropping values from the operand stack.
After that: temperature measurement, and some sort of "check status" command that checks for bad voltage or temperature, and turns on or off the bypass resistors based on a voltage threshold.
Edit: "extended to 35" was to 25 (no change)
Edit: byte times -> byte transmit times