atc1441/NETSGPClient

snapshot/capture of databox signals to inverter on changing output power

WeareGermans opened this issue ยท 50 comments

Hello,

I dont have a Databox and would like to change the output power with an esp32 and the LC12S.

Can anyone who does have a databox provide a snapshot/capture of the signal the databox sends to the inverter when changing the output power of the inverter to maybe 25%?

I already tried to send a message according to https://solaranzeige.de/phpBB3/viewtopic.php?f=23&t=1681, but this are the messages sent between the databox and the PC and it seems the PIC Controller of the databox does send something different to the inverter, or at least i do not get the inverter to reduce its output power that way.
Btw i am using a SG-700W inverter.

I would appreciate it if someone could help me there.
If if finally works i can provide the code via pull request or similar.

Thanks very much in advance!

enwi commented

@atc1441 sent me his databox, but I am currently moving to a new place, so I can get a capture next month.

Hi Moritz,
Are you already able to get the capture?
It would be nice to get some progress with this project. :-)

enwi commented

I am currently renovating the new apartment, so it'll take a few more days before I can setup my lab again ๐Ÿ˜…

Hi Moritz,
How is your lab? :-)

enwi commented

The lab is still not setup, becauseI still need to wallpaper and paint the whole room ๐Ÿฅด
But I might be able to pull it off this week

enwi commented

Another issue I have been facing is that I can't get the databox to work with my PC. For some reason the PC does not want to use the correct USB driver for the darn thing. I have already managed to get the PC into a bluescreen loop trying to force to use the other driver ๐Ÿคฆ

enwi commented

Hey @WeareGermans I have implemented changing the power grade on the dev branch, if you want you can try it

Thank you that sounds great.
I tried to implement a function into the .ino but my programming incompetence was in the way.
Could you maybe help me out with some sample code for switching on and off and setting the PowerGrade like in PollDemo.ino?

enwi commented

You should be able to just add one of the following function calls to the end of the setup function:

// Turn inverter on
client.activate(inverterID, true);

// Turn inverter off
client.activate(inverterID, false);

// Reboot inverter
client.reboot(inverterID);

// Change power grade to 50%
client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG50);

You can then use the returned bool value to check whether the command was successfull or not

I tried yesterday

  if (currentMillis2 - lastSendMillis2 > 60000)
 {
       lastSendMillis2 = currentMillis2;
            Serial.println("*********************************************");
            Serial.println("Received Inverter PowerGrade");
        bool test1 = client.activate(inverterID, false); 
            Serial.print("Aus: ");            
            Serial.println(test1 ? "HIGH" : "LOW");
        delay(1000);
        bool test2 = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG10);
            Serial.print("PowerGrade: ");
            Serial.println(test2 ? "HIGH" : "LOW");
        delay(1000);
        bool test3 = client.activate(inverterID, true); 
            Serial.print("An: ");
            Serial.println(test3 ? "HIGH" : "LOW");
  } 

In the main loop after the example code.

Sadly i always get for all three a LOW in return and the power is still ramping up to 500W and more and then gladly the Victron cuts the DC Power before the SMD Fuse does.

I did try "activate false" alone and that seems to have stopped the inverter from starting to inject power until the next reboot, but still returned a LOW.

Any ideas what i am doing wrong?

By the way do you know the meaning of the different status codes? I have seen 37, 39, 44, 58, 59, 60, 61, 62

enwi commented

It could be that there is still an error in my code, which needs to be fixed. But you could try to enable the debug output and post the console output here. For this uncomment the following line of code:

// #define DEBUG_SERIAL Serial1

If you use Serial1, which I would recommend to not send the serial output through the RF module, you need to hook up a separate TTL to Serial converter to GPIO2/D4 of the ESP8266

Hi enwi,
I tested it out on a SG700MD.
Turning the inverter on/off works well but the (bool-) return of client.active(...) is always false:

*WM-> inverterActive:0
43C1000000004100XXXX3F092D003F04A00118597A000A00646D160000000000
*WM-> failure

*WM-> inverterActive:1
43C1000000004100XXXX00000002CD43A00118597A000A00646D160000000000
*WM-> failure

BR, Brain

enwi commented

Interesting @Brain-Kiel. So basically when you tell the inverter to turn off you get 43C1000000004100XXXX3F092D003F04? And when you turn it on 43C1000000004100XXXX00000002CD43? (the part with A00118597A000A00646D160000000000 can be ignored here, because the debug output dumps the whole buffer)

enwi commented

So basically it boils down to this statement, because we can see the data being dumped:

return mBuffer[14] == calcCRC(14) && mBuffer[13] == value;

Looking at your dumps @Brain-Kiel I bet it is mBuffer[13] == value, because in your case these values are 00 when turned off and 02 when turned on, but we would expect 02 if turned off and 01 if turned on.

@enwi: When ignoring the feedback of the function activating / de-activating of the inverter is working well.

But I suffer from another problem - after a couple of minutes polling client.getStatus(inverterID) always returns false.
The LC12S still gets data from the inverter (LED is blinking twice) but there's no debug output!
On/off commands are working meanwhile - with no debug output as well.
The inverter comes back when I cut off DC/AC power from the inverter for some minutes.
ESP needs not to be restarted.

I just switched back to 1.1.1 and will let the system run for some hours to ckeck if this happens as well.

enwi commented

@Brain-Kiel I have added some more debug output so we can get a better insight on what is going wrong, if you could try the latest development branch code and post your serial output that would be very helpful.

Also I am using more or less the AsyncNETSGPClient code 24/7 for my solar installation and haven't had any issues so far, but it could be that client.getStatus(inverterID) of NETSGPClient will not find the correct data anymore, since it only tries to search the received data once:

default:
// technically we need to search for a magic byte again before we can say that no reply is found
DEBUGF("[findAndReadReply] Unexpected command 0x%02X", command);
return false;

@enwi:
1.1.1 client.getStatus(inverterID) works for hours as expected without returning any false.

2.0 returns (when swiching the inverter):

*WM-> '<inverterActive>:0'
43C1000000004100XXXX3F1FC100E9051801485855001100736C170000000000
[sendCommandAndValidate] CRC invalid & value invalid
*WM-> failure
*WM-> Sending request now
43C0000000004100XXXX00000002CD431801485855001100736C170000000000
CRC invalid
*WM-> no respond
*WM-> Sending request now
[findAndReadReply] Unexpected command 0xFF
*WM-> no respond
*WM-> Sending request now
[findAndReadReply] Unexpected command 0xFF
*WM-> no respond

Keep in mind your libary is some layers above my skills - but in NETSGPCLIENT.cpp I miss a break: between line 223 and 224 ?! Sorry for the bad format. I'm new to github.

enwi commented

@Brain-Kiel the missing break is on purpose, because both CONTROL and POWER_GRADE commands expect a reply of 16 bytes

enwi commented

@Brain-Kiel I have changed the findAndReadReply() function, could you try again? Now it should try to find the reply more than once

@enwi: Looks much better!

*WM-> Sending request now
43C0000000004100XXXX3F21670091051801485855001100736A180000000000
CRC valid
*WM-> Device: 4100XXXX
*WM-> Status: 106
*WM-> DC_Voltage: 13.04V
*WM-> DC_Current: 3.28A
*WM-> DC_Power: 42.77W
*WM-> AC_Voltage: 226.13V
*WM-> AC_Current: 0.17A
*WM-> AC_Power: 38.44W
*WM-> Power gen total: 0.63
*WM-> Temperature: 24
*WM-> '<inverterActive>:0'
43C1000000004100XXXX3F216700910518014858550011007369180000000000
[sendCommandAndValidate] CRC invalid & value invalid
*WM-> failure
*WM-> Sending request now
[findAndReadReply] Could not find command
*WM-> no respond
*WM-> Sending request now
43C0000000004100XXXX00000002CD4318014858550011007369180000000000
CRC invalid
*WM-> no respond
*WM-> Sending request now
43C0000000004100XXXX3F2167009109CF000058550000002A69180000000000
CRC valid
*WM-> Device: 4100XXXX
*WM-> Status: 105
*WM-> DC_Voltage: 25.11V
*WM-> DC_Current: 0.00A
*WM-> DC_Power: 0.00W
*WM-> AC_Voltage: 226.13V
*WM-> AC_Current: 0.00A
*WM-> AC_Power: 0.00W
*WM-> Power gen total: 0.63
*WM-> Temperature: 24
*WM-> '<inverterActive>:1'
43C1000000004100XXXX3F2167009109CF000058550000002A69180000000000
[sendCommandAndValidate] CRC invalid & value invalid
*WM-> failure
*WM-> Sending request now
[findAndReadReply] Could not find command
*WM-> no respond
*WM-> Sending request now
43C0000000004100XXXX00000001CC43CF000058550000002A69180000000000
CRC invalid
*WM-> no respond
*WM-> Sending request now
43C0000000004100XXXX3F2167009109CF0000582C0000002A69180000000000
CRC valid
*WM-> Device: 4100XXXX
*WM-> Status: 105
*WM-> DC_Voltage: 25.11V
*WM-> DC_Current: 0.00A
*WM-> DC_Power: 0.00W
*WM-> AC_Voltage: 225.72V
*WM-> AC_Current: 0.00A
*WM-> AC_Power: 0.00W
*WM-> Power gen total: 0.63
*WM-> Temperature: 24
enwi commented

Yes it does @Brain-Kiel, I also made some more changes and also found a bug. Could you try the latest development branch again?

enwi commented

@WeareGermans

By the way do you know the meaning of the different status codes? I have seen 37, 39, 44, 58, 59, 60, 61, 62

No we haven't fully figured out what they mean or if they are encoded where every bit means different things

Thanks for your work @enwi - the return of client.getStatus(inverterID) looks perfect now when switching the inverter:

*WM-> '<inverterActive>:0'
*WM-> failure
*WM-> Sending request now
43C0000000004100XXXX3F24BA00E709CF00005855000000296F150000000000
CRC valid
*WM-> Device: 4100XXXX
*WM-> Status: 111
*WM-> DC_Voltage: 25.11V
*WM-> DC_Current: 0.00A
*WM-> DC_Power: 0.00W
*WM-> AC_Voltage: 226.13V
*WM-> AC_Current: 0.00A
*WM-> AC_Power: 0.00W
*WM-> Power gen total: 0.64
*WM-> Temperature: 21
*WM-> '<inverterActive>:1'
*WM-> failure
*WM-> Sending request now
43C0000000004100XXXX3F24BA00E709CF00005855000000296F150000000000
CRC valid
*WM-> Device: 4100XXXX
*WM-> Status: 111
*WM-> DC_Voltage: 25.11V
*WM-> DC_Current: 0.00A
*WM-> DC_Power: 0.00W
*WM-> AC_Voltage: 226.13V
*WM-> AC_Current: 0.00A
*WM-> AC_Power: 0.00W
*WM-> Power gen total: 0.64
*WM-> Temperature: 21
enwi commented

That's good to hear @Brain-Kiel. Now what about turning the inverter OFF/ON? Do you have the debug output for that again?

enwi commented

@WeareGermans

Sadly i always get for all three a LOW in return and the power is still ramping up to 500W and more and then gladly the Victron cuts the DC Power before the SMD Fuse does.

Could you try with the current development version again. There was a bug where changing the power grade would not work, because the wrong command was sent. Could you also turn on debug mode and post the serial output?

Yes @enwi - DEBUG is on the whole time. client.activate(inverterID, true/false) now responds false without any DEBUG output.
The inverter itself switches on/off in the correct way when sending command.

enwi commented

Mhm, I would expect an output if false is returned in any way

enwi commented

Also how often do you send data to the inverter @Brain-Kiel? Because you should not send data more often than 1010ms

enwi commented

Well there is one more case that does not have a debug output yet (if not enough data is read). I pushed a new version, please give it a try @Brain-Kiel

Polling interval was 5 seconds this day. The latest dev returns as follows (polling is turned off now):

*WM-> '<autoPoll>:0'
*WM-> '<inverterActive>:1'
[findAndReadReply] Only read 13 of 14 bytes
*WM-> failure
*WM-> '<inverterActive>:0'
[findAndReadReply] Only read 13 of 14 bytes
*WM-> failure
enwi commented

Interesting, give me one sec and we will see if I am correct

enwi commented

I pushed a new version changing the size to 13 bytes, please try again @Brain-Kiel

Yes @enwi - working perfect:

*WM-> '<autoPoll>:0'
*WM-> '<inverterActive>:1'
43C1000000004100XXXX00000001CC09CF0000582C0000002A69180000000000
[sendCommandAndValidate] CRC valid & value valid
*WM-> Sucessfully turned on
*WM-> '<inverterActive>:0'
43C1000000004100XXXX00000002CD09CF0000582C0000002A69180000000000
[sendCommandAndValidate] CRC valid & value valid
*WM-> Sucessfully turned off

If there's need for further test, I will come back tomorror. It starts raining cats and dogs and I will loose the DC power soon.

BR, Brain

enwi commented

Nice ๐Ÿš€

enwi commented

Okay I made a final update and am now dumping the buffer in findAndReadReply, so it does not dump the whole buffer anymore.

@WeareGermans

Sadly i always get for all three a LOW in return and the power is still ramping up to 500W and more and then gladly the Victron cuts the DC Power before the SMD Fuse does.

Could you try with the current development version again. There was a bug where changing the power grade would not work, because the wrong command was sent. Could you also turn on debug mode and post the serial output?

Hi,

I did not get te Debug output to work on Serial1 yet but i can give you a normal Serial output with debug for now.

Stopping the power delivery works with the right answer, see below.

Setting the power grade with the code i already wrote delivers a "[waitForMessage] Timeout" and has no effect on the output power.

         bool test2 = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG10);
            Serial.print("PowerGrade: ");
           Serial.println(test2 ? "HIGH" : "LOW");

Result:

*********************************************
Received Inverter PowerGrade
43C10000000041000XXX00000002D6
[sendCommandAndValidate] CRC valid & value valid
Aus: HIGH
[waitForMessage] Timeout
PowerGrade: LOW

Sending request now
43C00000000041000XXX3F0B2C00490A9200000217000000003E0E
CRC valid
*********************************************
Received Inverter Status
Device: 41000XXX
Status: 62
DC_Voltage: 27.06V
DC_Current: 0.00A
DC_Power: 0.00W
AC_Voltage: 5.35V
AC_Current: 0.00A
AC_Power: 0.00W
Power gen total: 0.54
Temperature: 14
enwi commented

@Brain-Kiel did you try to set the power grade yet?

@WeareGermans I am not sure if you are supposed to set the powergrade after deactivating the inverter. Also you could try to use a bigger delay, just to make sure.

 if (currentMillis2 - lastSendMillis2 > 60000)
 {
       lastSendMillis2 = currentMillis2;
       Serial.println("*********************************************");
       Serial.print("Turning inverter off... "); 
       bool test1 = client.activate(inverterID, false);            
       Serial.println(test1 ? "success" : "error");
       delay(1200);
       Serial.print("Changing PowerGrade... ");
       bool test2 = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG10);
       Serial.println(test2 ? "success" : "error");
       delay(1200);
       Serial.print("Turning inverter on... "); 
       bool test3 = client.activate(inverterID, true); 
       Serial.println(test3 ? "success" : "error");
  } 

@enwi I will implement that function into my code and will give feedback ASAP.

I did also try only changing the powergrade without switching on or off and the result is the same.
It seems that the command is not right or the answer is different than expected.
Is my code for requesting the powergrade right?
I still use it in the main loop, not the setup part.

Is it possible, that a databox ID of 0 is not allowed/discarded for changing the powergrade?
Did you try to emulate a databox, so that the NETMS Software does communicate with it?

enwi commented

I think we will have to test and try until it works ๐Ÿฅด
I found this reference and we are pretty much doing the same

@enwi : Same here - current dev.
(If you could give me a hint, how the correct enum NETSGPClient::PowerGrade::PGXX can be generated from the int I'm coming in with, I would save alot of copy/paste :-))
But anyway - this function returns always false without changing AC-Power:

bool setPowerGrade(int _grade)
{
    bool response = false;
    switch (_grade)
    {
    case 0:
        response = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG0);
        break;
    case 50:
        response = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG50);
        break;
    case 100:
        response = client.setPowerGrade(inverterID, NETSGPClient::PowerGrade::PG100);
        break;
    default:
        break;
    }
    if (response) { return true; } else { return false; }
}

"Debug on" in lib reads:

*WM-> '<autoPoll>:0'
*WM-> '<powerGrade>:50'
[waitForMessage] Timeout
*WM-> Failure
*WM-> '<powerGrade>:100'
[waitForMessage] Timeout
*WM-> Failure

Your Timeout feedback is alright - the inverter sends no response to the command (LC12S blinks only once).

enwi commented

@Brain-Kiel PG0 = 0, PG1 = 1 and so forth. If the inverter is not replying it might be that the request is wrong somehow.

PG0 = 0, PG1 = 1 and so forth.
Very likely I do not understand how it is to be done...

grafik

enwi commented

Try casting the integer to a NETSGPClient::PowerGrade

client.setPowerGrade(inverterID, static_cast<NETSGPClient::PowerGrade>(50));

Technically I could also add a convenience method, but then I would need to check if the input lies between 0-100 before sending a command, but with the enum I think it is straight forward.

@enwi: Casting works fine in my code - result is still [waitForMessage] Timeout

First i did test if a databox id is neccessary -> it is not.

Second i found the bug in the code.
In NETSGPClient.cpp line 30.
The Command must be POWER_GRADE instead of CONTROL within NETSGPClient::setPowerGrade

Positive: The code seems to be working as expected

Received Inverter PowerGrade
43C31088000041000XXX0000000A78
[sendCommandAndValidate] CRC valid & value valid
PowerGrade: HIGH

Negative: the(my) inverter is not working als hoped/expected and still ramps the power up to 500W.

Very positive: using PG30 seems to work the inverter is only sending with around 200W(jumping in the range between 190W and 225W) into the grid!

Received Inverter PowerGrade
43C31088000041000XXX0000001E8C
[sendCommandAndValidate] CRC valid & value valid
PowerGrade: HIGH

Nice!!

Technical it is working as @WeareGermans said.
For the moment I cannot test the real output power - I dismounted the inverter from the panel and use a (smaller) power-supply as generator.

*WM-> '<autoPoll>:0'
*WM-> '<powerGrade>:100'
43C3000000004100XXXX0000006431
[sendCommandAndValidate] CRC valid & value valid
*WM-> Sucessfully set powergrade to 100%
enwi commented

Good call @WeareGermans sometimes it's better to let someone else take a look at the code

enwi commented

Should be fixed now