Monitoring the solar inverter
When we bought this house, it came with what we’re pretty sure is a 2kW PV system on the roof. I’m quite sure it’s old, and not optimized for our use: the instruction manual with it references software running on Windows XP, and it’s pointed westward (ie, optimized for afternoon use, when someone gets home, rather than all-day if it were oriented north). I want to replace it with the absolute biggest system we can reasonably fit on our roof (I’m hoping for something around 15kW), to maximize the potential for batteries some day and to hopefully eliminate our daytime energy use on all but the worst days.
But for now, it’d be nice to keep track of generation better than the utility company telling me what we sold them. Some time ago I worked out that there’s a DB-9 serial port on the bottom of the machine, and lots of folks have spent some time looking at the dodgy proprietary protocol the unit speaks. It’s documented in a PDF here (I’ve mirrored the PDF in case this goes down): https://www.snafu.priv.at/mystuff/growatt.html
A while back Greg gave me some serial cables that’d do the job for connecting to it, but I haven’t done anything with it until today, when I decided to take a look. I didn’t have anything with a serial port close enough for the cables to reach, so I dug out an old APU1c and connected it up.
This APU unfortunately only has FreeBSD 12 on it though, in a NanoBSD configuration (making getting additional software on it problematic). No Python, no Perl, no compilers of any sort. Only the base tools,
cat, some shell builtins, and
cu which provded to not be much use. Worse still, I didn’t actually know how to drive
sh, I only really speak
bash (not installed on this machine) these days after working at a Linux shop for way too long, so Peter on IRC had to come to my rescue with how to actually echo hex codes as the raw bytes.
After some messing around (getty was hogging my serial port), I finally got it to work with the most rudimentary tools:
stty -f /dev/ttyu0 speed 9600 echo -n $'\x3F\x23\x7E\x34\x41\x7E\x32\x59\x31\x30\x30\x30\x23\x3F' > /dev/ttyu0 echo -n $'\x3F\x23\x7E\x34\x42\x7E\x23\x3F' > /dev/ttyu0
and then watching the output:
cat /dev/ttyu0 | hd 00000000 02 0c 89 08 dc c3 f7 57 09 ec 0e c1 00 00 09 6b |.......W.......k| 00000010 13 87 4e 22 01 7d 01 00 00 00 00 00 00 3c 00 02 |..N".}.......<..| 00000020 0c 89 08 dc c3 f7 57 09 f2 0e c1 00 00 09 62 13 |......W.......b.| 00000030 87 4e 22 01 7d 01 00 00 00 00 00 00 3c 00 02 0c |.N".}.......<...| 00000040 89 08 dc c3 f7 57 09 f8 0e c6 00 00 09 6b 13 87 |.....W.......k..| 00000050 4e 22 01 7d 01 00 00 00 00 00 00 3c 00 02 0c 89 |N".}.......<....|
The output came much faster than expected - I requested a 1000ms (ie 1-second) update rate and it was spewing data constantly, not sure why that was. I’m also not sure how to stop it, so I rebooted the inverter by throwing both isolator switches to shut it up.
But picking out one of the records (starting at byte 7), it looks correct to me:
57 - start of record 09 ec - PV1 voltage x10: 0x09ec is 2540, or 254V. 0e c1 - junk, ignored 00 00 - PV2 voltage x10: I do not have a second string. 09 6b - grid voltage x10: 2411, or 241.1V. 13 87 - grid frequency x 100: 4999 or 49.99Hz 4e 22 - output power, watts x10: 20002 or ~2kW 01 7d - temperature x10: 381, or 38.1C 01 - status, guessing 1 is normal? 00 - fault code, 00 == normal? 00 00 00 00 - four bytes of junk 00 3c - EToday, x10: 60 is 6kWh? 00 02 0c 89 - EAll, x10: 134281, or 13428.1kWh, matches what's on the display. 08 dc c3 f7 - Seconds operated, 148685815, or 4.71 years
If the seconds operated only ticks up during daylight hours, as I think it does, that makes this quite an old system indeed… we may be eligible for some sort of grants to upgrade it. I am not banking on this though, and expecting to pay full price for it, which is why it has not happened yet.
So this will definitely work, it should be fairly easy to write a Python program which will read the serial port, blocking if necessary with a timeout, and every say, 5 minutes, sending the re-init command if the port isn’t communicating (because each time the unit goes to sleep it will need re-initializing). If it’s communicating, read these records, parse them and grab
EAll, and feed it into RRDtool. That should be job done.
The person who published the datasheet has written a program in perl to do it: http://www.snafu.priv.at/mystuff/read-growatt
I’m not averse to perl (a long time ago I wrote quite a lot in it) but it doesn’t quite do what I want and I think I’ll have an easier time in Python. We’ll see.
I did find this software, which I don’t think does what I want either: https://github.com/lemval/growatt-rs232-reader - it exposes an HTTP server that I would then have to poll to get the data into RRDtool anyway.