Help Required Uploading Growatt Inverter To PVOutput

Yes I did that by removing the single quotes from the system ID.
We are almost there:

root@OpenWrt:~/canadianSolar-pvoutput-multi-inv# sh pvoutput.sh
('2018-10-04 11:05', 'OOps: Something Else', InvalidHeader("Value for header {X-Pvoutput-SystemId: ['12345', '12345']} must be of type str or bytes, not <type 'list'>",))

Wow!

line 330, change from power_vdc=props['pv_power']) to power_vdc=props['pv_power'], system_id=props['system_id'])

I will upload the code but you can quick test by adding system_id parameter by hand.

!!SUCCESS!!
After changing line 330, the code is running for some hours now for two inverters without any problem.
I will let it run as is today and I will add the third inverter during the weekend.
I just noticed that the temperature is now rounded without any decimal

Hi, I have a minor bug and an enhancement request on version 0.6.12.

Bug

If you restart pvoutput.sh outside the start and stop monitoring times (shStart and shStop) then you get the following error:

Traceback (most recent call last):
File “/home/pi/canadianSolar-pvoutput-master/canadian_reads.py”, line 279, in
main_loop()
File “/home/pi/canadianSolar-pvoutput-master/canadian_reads.py”, line 271, in main_loop
str(snooze) + ’ minutes’
UnboundLocalError: local variable ‘snooze’ referenced before assignment
python script erro, sleeping few seconds and call it again

It looks like the variable snooze is only defined if canadian_reads.py is first run within the start and stop times.

Enhancement Request

Would it be possible to add shStart and shStop to the configuration file (pvoutput.txt). I am changing the start and end times as the days get shorter and this would mean that I wouldn’t have to keep changing the code.

0.6.12 is continuing to run well by the way.

Bob.

Nice!! Please, monitor it during some days and let me know if any issue happens. I will be in a business trip next week but might be able to code small changes as necessary.

Regarding temperature, are you talking about weather data or inverter data?

Hi @bobboulby,

I will handle this error. Thanks for report.

I already thought about it and forgot. It is possible to add shStart and shStop as configuration options but I dislike the idea of keep changing conf files in regular basis due days getting shorter. What do you think of using sunrise and sunset time (minus/plus small to buffer if necessary) to adjust start/stop time? Of course with a fallback to some default if sunrise/sunset are not available. I think OWM already give us sunrise/sunset times but it also can be calculated by a number of libraries. This way I believe that start/stop time will vary automatically throughout the year. Let me know your thoughts

Amazing!! I am running 0.7 that is 0.6.12 with povoutput function converted to a class basically to make it portable and less coupled. Until now everything is ok too on my side.

Yes, that would be a better way of doing it :slight_smile:

Bob.

@bobboulby

What have you set for shStart and shStop?

Currently set to 7 and 20.

Line 265 (on latest master branch) has elif shStart > hour <= 0: it should be elif shStart > hour >= 0: (hour >= 0)

The idea of that “if…else” statement is: if “current hour is greater than or equal to stop hour and less than 24” we are after stop timer but before midnight (since your stop hour is 20, then anything between 20 and 23). “else if current hour is greater than or equal to zero and smaller than start hour” meaning we are after midnight but before start time (since your start time is 7, anything between 0 and 6). I wrongly use “less than or equal to midnight” in the else statement.

Correcting now.

just submitted v0.7.1 with that correction. Let me know if it goes ok

(also cherry-picked that to “multi-inv” branch were the next version is being prepared)

Thanks, I’m not at home at the moment but should be able to try that tomorrow.

By the way, your support is much appreciated however just fixing the bug for a future version would have been ok. There is no need to create a special version just for me :slight_smile:

Bob.

Thanks for this kind words. Actually I am very happy I could help you and @lampra (maybe others) since I started from Stephen Nyeland work and improved to my needs; I am now able to give back to community.

Regarding versions, what I am doing at github is:

master branch holds the current/official/most stable release of this software. Hence, someone who wants to use shall get it from master

dev branch holds any bug fix not yet tested, any new small feature and testing codes. Eventually master branch will merge dev branch for a new release. Sometimes this branch will not run because incomplete or wrong code, this is were we do heavy tests

other branchs like “multi-env” are feature branches where I (or any other contributor who might join us) can code without fear of break things, do not worry of capabilities or API breaks. Once the feature is mature (it will evolve but no deep modifications in API will be required) it will be merge to dev branch for testing and release preparation (later dev will be merged into master).

So, most of the time dev will be ahead of master but master always will catch-up. Other branches are temporarily used to development and discarded after.

As of today:

  1. master branch is at version v0.7.0 that is totally compatible with code you already have (from v0.6.12rc)
  2. dev branch is ahead of master, it contains changes I made to Pvouput function (now a class) but does same thing as release in master. (not changes to functionality only a huge refactor of code)
  3. multi-inv branch is ahead of dev with code written to support multiple inverters, it aims to be compatible with current master code but need transformations in configuration file to accommodate multiple inverters. Hence, once merged back (probably for v1.0.0) it will break compatibility with current configuration files.

Once again, thanks for your kind words, I am really happy to code in retribution for the community.

BRs

2 Likes

Version 0.7.1 is up and running :+1:

I’ve tested starting it outside shStart and shStop and can confirm that the bug is now fixed. Running pvoutput.sh at 11:06 and with shStart temporarily set to 12 I got the following:

pi@Solar-2:~/canadianSolar-pvoutput-master $ ./pvoutput.sh
2018-10-06 11:06 - Next shift starts in 54 minutes

So all good, thanks.

Bob.

1 Like

@jrbenito, it looks like there might be a problem with outputting errors in version 0.7.1. I’ve got a missing 5 minute value today so I checked my log and there is nothing in there except for the “Next shift starts in xxx minutes” message. It is very unusual for me to have no entries at all - I usually have a few “Error getting weather” messages and for a missing 5 minute value would expect to see some errors like:

(‘2018-10-01 12:05’, ‘Error Connecting:’, ConnectionError(MaxRetryError(“HTTPConnectionPool(host=‘pvoutput.org’, port=80): Max retries exceeded with url: /service/r2/addstatus.jsp (Caused by NewConnectionError(’<urllib3.connection.HTTPConnection object at 0x75f32e50>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution’,))”,),))

I see that you’ve made some changes to the code following line 190, could this be the reason?

Bob.

Edited one day later. Please ignore the above, error logging looks ok today.

Never mind about temperature this was my bad at the config.

Till now I encountered an other issue. One of the inverters reports v1 while the other does not (at least during the day that I checked using tcpdump).
When v1 is sent, the cumulative flag is set to 1 causing pvoutput to reject v1 and apply 0 average production. According to the api I expect that c1 should be 0.
So It seems that the code needs to be reviewed probably at line 251 and/or at line 278.

I will wait 1-2 days with hardcoded c1=0 at line 279 and I will report back and then I will add the third inverter.

I have been uploading data successfully for the last 6 days for two inverters with hardcoded c1=0 at line 279.

There is one issue regarding average power for two out of three inverters. I am not sure if this is caused by the code or the inverter firmware.
Screenshot%20from%202018-10-13%2018-22-50 Screenshot%20from%202018-10-13%2018-23-10
I finally also managed to connect to the inverter manually and read the registers.

Summary

Here is what I did and the response for one inverter:

root@OpenWrt:~# python
Python 2.7.15 (default, Aug 16 2018, 07:51:15) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from pymodbus.client.sync import ModbusSerialClient as ModbusClient
>>> inv = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, stopbits=1,
                       parity='N', bytesize=8, timeout=1)... 
>>> inv.connect()
True
>>> rr = inv.read_holding_registers(0, 45, unit=0x1)
>>> print rr
ReadRegisterResponse (45)
>>> print rr.registers
[257, 0, 1, 100, 255, 65535, 5, 2320, 6000, 17478, 16705, 8237, 8241, 49, 32, 0, 1, 3000, 180, 1840, 2645, 4753, 5150, 19508, 12597, 12342, 12336, 13365, 16, 61745, 1, 0, 0, 0, 0, 1845, 2645, 4600, 5400, 1600, 2700, 4900, 5100, 2144, 515]
>>> inv.close()
>>> quit()
root@OpenWrt:~#

Are you seeing 5 minutes gap yet? I have to check my system as I was in a business trip last week (and I am still suffering jetlag effects) and could not look to it.

This average mismatches may happen when we send power value to pvoutput and also send energy value together (v1 and v2). Imagine that during the 5 minutes period your power varies and once it is time to send data to pvoutput we capture the value of current power on that moment. Pvoutput uses that power value to calculate how much energy have been produced over that 5 minute period. Hence, with a power of 1000W over a 5 minutes period the energy produced should be 83Wh. However, we know that it was not constant over the last 5 minutes and hence we send the energy accumulator value in the v1 parameter, let´s say that this v1 increased 80Wh since last report (below the 83 calculated previously). In this situation your green line (power) will be on the 1000W point but your yellow line (average power) is actually 960W (80Wh over 5 minutes period), hence, yellow would be below green. In the next 5 minutes the situation reverses and you report current power (v2) as 960W but energy accumulator (v1) as 83Wh, now your yellow line would be on 1000W point and green on the 960W (green below yellow). The point is everytime you report power and energy together than maybe a little divergence between yellow and green lines.

Now about the Growatt:
I don´t know if every Growatt is like mine but mine (and as far as I know @bobboulby´s unit also) only accumulate energy in 100Wh increments. This is a design decision (firmware) and improbably to change over model´s lifetime. The implication of this “low precision” increment is that, if you report v1 (energy accumulator) every 5 minutes, in a situation with less than 1200W average power over 5 minutes the increments to V1 will occur only at a 10 minutes intervals. In this scenario, the average power (yellow line) will drop to zero every other 5 minutes. On relatively small system like 1500W inverter or 3000W inverter like mine, during early morning hours or late afternoon (from 7am to 10am and after 15pm in my region) it is pretty common to have less than 1200W average power over 5 minutes period. At the end, there is a lot of Zero average power in the pvouput over the day. To avoid that I put a condition in the code, if the energy accumulator (v1) has not changed since last report code will not report v1, only v2. In this way, pvoutput figures v1 by itself and no zero average. However, at the end of the day it may drift a little from the actual energy produced since v2 is the current power not the last 5 minutes average. To avoid the drift, every time v1 changes from last report we send it to pvoutput, if a drift has occurred it will be correct shortly in the next v1 report.

By graphics you posted I see that one inverter might be reporting v1 and second might not (since the second graph has average equal to actual power I suppose it is only reporting power v2 but no energy accumulator v1). I will take a look in the code, when adding support for multiple inverters I probably messed with this logic.

Nice! You might need to “interpret” the data on each register. For holding registers in your post, take the first one with value 257, it is holding register 00; by Growatt documentation you read:

Register Number: 00
Variable name: OnOff
Description: The Inverter On/Off state and the auto start state, The low byte is the on/off(1/0), the high byte is the auto start state or not(1/0).
Customer Write: W
Value: 0x0000; 0x0001; 0x0100; 0x0101
Unit:
Initial Value: 0x0101
Note: Auto start means the auto power AC when next power on inverter.
(I broke the table into lines for readability since cannot paste tables here - or at least don´t know how)

We know that every register has 16 bits and, as per description, in a 0x0101 the bold part is the auto-start and ITALIC PART represents the on/off state, in this example 01 for autostart means autostart is enabled, and 01 for on/off, the inverter is on. In your reading you have 257 base decimal, convert it to 16-bits hexadecimal you have 0x101 (or pretty formatted 0x0101). So we conclude this inverter you read values from is set with auto-start enable and on/off state of On.

Following the table, jump to the 4th value, the value of 100. This is the register number 03, as per Growatt documents, this is the maximum active power output rate of the inverter. The value of 100 decimal base here converts to 0x0064 hexadecimal, but since this registers varies only between 0 and 100 we can interpret it directly, hence 100% active power output set for this inverter. Next register, the 5th value on the list, is tricky because it also varies from 0~100 as per documentation and it represents the maximum reactive power output rate. For a 100% active power it should be 0% reactive power right? I think so but you unit reports 255 and Growatt documents says it should fall in between 0~100 range. I guess that 255 is kind of “invalid” state for this register but cannot guarantee that. I bet that this would set if the active power was set to another value first but it is only and educated guess.
Next value, the 6th in the vector, is register number 5 or the power factor; document says it falls in the range 0 ~20000 and any value between 0~10000 is underexcited and others overexcited. Decimal value of 65535 is out of range again and, again, I guess this is not being used or not initialized. Keep in mind that every Growatt inverter will have all the registers but some of them maybe not implemented on a particular model, for instance, a single phase inverter will have the registers for 2nd and 3rd phases but it does not use it, hence it will report any invalid value since not used/initialized.
You can follow the Growatt documentation for interpret every value in the reading you have above or get to the exact one you are looking for. Some information will require more than 16-bits to be properly represented and on that case you need to shift the bits to make sense. (look into my code to see how I compute version and other strings from holding registers)

Any thing you could not figure out post here and I try to help.

Ah, one more thing:

I am interested in see what are readings for holding registers from 45 ~ 50 (rr = inv.read_holding_registers(45, 5, unit=0x1). They are meant for time settings (year, month, day, hour, minute, seconds respectively from 45 to 50) but my unit does not report meaningful information here, if I try to set those, unit issues an error. I conclude that my model does not have internal RTC (what I particularly consider a very bad design since a very good RTC costs less 1 dolar in production). Since there are documentation for this registers and someone reported to success read/write to it in the original article where I based of this work, I believe that some models do have time/date keeping mechanisms.

Tnx.