Wago 750-841 jest sterownikiem sieciowym - w jego nazwie pojawia się słowo 'Ethernet'. Dzięki podłączeniu do sieci obsługuje wiele dodatkowych potężnych funkcji. W niniejszym artykule opiszę wysyłanie danych ze sterownika do bazy SQL.
Wszystkim zainteresowanym polecam film, który szczegółowo opisuje wszystkie kroki. Zapraszam również do lektury opisu biblioteki WagoLibMySql i noty aplikacyjnej.
Zacząć trzeba oczywiście od przygotowania samej bazy. Na moim sieciowym serwerze stworzyłem bazę WagoDB i przypisałem do niej użytkownika wago. W bazie danych stworzyłem tabelę 'Temperatures' o 5 kolumnach: 'Timestamp', 'Temp1'...'Temp4'.
Ponadto w 'Menadżerze zdalnego połączenia MySQL' ustaliłem dostęp z zewnątrz dla wszystkich hostów. O szczegółach tego procesu rozpisywać się nie będę - polecam film, notki aplikacyjne i googla.
Chciałem, aby co 20 minut mój sterownik wysyłał do bazy SQL dane o temperaturze z 4 czujników. Ponadto, w przypadku problemów z połączeniem (mój router jest wyłączony w nocy) dane o temperaturach powinny być przechowywane w pamięci i przekazywane do bazy przy uzyskaniu pierwszego pomyślnego połączenia. Aby to zrobić konieczne były następujące kroki po stronie PLC:
VAR_GLOBAL CONSTANT gcMySql_iSqlUpperBound :INT:=59; gcMySql_iSqlLength :INT:=150; END_VAR
W programie SQL_DataStorage() w części definicjy zmiennych:
VAR SQLWrite_Interval :TP:=(IN:=TRUE, PT:=T#20m); SQLWrite_StartSignal :R_TRIG; Command :STRING(150); TemperatureCommand :ARRAY [0..59] OF STRING(150); ManualLogin, ManualLogout, ManualExecute, ManualStorageClean :BOOL; TemperatureLogin :BOOL; TemperatureSQLLogin :MySql_Login; Host: STRING:='xxxxxxxxx'; User: STRING:='xxxxxxxxx'; Password: STRING:='xxxxxxxxxxx'; Database:STRING:='xxxxxxxxxxxx'; TemperatureConnection :MySql_Context; TemperatureLoginEnds :R_TRIG; TemperatureExecute :BOOL; TemperatureSQLQuery : MySql_Execute; TemperatureExecuteEnds :R_TRIG; TemperatureCommandCounter :BYTE:=0; i :BYTE; TemperatureLogout :BOOL; TemperatureSQLLogout:MySql_Logout; END_VAR
Gdzie:
W części programowej:
SQLWrite_StartSignal(CLK:=NOT SQLWrite_Interval.Q); SQLWrite_Interval(IN:=SQLWrite_StartSignal.Q); (* Przygotuj komendę SQL *) IF (SQLWrite_StartSignal.Q OR ManualLogin) THEN Command:='INSERT INTO Temperatures (Timestamp, Temp1, Temp2, Temp3, Temp4) VALUES ("'; Command:=CONCAT(Command,MID(DT_TO_STRING(CURRENT_TIME),10,4)); Command:=CONCAT(Command,' '); Command:=CONCAT(Command,RIGHT(DT_TO_STRING(CURRENT_TIME),8)); Command:=CONCAT(Command,'",'); Command:=CONCAT(Command,REAL_TO_STRING(SensorReader.TEMPERATURE_1)); Command:=CONCAT(Command,','); Command:=CONCAT(Command,REAL_TO_STRING(SensorReader.TEMPERATURE_5)); Command:=CONCAT(Command,','); Command:=CONCAT(Command,REAL_TO_STRING(SensorReader.TEMPERATURE_6)); Command:=CONCAT(Command,','); Command:=CONCAT(Command,REAL_TO_STRING(SensorReader.TEMPERATURE_8)); Command:=CONCAT(Command,');'); TemperatureCommand[TemperatureCommandCounter]:=Command; TemperatureCommandCounter:=TemperatureCommandCounter+1; (* Jeśli tablica jest pełna wyzeruj licznik, zacznij zapisy od początku *) IF TemperatureCommandCounter=60 THEN TemperatureCommandCounter:=0; END_IF; END_IF; (* Rozpocznij komunikację z Bazą SQL *) TemperatureLogin:=SQLWrite_StartSignal.Q OR ManualLogin; TemperatureSQLLogin(sHost:=Host, sUsername:=User, sPassword:=Password, sDatabase:=Database,oMySql:=TemperatureConnection, xStart:=TemperatureLogin); TemperatureLoginEnds(CLK:=TemperatureSQLLogin.xConnected); TemperatureExecute:=TemperatureLoginEnds.Q OR ManualExecute; TemperatureSQLQuery(xStart:=TemperatureExecute, oMySql:=TemperatureConnection, asSqlCommand:=TemperatureCommand); TemperatureExecuteEnds(CLK:=(TemperatureSQLQuery.wState=0)); (* Przy pomyślnym zapisie do Bazy SQL, wyczyść tablicę TemperatureCommand *) IF (TemperatureExecuteEnds.Q AND (TemperatureSQLQuery.diError=16#00000000)) OR ManualStorageClean THEN TemperatureCommandCounter:=0; FOR i:=0 TO 59 BY 1 DO TemperatureCommand[i]:=''; END_FOR; END_IF; (* Wyloguj z Bazy SQL *) TemperatureLogout:=(TemperatureExecuteEnds.Q OR ManualLogout); TemperatureSQLLogout(xStart:= TemperatureLogout, oMySql:=TemperatureConnection);
Aby obserwować przebieg i sprawdzać postępy komunikacji proponuję zbudować prostą wizualizację, w której umieścić trzeba przyciski zmieniające wartości zmiennych ManualLogin, ManualLogout, ManualExecute, ManualStorageClean i pola tekstowe wyświetlające zmienne wyjściowe sStatus wszystkich 3 bloków funkcyjnych: TemperatureSQLLogin, TemperatureSQLQuery, TemperatureSQLLogout.
Po co to wszystko? Ano choćby po to, by przeanalizować temperatury w zadanym okresie czasowym. Przykładowy, zrobiony na szybko wykres wygląda tak: (to oczywiscie wizualizacja w html, w oparciu o Highcharts Tools...)
Opis, jak zbudować wykresy dostępne przez przeglądarkę znajduje się w artykule Wykresy Danych - Highcharts