This is a common quirk of modbus, I have been working with many modbus devices recently and found as many docs use address as register, and sometimes the terms are used interchangeably, this seems to be rooted in the age old fact that the “first” position in an array is always index 0 etc, although I have written my own universal modbus reading code, I too have to +1 on some devices, but not all, it depends on what is documented, so even if you rewrite emonhub to +1 automatically, there would then be instances where some users have to -1 depending on the published documentation (and recognizing the difference, which even some manufacturers seem unable to do).
Hi All
I am also trying to connect to my Fronius Primo (8.2) unit, but not having any success. I can poll the inverter using a python script and get results, but can’t seem to get past square 1 (or 0 in linux…) with configuring emonhub. Here is my config file extract:
[[ModbusTCP]]
# this interfacer retrieves register information from modbusTCP clients
# retrieve register information from modbus TCP documentation for your inverter.
# Information here is designed for Fronius Symo 3 phase inverter. #changed to check operation of Primo
Type = EmonModbusTcpInterfacer
[[[init_settings]]]
modbus_IP = 10.0.0.9 # ip address of client to retrieve data from
modbus_port = 502 # Portclient listens on
[[[runtimesettings]]]
# list of names of items being retrieved
rName = ID,L,A,W,Hz,VA,VAr,PF,WH,DCW
#
# List of starting registers for items listed above
register = 40070,40071,40072,40092,40094,40096,40098,40100,40102,40108
#
# List of # of registers used for each item
nReg = 1,1,2,2,2,2,2,2,2,2
# Data type for each item above
rType = uint16,uint16,float32,float32,float32,float32,float32,float32,float32,float32
# nodeid used to match with node definition in nodes section below. Can be set to any integer value not previously used.
nodeId = 30
# Channel to publish data to should leave as ToEmonCMS
pubchannels = ToEmonCMS,
# time in seconds between checks, This is in addition to emonhub_interfacer.run() sleep time of .01
# use this value to set the frequency of data retrieval from modbus client
interval = 10
[[MQTT]]
Type = EmonHubMqttInterfacer
[[[init_settings]]]
mqtt_host = 127.0.0.1
mqtt_port = 1883
mqtt_user = emonpi
mqtt_passwd = emonpimqtt2016
[[[runtimesettings]]]
pubchannels = ToRFM12,
subchannels = ToEmonCMS,
# emonhub/rx/10/values format
# Use with emoncms Nodes module
node_format_enable = 1
node_format_basetopic = emonhub/
# emon/emontx/power1 format - use with Emoncms MQTT input
# http://github.com/emoncms/emoncms/blob/master/docs/RaspberryPi/MQTT.md
nodevar_format_enable = 1
nodevar_format_basetopic = emon/
and my nodes section:
[[30]]
nodename = fronius
[[[rx]]]
names = ID,L,A,W,Hz,VA,VAr,PF,WH,DCW
datacodes = H,H,f,f,f,f,f,f,f,f
scale = 1
units = V,W,kWh,Wh,W,W,V,V,V,V,V
I’ve install pymodbus and pymodbusTCCP onto my emonbase, but no matter what I try, I can’t seem to get any output from node 30…
I’m using the latest versions as far as I can tell:
Emoncms Version low-write 9.9.5
Modules Administration | App v1.2.0 | Backup v1.1.6 | EmonHub Config v1.0.0 | Dashboard v1.3.1 | Device v1.2.0 | EventProcesses | Feed | Graph v1.2.1 | Input | Postprocess v1.0.0 | CoreProcess | Schedule | Network Setup v1.0.0 | sync | Time | User | Visualisation | WiFi v1.3.0
but nothing from node 30 to be seen in inputs or using
mosquitto_sub -v -u 'emonpi' -P 'emonpimqtt2016' -t '#'
I’ve looked at the emonhub logs but no mention of fronius or node 30…
Can anyone suggest a way forward?
Hi,
What python script are you using to test, can you give more details about this script?
scale must be defined by all registers, see this example:
Missatge de Anthony Vassallo [email protected] del dia dl., 31 de des. 2018 a les 6:38:
Well,
finally seems that I can obtain data and graphs! Great!
Now I only have one problem, I cna obtain a value of daywh by day from fronius, but I can generate a daily graphs from this daily ouput, anybody can give informatin how to do this with this daily value from fronius?
I see another option generatin from power consumption but also is not working or I don’t know ho to do this power to kwh, any suggestion?
Thanks!
Missatge de Anthony Vassallo [email protected] del dia dl., 31 de des. 2018 a les 6:38:
Python script is basic, but uses Rcihard Stobor’s type translation. It took some effort to find and use the Primo modbus registers, but is now working OK. Note all the register lines from 40070 down are commented out in the script, but I had to remove the quotes to past here:
from pyModbusTCP.client import ModbusClient
import time
import ctypes
#
# byte translation from: https://github.com/stoberblog/sunspec-modbus/blob/master/sunspecModbus.py
# Fronius Primo has 62 registers starting at 40070
# reg 0 should be inverter model 111 (unint16)
# reg 1 should be length of reg blocks = 60 (unint16)
# next 23 are 2 register blocks of float32
# then 2 single register blocks
# then final six 2 register blocks
# from docs:
# -----following should be commented out ---------------
40070 40070 1 ID Uniquely identifies this as a SunSpec Inverter Float Modbus Map; 111: single phase, 112: split phase, 113: three phase uint16
40071 40071 1 L Length of inverter model block uint16
40072 40073 2 A AC Total Current value float32
40074 40075 2 AphA AC Phase-A Current value float32
40076 40077 2 AphB AC Phase-B Current value float32
40078 40079 2 AphC AC Phase-C Current value float32
40080 40081 2 PPVphAB AC Voltage Phase-AB value float32
40082 40083 2 PPVphBC AC Voltage Phase-BC value float32
40084 40085 2 PPVphCA AC Voltage Phase-CA value float32
40086 40087 2 PhVphA AC Voltage Phase-A-to-neutral value float32
40088 40089 2 PhVphB AC Voltage Phase-B-to-neutral value float32
40090 40091 2 PhVphC AC Voltage Phase-C-to-neutral value float32
40092 40093 2 W AC Power value float32
40094 40095 2 Hz AC Frequency value float32
40096 40097 2 VA Apparent Power float32
40098 40099 2 VAr Reactive Power float32
40100 40101 2 PF Power Factor float32
40102 40103 2 WH AC Lifetime Energy production float32
40104 40105 2 DCA DC Current value float32
40106 40107 2 DCV DC Voltage value float32
40108 40109 2 DCW DC Power value float32
40110 40111 2 TmpCab Cabinet Temperature float32
40112 40113 2 TmpSnk Coolant or Heat Sink Temperature float32
40114 40115 2 TmpTrns Transformer Temperature float32
40116 40117 2 TmpOt Other Temperature float32
40118 40118 1 St Operating State enum16
40119 40119 1 StVnd Vendor Defined Operating State enum16
40120 40121 2 Evt1 Event Flags (bits 0-31) uint32
40122 40123 2 Evt2 Event Flags (bits 32-63) uint32
40124 40125 2 EvtVnd1 Vendor Defined Event Flags (bits 0-31) uint32
40126 40127 2 EvtVnd2 Vendor Defined Event Flags (bits 32-63) uint32
40128 40129 2 EvtVnd3 Vendor Defined Event Flags (bits 64-95) uint32
40130 40131 2 EvtVnd4 Vendor Defined Event Flags (bits 96-127) uint32
so read 62 registers at once, then pull out what is required and convert bytes according to type
eg AC power value will be 2 registers 24,25 corresponding to regs[22,23]
this from the 2MPPT model specs
40264 40264 1 ID A well-known value 160. Uniquely identifies this as a SunSpec Multiple MPPT Inverter Extension Model Mode unit16 160
40265 40265 1 L Length of Multiple MPPT Inverter Extension Model uint16 48
40266 40266 1 DCA_SF Current Scale Factor sunssf
40267 40267 1 DCV_SF Voltage Scale Factor sunssf
40268 40268 1 DCW_SF Power Scale Factor sunssf
40269 40269 1 DCWH_SF Energy Scale Factor sunssf
40270 40271 2 Evt Global Events bitfield32
40272 40272 1 N Number of Modules uint16 2
40273 40273 1 TmsPer Timestamp Period uint16 Not supported
40274 40274 1 1_ID Input ID uint16 1
40275 40282 8 1_IDStr Input ID Sting String16 "String 1"
40283 40283 1 1_DCA DC Current uint16 A DCA_SF
40284 40284 1 1_DCV DC Voltage uint16 V DCV_SF
40285 40285 1 1_DCW DC Power uint16 W DCW_SF
40286 40287 2 1_DCWH Lifetime Energy acc32 Wh DCWH_SF
40288 40289 2 1_Tms Timestamp uint32 Secs
40290 40290 1 1_Tmp Temperature int16 C
40291 40291 1 1_DCSt Operating State enum16
40292 40293 2 1_DCEvt Module Events bitfield32
40294 40294 1 2_ID Input ID uint16 2
40295 40302 8 2_IDStr Input ID Sting String16
# ---------commented out to here-------------------------------------
'''
'''
These classes/structures/unions, allow easy conversion between
modbus 16bit registers and ctypes (a useful format)
'''
# Single register (16 bit) based types
class convert1(ctypes.Union):
_fields_ = [("u16", ctypes.c_uint16),
("s16", ctypes.c_int16)]
# Two register (32 bit) based types
class x2u16Struct(ctypes.Structure):
_fields_ = [("h", ctypes.c_uint16),
("l", ctypes.c_uint16)]
class convert2(ctypes.Union):
_fields_ = [("float", ctypes.c_float),
("u16", x2u16Struct),
("sint32", ctypes.c_int32),
("uint32", ctypes.c_uint32)]
# Four register (64 bit) based types
class x4u16Struct(ctypes.Structure):
_fields_ = [("hh", ctypes.c_uint16),
("hl", ctypes.c_uint16),
("lh", ctypes.c_uint16),
("ll", ctypes.c_uint16)]
class convert4(ctypes.Union):
_fields_ = [("u16", x4u16Struct),
("sint64", ctypes.c_int64),
("uint64", ctypes.c_uint64)]
counterA = 0
SERVER_HOST = "10.0.0.9"
SERVER_PORT = 502
c = ModbusClient()
# uncomment this line to see debug message
# c.debug(True)
# define modbus server host, port
c.host(SERVER_HOST)
c.port(SERVER_PORT)
while True:
# open or reconnect TCP to server
counterA += 1
if not c.is_open():
if not c.open():
print("unable to connect to "+SERVER_HOST+":"+str(SERVER_PORT))
# if open() is ok, read register (modbus function 0x03)
if c.is_open():
# read 60 registers at address subtracting 1, store result in regs list
# first series is std inverter functions
# second series is the multiple string modes
regs1 = c.read_holding_registers(40070-1, 62)
regs2 = c.read_holding_registers(40264-1, 50)
# if success display MPT identifier once
if (regs2 and counterA ==1):
print("Success")
Translate = convert1()
Translate.u16 = regs2[0]
print("Multiple MPT value = "+str(Translate.u16))
# sleep 2s before next polling
time.sleep(2)
# check if MPPT
Translate = convert1()
Translate.u16 = regs2[0]
#
# check AC power from regs 40093,4
Translate=convert2()
Translate.u16.h = regs1[23]
Translate.u16.l = regs1[22]
print("Site Power="+str(Translate.float))
# check AC frequency
Translate.u16.h = regs1[25]
Translate.u16.l = regs1[24]
ACFreq = Translate.float
print("AC Frequency = "+str('{:g}'.format(ACFreq)))
# check DC power
Translate.u16.h = regs1[39]
Translate.u16.l = regs1[38]
DCPower = Translate.float
print("DC Power = " + str('{:g}'.format(DCPower)))
# check DC voltage
# first get scale factor, which is signed 16 bit as exponent
Translate=convert1()
Translate.s16 = regs2[3]
DCV_SF = Translate.s16
# now get voltage value, which is u16 from MPPT ID 1 and 2
Translate2=convert1()
Translate2.u16 = regs2[20]
DCMPPT1 = Translate2.u16*10**DCV_SF
Translate2.u16 = regs2[40]
DCMPPT2 = Translate2.u16*10**DCV_SF
print("DC Voltage 1 ="+str('{:g}'.format(DCMPPT1)))
print("DC Voltage 2 ="+str('{:g}'.format(DCMPPT2)))
Hi, Gret that now is working.
One question, I also have a smart meter and I’m trying to obtain total consumption but from smart meter I only receive + o -, depending if consumption is from solar or from grid, do you know here to obtain total consumption?
Thanks
Missatge de Anthony Vassallo [email protected] del dia dl., 31 de des. 2018 a les 9:58:
If you are asking how to access the Fronius smart meter you have to use its unit ID which is 240. This is used by pyModbusTCP.client import ModbusClient
in a different script.
Then you poll the register(s) you want. There are at least 2 - total imported and total exported.
I have used this in the past but need to go back and find my script if you need it.
Hi,
Thanks with ID240 and nUnit=240 I can obtian smart meter values, my problema is that I need to obtain total consumption grid + solar but I can’t find any value from modbus… any suggestion how to obtain this value from modbus?
Thanks
Missatge de Anthony Vassallo [email protected] del dia dl., 31 de des. 2018 a les 10:55:
Wouldn’t it just be import + generation - export?
How can I configure this to be calculated and showed as graph?
Thanks
El dl., 31 de des. 2018, 11:22, Anthony Vassallo [email protected] va escriure:
If you have these values as inputs, then I think it should be easy to use the process list. This isn’t something I have done, but looking at this post might give you a start: heatpump
I have tried from postprocess but only I can make +, I can’t find where I can use - in postprocess. You screenshot is from inputs and I don’t know how to integrate postprocess and inputs in this siutations…
Sorry but I’m new with this situation
Thanks
Missatge de Anthony Vassallo [email protected] del dia dl., 31 de des. 2018 a les 12:13:
Hi,
I think I have calculated as you suggested but result is not consumption, what is wrong?
Thanks
Missatge de klxout [email protected] del dia dl., 31 de des. 2018 a les 12:31:
The values you are using are already in kWh - why are you adding Power to kWh?
I think that this values are wh no kwh.
I removed but results are the same, any suggestion?
Missatge de klxout [email protected] del dia dl., 31 de des. 2018 a les 13:01:
@icenov : It seems you are using an old version of the interfacer, not working with recent version of pymodbus…you should update with the last version of EmonHub
The configuration of the interfacer is simplified - cf klxout link
Moreover you are having 11 units and 10 datacodes
AFAIK it is the latest version - pulled from github following @TrystanLea Emonbase started hanging randomly - #7 by icenov
this from my emonhub a few minutes ago:
fc60e98180cf14e36203ae68c54e296114638fc2
pi@emonpi:~/emonhub $ git status
On branch emon-pi
Your branch is up-to-date with 'origin/emon-pi'.
nothing to commit, working tree clean
pi@emonpi:~/emonhub $ git pull origin emon-pi
From https://github.com/openenergymonitor/emonhub
* branch emon-pi -> FETCH_HEAD
Already up-to-date.
pi@emonpi:~/emonhub $
Thanks for pointing out excess units - I’ve removed one.
Ok fine
Have you simplified the interfacer section in emonhub.conf ? You dont need anymore nReg, rType,rName in the interfacer section…
[[ModbusTCP]]
Type = EmonModbusTcpInterfacer
[[[init_settings]]]
modbus_IP = 10.0.0.9 # ip address of client to retrieve data from
modbus_port = 502 # Portclient listens on
[[[runtimesettings]]]
# List of starting registers for items listed above
register = 40070,40071,40072,40092,40094,40096,40098,40100,40102,40108
# nodeid used to match with node definition in nodes section below. Can be set to any integer value not previously used.
nodeId = 30
# Channel to publish data to should leave as ToEmonCMS
pubchannels = ToEmonCMS,
# time in seconds between checks, This is in addition to emonhub_interfacer.run() sleep time of .01
# use this value to set the frequency of data retrieval from modbus client
interval = 10
by the way, you have to give the registers values +1 when yu declare them in the interfacer section of emonhub.conf, but maybe it is not needed with the Fronius (This I dont know)
what do yu have in the emonhub log ?
please note that if you want to access to different slave id, you have to declare this in the interfacer section…if your device id is 1, it is OK yu dont have to do anything but if your device id is different, you have to specifiy it…for example :
nUnit = 1,1,1,1,1,1,1,1,1,2
in this version if yu want to access to id 2 with ten registers your have to do
nUnit = 2,2,2,2,2,2,2,2,2,2
Alex
Thanks @alexandrecuer - OK, some things being logged now! I went to check the logs but found it stopped logging yesterday as it was full. Cleared that out then checked new log to find message that no pymodbus installed (I used pip install without sudo first time) Now it is sending through data.
For others that might come across this topic later, I didn’t have to add a +1 to each register. In my python scripts I normally have to subtract a 1, which I think is because python starts arrays at 0. But I just used the actual register values in the interfacer (eg register 40070 is the inverter ID, which is 111 for my model (2xMPPT).
Some of the values need division by 100, but I should be able to sort that out easily.
Many thanks!
BTW I have a python script to probe the Fronius Primo inverter if anyone needs it.
Now to work on the Fronius smart meter which logs consumption etc. But its ID is 240, so will have to try your nUnit like 240,240,240,240…