
BMW BMW
The BMW battery storage system is a stationary energy storage unit built around BMW high-voltage battery packs, used in commercial and industrial installations managed via OpenEMS. This template connects over Modbus RTU and reads a comprehensive set of BMS registers: state of charge, state of health, DC link and internal voltage, pack current, per-cell voltage extremes in millivolts, cell and pack temperatures, insulation resistance, string topology, remaining charge and discharge energy, and full cycle count. The writable battery state command register allows the EMS to trigger state transitions. ModbusCloud makes this data continuously available for monitoring, alerting, and long-term performance analysis.
- Protocol
- Modbus RTU
- Connection
- RS485
- Registers
- 36, read and write
- Brand
- BMW
- Last updated
Registers (36)
35 read, 1 write
| Name | Unit | Access | Address (Hidden until you enter your email) | Function (hidden) | Type (hidden) |
|---|---|---|---|---|---|
| battery_state_command | Write | ||||
| battery_state | Read | ||||
| max_operating_current | A | Read | |||
| min_operating_current | A | Read | |||
| charge_max_voltage | V | Read | |||
| discharge_min_voltage | V | Read | |||
| bp_discharge_bms | Read | ||||
| bp_charge_bms | Read | ||||
| max_dynamic_voltage | V | Read | |||
| min_dynamic_voltage | V | Read | |||
| connected_string_number | count | Read | |||
| installed_string_number | count | Read | |||
| battery_total_soc | % | Read | |||
| battery_soc | % | Read | |||
| remaining_charge_capacity | Read | ||||
| remaining_discharge_capacity | Read | ||||
| remaining_charge_energy | Wh | Read | |||
| remaining_discharge_energy | Wh | Read | |||
| nominal_energy | Wh | Read | |||
| nominal_energy_total | Read | ||||
| nominal_capacity | Read | ||||
| capacity | Wh | Read | |||
| soh | % | Read | |||
| link_voltage | V | Read | |||
| internal_voltage | V | Read | |||
| current | A | Read | |||
| avg_battery_temperature | °C | Read | |||
| min_cell_temperature | °C | Read | |||
| max_cell_temperature | °C | Read | |||
| min_cell_voltage | mV | Read | |||
| max_cell_voltage | mV | Read | |||
| avg_cell_temperature | °C | Read | |||
| insulation_resistance | Read | ||||
| discharge_max_current_high_resolution | A | Read | |||
| charge_max_current_high_resolution | A | Read | |||
| full_cycle_count | count | Read |
Loading registers…
Send your device list
If a device is not in the library yet, we build the template for free as soon as we have the register data.
Use cases
- Track battery_total_soc and battery_soc together to detect imbalance across connected strings over time.
- Monitor soh and full_cycle_count to schedule preventive maintenance before capacity degrades below site thresholds.
- Alert on min_cell_voltage or max_cell_voltage extremes to catch cell drift before the BMS triggers a protective shutdown.
- Compare connected_string_number against installed_string_number to verify all strings remain online after maintenance.
- Log insulation_resistance readings over time to detect early-stage isolation faults in the high-voltage pack enclosure.
Installation
Confirm the BMW battery system is configured for Modbus RTU communication and note its assigned RS485 slave address in the BMS or system controller settings.
Wire the RS485 A and B lines from the battery system's Modbus port to the ModbusCloud Gateway serial terminals, observing polarity and fitting a 120-ohm termination resistor at each end of the bus.
In the ModbusCloud portal, add the Gateway, create a new device, import the BMW battery template, and set the Modbus unit ID to match the slave address configured on the battery.
Trigger a live poll on register 1016 (battery_total_soc) and register 1026 (soh) in the portal console to confirm values are being received correctly before enabling full dashboard collection.
Things to watch for
All registers return zero or an error. What should I check?
Verify the RS485 wiring polarity first: swapped A and B lines are the most common cause. Then confirm the Modbus slave address in the portal matches the address set on the BMW BMS. Check that the baud rate and parity settings on the Gateway match the battery's RS485 configuration, typically 9600 or 19200 baud, 8 data bits, no parity.
battery_total_soc and battery_soc read different values. Is that normal?
Yes, when multiple strings are installed but not all are connected, the two registers diverge. battery_total_soc (address 1016) aggregates all installed strings while battery_soc (address 1017) reflects the active string. Compare both against connected_string_number and installed_string_number to understand whether a string has been taken offline.
min_cell_voltage and max_cell_voltage show unexpected large numbers. Why?
Both registers use millivolt units, so a reading of 3500 represents 3.5 V per cell. Divide raw values by 1000 to convert to volts. If your dashboard shows raw integers without scaling, check that the unit field is set to mV and apply the correct factor in your chart configuration.
Is it safe to write to the battery_state_command register during normal operation?
Use write register 1400 with caution. Sending an unintended state transition command while the system is under load can cause the BMS to open contactors, interrupting active charge or discharge cycles and potentially triggering protective lockouts. Only issue commands when the system is at rest and always follow the BMW battery system's documented state machine sequence.
Want to see how it works?













