Skip to content
Merged
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ manuals for definitive guidance):
|---|---|---|---|---|---|---|---|---|---|
| EM24 | 3 | + | + | + | + | + | + | +/- | - |
| EM24_E1 | 3 | + | + | + | + | + | + | +/- | - |
| Eltako DSZ15DZMOD/DSZ16 | 3 | + | + | + | + | + | + | - | - |
| SDM54 | 3 | + | + | + | + | + | + | + | + |
| SDM72 | 3 | - | - | + | - | + | + | - | - |
| SDM120/220 | 1 | + | + | + | + | + | + | - | - |
Expand All @@ -263,6 +264,7 @@ manuals for definitive guidance):

- **EM24**: Compact (4TE), 3P meter with RS-485 interface.
- **EM24_E1**: Compact (4TE), 3P meter with Ethernet interface.
- **Eltako DSZ15DZMOD/DSZ16**: Bidirectional 3P MID meters with Modbus RTU.
- **SDM54**: Compact (3TE), 3P meter with a lot of features. Can be configured using the builtin display.
- **SDM72**: Compact (4TE), 3P meter with bare minium of total measurements, no currents. Can be configured using the builtin display.
- **SDM120**: Cheap and small (1TE), but communication parameters can only be set over MODBUS, which is currently not supported by this project.
Expand Down Expand Up @@ -301,7 +303,6 @@ WE-517 has a lithium battery and multi-tariff support, WE-516 does not support t
- **B+G e-tech DS100**: Looks to be similar potent as SDM630 if not better, very cheap in Germany (below 50€)
Able to set higher Baudrate than SDM630 so measurements can be taken more often.
There is also a MID Version and Multi Traif ("-30B") Version.
(https://data.xn--stromzhler-v5a.eu/manuals/bg_ds100serie_de.pdf)

## Modbus TCP Grid Inverters

Expand Down
2 changes: 2 additions & 0 deletions docs/mbmd_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ mbmd inspect [flags]
DS100 B+G e-tech DS100
DTSU666 Chint DTSU666
DZG DZG Metering GmbH DVH4013 meters
ELTAKODSZ15Eltako DSZ15DZMOD / DSZ16
ELTAKODSZ16Eltako DSZ15DZMOD / DSZ16
FIND7M24 Finder 7M.24
FIND7M38 Finder 7M.38
IEM3000 Schneider Electric iEM3000 series
Expand Down
2 changes: 2 additions & 0 deletions docs/mbmd_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ mbmd run [flags]
DS100 B+G e-tech DS100
DTSU666 Chint DTSU666
DZG DZG Metering GmbH DVH4013 meters
ELTAKODSZ15Eltako DSZ15DZMOD / DSZ16
ELTAKODSZ16Eltako DSZ15DZMOD / DSZ16
FIND7M24 Finder 7M.24
FIND7M38 Finder 7M.38
IEM3000 Schneider Electric iEM3000 series
Expand Down
113 changes: 113 additions & 0 deletions meters/rs485/eltako.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package rs485

import . "github.com/volkszaehler/mbmd/meters"

func init() {
// Both meters share the same (publicly documented) register layout, so a
// single producer is registered under both type codes.
Register("ELTAKODSZ15", NewEltakoProducer)
Register("ELTAKODSZ16", NewEltakoProducer)
}

type EltakoProducer struct {
Opcodes
}

func NewEltakoProducer() Producer {
/**
* Opcodes for Eltako DSZ15DZMOD (and DSZ16 series in integer data format).
* https://www.eltako.com/fileadmin/downloads/de/_bedienung/Modbus-RTU_protocol_specification_for_DSZ15DZMOD_V1.6_English_version.pdf
*
* TODO: the DSZ16 series additionally exposes reactive/apparent power,
* frequency, per-phase energy and a float data format. These registers are
* not part of the public DSZ15DZMOD spec.
*/
ops := Opcodes{
VoltageL1: 0x0000,
VoltageL2: 0x0002,
VoltageL3: 0x0004,

CurrentL1: 0x0006,
CurrentL2: 0x0008,
CurrentL3: 0x000A,

PowerL1: 0x000C,
PowerL2: 0x000E,
PowerL3: 0x0010,
Power: 0x0034,

CosphiL1: 0x001E,
CosphiL2: 0x0020,
CosphiL3: 0x0022,
Cosphi: 0x003E,

Import: 0x0048,
Export: 0x004A,
}
return &EltakoProducer{Opcodes: ops}
}

// Description implements Producer interface
func (p *EltakoProducer) Description() string {
return "Eltako DSZ15DZMOD / DSZ16"
}

func (p *EltakoProducer) snip(iec Measurement, transform RTUTransform, scaler ...float64) Operation {
if len(scaler) > 0 {
transform = MakeScaledTransform(transform, scaler[0])
}

return Operation{
FuncCode: ReadInputReg,
OpCode: p.Opcode(iec),
ReadLen: 2,
IEC61850: iec,
Transform: transform,
}
}

// snipU creates a modbus operation for an unsigned 32 bit register
func (p *EltakoProducer) snipU(iec Measurement, scaler ...float64) Operation {
return p.snip(iec, RTUUint32ToFloat64, scaler...)
}

// snipI creates a modbus operation for a signed 32 bit register
func (p *EltakoProducer) snipI(iec Measurement, scaler ...float64) Operation {
return p.snip(iec, RTUInt32ToFloat64, scaler...)
}

// Probe implements Producer interface
func (p *EltakoProducer) Probe() Operation {
return p.snipU(VoltageL1, 100)
}

// Produce implements Producer interface
func (p *EltakoProducer) Produce() (res []Operation) {
for _, op := range []Measurement{
VoltageL1, VoltageL2, VoltageL3,
CurrentL1, CurrentL2, CurrentL3,
} {
res = append(res, p.snipU(op, 100))
}

for _, op := range []Measurement{
CosphiL1, CosphiL2, CosphiL3, Cosphi,
} {
res = append(res, p.snipI(op, 1000))
}

for _, op := range []Measurement{
PowerL1, PowerL2, PowerL3, Power,
} {
res = append(res, p.snipI(op))
}

// energy registers report kWh with 2 decimals
for _, op := range []Measurement{
Import, Export,
} {
res = append(res, p.snipU(op, 100))
}

return res
}