Hallo,
ich nutze den Baustein IP_CONTROL um über eine Socket Verbindung meine Wärmepumpe (Luxtronic) abzufragen.
Das Protokoll besteht aus:
- Sende Paket 1 an WWP: 00 00 0b bc
- Sende Paket 2 an WWP: 00 00 00 00
- Empfange Daten 820 Bytes mit Werten
Das Programm funktioniert, die Daten in der ersten Ausführung an.
In der Zweiten Ausführung wird nur noch Paket 00 00 00 00 gesendet.
In der dritten Ausführung erhalte ich einen Error im IP_C.C_ERROR
In der vierten Ausführung klappts dann (meistens) wieder
usw. usw.
Ich vermute die State-Machine hat noch einen Fehler, oder ich habe irgendwas übersehen beim sauberen Verbindungsabbau?
Bin für jeden Tipp dankbar!
Das ist der Code:
(* IF the send command is active AND the system is busy, ignore the send request *)
IF xSend THEN
(* Init status variables *)
xSend := FALSE;
xBusy := TRUE;
iStep := 0;
S_BUF.SIZE := 0; (* reset send-buffer *)
IP_C.C_PORT := uiPort;
IP_C.C_IP := IP4_DECODE('192.168.50.120');
IP_C.C_MODE := 0;
IP_C.TIME_RESET := TRUE;
IP_C.R_OBSERVE := TRUE;
IP_C.C_ENABLE := TRUE;
IPClient.TIME_OUT := T#500ms;
END_IF
IF xBusy THEN
CASE iStep OF
0: (* SEND Paket 1 *)
S_BUF.BUFFER[0] := 16#00;
S_BUF.BUFFER[1] := 16#00;
S_BUF.BUFFER[2] := 16#0B;
S_BUF.BUFFER[3] := 16#BC;
S_BUF.SIZE := 4;
IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
R_BUF.SIZE := 0;
IF IP_C.C_STATE = 255 THEN
iStep := 1;
END_IF
1: (* SEND Paket 2 *)
S_BUF.BUFFER[0] := 16#00;
S_BUF.BUFFER[1] := 16#00;
S_BUF.BUFFER[2] := 16#00;
S_BUF.BUFFER[3] := 16#00;
S_BUF.SIZE := 4;
IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
R_BUF.SIZE := 0;
IF IP_C.C_STATE = 255 OR IP_C.C_STATE = 1 THEN
iStep := 2;
END_IF
IF IP_C.ERROR = 0 THEN
iStep := 10;
END_IF
2: (* CONVERT *)
FB_CONVERT(VAR_IN := R_BUF.BUFFER[0], VAR_OUT => status);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[18], VAR_OUT => tempAussen);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[13], VAR_OUT => tempVorlauf);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[14], VAR_OUT => tempRuecklauf);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[15], VAR_OUT => tempVorlaufS);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[20], VAR_OUT => tempWWIst);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[21], VAR_OUT => tempWWSoll);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[24], VAR_OUT => tempMKVLIst);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[25], VAR_OUT => tempMKVLSoll);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[154], VAR_OUT => kwhHeizung);
FB_CONVERT(VAR_IN := R_BUF.BUFFER[155], VAR_OUT => kwhWasser);
iStep := 10;
10:
IP_C.C_ENABLE := FALSE;
IF IP_C.C_STATE = 0 THEN
xBusy := FALSE;
iStep := 0;
END_IF
END_CASE;
(*
IP_FIFO(FIFO:=IP_C.FIFO,STATE:=IP_STATE,ID:=IP_ID);
IP_C.FIFO:=IP_FIFO.FIFO;
IP_STATE := IP_FIFO.STATE;
IP_ID:=IP_FIFO.ID;
*)
END_IF
Variablen
PROGRAM PRG_LWP_SOCKET
VAR_INPUT
xSend : BOOL := FALSE;
END_VAR
VAR
(* Relevante Werte *)
(* siehe globale Variablenliste *)
IP_C : IP_C;
IP_FIFO : IP_FIFO;
IPClient : IP_CONTROL;
IPClient2 : IP_CONTROL;
IP_STATE : BYTE;
IP_ID : BYTE;
R_BUF : NETWORK_BUFFER;
S_BUF : NETWORK_BUFFER;
xBusy : BOOL := FALSE;
iStep : UINT := 0;
FB_CONVERT : FB_BYTESWAP_DWORD;
FB_SOCK_ERROR : SysSockGetLastError;
END_VAR
kann leider den Beitrag oben nicht editieren, in iStep 2 muss es natürlich heissen
IF IP_C.C_ERROR <> 0 THEN iStep := 10 ...... anstelle von
IF IP_C.C_ERROR = 0 THEN iStep := 10
iStep = 10 sollte die Verbindung beenden.
So ist es auch auf der Steuerung hinterlegt, allerdings mit genau obig beschriebenem Verhalten :-(
ja deine statemaschine ist etwas wackelig
der xSend schritt ist nicht teil der schrittkette
wenn die schrittkette läuft kann xsend alles übersteuern
du wartest auch nie das die daten gesendet worden sind 0
erst wenn S_BUF.SIZE = 0 ist sind die daten sicher versendet
wenn es einen fehler gibt was durchaus sein kann das es normal ist musst du die verbindung wieder neu initialisiernen
das beste wäre es also wenn der xsend block schon teil der echten schrittkette ist somit muss alles der reihe nach ablaufen
und immer am anfang und nach fehler die verbindung neu initialisieren
Vielen herzlichen Dank peewitt, werde das nachher ausprobieren!
Noch eine Frage zum Empfangsbuffer R_BUF.SIZE - obwohl ich Daten empfange und in dem Array definitiv Werte enthalten sind, ist SIZE immer 0.
Wie kann ich abfragen ob Werte erhalten wurden - klar, ich kann einen Index im Array abfragen, bei dem ich sicher weiss, dass er einen Wert haben muss <> 0, aber eleganter wäre es über "SIZE".
Danke!
hallo
natürlich gibt es noch mehr fehler...
S_BUF.BUFFER[1] := 16#00;
S_BUF.BUFFER[2] := 16#0B;
S_BUF.BUFFER[3] := 16#BC;
S_BUF.SIZE := 4;
IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
R_BUF.SIZE := 0;
1. vor dem senden solltest R_BUF_SIZE := 0 machen und nicht nach dem IP_Client aufruf denn nach dem Aufruf könnten theoretisch schon daten empfangen werden und dann knallst du R_BUF_SIZE := 0 drüber
Aber das ist nicht das hauptproblem
der Baustein IP_CONTROL arbeitet azyklisch - der baustein muss unabhängig deiner schritte zyklisch immer aufgerufen werden
sonst würde deine sps ja sofort abstürzen wenn der ip_control solange warten würde bis eine antwort kommt
schau dir doch die diversen demo bausteine an dort ist es auch immer so der der ip_control am baustein ende immer zyklisch durchlaufen wird
kurz gesagt deine konstruktion wirfst du am besten weg und schau dir die vorhandenen bausteine mal in ruhe an