rasProject_01 / weSweetHome  R. 240
process control       /     RasPi software         by   weinert-automation
Loading...
Searching...
No Matches
growattLink.c File Reference

Communication with a Growatt inverter. More...

#include "arch/config.h"
#include <stdint.h>
#include "mqttHome.h"
#include "growattHome.h"
#include "weUtil.h"
#include "weModbus.h"
#include "weStateM.h"
#include "weLockWatch.h"
#include "weShareMem.h"
#include <errno.h>
#include <sys/sem.h>
#include <getopt.h>
#include "weGPIOd.h"

Macros

#define GNLED
 Green LED, PIN13. More...
 
#define RDLED
 Red LED, PIN11. More...
 
#define YELED
 Yellow LED, PIN22. More...
 

Functions

int main (int argc, char **argv)
 The program. More...
 
void mqttClean ()
 End as MQTT client.
 
int mqttInit ()
 Initialise as MQTT client. More...
 
void * processIOthread (void *args)
 The task of controlling process IO. More...
 
void * rs232ModThread (void *args)
 

Variables

char clientId [38]
 MQTT client ID. More...
 
modBvals_t modBvals
 modbus respectively process values
 
char const prgNamPure []
 The pure program name. More...
 
char const prgSVNdat []
 The complete SVN date string. More...
 
char const prgSVNrev []
 The complete SVN revision string. More...
 
char subTopStPlg01 [14]
 State sub topic of S20 plug Number 01 to 09. More...
 

Detailed Description

Communication with a Growatt inverter.

The program's main task is to communicate with (currently) one Growatt PV (photovoltaics) inverter via its RS232 Modbus interface. Data got on a regular basis from the input and holding registers are made available to other programs, like e.g. the GCI program growattRead.c, by shared memory and by MQTT. Locking and signalling for the shared memory is done by a semaphore set. This is the same approach as in hometersControl.c. The MQTT message has the form: Up: 119.6V P: 65.0W L: 7.2W T: 26.5gdC Wd/t: 1.2 / 2316.2kWh featuring Panel DC voltage, line Power (to grid), inverter loss and temperature, day's and total work.

The program runs on a Raspberry with GUI-less (no graphics) Raspbian lite. GUI/HMI is featured as Web-Interface (Apache, C CGI) in the (W)LAN. For the Web-HMI with the GCI program growattRead.c an Apache Webserver

Copyright (c) 2019 Albrecht Weinert
weinert-automation.de a-weinert.de
/ / /\
/ /___ / \ |
\ /____\ /____\ | _|__
\ /\ / \ / \| |
\/ \/ \__/ \__/|_

Revision history

Rev. 247 5.05.2023
Rev. 213 13.08.2019 : new; derived from hometersControl.c
Rev. 216 31.08.2019 : first operable with Modbus outages (hopefuly)
Rev. 217 07.09.2019 : Growatt MQTT first steps
Rev. 219 06.11.2019 : Growatt MQTT all important values in one message

Communication

This program uses serial communication with a RS232 converter to handle the Growatt inverter's Modbus link.

MQTT protocol via Ethernet or WLAN is used to publish essential inverter values and data. The MQTT broker or host defaults to 192.168.178.87, the port is 1883.

HTTP is used for GUI (via Apache). HTTPS is not used as all LAN communication is in guarded private home or laboratory networks.

Common memory is used to communicate with other programs. At present this is a a small CGI program handling the AJAX link to the Apache based Web interface.

A backlink via HTTP parameter and shared memory and/or MQTT to control the inverter (via holding registers) is not implemented but may be in the future.

GPIO usage

This communication program currently uses no GPIO pins but includes all libraries etc. to do so.
As Test it uses three pins as output assuming LEDs connected to as Hi=On

Pi 1 / Pi 3 Pin
GPIO17/ 17 : red 11
GPIO21/ 27 : green 13
GPIO25 : yellow 22

Modbus usage

This program acts as client for one Growatt inverter 1500P "GEAD1018" with firmware G.2.0 and Modbus protocol version 3.01. It is a single line phase, single PV array and zero battery type.

Communication setting will be 'RTU / RS232 9600, none'.

Timing

The program has a cyclic process control (in SPS manner). We have /code a) a 100 ms cycle for process control, process I/O, SFCs etc. b) an 1s cycle for Modbus communication, timer handling and some SFCs /code

Server functions

Shared memory and a set of three semaphores is provided to share current values with other (C) programs as well as (in future) for receiving command and status information. This interface is also used to provide web interfaces in a flexible way.

Client functions

The program acts as (see above) as Modbus client. And it acts as MQTT publisher currently using a mosquitto broker on another Raspberry in the same private (W)LAN.

Library usage

The program uses the standard libraries pthread, pigpiod_if2, modbus, shm, sem and mosquitto. The own libraries in weRasp/..c and include/..h, namely weModbus, weGPIOd, sysUtil, weShareMem, weCGIajax etc. are compiled and linked in.

cross-compile by:

make PROGRAM=growattLink TARGET=growPi clean all

program respectively transfer to target machine by:

make PROGRAM=growattLink TARGET=growPi FTPuser=pi:piPas progapp

The building of this application is governed by the make include makeProg_growattLink_settings.mk:

# A makefile include for raspberry projects
# program include for one program
# Copyright 2018 Albrecht Weinert < a-weinert.de >
MAKE_INCLUDE_PROGRAM = growattLink
MAKE_PROGRAM_LAST_CHANGE = '$Date: 2021-02-02 18:11:02 +0100 (Di, 02 Feb 2021) $ '
MAKE_PROGRAM_REVISION = '$Revision: 236 $ '
ifndef COPYRIGHT_YEAR
$(error includefile $(MAKE_INCLUDE_PROGRAM) used directly.)
endif
# PROGRAM or MAIN_F might have been given in wrong case (at least on Windows)
override MAIN_F = $(MAKE_INCLUDE_PROGRAM)
# makeProg_hometersControl_settings.mk
# An optional short multiline description of this program's
# specifica.
# May be empty. Do not change the three lines define endef and export
define PROG_DES_TEXT
Program growattLink
This program handles the Modbus communication wit one Growatt PV inverter.
As a server it provides those date via shared memory and by MQTT.
The program should be run (auto start) as server with no direct UI.
endef
export PROG_DES_TEXT
extraLDFLAGS = -lrt -pthread -lmodbus -lpigpiod_if2 -lmosquitto
extraSOURCES = weRasp/sysBasic.c weRasp/weUtil.c weRasp/weModbus.c
extraSOURCES += weRasp/weShareMem.c weRasp/weStateM.c
extraSOURCES += weRasp/weGPIOd.c weRasp/weLockWatch.c

Macro Definition Documentation

◆ RDLED

#define RDLED

Red LED, PIN11.

On in steps 0 *) and 5;
Off in steps 3 and 8   of the 100ms cycle.
Note *): will be done by Modbus start receive (success) in 1s cycle.

◆ GNLED

#define GNLED

Green LED, PIN13.

On in steps 2 and 7;
Off in steps 5 and 0   of the 100ms cycle.

◆ YELED

#define YELED

Yellow LED, PIN22.

On in step 9;
Off in step 4 *)   of the 100ms cycle.
Note *): will be done by Modbus end of receive (success) in 1s cycle.

Function Documentation

◆ mqttInit()

int mqttInit ( )

Initialise as MQTT client.

On success only: subscribe, loop and publish.

Returns
0: success the common mosq is set and usable; else: errno

◆ processIOthread()

void * processIOthread ( void *  args)

The task of controlling process IO.

Except for the Modbus communication, this thread controls all processIO: at present this is just three LEDs.

It is a 100 ms cycle thread.
The cyclic 100 ms task then distinguishes 10 steps within a second. This ten (0..9) steps serve for the synchronisation with the other thread and act as state machine framework.

◆ rs232ModThread()

void * rs232ModThread ( void *  args)

out char formIfix[60] = // form P 2 l7 Wd 16 l4 T 27 l5 Up 40 l 6 0123456789x123456789v123456789t123456789q123456789c1 2 3 4 "P: 1299.4W, Wd: 12.4kWh, T: 29.7gdC, Up: 114.3V\0\0\0"; formFixed16(formIfix + 2, 7, // form P 2 l7 modBvals.imp0Regs.regs[12], 1); // lo line power / .1W formFixed16(formIfix + 16, 4, modBvals.imp0Regs.regs[27], 1); // lo work day / .1 kWh formFixed16(formIfix + 27, 5, modBvals.imp0Regs.regs[32], 1); // Temp / .grdC formFixed16(formIfix + 40, 6, modBvals.imp0Regs.regs[3], 1); // Upanel / .1V = out

◆ main()

int main ( int  argc,
char **  argv 
)

The program.

run by: growattLink [options
For options see longOptions and :: optHlpTxt.

Parameters
argcnumber of parameters + 1
argvoptional options

xxxxx for(;commonRun;) { // use main thread for async tasks like MQTT pthread_yield(); break; // no asyn tasks yet if (!commonRun) break; pthread_yield(); if (!commonRun) break; if (!commonRun) break; pthread_yield(); if (!commonRun) break; } // commonRun async tasks xxxx

Variable Documentation

◆ prgNamPure

char const prgNamPure[]

The pure program name.

To be provided in the application's / program's source.

See also
progNam() progNamB()

◆ prgSVNrev

char const prgSVNrev[]

The complete SVN revision string.

To be provided in the application's / program's source.

See also
progRev()

◆ prgSVNdat

char const prgSVNdat[]

The complete SVN date string.

To be provided in the application's / program's source.

See also
progDat()

◆ subTopStPlg01

char subTopStPlg01[14]

State sub topic of S20 plug Number 01 to 09.

It's preset as plug01/POWER for 01, but the digit at index [5] will be set before each use accordingly.

◆ clientId

char clientId[38]

MQTT client ID.

default value: sweetHomeControl; length: 15; max. length: 36
May be changed before mqttInit().