Solaredge inverter via Modbus TCP 2

Tags: #<Tag:0x00007f186b525438> #<Tag:0x00007f186b525168> #<Tag:0x00007f186b524d58>

Heavily based on this topic created by @tkuehne I decided to take the information and move it to the Modbus 2 binding. Below you will find the result up to now.

I have a SolarEdge SE5000H (no display, but SetApp) with CPU version 4.6.27.

I have read a lot on not being able to reach the commissioning interface of the SolarEdge invertor. That is why I have placed my invertor in the 172.16.0.X/24 network. In this network 172.16.0.1 is taken by the SE itself (also used during commissioning by the SetApp) and so my gateway for this segment is 172.16.0.10.

First of all -----> make sure the modbus binding is installed <-----------------

Create a modbus.things file. I have commented out all the stuff I do not use yet, but it is there for convenience. I have noted that somehow my invertor is 1 address different from the ones mentioned in the SunSpec document.

Bridge modbus:tcp:SE5000TCP [ host="172.16.0.12", port=1502, id=1, timeBetweenTransactionsMillis=60, 
timeBetweenReconnectMillis=0, connectMaxTries=3, reconnectAfterMillis=0, connectTimeoutMillis=10000 ] {

    Bridge poller Registers [ start=69, length=50, refresh=5000, type="holding" ] {
      // Setting polling to 1000 ms sometimes led to strange values in I_AC_POWER

     //   Thing data C_DeviceAddress   [ readStart="69", readValueType="uint16" ]        // MODBUS Unit ID
        Thing data C_SunSpec_DID     [ readStart="69", readValueType="uint16" ]        // 101 = single phase, 102 = split phase, 103 = three phase 
        Thing data C_SunSpec_Length  [ readStart="70", readValueType="uint16" ]        // 50 = Length of model block
        Thing data I_AC_Current      [ readStart="71", readValueType="uint16" ]        // AC Total Current value
     //   Thing data I_AC_CurrentA     [ readStart="72", readValueType="uint16" ]        // AC Phase A Current value
     //   Thing data I_AC_CurrentB     [ readStart="73", readValueType="uint16" ]        // AC Phase B Current value
     //   Thing data I_AC_CurrentC     [ readStart="74", readValueType="uint16" ]        // AC Phase C Current value
        Thing data I_AC_Current_SF   [ readStart="75", readValueType="int16"  ]        // AC Current scale factor
     //   Thing data I_AC_VoltageAB    [ readStart="76", readValueType="uint16" ]        // AC Voltage Phase AB value
     //   Thing data I_AC_VoltageBC    [ readStart="77", readValueType="uint16" ]        // AC Voltage Phase BC value
     //   Thing data I_AC_VoltageCA    [ readStart="78", readValueType="uint16" ]        // AC Voltage Phase CA value
     //   Thing data I_AC_VoltageAN    [ readStart="79", readValueType="uint16" ]        // AC Voltage Phase A to N value
     //   Thing data I_AC_VoltageBN    [ readStart="80", readValueType="uint16" ]        // AC Voltage Phase B to N value
     //   Thing data I_AC_VoltageCN    [ readStart="81", readValueType="uint16" ]        // AC Voltage Phase C to N value
     //   Thing data I_AC_Voltage_SF   [ readStart="82", readValueType="int16"  ]        // AC Voltage scale factor
        Thing data I_AC_Power        [ readStart="83", readValueType="int16"  ]        // AC Power value
        Thing data I_AC_Power_SF     [ readStart="84", readValueType="int16"  ]        // AC Power scale factor
        Thing data I_AC_Frequency    [ readStart="85", readValueType="uint16" ]        // AC Frequency value
     //   Thing data I_AC_Frequency_SF [ readStart="86", readValueType="int16"  ]        // Scale factor
     //   Thing data I_AC_VA           [ readStart="87", readValueType="int16"  ]        // Apparent Power
     //   Thing data I_AC_VA_SF        [ readStart="88", readValueType="int16"  ]        // Scale factor
     //   Thing data I_AC_VAR          [ readStart="89", readValueType="int16"  ]        // Reactive Power
     //   Thing data I_AC_VAR_SF       [ readStart="90", readValueType="int16"  ]        // Scale factor
     //   Thing data I_AC_PF           [ readStart="91", readValueType="int16"  ]        // Power Factor
     //   Thing data I_AC_PF_SF        [ readStart="92", readValueType="int16"  ]        // Scale factor
        Thing data I_AC_Energy_WH    [ readStart="93", readValueType="acc32"  ]        // AC Lifetime Energy Production
        Thing data I_AC_Energy_WH_SF [ readStart="95", readValueType="uint16" ]        // Scale factor
        Thing data I_DC_Current      [ readStart="96", readValueType="uint16" ]        // DC Current value
        Thing data I_DC_Current_SF   [ readStart="97", readValueType="int16"  ]        // Scale factor
        Thing data I_DC_Voltage      [ readStart="98", readValueType="uint16" ]        // DC Voltage value
        Thing data I_DC_Voltage_SF   [ readStart="99", readValueType="int16"  ]        // Scale factor
        Thing data I_DC_Power        [ readStart="100", readValueType="int16" ]        // DC Power value
        Thing data I_DC_Power_SF     [ readStart="101", readValueType="int16" ]        // Scale factor
        Thing data I_Temp_Sink       [ readStart="103", readValueType="int16" ]        // Heat sink temperature
        Thing data I_Temp_SF         [ readStart="106", readValueType="int16" ]        // Scale factor
        Thing data I_Status          [ readStart="107", readValueType="uint16"]        // Operating state
     //   Thing data I_Status_Vendor   [ readStart="109", readValueType="uint16"]        // Vendor-defined operating state and error codes

    }

Items file

Number C_SunSpec_DID "Invertor type" 
	{channel="modbus:data:SE5000TCP:Registers:C_SunSpec_DID:number" }
Number Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power "AC Power value" 
	{channel="modbus:data:SE5000TCP:Registers:I_AC_Power:number" }
Number Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power "PV opbrengst [%.0f Wh]" 								<sun>				(gPowerMeasurement)
Number Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power_Graph
Number I_AC_Power_SF "AC Power scale" 
	{channel="modbus:data:SE5000TCP:Registers:I_AC_Power_SF:number" }

Number Sensor_VH_Meterkast_SE5000_I_Temp_Sink
	{channel="modbus:data:SE5000TCP:Registers:I_Temp_Sink:number" }								
Number Sensor_VH_Meterkast_SE5000_Temp_Sink "SE5000 temperatuur [%d C]"															(gClimateItems)	
Number I_Temp_SF "SE5000 temperatuur scale" 
	{channel="modbus:data:SE5000TCP:Registers:I_Temp_SF:number" }

Number Sensor_VH_Meterkast_SE5000_ModBus_I_Status		"Invertor status [MAP(SE5000_status.map):%s]"		<energy>			(gStatusItems,gApparatuur)
	{channel="modbus:data:SE5000TCP:Registers:I_Status:number", autoupdate="false" }

MAP file

//  SE5000H Inverter Device Status Values
//	The following I_Status_ xxxx values are supported:
//	Parameter 				Value 					Description
//	I_STATUS_OFF 				1 					Off
//	I_STATUS_SLEEPING 			2 					Sleeping (auto-shutdown) – Night mode
//	I_STATUS_STARTING 			3 					Grid Monitoring/wake-up
//	I_STATUS_MPPT 				4 					Inverter is ON and producing power
//	I_STATUS_THROTTLED 			5 					Production (curtailed)
//	I_STATUS_SHUTTING_DOWN 		6 					Shutting down
//	I_STATUS_FAULT 				7 					Fault
//	I_STATUS_STANDBY 			8 					Maintenance/setup

1=OFF
2=SLEEPING
3=WAKEUP
4=PRODUCTIE
5=PRODUCTIE_THROTTLED
6=SHUTTING_DOWN
7=MAINT
=UNDEFINED

Rules file

rule "Zonnepanelen AC productie momentaan"
when
	Item Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power changed
then
    Thread::sleep(100)						// Let modbus finish reading all registers
	var Double power = (Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power.state as DecimalType).doubleValue
	var Double SF = (I_AC_Power_SF.state as DecimalType).doubleValue
	var Double result = power * Math::pow(10,SF)
	postUpdate(Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power, Math.round(result))
end

rule "SE5000 temperatuur"
when
	Item Sensor_VH_Meterkast_SE5000_I_Temp_Sink changed
then
    var Double temp = (Sensor_VH_Meterkast_SE5000_I_Temp_Sink.state as DecimalType).doubleValue
	var Double SF = (I_Temp_SF.state as DecimalType).doubleValue
	var Double result = temp * Math::pow(10,SF)
	postUpdate(Sensor_VH_Meterkast_SE5000_Temp_Sink, result)
end

Sitemap file

Text item=Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power

ATM I am fighting with the rule file still a bit, because as far as I can see the values in the registers for the items I use are integer plus a scale factor. So I think the “double” variables can go.

I use the above calculated value to calculate my current power use via a rule and the variables I get from my smart meter:

ule "Calculate own power use every 10 seconds"
when 
	Time cron "0/10 * * ? * * *" 
then 
	if (Sensor_VH_Meterkast_SE5000_ModBus_I_Status.state == 4 || Sensor_VH_Meterkast_SE5000_ModBus_I_Status.state == 5) {
		Calculated_InternalPowerUse.postUpdate(
			
			(Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power.state as Number) 
			+ ((Sensor_VH_Meterkast_emeter_actual_delivery.state as Number)*1000) 
			- ((Sensor_VH_Meterkast_emeter_actual_production.state as Number)*1000)
			)
		}
 	else {
		Calculated_InternalPowerUse.postUpdate((Sensor_VH_Meterkast_emeter_actual_delivery.state as Number)*1000)
		}
end 

Hopefully this is interesting for somebody.

3 Likes

Excellent! I have put off converting my setup to the modbus 2 binding, because it took me weeks to finally get my conversion from KNX1.x to 2.x done, and I was dreading having to recode everything. But now, I can maybe see a project for the christmas break, using your foundation. :slight_smile:

Thanks,

Thomas

Allthough the majority of the values coming from ModBus are ok, sometimes I get very strange results:

2019-11-22 16:23:11.266 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=17520, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:11.267 [INFO ] [smarthome.model.script.[se5k] power ] - 17520.0
2019-11-22 16:23:11.268 [INFO ] [se.smarthome.model.script.[se5k] SF ] - 0.0
2019-11-22 16:23:11.270 [INFO ] [arthome.model.script.[se5k] Result: ] - 17520.0
2019-11-22 16:23:11.271 [INFO ] [thome.model.script.[se5k] DB value: ] - Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power (Type=NumberItem, State=0, Label=PV opbrengst, Category=sun, Groups=[gPowerMeasurement])
2019-11-22 16:23:12.320 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:12.325 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=18133, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:12.326 [INFO ] [smarthome.model.script.[se5k] power ] - 18133.0
2019-11-22 16:23:12.327 [INFO ] [se.smarthome.model.script.[se5k] SF ] - -6.0
2019-11-22 16:23:12.329 [INFO ] [arthome.model.script.[se5k] Result: ] - 0.018133
2019-11-22 16:23:13.355 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:13.357 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=6900, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:13.358 [INFO ] [smarthome.model.script.[se5k] power ] - 6900.0
2019-11-22 16:23:13.359 [INFO ] [se.smarthome.model.script.[se5k] SF ] - -4.0
2019-11-22 16:23:13.362 [INFO ] [arthome.model.script.[se5k] Result: ] - 0.6900000000000001
2019-11-22 16:23:13.364 [INFO ] [thome.model.script.[se5k] DB value: ] - Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power (Type=NumberItem, State=1, Label=PV opbrengst, Category=sun, Groups=[gPowerMeasurement])
2019-11-22 16:23:14.429 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:14.432 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=8288, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:14.434 [INFO ] [smarthome.model.script.[se5k] power ] - 8288.0
2019-11-22 16:23:14.437 [INFO ] [se.smarthome.model.script.[se5k] SF ] - -4.0
2019-11-22 16:23:14.438 [INFO ] [arthome.model.script.[se5k] Result: ] - 0.8288000000000001
2019-11-22 16:23:14.441 [INFO ] [thome.model.script.[se5k] DB value: ] - Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power (Type=NumberItem, State=1, Label=PV opbrengst, Category=sun, Groups=[gPowerMeasurement])
2019-11-22 16:23:15.483 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:15.485 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=10169, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:15.486 [INFO ] [smarthome.model.script.[se5k] power ] - 10169.0
2019-11-22 16:23:15.487 [INFO ] [se.smarthome.model.script.[se5k] SF ] - -4.0
2019-11-22 16:23:15.489 [INFO ] [arthome.model.script.[se5k] Result: ] - 1.0169000000000001
2019-11-22 16:23:15.490 [INFO ] [thome.model.script.[se5k] DB value: ] - Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power (Type=NumberItem, State=1, Label=PV opbrengst, Category=sun, Groups=[gPowerMeasurement])
2019-11-22 16:23:16.548 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:16.550 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=0, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:16.551 [INFO ] [smarthome.model.script.[se5k] power ] - 0.0
2019-11-22 16:23:16.552 [INFO ] [se.smarthome.model.script.[se5k] SF ] - -4.0
2019-11-22 16:23:16.557 [INFO ] [arthome.model.script.[se5k] Result: ] - 0.0
2019-11-22 16:23:16.558 [INFO ] [thome.model.script.[se5k] DB value: ] - Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power (Type=NumberItem, State=1, Label=PV opbrengst, Category=sun, Groups=[gPowerMeasurement])
2019-11-22 16:23:18.634 [INFO ] [clipse.smarthome.model.script.[se5k]] - *****************************************Zonnepanelen AC productie momentaan*************************************************
2019-11-22 16:23:18.636 [INFO ] [ome.model.script.[se5k] I_AC_Power: ] - Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power (Type=NumberItem, State=3942, Label=AC Power value, Category=null, Groups=[gVoltageMeasument])
2019-11-22 16:23:18.637 [INFO ] [smarthome.model.script.[se5k] power ] - 3942.0
2019-11-22 16:23:18.639 [INFO ] [se.smarthome.model.script.[se5k] SF ] - 0.0
2019-11-22 16:23:18.641 [INFO ] [arthome.model.script.[se5k] Result: ] - 3942.0

looks like there is a glitch when reading the produced PV power and the correlating SF (Scale Factor).
First value is the value coming from ModBus, the second value is de SF also from ModBus. “Result” is the result from the math calculation in my rules.
At 2019-11-22 16:23:11.267 my PV panels are producing 17,5 kW, naahhh don’t think so. Maximum is 5kW and because its winter at this time of the day it should be something like 17,5 or even 1,75 watt.

I think the produced PV Power and SF do not belong together. I am open for suggestions :joy:

I wonder if work by @mrbig might be relevant : https://github.com/openhab/openhab2-addons/pull/6331

It is sunspec binding built on top of openhab2 modbus, to provide first class support for these devices.

@ssalonen I think it is relevant, but no idea how to use it yet.

@mrbig, any chance I can have some files and a bit of guidance to test this?

Hello @havaak,

Power and the Scaling factor for the power go together, alright. I can’t spot anything wrong with your code, The only thing I noted is that you are reading individual registers with the correct datatype (int16, uint16, and so on). Maybe this is a timing thing on the modbus, or the modbus registers are being updated by the converter while you are reading the registers.

What I did to prevent this from happening, was to read all registers at once using uint16 and then having some code to extract the signed variants manually (for the scaling factors) or the 32bit counters by putting two bytes together. Not sure if that is what’s happening here, though.

Best,

Thomas

Each poller Thing reads its specified block of registers in one transfer.
It doesn’t matter how you arrange its data Things.

If you try to process several data Things in one rule, there is a risk of getting chunks from different transfers. Not recommended, choose rule triggers very carefully.

I should expand on that, perhaps.
Example rule from earlier -

rule "Calculate own power use every 10 seconds"
when 
	Time cron "0/10 * * ? * * *" 
then 
	if (Sensor_VH_Meterkast_SE5000_ModBus_I_Status.state == 4 || Sensor_VH_Meterkast_SE5000_ModBus_I_Status.state == 5) {
		Calculated_InternalPowerUse.postUpdate(
			
			(Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power.state as Number) 
			+ ((Sensor_VH_Meterkast_emeter_actual_delivery.state as Number)*1000) 
			- ((Sensor_VH_Meterkast_emeter_actual_production.state as Number)*1000)
			)
		}
 	else {
		Calculated_InternalPowerUse.postUpdate((Sensor_VH_Meterkast_emeter_actual_delivery.state as Number)*1000)
		}
end

Okay, so what are the risks here? The rule is periodically triggered by cron, it’s not synchronized with the Modbus poll in any way. The rule can run just before, or just after a poll - or a poll can take place when we’re part way through the rule. That’s a disaster - we will have some Item values from one poll cycle, and some from a different poll. They don’t belong together.

What can be done? Let’s look at rule triggers. Is running from a cron sensible? Do you need to do calculations if nothing actually changes? I’d look to trigger the rule from a key Item changed. Remember you can trigger a rule from an Item and not use that Item in the rule at all.

I don’t fully understand your Items here - is there one like a cumulative kWh reading that you can be sure changes on every poll? Use that as a trigger.

That still leaves a small risk - all the Items associated with one poll are not instantly updated at the same moment. With bad luck, we could trigger a rule off one Item and have another Item change a millisecond later - part way through the rule.

To get round that, a simple delay after rule triggering - just 50mS probably - should allow the binding to complete its cycle of updates before we process them.

These careful precautions are not need when dealing with readings like temperature and humidity, which never change much from one Modbus poll to the next.
But where you’ve got things like a number and a scale factor, which could change in big steps, care is needed to make sure you are dealing with a “matched pair”.

1 Like

@havaak I’ve sent you a PM with the details

I see what you are getting at but (there is always a but :grinning:) the 3 variables used here a coming from different systems; 1 is coming from modbus (solar panels) and the other from a smart meter. So what ever I do, start a rule on one of the 3 changing or cron, I always have a risk on colliding data. I choose the cron option as it will always make the calculation of my internal power use, even if none of the variables have changed.

And like always its useful remarks like these that make you think as well: “maybe if I change this, then…”. So I had another look at my rule where I calculate my solar panel produced power:

and when looking at this I realised that if the rule is being called, the modbus read was started milliseconds ago. So if the rule is started it could be possible that the next value was not yet read or updated. So I changed my rule to incorporate a 100 ms delay:

rule "Zonnepanelen AC productie momentaan"
when
	Item Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power changed
then
	Thread::sleep(100)						// Let modbus finish reading all registers
	var Double power = (Sensor_VH_Meterkast_SE5000H_ModBus_I_AC_Power.state as DecimalType).doubleValue
	var Double SF = (I_AC_Power_SF.state as DecimalType).doubleValue
	var Double result = power * Math::pow(10,SF)
	postUpdate(Sensor_VH_Meterkast_SE5000H_ModBus_AC_Power, Math.round(result))
end

I am now checking if all the values are up to spec…

1 Like

Values are still within spec so I think my problem is solved. I will update my first post. Thx all for helping out!

How you Calculate the Sensor_VH_Meterkast_emeter_actual_delivery and Sensor_VH_Meterkast_emeter_actual_production Value?

Thanks Marijan

Hey Marijan,

these values are not calculated but are coming from my smartmeter

kr

Han