Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is a Python module that implements the communication to several electricity

At the moment, the following meters are supported:

* ABB B21, B23, A43 and similar ABB meters (Modbus Serial)
* ABB B21, B23, A43, EV3 and similar ABB meters (Modbus Serial)
* SMA SunnyBoy (Modbus TCP)
* MultiCube meters

Expand All @@ -31,6 +31,15 @@ data = meter.read()

This returns a dictionary with all key-value pairs of data.

To read all resgisters from ABB EV3 (using default serial values 9600, 8E1):
```
from energymeter import ABBMeter
import serial

meter = ABBMeter(port="/dev/ttyUSB0", baudrate=9600, parity=serial.PARITY_EVEN, slaveaddress=1, model="EV3")
data = meter.read()
```

To read a single register:

```
Expand Down
26 changes: 21 additions & 5 deletions energymeter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import struct
import asyncio
import time
import serial

import minimalmodbus
import tinysbus
Expand All @@ -13,22 +14,25 @@

class ModbusRTUMeter:
"""Meter class that uses a minimalmodbus Instrument to query an ABB meter."""
def __init__(self, port, baudrate=38400, slaveaddress=1, timeout=0.5):
def __init__(self, port, baudrate=38400, parity=serial.PARITY_NONE, slaveaddress=1, timeout=0.5, debug=False):
""" Initialize the ModbusRTUmeter object.

Arguments:
* port: a serial port (string)
* baudrate: the baudrate to use (integer)
* parity: the serial parity to use
* slaveaddress: the address of the modbus device (integer)
* Specification of the type. Used to limit the registers to a specific set.
* debug: toggle debug output

Returns:
* An ABBMeter object

"""
self.instrument = minimalmodbus.Instrument(port, slaveaddress)
self.instrument = minimalmodbus.Instrument(port, slaveaddress, debug=debug)
self.instrument.serial.baudrate = baudrate
self.instrument.serial.timeout = timeout
self.instrument.serial.parity = parity

def read(self, regnames=None):
""" Read one, many or all registers from the device
Expand Down Expand Up @@ -224,8 +228,8 @@ def _convert_value(self, values, signed=False, number_of_decimals=0, is_float=Fa


class ABBMeter(ModbusRTUMeter):
def __init__(self, port, baudrate=38400, slaveaddress=1, timeout=0.5, model=None):
super().__init__(port, baudrate, slaveaddress, timeout)
def __init__(self, port, baudrate=38400, parity=serial.PARITY_NONE, slaveaddress=1, timeout=0.5, model=None, debug=False):
super().__init__(port, baudrate, parity, slaveaddress, timeout, debug)
if model in ABBMeter.REGSETS:
self.REGS = [register for register in ABBMeter._REGS if register['name'] in ABBMeter.REGSETS[model]]
else:
Expand Down Expand Up @@ -555,7 +559,19 @@ def __init__(self, port, baudrate=38400, slaveaddress=1, timeout=0.5, model=None
"voltage_l1_n", "current_l1", "active_power_total",
"reactive_power_total", "apparent_power_total", "frequency",
"phase_angle_power_total", "power_factor_total",
"current_quadrant_total"]
"current_quadrant_total"],
"EV3": ["active_import", "active_export", "active_net",
"active_import_l1", "active_import_l2", "active_import_l3",
"active_export_l1", "active_export_l2", "active_export_l3",
"active_net_l1", "active_net_l2", "active_net_l3",
"voltage_l1_n", "voltage_l2_n", "voltage_l3_n",
"voltage_l1_l2", "voltage_l3_l2", "voltage_l1_l3",
"current_l1", "current_l2", "current_l3",
"active_power_total", "active_power_l1", "active_power_l2",
"active_power_l3", "reactive_power_total",
"frequency", "phase_angle_power_total",
"power_factor_total", "power_factor_l1", "power_factor_l2",
"power_factor_l3", "ev3_serial_number"]
}
NULLS = [pow(2, n) - 1 for n in (64, 63, 32, 31, 16, 15)]

Expand Down