Well, presumably each slave module has a pair of optocouplers, one in each direction. The main => slave MCU opto wiring is easy - Opto LEDs are highly reliable, so if all the modules have unique addresses, you just connect series strings of as many Opto LEDs as your max. available supply voltage supports, right at the modules, with only a pair of wires per string back to the main board.
Slave => main MCU is harder - you need to be able to disable individual Optos in case a slave is jabbering. There is therefore no way of getting away from one wire per slave + a common to all of them. If you make the opto collectors common, wired straight to the main MCU UART RX pin (+ a pullup, and possibly clamping), you can simply wire the individual slave opto emitters to main board open drain outputs (or faked open drain with a schottky diode). They are normally all logic '0' so all slaves can talk, but you can set one to logic '1' to disable it if its jabbering, or all except one to logic '1' so you can interrogate the slaves one by one by position in the battery string, to get their unique IDs so you can auto-assign and set short addresses to poll them with based on their position.
Back to the original topic, just for sh!ts & giggles, I've done a LTspice sim of Gnif's original OPAMP idea with my mods to use a Zener. and also of my suggested TL431 + PMOSFET idea.
Edit: clarified description of slave => main opto wiring. Also note the sim has embedded the Eugene Dvoskin / AudioPerfection TL431 model, but in a comparator application, it seems to be a bit fussier than it should be. It may be worth switching to Helmut Sennewald's model.