Battery Prime RAK9156 Modbus Register Reference
The Modbus register map of the RAK9156 is divided into two functional areas: read-only registers for monitoring system status and measurements, and system-control registers for executing control operations.
Communication Parameters
The RAK9156 communicates over a 2-wire, half-duplex RS485 interface using the Modbus RTU protocol.
| Parameter | Description |
|---|---|
| Physical Layer | RS485, 2-wire, half-duplex |
| Protocol | Modbus RTU |
| Device Role | Slave (the host acts as the Modbus master) |
| Default Slave Address | The default slave address is 110 (0x6E). It can be changed by writing to register 0x2001. |
| Slave Address Range | 1–247 |
| Baud Rate | 9600° bps |
| Data Bits | 8 |
| Parity | None |
| Stop Bits | 1 |
| CRC | CRC-16/Modbus with polynomial 0xA001 (reflected), an initial value of 0xFFFF, and low-byte-first transmission order. |
Function Codes
The RAK9156 supports the following Modbus function codes:
| Function Code | Name | Description |
|---|---|---|
0x03 | Read Holding Registers | Supported. Reads up to 125 registers per request. |
0x06 | Write Single Register | Supported only for system-control registers 0x2000, 0x2001, and 0x2002. |
- Registers in the System Information, Battery Data, Cell Data, Protection & FET Status, and Charger Status regions are read-only. Write requests to these registers do not change their values.
- Function code
0x10(Write Multiple Registers) is not used for system-control registers. Each system-control register must be written individually using function code0x06.
Exception Codes
The RAK9156 returns the following Modbus exception codes when a request cannot be processed:
| Exception Code | Name | Description |
|---|---|---|
0x01 | Illegal Function | The requested function code is not supported. |
0x02 | Illegal Data Address | The requested register range contains a reserved address, or the requested data is temporarily unavailable. |
0x03 | Illegal Data Value | The requested register quantity is 0 or exceeds 125. |
An exception response is indicated by setting bit 7 of the function code in the response. For example, a failed 0x03 request returns function code 0x83.
Data Types and Byte Order
The RAK9156 uses the following data types and byte-order conventions for Modbus register values.
| Data Type | Size | Description |
|---|---|---|
uint16 | 1 register | Unsigned 16-bit integer, range: 0–65535. |
int16 | 1 register | Signed 16-bit integer using two's complement, range: -32768–32767. Example: 0xFFF6 = -10. |
| String | N registers | ASCII characters, two characters per register. The high byte contains the first character, and the low byte contains the second character. |
Byte Order
Each register is transmitted high byte first (big-endian), as defined by the Modbus specification.
Physical Value Conversion
Physical values are obtained by multiplying the raw value by the unit in the register table.
Example: Battery Temperature
0x00FD = 253 × 0.1° C = 25.3° C.
Polling and Timing
The following parameters are recommended for Modbus communication:
| Item | Recommendation |
|---|---|
| Data Refresh Interval | Measurement data is updated approximately once per second. |
| Polling Interval | At least 1 second per register block. Faster polling returns the same measurement values. |
| Response Timeout | 500 ms |
| Retry Attempts | Retry up to 2 times after a timeout before reporting the device as offline. |
| Inter-frame Gap | At least 3.5 character times between frames (approximately 4 ms at 9600 bps). |
When no charger input is present and the absolute pack current remains below 20 mA for 15 minutes, the device enters a low-power off state and stops responding to Modbus requests.
A charge or discharge current of 20 mA or more counts as activity and restarts the timer. Modbus traffic does not keep the device awake.
The device resumes operation when:
- Charger input is applied.
- The power button is pressed.
- The discharge current reaches 20 mA.
Register Address Map
The Modbus register address space is organized into the following functional regions:
| Address Range | Region | Access | Description |
|---|---|---|---|
0x0000–0x00FF | System Information | Read-only | Device ID, hardware and firmware versions, system status, design parameters, heater status, and serial number. |
0x0100–0x01FF | Battery Data | Read-only | Pack voltage, current, temperature, SOC, SOH, capacity, and cycle count. |
0x0200–0x02FF | Cell Data | Read-only | Individual cell voltages and balancing status. |
0x0300–0x03FF | Protection & FET Status | Read-only | Primary and secondary protection status, fault status, and FET conduction status. |
0x1000–0x10FF | Charger Status | Read-only | Status and fault bitmaps, electrical measurements (voltage/current), charging state, and MPPT parameters. |
0x2000–0x2002 | System Control | Write; 0x2001 is also readable | Software reset, slave address configuration, and factory reset. |
Readable Register Blocks
Addresses not listed in the readable register blocks are reserved. Reading a reserved address returns exception 0x02 (Illegal Data Address).
A multi-register read request fails as a whole if any address within the requested range is reserved.
Each block listed below is a contiguous address range with no reserved addresses. The host can read any sub-range within a block using a single request. Separate requests are required when reading registers from different blocks.
| Block | Start Address | Register Quantity | Contents |
|---|---|---|---|
| 1 | 0x0000 | 6 | Device ID, hardware version, firmware version, build version, bootloader version, and AFE version. |
| 2 | 0x0008 | 1 | System Status |
| 3 | 0x0010 | 13 | Cell count, design capacity, design voltage, heater status, and serial number. |
| 4 | 0x0100 | 9 | Battery Data |
| 5 | 0x0200 | 4 | Cell 1–4 Voltages |
| 6 | 0x0230 | 1 | Balancing Status |
| 7 | 0x0300 | 3 | Primary Protection, Secondary Protection, and Fault Status. |
| 8 | 0x0320 | 1 | FET Status |
| 9 | 0x1000 | 3 | Charger Status, Charger Fault Status, and Charge Stage. |
| 10 | 0x1010 | 4 | Input/Output Voltage and Current |
| 11 | 0x1020 | 2 | MPPT Status and MPP Voltage |
System Information (0x0000–0x00FF)
System Information Registers
The following registers provide device identification, firmware information, battery design parameters, and system status.
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x0000 | Device ID | uint16 | - | Device model identifier used for host recognition. Fixed value: 0x9156. |
0x0001 | Hardware Version | uint16 | - | Hardware version, encoded as Major.Minor.Patch. |
0x0002 | Firmware Version | uint16 | - | Application firmware version, encoded as Major.Minor.Patch. |
0x0003 | Firmware Build Number | uint16 | - | Build number used for version tracking. |
0x0004 | Bootloader Version | uint16 | - | Bootloader version, encoded as Major.Minor.Patch. |
0x0005 | AFE Firmware Version | uint16 | - | AFE firmware version, encoded as Major.Minor.Patch. Returns 0x0000 when the AFE is unavailable. |
0x0008 | System Status | uint16 | - | Bitmap representing current system states, including idle, charging, discharging, low battery, and fault conditions. |
0x0010 | Cell Count | uint16 | cells | Number of series-connected cells in the battery pack. |
0x0011 | Design Capacity | uint16 | mAh | Rated design capacity of the battery pack. |
0x0012 | Design Voltage | uint16 | mV | Rated design voltage of the battery pack. |
0x0013 | Heater Status | uint16 | - | Heater state: 0 = Off, 1 = On. |
0x0014–0x001C | Serial Number | String | - | Fixed-length 18-character ASCII string stored across 9 registers, with no terminating null character. Each register contains two characters: high byte = character N; low byte = character N+1. |
Reserved Addresses: 0x0006–0x0007, 0x0009–0x000F, and 0x001D–0x00FF are reserved.
Version Encoding
Registers 0x0001, 0x0002, 0x0004, and 0x0005 use the same version encoding scheme.
The 16-bit register value is divided into three fields:
| Field | Bit Range | Width | Value Range |
|---|---|---|---|
| Major | bits[15:11] | 5 bits | 0–31 |
| Minor | bits[10:6] | 5 bits | 0–31 |
| Patch | bits[5:0] | 6 bits | 0–63 |
Decoding Formula
| Field | Formula |
|---|---|
| Major | major = (reg >> 11) & 0x1F |
| Minor | minor = (reg >> 6) & 0x1F |
| Patch | patch = reg & 0x3F |
Examples
0x0841=0b0000_1000_0100_0001→ Major =0b00001, Minor =0b00001, Patch =0b000001→v1.1.10x1042=0b0001_0000_0100_0010→ Major =0b00010, Minor =0b00001, Patch =0b000010→v2.1.2
System Status Bit Definitions (0x0008)
Register 0x0008 provides a bitmap of the current system operating states. Each defined bit represents a specific status or condition.
| Bit | Name | Description |
|---|---|---|
| bit0 | IDLE | System is idle — neither charging nor discharging. |
| bit1 | CHARGER_PRESENT | Charger detected or connected. |
| bit2 | CHARGING | System is charging. |
| bit3 | DISCHARGING | System is discharging. |
| bit4 | FULL_CHARGE | Battery is fully charged. |
| bit5 | LOW_BATTERY | Battery level is low. |
| bit6 | PROTECTION_ACTIVE | Primary (0x0300) or secondary (0x0301) protection is active. Charging or discharging may be restricted. |
| bit7 | FAULT | A system fault is present. Read register 0x0302 for fault details. Charger electrical faults are reported in register 0x1001. |
Reserved Bits: bits[15:8] are reserved.
Battery Data (0x0100–0x01FF)
Battery Data Registers (0x0100–0x0108)
The following registers provide battery pack measurements, capacity information, and battery health data.
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x0100 | Pack Voltage | uint16 | mV | Battery pack terminal voltage. |
0x0101 | Pack Current | int16 | mA | Signed current value. Positive = charging; negative = discharging. |
0x0102 | Battery Temperature | int16 | 0.1° C | Battery pack temperature. |
0x0103 | MOSFET Temperature | int16 | 0.1° C | Temperature of the power MOSFET area. |
0x0104 | Relative SOC | uint16 | % | Current relative state of charge (0–100). |
0x0105 | SOH | uint16 | % | State of health, reflecting battery capacity degradation (0–100). |
0x0106 | Remaining Capacity | uint16 | mAh | Currently available remaining battery capacity. |
0x0107 | Full Charge Capacity | uint16 | mAh | Actual battery capacity when fully charged. |
0x0108 | Cycle Count | uint16 | cycles | Cumulative charge/discharge cycle count. |
Temperature values are stored as signed 16-bit integers. Convert the raw register value using the following formula:
Temperature (°C) = (int16)Raw Value × 0.1
Examples:
0x00FD(253) → 253 × 0.1 = 25.3° C0xFFF6(-10) → -10 × 0.1 = -1.0° C
Reserved Addresses: 0x0109–0x01FF are reserved.
Cell Data (0x0200–0x02FF)
Individual Cell Voltages
The following registers provide individual cell voltage measurements.
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x0200 | Cell 1 Voltage | uint16 | mV | Voltage of cell 1. |
0x0201 | Cell 2 Voltage | uint16 | mV | Voltage of cell 2. |
0x0202 | Cell 3 Voltage | uint16 | mV | Voltage of cell 3. |
0x0203 | Cell 4 Voltage | uint16 | mV | Voltage of cell 4. |
The host can calculate the max/min cell voltage, voltage difference, and corresponding cell index from the four values above.
Reserved Addresses: 0x0204–0x022F are reserved.
Balancing Status (0x0230)
Register 0x0230 provides the balancing status of individual cells. Each bit indicates whether the corresponding cell is currently being balanced.
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x0230 | Balancing Status | uint16 | - | Bit field indicating the balancing status of each cell. |
Balancing Status Bit Definitions
| Bit | Name | Description |
|---|---|---|
| bit0 | CELL1_BALANCING | Cell 1 is being balanced. |
| bit1 | CELL2_BALANCING | Cell 2 is being balanced. |
| bit2 | CELL3_BALANCING | Cell 3 is being balanced. |
| bit3 | CELL4_BALANCING | Cell 4 is being balanced. |
Reserved Bits: bits[15:4] are reserved.
Reserved Addresses: 0x0231–0x02FF are reserved.
Protection & FET Status (0x0300–0x03FF)
The following registers provide primary and secondary protection status, fault information, and charge/discharge FET conduction status.
Protection & FET Status Registers
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x0300 | Primary Protection Status | uint16 | - | Bitmap indicating active primary protection conditions. See Primary Protection Status Bit Definitions. |
0x0301 | Secondary Protection Status | uint16 | - | Bitmap indicating active secondary protection conditions. See Secondary Protection Status Bit Definitions. |
0x0302 | Fault Status | uint16 | - | Bitmap indicating communication and diagnostic faults. See Fault Status Bit Definitions. |
0x0320 | FET Status | uint16 | - | Bitmap indicating charge and discharge path conduction states. See FET Status Bit Definitions. |
Reserved Addresses: 0x0303–0x031F are reserved.
Primary Protection Status (0x0300) Bit Definitions
When a bit is set to 1, the corresponding primary protection condition is active.
| Bit | Name | Description |
|---|---|---|
| bit0 | OV | Cell overvoltage protection. |
| bit1 | UV | Cell undervoltage protection. |
| bit2 | OC_CHG | Charge overcurrent protection. |
| bit3 | OC_DSG | Discharge overcurrent protection. |
| bit4 | SC | Short circuit protection. |
| bit5 | OTC | Charge overtemperature protection. |
| bit6 | OTD | Discharge overtemperature protection. |
| bit7 | UTC | Charge undertemperature protection. |
| bit8 | UTD | Discharge undertemperature protection. |
| bit9 | FET_OT | MOSFET overtemperature protection. |
| bit10 | DCOT | Unused. This bit always remains 0. |
Reserved Bits: bits[15:11] are reserved.
For protection trigger and recovery conditions, refer to the RAK9156 datasheet.
Secondary Protection Status (0x0301) Bit Definitions
The bit positions correspond to those in the Primary Protection Status Bit Definitions.
When a bit is set to 1, the corresponding secondary protection condition is active.
| Bit | Name | Description |
|---|---|---|
| bit0 | OV | Cell overvoltage protection. |
| bit1 | UV | Cell undervoltage protection. |
| bit2 | OC_CHG | Charge overcurrent protection. |
| bit3 | OC_DSG | Discharge overcurrent protection. |
| bit4 | SC | Unused. This bit always remains 0. |
| bit5 | OTC | Charge overtemperature protection. |
| bit6 | OTD | Discharge overtemperature protection. |
| bit7 | UTC | Unused. This bit always remains 0. |
| bit8 | UTD | Unused. This bit always remains 0. |
| bit9 | FET_OT | Unused. This bit always remains 0. |
| bit10 | DCOT | Cell temperature-difference protection. |
Reserved Bits: bits[15:11] are reserved.
For protection trigger and recovery conditions, refer to the RAK9156 datasheet.
Protection Behavior
- Primary protection acts first during normal operation.
- Secondary protection does not normally trip if primary protection operates as expected.
- If primary protection does not trip, secondary protection still disconnects the affected path.
- The cell temperature-difference protection status (
DCOT) is reported only in the Secondary Protection Status register (0x0301).
Fault Status (0x0302) Bit Definitions
This register reports communication and diagnostic faults, which are separate from the primary and secondary protection conditions reported in registers 0x0300 and 0x0301.
Fault bits are cleared when the corresponding fault condition is resolved. All bits reset to 0 when the MCU is reset.
| Bit | Name | Description |
|---|---|---|
| bit0 | AFE_COMM_FAULT | AFE communication failure. |
| bit1 | CHG_COMM_FAULT | Charger communication failure. |
| bit2 | TEMP_SENSE_FAULT | Temperature sensing fault. |
| bit3 | CELL_SENSE_FAULT | Cell voltage sensing fault. |
| bit4 | CURR_SENSE_FAULT | Current sensing fault. |
Reserved Bits: bits[15:5] are reserved.
The secondary charge and discharge paths are turned off when bit0 (AFE_COMM_FAULT), bit2 (TEMP_SENSE_FAULT), bit3 (CELL_SENSE_FAULT), or bit4 (CURR_SENSE_FAULT) is set, while bit1 (CHG_COMM_FAULT) does not affect these paths.
FET Status (0x0320) Bit Definitions
This register indicates the conduction status of the charge, discharge, and pre-charge FET paths.
| Bit | Name | Description |
|---|---|---|
| bit0 | CHG_ON | Charge FET is on — charging is allowed. |
| bit1 | DSG_ON | Discharge FET is on — discharging is allowed. |
| bit2 | PCHG_ON | Pre-charge FET is on. |
| bit3 | CHG2_ON | Secondary charge path is on. |
| bit4 | DSG2_ON | Secondary discharge path is on. |
- Reserved Bits: bits[15:5] are reserved.
- Reserved Addresses:
0x0321–0x03FFare reserved.
Charger Status (0x1000–0x10FF)
Charger registers are organized into aligned address blocks, with reserved address ranges available for future expansion.
Status, Fault Status, and Charge Stage (0x1000–0x100F)
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x1000 | Charger Status | uint16 | - | Bitmap indicating the current charger status. See Charger Status Bit Definitions. |
0x1001 | Charger Fault Status | uint16 | - | Bitmap indicating active charger fault conditions. See Charger Fault Status Bit Definitions. |
0x1002 | Charge Stage | uint16 | - | Enumeration indicating the current charging stage. See Charge Stage Values. |
Reserved Addresses: 0x1003–0x100F are reserved.
Electrical Measurements (0x1010–0x101F)
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x1010 | Input Voltage | uint16 | mV | Adapter/input voltage. |
0x1011 | Input Current | int16 | mA | Input current, represented as a signed 16-bit value. |
0x1012 | Output Voltage | uint16 | mV | Charger output voltage. |
0x1013 | Output Current | int16 | mA | Battery charging current, represented as a signed 16-bit value. |
Reserved Addresses: 0x1014–0x101F are reserved.
MPPT (0x1020–0x102F)
| Address | Register Name | Data Type | Unit | Description |
|---|---|---|---|---|
0x1020 | MPPT Status | uint16 | - | Enumeration indicating the current MPPT operating state. See MPPT Status Values. |
0x1021 | MPP Voltage (VMPP) | uint16 | mV | Maximum power point input voltage tracked by MPPT. |
Reserved Addresses: 0x1022–0x10FF are reserved.
Charger Status (0x1000) Bit Definitions
Each bit indicates a specific charger operating status.
| Bit | Name | Description |
|---|---|---|
| bit0 | PG | Power good status. |
| bit1 | CHARGE_ENABLED | Charge enable is asserted. |
| bit2 | CHARGING | Charging is in progress. Refer to register 0x1002 for the current charging stage. |
| bit3 | FAULT_PRESENT | A charger fault is present. Refer to register 0x1001 for fault details. |
Reserved Bits: bits[15:4] are reserved.
Charger Fault Status (0x1001) Bit Definitions
Each bit indicates a specific charger fault condition.
| Bit | Name | Description |
|---|---|---|
| bit0 | INPUT_OV | Input overvoltage. |
| bit1 | INPUT_UV | Input undervoltage. |
| bit2 | INPUT_OC | Input overcurrent. |
| bit3 | BAT_OV | Battery overvoltage. |
| bit4 | BAT_OC | Battery overcurrent. |
| bit5 | THERM_SD | Thermal shutdown. |
Reserved Bits: bits[15:6] are reserved.
Charge Stage (0x1002) Values
The register indicates the current charging stage.
| Value | Description |
|---|---|
0 | Idle |
1 | Pre-charge |
2 | Constant Current (CC) |
3 | Constant Voltage (CV) |
4 | Charge Complete |
MPPT Status (0x1020) Values
The register indicates the current MPPT operating state.
| Value | Description |
|---|---|
0 | MPPT Disabled |
1 | MPPT Enabled, Idle |
2 | MPPT Scanning |
3 | Maximum Power Point Detected |
Reserved Addresses: All addresses not listed within the 0x1000–0x10FF range are reserved.
System Control (0x2000–0x2002)
Registers 0x2000 and 0x2002 are write-only; reading either register, individually or as part of a multi-register request, returns exception 0x02. Register 0x2001 supports individual read access. Invalid write values are rejected with exception 0x02, without rebooting the device or changing the slave address.
Successful writes to 0x2000 and 0x2002 return a function 0x06 echo response, followed by a reboot after 100 ms. Wait for the device to restart before sending the next request. After a software reset, use the existing slave address; after a factory reset, use the default address 110 (0x6E). An exception 0x02 indicates an invalid write value or a factory-reset save failure. In either case, the device does not reboot.
| Address | Register Name | Access | Write Value | Behavior |
|---|---|---|---|---|
0x2000 | Software Reset | Write-only | 0x5A5A | Returns an echo response, then reboots. |
0x2001 | Modbus Slave Address | Read/Write | 1–247 | Changes and saves the Modbus slave address. The response uses the slave address from the request. Subsequent requests must use the new address. A read returns the current slave address. |
0x2002 | Factory Reset | Write-only | 0xA55A | Restores factory parameters, including the default RS485 slave address 110 (0x6E). Returns an echo response, then reboots. |
Address 0 is the Modbus broadcast address and cannot be stored in register 0x2001.
Software reset and factory reset requests sent to broadcast address 0 are executed without a response. On a bus with multiple slave devices, all devices execute the broadcast request.
Change the Slave Address
This example changes the slave address from the default 110 (0x6E) to 20 (0x14).
Request
The write request uses the current slave address 110:
6E 06 20 01 00 14 DA 9A
| Field | Bytes | Description |
|---|---|---|
| Slave Address | 6E | 110, the current address used for this request. |
| Function Code | 06 | Write Single Register. |
| Register Address | 20 01 | 0x2001, Modbus Slave Address. |
| Value | 00 14 | 20, the new slave address. |
| CRC | DA 9A | CRC-16/Modbus. |
Response
The device returns the same frame as the write request. The response still uses the original slave address 110.
6E 06 20 01 00 14 DA 9A
After receiving the response, subsequent requests must use the new slave address 20 (0x14).
Read Back the New Address
Send a read request using slave address 20:
Request:
14 03 20 01 00 01 DC CF
Response (register value: 0x0014):
14 03 02 00 14 B5 88