Jump to content

SunSynk - Inverter Monitoring


Bloubul7

Recommended Posts

14 minutes ago, GVC said:

Thanks to @Bloubul7and all the other contributors. This is my HA dashboard. It has all I need to view at a glance. (PS: really impressed with the Sunsynk)

 

Screenshot from 2023-01-02 07-18-16.png

I want to add, that 3 metrics exposed on the top, thats some good ergonomics.  It just eases and routes the eye towards the important stuff. 

Pity that 7 and 10 inch TFT displays are expensive, would be great to have that on permanent display. 

Link to comment
Share on other sites

Think I figured it out. Copied the Raw Config file.

EDIT: Open the file at the bottom with notepad or Text Editor. Copy and paste in Dashboard "Raw configuration editor"

You need to install the following custom cards:

card-mod

Flexible Horseshoe card

Layout card

Atomic Calendar Revive card

Mushroom card

Plotly Graph card

Sunsynk card (manual download from @slipx

 

Home Assistant Dashboard

Edited by GVC
Added resources
Link to comment
Share on other sites

41 minutes ago, GVC said:

Think I figured it out. Copied the Raw Config file.

EDIT: Open the file at the bottom with notepad or Text Editor. Copy and paste in Dashboard "Raw configuration editor"

You need to install the following custom cards:

card-mod

Flexible Horseshoe card

Layout card

Atomic Calendar Revive card

Mushroom card

Plotly Graph card

Sunsynk card (manual download from @slipx

 

Home Assistant Dashboard 50.37 kB · 1 download

Nice one, thanks!

Link to comment
Share on other sites


 

On 2023/01/02 at 7:30 AM, GVC said:

Thanks to @Bloubul7and all the other contributors. This is my HA dashboard. It has all I need to view at a glance. (PS: really impressed with the Sunsynk)

 

Screenshot from 2023-01-02 07-18-16.png

Thanks for sharing. Did not know about the horseshoe or plotly cards. Added to Dashboard

image.thumb.png.fc83c32cf6bd4bdcdf7d105f257c5923.png

 

Edited by slipx
Link to comment
Share on other sites

Energy-Jason
This post was recognized by Energy-Jason!

Sc00bs was awarded the badge 'Helpful' and 50 points.

1 hour ago, slipx said:

Does anyone know which modbus registers give you the monthly and yearly stats for PV, Load, Grid etc ?

 

These might help, attached the latest Modbus register I could find as well.

 

image.png.c6c978899ed3d851ac5ea0792f88614e.png

 

Modbus储能-组串-微逆宁波德业V118 (2).pdf

Link to comment
Share on other sites

1 hour ago, RocketBoy said:

I hate asking stuff like this, but without reading through all 25 pages... does anyone know of a good USB-RS485 cable to get for communicating with the Sunsynks? Im most likely going to use it through a Raspberry pi.

Lol, and that ain't the half of it. 

There are good instructions on getting it to work on @kellerza 's Github page 

https://github.com/kellerza/sunsynk

Link to comment
Share on other sites

3 hours ago, RocketBoy said:

I hate asking stuff like this, but without reading through all 25 pages... does anyone know of a good USB-RS485 cable to get for communicating with the Sunsynks? Im most likely going to use it through a Raspberry pi.

I went through all the suggestions. This was the one that was easiest and worked the best for me:

https://solar-assistant.io/shop/products/sunsynk_rs485

Link to comment
Share on other sites

22 hours ago, JuanH said:

I went through all the suggestions. This was the one that was easiest and worked the best for me:

https://solar-assistant.io/shop/products/sunsynk_rs485

There is probably nothing wrong with the cable, but if I see a pre made-up cable, I always wonder: Do you cut the connector off to route the cable through sprague & the cable glands, or do you cut the cable gland to make the connector fit? 

(And if you use a RJ45 inline extender, then you still need a crimping tool 😉)

Link to comment
Share on other sites

I have just started playing with node-red to try move my geyser control from Arduino for easier automation and remote management.

To do this, I need to read a block of values every second. Doing this register by register is just way too inefficient, so I need to read them in bulk and then process the results sequentially.

I have never used node-red before, so I am not sure what will work best.

For testing, I have created a decoder function based on https://github.com/jacauc/SunSynk-NodeRed :

//  per register
//   props = properties of new message object
//   conv = conversion function to get payload.value from modbus response data
//   scale = (optional) scaling factor to apply to payload.value after conversion
//   skip = (optional) do not produce output for this register
//
//  conversion algorithms
//   s16 = signed 16 bit
//   u16 = unsigned 16 bit
//   temp = sunsynk temperature value
const regs = {
  '182': {
    props: {
      topic: 'battery_temp',
      deviceclass: 'battery',
      unit: '°C',
    },
    conv: 'temp',
  },
  '183': {
    props: {
      topic: 'battery_volt',
      deviceclass: 'battery',
      unit: 'V',
    },
    conv: 'u16',
    scale: 0.01,
  },
  '184': {
    props: {
      topic: 'battery_soc',
      deviceclass: 'battery',
      unit: '%',
    },
    conv: 's16',
  },
};

// paranoia
if (msg.values.length != msg.modbusRequest.quantity) {
  node.warn("Read failed - response length does not match request...");
  return null;
}
var base = msg.modbusRequest.address;
//node.warn("start: "+base);
var outs = [];
var i = 0;
while(i < msg.values.length) {
  var reg = base + i;
  var rem = msg.values.length - i;
  //node.warn("reg: "+reg);
  //node.warn("remain: " + rem);
  if(!(reg in regs)) {
    //node.warn('key not found:'+reg)
    i++;
    continue;
  }
  var config = regs[reg];
  //node.warn("config: "+config);
  if("skip" in config && config.skip) {
    node.warn('key set to skip:' + reg)
    i++;
    continue;
  }
  var newmsg = Object.assign({}, config.props);
  if(config.conv == 's16') {
    var val = (msg.values[i] + 0);
    if(val > 32767) {
      val = val - 65535;
    }
    newmsg.payload = val;
  } else if (config.conv == 'u16') {
    newmsg.payload = (msg.values[i] + 0);
  } else if (config.conv == 'temp') {
    newmsg.payload = (msg.values[i] - 1000) / 10;
  } else {
    node.warn('conversion function not found:' + config.conv);
    i++;
    continue;
  }
  if("scale" in config) {
    newmsg.payload *= config.scale;
  }
  outs.push(newmsg);
  i++;
}
//node.warn("outs: "+outs.length);
return [outs];

So, issue a bulk read to Modbus-Flex-Getter ( {"fc": 3,"unitid": 1,"address":180,"quantity":10} ) - pass the result into the above function, and it spits out a stream of messages for each configured register.

From the outset, that 'regs' array should not be defined here.  Probably an external JSON file loaded into global context and referenced from there.

Other than that, what do the node-red experts think.  Will this scale efficiently if I extend 'regs' to include all registers of interest?

Link to comment
Share on other sites

26 minutes ago, JustinSchoeman said:

I have just started playing with node-red to try move my geyser control from Arduino for easier automation and remote management.

To do this, I need to read a block of values every second. Doing this register by register is just way too inefficient, so I need to read them in bulk and then process the results sequentially.

I have never used node-red before, so I am not sure what will work best.

For testing, I have created a decoder function based on https://github.com/jacauc/SunSynk-NodeRed :

//  per register
//   props = properties of new message object
//   conv = conversion function to get payload.value from modbus response data
//   scale = (optional) scaling factor to apply to payload.value after conversion
//   skip = (optional) do not produce output for this register
//
//  conversion algorithms
//   s16 = signed 16 bit
//   u16 = unsigned 16 bit
//   temp = sunsynk temperature value
const regs = {
  '182': {
    props: {
      topic: 'battery_temp',
      deviceclass: 'battery',
      unit: '°C',
    },
    conv: 'temp',
  },
  '183': {
    props: {
      topic: 'battery_volt',
      deviceclass: 'battery',
      unit: 'V',
    },
    conv: 'u16',
    scale: 0.01,
  },
  '184': {
    props: {
      topic: 'battery_soc',
      deviceclass: 'battery',
      unit: '%',
    },
    conv: 's16',
  },
};

// paranoia
if (msg.values.length != msg.modbusRequest.quantity) {
  node.warn("Read failed - response length does not match request...");
  return null;
}
var base = msg.modbusRequest.address;
//node.warn("start: "+base);
var outs = [];
var i = 0;
while(i < msg.values.length) {
  var reg = base + i;
  var rem = msg.values.length - i;
  //node.warn("reg: "+reg);
  //node.warn("remain: " + rem);
  if(!(reg in regs)) {
    //node.warn('key not found:'+reg)
    i++;
    continue;
  }
  var config = regs[reg];
  //node.warn("config: "+config);
  if("skip" in config && config.skip) {
    node.warn('key set to skip:' + reg)
    i++;
    continue;
  }
  var newmsg = Object.assign({}, config.props);
  if(config.conv == 's16') {
    var val = (msg.values[i] + 0);
    if(val > 32767) {
      val = val - 65535;
    }
    newmsg.payload = val;
  } else if (config.conv == 'u16') {
    newmsg.payload = (msg.values[i] + 0);
  } else if (config.conv == 'temp') {
    newmsg.payload = (msg.values[i] - 1000) / 10;
  } else {
    node.warn('conversion function not found:' + config.conv);
    i++;
    continue;
  }
  if("scale" in config) {
    newmsg.payload *= config.scale;
  }
  outs.push(newmsg);
  i++;
}
//node.warn("outs: "+outs.length);
return [outs];

So, issue a bulk read to Modbus-Flex-Getter ( {"fc": 3,"unitid": 1,"address":180,"quantity":10} ) - pass the result into the above function, and it spits out a stream of messages for each configured register.

From the outset, that 'regs' array should not be defined here.  Probably an external JSON file loaded into global context and referenced from there.

Other than that, what do the node-red experts think.  Will this scale efficiently if I extend 'regs' to include all registers of interest?

While I cannot really comment on where you want to store these registers in Node-Red, I can comment on the concept behind bulk reading. And agree that it makes a lot of sense!

A call to read the RS485 holding registers needs a start and a length, so you obviously want to read the optimal length. Since all the registers you need are not sequential, you will have to group your reads. There is a couple of factors you should keep in mind. Sometimes it might make sense to read a register or two that you do not need, since skipping one might be expensive. With some hardware the size of the blocks you can read can be limited.

Once you've figured out what registers you need, you can have a look at what we do in the Sunsynk Python library to group these - groups 

Btw with the library it's easy to react within a second or two to a major load/power change. The idea from the start was that I can control loads, and even remove them if the inverter goes above its rated 5Kw output. In reality the solution was much simpler, and I ended up simply spreading my heavy loads through the day (geyser & pool pump+heatpump).

 

Link to comment
Share on other sites

I already have everything working (batched reads and such) on my Arduino setup:

https://github.com/justinschoeman/ModbusThermostat/blob/master/SunsynkController/sunsynk.h

Been running flawlessly 24/7 for over 2 years now.

But now I would like to add some UI components and flexible load management for more loads (with priorities and overrides).

I could extend the Arduino code to do this. I could also do it in Python. But both would require a lot of UI development around it.

Node-red gives me a UI with the flexibility I require.  But I have 0 experience in it, and would appreciate some feedback on my implementation choices.

If, at the same time, I can preserve the basics of the existing node-red project, then I can steal the logging and dashboarding goodness that has already been developed.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...