Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add additional meters - how to ?? #174

Closed
craigcurtin-dev opened this issue Oct 16, 2020 · 12 comments · May be fixed by #175
Closed

How to add additional meters - how to ?? #174

craigcurtin-dev opened this issue Oct 16, 2020 · 12 comments · May be fixed by #175
Labels
question Further information is requested

Comments

@craigcurtin-dev
Copy link

Hi guys, i have a 3phase meter - various names - Acrel DTSD1352, ADL3000E/CT , Solis 3P, etc.

It is an RS485 Modbus compliant device - and i have the Modbus map for it - is there a way to include a translation table or some such going forward (i guess similar to what the SUnspec guys are trying to do) - i do not believe this meter is Sunspec compliant).

I know nothing about Go so if someone could point me to some sample files for other meters i will have a go at modifying one to support this meter

Craig

@andig
Copy link
Contributor

andig commented Oct 17, 2020

Thank you for the question! The RTU meters are implemented here in this folder: https://github.com/volkszaehler/mbmd/tree/master/meters/rs485.
Choose one that looks closest to how your meter is read and start with a copy!
PRs are welcome.

@andig andig added the question Further information is requested label Oct 17, 2020
@craigcurtin-dev
Copy link
Author

craigcurtin-dev commented Oct 18, 2020 via email

@craigcurtin-dev
Copy link
Author

Hey AndiG

Not really sure what i am doing here - i have tried to add a new meter ACREL3000 - which is a 3phase meter.

I have used the mbmd commandline with the read option and have been able to successfully query the meter. Not sure how to compile a new version that includes the meter file that i have attempted to put together to enable me to test it ?

regards

Craig

@andig
Copy link
Contributor

andig commented Oct 18, 2020

See https://github.com/volkszaehler/mbmd#building-from-source for how to build from source. It assumes you have the sources checked out. Run make install once to setup the build tools.

@craigcurtin-dev
Copy link
Author

Yes thanks for the quick reply.

I have tried that on the machine that i am using (Ubuntu 18.04) and have gotten it into a terrible mess - each time i try and run the make install as per your directions i am getting an error about other github repos - i have looked in the makefile (which is about the extent of my abilities) and can see it looking for other repos (enumer for instance) and failing on those.

So i have gotten about as far as i can. I was going to run up a new VM and attempt to start from scratch tomorrow and see how i go

Craig

@andig
Copy link
Contributor

andig commented Oct 18, 2020

Just post your file here and I‘ll wip up a quick PR for you to checkout and test

@andig
Copy link
Contributor

andig commented Oct 18, 2020

But.. you‘ll still need to be able to compile a PR ;)

@craigcurtin-dev
Copy link
Author

package rs485

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

func init() {
Register(ACREL3000)

}

const (
METERTYPE_ACREL3000 = "ACREL3000"
)

var ops3p Opcodes = Opcodes{

	Frequency:       0x0077, // 32 bit, Hz

	VoltageL1:       0x0061, // 32 bit, V
	CurrentL1:       0x0064, // 32 bit, A
	PowerL1:         0x0067, // 32 bit, kW
	ReactivePowerL1: 0x006B, // 32 bit, kvar
	ApparentPowerL1: 0x006F, // 32 bit, kva

// CosphiL1: 0x0036, // 32 bit, XX,X(literal)

	VoltageL2:       0x0062, // 32 bit, V
	CurrentL2:       0x0065, // 32 bit, A
	PowerL2:         0x0068, // 32 bit, kW
	ReactivePowerL2: 0x006C, // 32 bit, kvar
	ApparentPowerL2: 0x0070, // 32 bit, kva

// CosphiL2: 0x0038, // 32 bit, XX,X(literal)

	VoltageL3:       0x0063, // 32 bit, V
	CurrentL3:       0x0066, // 32 bit, A
	PowerL3:         0x0069, // 32 bit, kW
	ReactivePowerL3: 0x006D, // 32 bit, kvar
	ApparentPowerL3: 0x0071, // 32 bit, kva

// CosphiL3: 0x003A, // 32 bit, XX,X(literal)

	Power:           0x001C, // 32 bit, kW
	ReactivePower:   0x006E, // 32 bit, kvar
	ApparentPower:   0x0072, // 32 bit, kva

// Cosphi: 0x0034, // 32 bit, XX,X(literal)

// Sum: 0x0100, //32 Bit, kwh
// SumL1: 0x0102, //32 Bit, kwh
// SumL2: 0x0104, //32 Bit, kwh
// SumL3: 0x0106, //32 Bit, kwh

// Import: 0x0108, //32 Bit, kwh
// ImportL1: 0x010A, //32 Bit, kwh
// ImportL2: 0x010C, //32 Bit, kwh
// ImportL3: 0x010E, //32 Bit, kwh

// Export: 0x0110, //32 Bit, kwh
// ExportL1: 0x0112, //32 Bit, kwh
// ExportL2: 0x0114, //32 Bit, kwh
// ExportL3: 0x0116, //32 Bit, kwh

// ReactiveSum: 0x0118, //32 Bit, kvarh
// ReactiveSumL1: 0x011A, //32 Bit, kvarh
// ReactiveSumL2: 0x011C, //32 Bit, kvarh
// ReactiveSumL3: 0x011E, //32 Bit, kvarh

// ReactiveImport: 0x0120, //32 Bit, kvarh
// ReactiveImportL1:0x0122, //32 Bit, kvarh
// ReactiveImportL2:0x0124, //32 Bit, kvarh
// ReactiveImportL3:0x0126, //32 Bit, kvarh

// ReactiveExport: 0x0128, //32 Bit, kvarh
// ReactiveExportL1:0x012A, //32 Bit, kvarh
// ReactiveExportL2:0x012C, //32 Bit, kvarh
// ReactiveExportL3:0x012E, //32 Bit, kvarh

// SumT1: 0x0130, //32 Bit, kwh
// ImportT1: 0x0132, //32 Bit, kwh
// ExportT1: 0x0134, //32 Bit, kwh
// ReactiveSumT1: 0x0136, //32 Bit, kvarh
// ReactiveImportT1:0x0138, //32 Bit, kvarh
// ReactiveExportT1:0x013A, //32 Bit, kvarh

// SumT2: 0x013C, //32 Bit, kwh
// ImportT2: 0x013E, //32 Bit, kwh
// ExportT2: 0x0140, //32 Bit, kwh
// ReactiveSumT2: 0x0142, //32 Bit, kvarh
// ReactiveImportT2:0x0144, //32 Bit, kvarh
// ReactiveExportT2:0x0146, //32 Bit, kvarh

/* // Curently not supported
SumT3: 0x0148, //32 Bit, kwh
ImportT3: 0x014A, //32 Bit, kwh
ExportT3: 0x014C, //32 Bit, kwh
ReactiveSumT3: 0x015E, //32 Bit, kvarh
ReactiveImportT3:0x0150, //32 Bit, kvarh
ReactiveExportT3:0x0152, //32 Bit, kvarh

	SumT4:           0x0154, //32 Bit, kwh
	ImportT4:        0x0156, //32 Bit, kwh
	ExportT4:        0x0158, //32 Bit, kwh
	ReactiveSumT4:   0x015A, //32 Bit, kvarh
	ReactiveImportT4:0x015C, //32 Bit, kvarh
	ReactiveExportT4:0x015E, //32 Bit, kvarh

*/
}

type ORNO3PProducer struct {
Opcodes
}

func NewORNO3PProducer() Producer {
return &ORNO3PProducer{Opcodes: ops3p}
}

// Type implements Producer interface
func (p *ORNO3PProducer) Type() string {
return METERTYPE_ORNO3p
}

// Description implements Producer interface
func (p *ORNO3PProducer) Description() string {
return "ACREL3000 3Phase"
}

// snip creates modbus operation
func (p *ORNO3PProducer) snip(iec Measurement, readlen uint16) Operation {
return Operation{
FuncCode: ReadHoldingReg,
OpCode: p.Opcode(iec), // adjust according to docs
ReadLen: readlen,
IEC61850: iec,
}
}

// snip32 creates modbus operation for double register
func (p *ORNO3PProducer) snip32(iec Measurement, scaler ...float64) Operation {
snip := p.snip(iec, 2)

    snip.Transform = RTUIeee754ToFloat64 // default conversion
    if len(scaler) > 0 {
            snip.Transform = MakeScaledTransform(snip.Transform, scaler[0])
    }

    return snip

}

func (p *ORNO3PProducer) Probe() Operation {
return p.snip32(VoltageL1,1)
}

// Produce implements Producer interface
func (p *ORNO3PProducer) Produce() (res []Operation) {

// These values are stored as literals
for _, op := range []Measurement{
Frequency,
VoltageL1, CurrentL1,
VoltageL2, CurrentL2,
VoltageL3, CurrentL3,
// Sum, SumL1, SumL2, SumL3,
// Import, ImportL1, ImportL2, ImportL3,
// Export, ExportL1, ExportL2, ExportL3,
ReactiveSum, ReactiveSumL1, ReactiveSumL2, ReactiveSumL3,
// ReactiveImport, ReactiveImportL1, ReactiveImportL2, ReactiveImportL3,
// ReactiveExport, ReactiveExportL1, ReactiveExportL2, ReactiveExportL3,
// SumT1, ImportT1, ExportT1, ReactiveSumT1, ReactiveImportT1, ReactiveExportT1,
// SumT2, ImportT2, ExportT2, ReactiveSumT2, ReactiveImportT2, ReactiveExportT2,
} {
res = append(res, p.snip32(op, 1))
}

// For Power values, we need to scale by 1000 (aka convert kW/kva -> W/va)
for _, op := range []Measurement{
PowerL1, ReactivePowerL1, ApparentPowerL1,
PowerL2, ReactivePowerL2, ApparentPowerL2,
PowerL3, ReactivePowerL3, ApparentPowerL3,
Power, ReactivePower, ApparentPower,
} {
res = append(res, p.snip32(op, 0.001))
}
return res
}

@craigcurtin-dev
Copy link
Author

This is where i am at so far but need to test it before i flesh it out and rename all of the internal variables etc

Hmm, the whole GO compile thing is a bit of a nightmare !

Craig

@craigcurtin-dev
Copy link
Author

Thanks AndiG - now trying to work out how to get this PR onto my system and then compile !!

Craig

@andig
Copy link
Contributor

andig commented Nov 6, 2020

Ping @craigcurtin-dev would appreciate some feedback after putting everything together for you ;)

@craigcurtin-dev
Copy link
Author

Yeah i am struggling with the whole compile the PR in go thing at the moment and it has slipped off my urgent list (so many things to do - so little time !)

I have a weekly reminder to get back to it but will be another couple of weeks until i free up the time.

thanks for the follow up

Craig

@andig andig closed this as completed Mar 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants