Elmark Automatyka Sp. z o.o.
Menu
Strona główna
O nas: Elmark Automatyka Sp. z o.o.
Nasze forum
Inne/ciekawe strony www
Artykuły
WISE-4000 - moduły IoT
ADAM-6266 - kontrola wentylacji
ADAM-6200 - inteligentne moduły I/O
WIRE-CHIP, JAZZ i moduły ADAM
EKI-122X - konwertery Modbus
ADAM-6000 - funkcje P2P i GCL
O czym warto wiedzieć
Protokół ADAM-ASCII
Protokół Modbus
Implementacja Modbus/RTU
Implementacja Modbus/TCP
Wyjścia przekaźnikowe
Seria ADAM-6000 i język PHP
Najpopularniejsze modele
ADAM-4520 Optoizolowany
konwerter RS-232/422/485
ADAM-4017+
Wejścia analogowe (RS-485)
ADAM-4055
We/wy cyfrowe (RS-485)
ADAM-5000/TCP
Kaseta Modbus/TCP
ADAM-6017
Wejścia analogowe
ADAM-6060
We/wy cyfrowe (przekaźnikowe)
USB-4711A Uniwersalny
moduł pomiarowy AI/AO/DI/DO
Protokół Modbus/TCP
Czyli komunikacja w sieci Ethernet

      W implementacji TCP/IP zrezygnowano z pola adresowego (w odwołaniach Modbus/TCP adres urządzeń, do których kierowane jest zapytanie jednoznacznie określa już przy samym nawiązywaniu połączenia docelowy adres IP) i sumy kontrolnej. Wprowadzono natomiast rozszerzony nagłówek MBAP (Modbus Application Protocol Header) zawierający cztery pola:

identyfikator transakcji (2 bajty) - wykorzystywany przez urządzenie master do prawidłowego kojarzenia odpowiedzi uzyskiwanych na jego kolejne zapytania (wartość ta zostaje ustalona i umieszczona w ramce zapytania przez jednostkę master, a następnie skopiowana i umieszczona w ramce odpowiedzi przez jednostkę slave)
identyfikator protokołu (2 bajty) - pole to ma zawsze wartość 0 odpowiadającą oznaczeniu protokołu Modbus
rozmiar wiadomości (2 bajty) - liczba pozostałych bajtów wiadomości (poczynając od pola identyfikatora urządzenia; pole to zostało wprowadzone ze względu na możliwość dzielenia pojedynczej wiadomości na oddzielne pakiety TCP/IP)
identyfikator urządzenia (1 bajt) - odgrywający znaczenie np. w przypadku komunikacji z urządzeniami Modbus wyposażonymi w interfejs szeregowy za pomocą bram (Modbus Data Gateway)

      Odnośnie wykorzystywanych funkcji i ich parametrów: obowiązują oczywiście te przedstawione wcześniej - jak w przypadku implementacji RTU (np. dla modułów serii ADAM-4000). Podobnie jak w przypadku Modbus/RTU musimy oczywiście także posiadać informacje na temat listy adresów rejestrów naszego urzadzenia. Dla dwóch najpopularniejszych reprezentantów serii ADAM-6000 i wybranych ich rejestrów będą to:

ADAM-6017
40001-40008AI0-AI7 Current ValueR
40011-40018AI0-AI7 Max ValueR
40021-40028AI0-AI7 Min ValueR
00101-00108AI0-AI7 Max Value ResetR/W
00111-00118AI0-AI7 Min Value ResetR/W
00131-00138AI0-AI7 HI Alarm FlagR
00141-00148AI0-AI7 LO Alarm FlagR
 
ADAM-6060
00001-00006DI0-DI5R
00017-00022DO0-DO5R/W
40001CNT0R (32bit)
00033CNT0 Start[1]/Stop[0]W
00034CNT0 Clear[1]W

W przypadku kasety komunikacyjnej ADAM-5000/TCP adresy przypisane są natomiast do poszczególnych jej slotów:

Slot numberAnalog I/ODigital I/O
040001÷4000800001÷00016
140009÷4001600017÷00032
240017÷4002400033÷00048
340025÷4003200049÷00064
440033÷4004000065÷00080
540041÷4004800081÷00096
640049÷4005600097÷00112
740057÷4006400113÷00128

Przykładowe transakcje Modbus/TCP będą więc wyglądały następująco:

• Odczyt wartości wejścia analogowego AI-0 dla modułu ADAM-6017:

45-72-00-00-00-06010300-0000-01 -> 45-72-00-00-00-05010302B8-FA

• Odczyt stanu DI2-DI5 w module ADAM-6060:

45-72-00-00-00-06010200-0200-04 -> 45-72-00-00-00-040102010F

• Odczyt zawartości licznika CNT0 (DI0) w module ADAM-6060:

45-72-00-00-00-06010300-0000-02 -> 45-72-00-00-00-0701030400-19-00-00

• Skasowanie zawartości licznika CNT0 (na DI0) w module ADAM-6060:

45-72-00-00-00-06010500-21FF-00 -> 45-72-00-00-00-06010500-21FF-00

• Wyłączenie/włączenie licznika CNT0 (na DI0) w module ADAM-6060:

45-72-00-00-00-06010500-2000-00 -> 45-72-00-00-00-06010500-2000-00

45-72-00-00-00-06010500-20FF-00 -> 45-72-00-00-00-06010500-20FF-00

• Ustawienie wartości 7.000V dla wyjścia analogowego A03 w module ADAM-5024 (slot 2 kasety ADAM-5000/TCP):

45-72-00-00-00-06010600-130B-32 -> 45-72-00-00-00-06010600-130B-32

gdzie:

   - adres rejestru pobrany ze schematu adresowania (40020 -> 0x0013)
   - wartość docelowa rejestru obliczona jako 7/10*4095=2866=0x0B32
   - wykorzystana nie opisana tutaj dotychczas funkcja 0x06 - Write Single Register:

Write Single Register - struktura zapytania
FUNCTION CODE1 bajt0x06
DATARegister Address2 bajty0x0000-0xFFFF
Register Value2 bajty0x0000-0xFFFF

Write Single Register - struktura odpowiedzi
FUNCTION CODE1 bajt0x06
DATARegister Address2 bajty0x0000-0xFFFF
Register Value2 bajty0x0000-0xFFFF


      Na podstawie powyższych informacji możemy już ponownie próbować zaimplementować ten protokół w naszej aplikacji. Nasza bardzo prosta procedura ustawiająca wyjście cyfrowe DO-0 w module ADAM-6060 o adresie IP=192.168.2.130, korzystająca z gotowej kontrolki ClientSocket mógłaby więc wyglądać następująco:

procedure DO0ON;
var start,aktu:word;
komenda:string;
begin
//KONFIGURACJA GNIAZDA
Clientsocket1.Address:='192.168.2.130';
Clientsocket1.Port:=502;
//NAWIĄZANIE POŁĄCZENIA
Clientsocket1.Open;
start:=gettickcount;
repeat
   aktu:=gettickcount;
   Application.ProcessMessages;
until (aktu-start>500)or(Clientsocket1.Socket.Connected=true);
if aktu-start>500 then
   begin
   ShowMessage('Połączenie nie zostało nawiązane...');
   exit;
   end;
//KOMENDA=MBAP+ID+FUNCTIONCODE+DATA
komenda:=chr($AA)+chr($BB)+chr($00)+chr($00)+chr($00)+chr($06)+chr($01)+chr($05)+chr($00)+chr($10)+chr($FF)+chr($00);
//WYSŁANIE KOMENDY (ZAPYTANIA)
Clientsocket1.Socket.SendText(komenda);
//ZERWANIE POŁĄCZENIA
Clientsocket1.Close;
end;