drivers.ADM3061E.ADM3061E.ADM3061E

class drivers.ADM3061E.ADM3061E.ADM3061E

Modbus RTU driver for the ADM3061E battery measurement unit.

Exposes battery voltage, PSU temperature, and module voltage as individual reads or a single bulk transaction. Register layout uses two consecutive 16-bit Modbus holding registers per 32-bit float value (big-endian word order).

Variables:
  • DEBUG (bool) – Print detailed register hex dumps and decoded values when True.

  • SLAVE_ADDRESS (int) – Modbus slave address of the ADM3061E (default: 100 / 0x64).

  • REG_BATTERY_VOLTAGE (int) – Starting register for battery voltage (0x0000).

  • REG_PSU_TEMPERATURE (int) – Starting register for PSU temperature (0x0002).

  • REG_MODULE_VOLTAGE (int) – Starting register for module voltage (0x0004).

Initialise the driver with no open serial connection.

_read_float32_register(start_address: int) float

Read a 32-bit big-endian IEEE 754 float from two consecutive holding registers.

Opens the serial port, issues one read_holding_registers request for two 16-bit words at start_address, repacks them as struct.pack(">HH", high, low) and unpacks as >f, then closes the port.

Parameters:

start_address – Zero-based Modbus holding-register address of the high word.

Returns:

Decoded float value, or None on connection failure, Modbus exception response, or decode error.

Raises:

None – All exceptions are caught; None is returned on failure.

Note

Port is opened and closed per call — concurrent access from multiple threads requires an external lock.

Example

>>> adm._read_float32_register(0x0000)
diagnose(slave_range: range = range(1, 248), timeout: float = 0.3) None

Scan the serial port for any responding Modbus slave.

Opens a fresh ModbusSerialClient on /dev/ttyAMA2 at 9600 baud and probes every slave ID in slave_range by reading register 0x0000. Devices that respond (with data or an exception response) are printed and collected.

Parameters:
  • slave_range – Slave IDs to probe (default: 1–247).

  • timeout – Per-request timeout in seconds (default: 0.3).

Returns:

Results are printed to stdout. Also warns if SLAVE_ADDRESS was not found among the responding devices.

Return type:

None

Raises:

None – All exceptions are caught internally.

Note

Diagnostic use only — do not call in production loops. The scan takes at least len(slave_range) × timeout seconds.

Example

>>> adm.diagnose(slave_range=range(95, 106))
getADM3061E()

Return battery voltage only.

Deprecated since version Use: getBatteryVoltage() for clarity. This method remains for backward compatibility only.

Returns:

Battery voltage in Volts (V) from getBatteryVoltage(), or None on error.

getAllData() dict

Read all three measurements in a single 6-register Modbus transaction.

Issues one read_holding_registers call for 6 consecutive 16-bit words starting at REG_BATTERY_VOLTAGE, then decodes three big-endian 32-bit floats. More efficient than three separate getBatteryVoltage() / getPSUTemperature() / getModuleVoltage() calls.

Returns:

Dict with keys battery_voltage (V), psu_temperature (°C), and module_voltage (V) on success, or None on any error.

Raises:

None – All exceptions are caught; None is returned on failure.

Example

>>> adm.getAllData()
{'battery_voltage': 12.42, 'psu_temperature': 38.5, 'module_voltage': 5.01}

Note

Prefer getAllData() over three individual reads in production — fewer serial transactions reduce latency and bus contention.

getBatteryVoltage() float

Read battery voltage from register REG_BATTERY_VOLTAGE (0x0000).

Returns:

Battery voltage in Volts (V), or None on error.

Raises:

None – Delegates to _read_float32_register() which catches all exceptions.

Example

>>> adm.getBatteryVoltage()
12.42
getData() list

Return all measurements as an ordered list.

Deprecated since version Use: getAllData() which returns a labelled dict. This method remains for backward compatibility only.

Returns:

[battery_voltage, psu_temperature, module_voltage] on success, or [] if getAllData() returns None.

getModuleVoltage() float

Read module voltage from register REG_MODULE_VOLTAGE (0x0004).

Returns:

Module voltage in Volts (V), or None on error.

Raises:

None – Delegates to _read_float32_register() which catches all exceptions.

Example

>>> adm.getModuleVoltage()
5.01
getPSUTemperature() float

Read PSU temperature from register REG_PSU_TEMPERATURE (0x0002).

Returns:

PSU temperature in degrees Celsius (°C), or None on error.

Raises:

None – Delegates to _read_float32_register() which catches all exceptions.

Example

>>> adm.getPSUTemperature()
38.5
initialize(adm3061e_port: str = '/dev/ttyAMA2', baud: int = 9600)

Create the Modbus RTU client for the ADM3061E (does not open the port).

Constructs a ModbusSerialClient in RTU mode with 8N1 framing. The port is opened lazily on each call to _read_float32_register().

Parameters:
  • adm3061e_port – Serial device path (default: /dev/ttyAMA2).

  • baud – Baud rate in bits-per-second (default: 9600).

Returns:

1 on success (legacy return value).

Raises:

Exception – Any pymodbus client construction error propagates.

Example

>>> adm = ADM3061E()
>>> adm.initialize("/dev/ttyAMA2", 9600)
micros() int

Return the current epoch time in microseconds.

Returns:

Current Unix timestamp multiplied by 1 000 000, as an integer.

millis() int

Return the current epoch time in milliseconds.

Returns:

Current Unix timestamp multiplied by 1 000, as an integer.

DEBUG = True
REG_BATTERY_VOLTAGE = 0
REG_MODULE_VOLTAGE = 4
REG_PSU_TEMPERATURE = 2
SLAVE_ADDRESS = 100
TIMEOUT = 8000
_timeout_ = 8
adm3061e = None