Skip to content

Commit

Permalink
Differentiate SDM220/230 meters (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: joekokker <59933882+joekokker@users.noreply.github.com>
  • Loading branch information
andig and joekokker authored Mar 23, 2020
1 parent 9d53a95 commit 510de61
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 59 deletions.
7 changes: 7 additions & 0 deletions assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,13 @@ <h1>Measurements</h1>
<td class="col-3" v-if="pop(m.THD)">${ m.THD }</td>
<td class="col-3" v-else>&mdash;</td>
</tr>
<tr class="d-flex" v-if="populated(m.PhaseAngle)">
<td class="col-3">Phase Angle</td>
<td class="col-2">&mdash;</td>
<td class="col-2">&mdash;</td>
<td class="col-2">&mdash;</td>
<td class="col-3">${ m.PhaseAngle }</td>
</tr>
<tr class="d-flex" v-if="pop(m.Frequency)">
<td class="col-3">Frequency (Hz)</td>
<td class="col-2">&mdash;</td>
Expand Down
4 changes: 3 additions & 1 deletion docs/mbmd_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ mbmd inspect [flags]
INEPRO Inepro Metering Pro 380
JANITZA Janitza B-Series meters
SBC Saia Burgess Controls ALE3 meters
SDM Eastron SDM meters
SDM Eastron SDM630
SDM220 Eastron SDM220
SDM230 Eastron SDM230
TCP
SUNS Sunspec-compatible MODBUS TCP device (SMA, SolarEdge, KOSTAL, etc)
To use an adapter different from default, append RTU device or TCP address separated by @.
Expand Down
4 changes: 3 additions & 1 deletion docs/mbmd_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ mbmd run [flags]
INEPRO Inepro Metering Pro 380
JANITZA Janitza B-Series meters
SBC Saia Burgess Controls ALE3 meters
SDM Eastron SDM meters
SDM Eastron SDM630
SDM220 Eastron SDM220
SDM230 Eastron SDM230
TCP
SUNS Sunspec-compatible MODBUS TCP device (SMA, SolarEdge, KOSTAL, etc)
To use an adapter different from default, append RTU device or TCP address separated by @.
Expand Down
5 changes: 3 additions & 2 deletions meters/measurement_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions meters/measurements.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ const (
// Battery
ChargeState
BatteryVoltage

PhaseAngle
)

var iec = map[Measurement][]string{
Expand Down Expand Up @@ -232,6 +234,7 @@ var iec = map[Measurement][]string{
DCEnergyS3: {"String 3 Generation", "kWh"},
ChargeState: {"Charge State", "%"},
BatteryVoltage: {"Battery Voltage", "V"},
PhaseAngle: {"Phase Angle", "°"},
}

// MarshalText implements encoding.TextMarshaler
Expand Down
24 changes: 12 additions & 12 deletions meters/rs485/sdm.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ type SDMProducer struct {

func NewSDMProducer() Producer {
/**
* Opcodes as defined by Eastron.
* Opcodes as defined by Eastron SDM630.
* See http://bg-etech.de/download/manual/SDM630Register.pdf
* Please note that this is the superset of all SDM devices -
* some opcodes might not work on some devicep.
* This is to a large extent a superset of all SDM devices, however there are
* subtle differences (see 220, 230). Some opcodes might not work on some devices.
*/
ops := Opcodes{
VoltageL1: 0x0000,
VoltageL1: 0x0000, // 220, 230
VoltageL2: 0x0002,
VoltageL3: 0x0004,
CurrentL1: 0x0006,
CurrentL1: 0x0006, // 220, 230
CurrentL2: 0x0008,
CurrentL3: 0x000A,
PowerL1: 0x000C,
PowerL1: 0x000C, // 230
PowerL2: 0x000E,
PowerL3: 0x0010,
Power: 0x0034,
Expand All @@ -38,24 +38,24 @@ func NewSDMProducer() Producer {
ImportL1: 0x015a,
ImportL2: 0x015c,
ImportL3: 0x015e,
Import: 0x0048,
Import: 0x0048, // 220, 230
ExportL1: 0x0160,
ExportL2: 0x0162,
ExportL3: 0x0164,
Export: 0x004a,
Export: 0x004a, // 220, 230
SumL1: 0x0166,
SumL2: 0x0168,
SumL3: 0x016a,
Sum: 0x0156,
CosphiL1: 0x001e,
Sum: 0x0156, // 220
CosphiL1: 0x001e, // 230
CosphiL2: 0x0020,
CosphiL3: 0x0022,
Cosphi: 0x003e,
THDL1: 0x00ea, // voltage
THDL2: 0x00ec, // voltage
THDL3: 0x00ee, // voltage
THD: 0x00F8, // voltage
Frequency: 0x0046,
Frequency: 0x0046, // 230
//L1THDCurrent: 0x00F0, // current
//L2THDCurrent: 0x00F2, // current
//L3THDCurrent: 0x00F4, // current
Expand All @@ -70,7 +70,7 @@ func (p *SDMProducer) Type() string {
}

func (p *SDMProducer) Description() string {
return "Eastron SDM meters"
return "Eastron SDM630"
}

func (p *SDMProducer) snip(iec Measurement) Operation {
Expand Down
64 changes: 64 additions & 0 deletions meters/rs485/sdm220.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package rs485

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

func init() {
Register(NewSDM220Producer)
}

const (
METERTYPE_SDM220 = "SDM220"
)

type SDM220Producer struct {
Opcodes
}

func NewSDM220Producer() Producer {
/**
* Opcodes as defined by Eastron SDM220.
* See https://bg-etech.de/download/manual/SDM220StandardDE.pdf
*/
ops := Opcodes{
Voltage: 0x0000, // 220, 230
Current: 0x0006, // 220, 230
Import: 0x0048, // 220, 230
Export: 0x004a, // 220, 230
Sum: 0x0156, // 220, 230
ReactiveSum: 0x0158, // 220
ReactiveImport: 0x4C, // 220, 230
ReactiveExport: 0x4E, // 220, 230
}
return &SDM220Producer{Opcodes: ops}
}

func (p *SDM220Producer) Type() string {
return METERTYPE_SDM220
}

func (p *SDM220Producer) Description() string {
return "Eastron SDM220"
}

func (p *SDM220Producer) snip(iec Measurement) Operation {
operation := Operation{
FuncCode: ReadInputReg,
OpCode: p.Opcode(iec),
ReadLen: 2,
IEC61850: iec,
Transform: RTUIeee754ToFloat64,
}
return operation
}

func (p *SDM220Producer) Probe() Operation {
return p.snip(Voltage)
}

func (p *SDM220Producer) Produce() (res []Operation) {
for op := range p.Opcodes {
res = append(res, p.snip(op))
}

return res
}
69 changes: 69 additions & 0 deletions meters/rs485/sdm230.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package rs485

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

func init() {
Register(NewSDM230Producer)
}

const (
METERTYPE_SDM230 = "SDM230"
)

type SDM230Producer struct {
Opcodes
}

func NewSDM230Producer() Producer {
/**
* Opcodes as defined by Eastron SDM230.
* See https://bg-etech.de/download/manual/SDM230-register.pdf
*/
ops := Opcodes{
Voltage: 0x0000, // 220, 230
Current: 0x0006, // 220, 230
Power: 0x000C, // 230
Import: 0x0048, // 220, 230
Export: 0x004a, // 220, 230
Cosphi: 0x001e, // 230
Frequency: 0x0046, // 230
ReactiveImport: 0x4C, // 220, 230
ReactiveExport: 0x4E, // 220, 230
ApparentPower: 0x0012, // 230
ReactivePower: 0x0018, // 230
Sum: 0x0156, // 230
PhaseAngle: 0x0024, // 230
}
return &SDM230Producer{Opcodes: ops}
}

func (p *SDM230Producer) Type() string {
return METERTYPE_SDM230
}

func (p *SDM230Producer) Description() string {
return "Eastron SDM230"
}

func (p *SDM230Producer) snip(iec Measurement) Operation {
operation := Operation{
FuncCode: ReadInputReg,
OpCode: p.Opcode(iec),
ReadLen: 2,
IEC61850: iec,
Transform: RTUIeee754ToFloat64,
}
return operation
}

func (p *SDM230Producer) Probe() Operation {
return p.snip(Voltage)
}

func (p *SDM230Producer) Produce() (res []Operation) {
for op := range p.Opcodes {
res = append(res, p.snip(op))
}

return res
}
87 changes: 44 additions & 43 deletions server/assets.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 510de61

Please sign in to comment.