Modbus binding with Sunny Boy SMA inverter

Thats because the value -214748364 cant be translated in the JS script…
I use a modified JS script for my Sunny Boy Storage 2.5 which handle this…
Look in this thread: [SOLVED] Convert an item negative value to 0 (zero)

Hello,
I tried many things, but get the modbus to start working. Only the actual power and total yield values I already discovered. The usual modbus adresses for the other fields didn’t work for me.
I created a rule to recover the daily yield out of the total yield, by storing the start every day.

First, and very important is the fact that my inverter only gives some good values when the sun is shining. For example, the actual value for the power is always the fixed value 214748364 when it’s dark outside. So when you are trying to get your scripts working, do it during the day when the inverter is active. At least for the actual powers etc…
To recover the actual power when the actual power=0, I used a javascript. When I receive a value too high for my maximum production I set the actual value==0.

Things:

Bridge modbus:tcp:inverter [ host="10.0.0.78", port=502, id=3 ] {
    Bridge poller sma30529 [ start=30529, length=2, refresh=5000, type="input" ] {
        Thing data Total_Yield [ readStart="30529", readValueType="uint32" ]
    }
    Bridge poller sma30775 [ start=30775, length=2, refresh=5000, type="input" ] {
        Thing data Power [ readStart="30775", readValueType="uint32", readTransform="JS(sunpower.js)"]
    }
}

Items:

Number Power         "Actual Power [%.0f W]"   { channel="modbus:data:inverter:sma30775:Power:number" }
Number Day_Yield     "Day Yield [%.0f Wh]"
Number Total_Yield   "Total Yield [%.0f Wh]"   { channel="modbus:data:inverter:sma30529:Total_Yield:number" }
Number Day_Start     "Day Start [%.0f Wh]"

Rules:

rule "Reset_Zonnepanelen_Dag"
when
  Time cron "0 0 0 * * ?" // every day
then
  var Number Zon=Total_Yield.state as DecimalType
  Day_Start.postUpdate(Zon)
end

rule "Update Day_Yield"
when
  Item Total_Yield received update
then
  var Number Zon_Totaal=Total_Yield.state as DecimalType
  if (Day_Start.state==NULL)      { Day_Start.postUpdate(Zon_Totaal) }

  var Number Zon_Start=Day_Start.state as DecimalType
  Day_Yield.postUpdate(Zon_Totaal-Zon_Start)
end

sunpower.js

(function(i) {
   power=parseFloat(i);
   if (power>5000) {power=0;}
   return power;
})(input)

I found a very interesting xls file with a lot of sma types and modbus adresses:
https://www.sma.de/fileadmin/content/landingpages/pl/FAQ/SunSpec_Modbus-TI-en-13.xlsx

Click on the second tab (below) and select your sma type.

Regards, Hans

Hi Hans,

Thanks to your example it works a little bit more.
Only the figures are still a constant value. Now divided by 1000.

When I change the ID of the bridge from 2 to 3 nothing changes.
Or do I have to reset ?

Kind regards,
Pieter

Hey Pieter,

While testing, sometimes it works after changing the scripts.
But it is always safe to do a reboot or
sudo systemctl restart openhab2.service

Your current reading for actual power is 2^31=2147483648 (no power).
Then your script should convert it to 0 (zero).
Regards, Hans

Thanks Hans,

A little bit further. No power reading on address 30775.
It’s quite dark today, but the actual reading according to the SunnyBoy webpage is 69W.

According to the SMA manual ID=2

I will check other addresses tonight

After several attempts, I still don’t receive data from my Sunny Boy Inverter.
The XLS-file shows different addresses like 40200 for actual Power. This address gives a result of -1

Meanwhile, I updated OpenHAB to version 2.5.1

Also tried to read other addresses like 30774 and 30776.

Did you look at SMA´s website?
You´ll need to find the specific list of registers for your device.
The best I could find right now online was this one… It will open a Excel document in where you can pick your device:
https://www.photovoltaikforum.com/core/attachment/13916-sma-modbus-ti-en-23-xlsx/

EDIT - Try read register 30053. If it read correctly, you should be reading value 9302 which means, its a “Sunny Boy 2.5

1 Like

Thanks Kim,

This worked !!

Great… Now all you need to do, is to put in the registers you want to read :smiley:

I understand. But when I add the register for actual power, an enormous number appears. something like 4 billion …

Look in the excel sheet I´d link to… Sometimes you need to read a different register to get the “right” power reading. It can be a bit of a pain to find the correct one to read… But a fast look at the sheet, I believe these are the ones you should be reading:

30775	Power      	W	S32	FIX0	RO		
30777	Power L1	W	S32	FIX0	RO		
30779	Power L2	W	S32	FIX0	RO		
30781	Power L3	W	S32	FIX0	RO		

FYI: https://github.com/openhab/openhab-addons/pull/6331#issuecomment-576666298

Btw, the Excel sheet says nothing about the length of the numbers. Or is there a standard ?

I have added another register. Now I have those strange values again after an OpenHAB restart. I’m suspecting my SMA inverter.

They have to fit into Modbus 16-bit registers/words. Looks to me like this SMA generally uses two words e.g. 32-bit. That still leaves a choice of integer, signed, floating point formats. There’s no way to guess that and you must find out from maker’s docs.

If only we knew what registers you were looking at … need a bit to work with, here.

Markus, what has this got to do with modbus for SMA inverters?

1 Like

SunSPEC is a vendor agnostic protocol. I would expect you could use this with SMA inverters, too.

The Excel sheet tells you the format. But not the length… Ususally it´s 4. But otherweise just give it a shot, play around with it. Its is written in the General Modbus Docs from SMA (somewhere). But as far as I recall it´s not specific to each model and register. (Its a huge document).

Here is my Things file for my main SMA inverter model STP 6000 TL-20… It looks like you can use most of the same registers for your inverter.

Bridge modbus:tcp:inverter1 [ host="10.4.28.248", port=502, id=3, connectMaxTries=3] {

// SMA Inverter Device Type
	Bridge poller DevType [ start=30053, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data DevType [ readStart="30053", readValueType="int32" ]
	   	 
  	 }

// SMA Inverter Status
	Bridge poller SMA_Status [ start=30201, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data SMA_Status [ readStart="30201", readValueType="uint32" ]

  	 }

// SMA Inverter Grid_Contactor
	Bridge poller Grid_Contactor [ start=30217, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data Grid_Contactor [ readStart="30217", readValueType="uint32" ]
	    
  	 }

// SMA Inverter Day Yield
	Bridge poller Day_Yield [ start=30517, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data Day_Yield [ readStart="30517", readValueType="uint64", readTransform="JS(divide1000.js)" ]
	    
   	 }

// Total Yield
	Bridge poller Total_Yield [ start=30529, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data Total_Yield [ readStart="30529", readValueType="uint32", readTransform="JS(divide1000.js)" ]
	    
 	 }

// SMA Inverter Power Section West
	Bridge poller power_a [ start=30773, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data power_a [ readStart="30773", readValueType="int32", readTransform="JS(smalimit.js)" ]
	   	 
  	 }

// SMA Inverter Power Total 
	Bridge poller Active_Power [ start=30775, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data active_power [ readStart="30775", readValueType="int32", readTransform="JS(smalimit.js)" ]
	    
  	 }

// SMA Inverter Power Section East
	Bridge poller power_b [ start=30961, length=4, refresh=5000, type="input" ] {
	    
	    	 Thing data power_b [ readStart="30961", readValueType="int32", readTransform="JS(smalimit.js)" ]
	   	 
   	 }

// SMA Inverter Operation
	Bridge poller SMA_Status_Operate [ start=40029, length=4, refresh=5000, type="holding" ] {
    
	    	 Thing data SMA_Status_Operate [ readStart="40029", readValueType="uint32" ]
	    
   	 }

}

Notice, I have two sets of solar panels. I have them named power_a and power_b.
You device can only handle one sets of panels, which is register 30773 according to the Excel sheet for your inverter…

You need to provide us with some help here. Show us which registers and how you have added it.
(Ie show us your things files, screendump from PaperUI / whatever you use).

Also - Be aware, sometimes modbus is very strange. If you make changes and it looks strange afterwards, it´s either due to there is an error somewhere, or the cache has screwed up… You´ll need to clear cahce and restart… Its a pain in the butt! After running into this issue a few times, you´ll learn to do the things right first time :grin: (I have struggled with this quite a few times… Making sure everything was good, Brigde and poller are online, but I got no data… Sometimes it can help restarting the modbus binding in Karaf consol insted of cleaning cache and restart, which is another pain in the butt for openhab).

Ahh okay… I wasn´t aware of that… Sorry, and nice to know.

Hi Kim,
This is my Things file:

Bridge modbus:tcp:SMAinverter [ host="192.168.178.130", port=502, id=2 ] {

// SMA SunnyBoy Device Type 30053 Device Type
     Bridge poller DevType [ start=30053, length=4, refresh=5000, type="input" ] {
        Thing data DevType [ readStart="30053", readValueType="int32" ]
     }

// SMA SunnyBoy Device Type 30057 Serial Nr
     Bridge poller SerialNr [ start=30057, length=4, refresh=5000, type="input" ] {        
        Thing data SerialNr [ readStart="30057", readValueType="int32" ]
     }

}

This is my items file:

Number DevType     "DeviceType [%d]"   <keyring>  { channel="modbus:data:SMAinverter:DevType:DevType:number" }
Number SerialNr    "Serienummer [%d]"  <keyring>  { channel="modbus:data:SMAinverter:SerialNr:SerialNr:number" }
Number SolarPower  "Vermogen [%.0f W]" <sun>      { channel="modbus:data:SMAinverter:SolarPower:SolarPower:number" }

I rebooted my Raspberry3B with OpenHAB. Device ID is now 4294967295
SolarPower is not yet present in my sitemap. First, I like to be succesfull with a simple field like the DeviceType.