How to / Sterowanie i akwizycja danych

Protokół Modbus/TCP, czyli komunikacja w sieci Ethernet z modułami ADAM i nie tylko - część 2/2

10.09.2015 Producent: Advantech Zastosowanie: Zakłady przemysłowe
Wizerunek autora
Jarosław Molenda Inne artykuły tego autora
Protokół Modbus/TCP, czyli komunikacja w sieci Ethernet z modułami ADAM i nie tylko

 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-40008 AI0-AI7 Current Value R
40011-40018 AI0-AI7 Max Value R
40021-40028 AI0-AI7 Min Value R
00101-00108 AI0-AI7 Max Value Reset R/W
00111-00118 AI0-AI7 Min Value Reset R/W
00131-00138 AI0-AI7 HI Alarm Flag R
00141-00148 AI0-AI7 LO Alarm Flag R
 
ADAM-6060
00001-00006 DI0-DI5 R
00017-00022 DO0-DO5 R/W
40001 CNT0 R (32bit)
00033 CNT0 Start[1]/Stop[0] W
00034 CNT0 Clear[1] W


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

Slot number Analog I/O Digital I/O
0 40001÷40008 00001÷00016
1 40009÷40016 00017÷00032
2 40017÷40024 00033÷00048
3 40025÷40032 00049÷00064
4 40033÷40040 00065÷00080
5 40041÷40048 00081÷00096
6 40049÷40056 00097÷00112
7 40057÷40064 00113÷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-06 01 03 00-00 00-01 -> 45-72-00-00-00-05 01 03 02 B8-FA


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

45-72-00-00-00-06 01 02 00-02 00-04 -> 45-72-00-00-00-04 01 02 01 0F


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

45-72-00-00-00-06 01 03 00-00 00-02 -> 45-72-00-00-00-07 01 03 04 00-19-00-00


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

45-72-00-00-00-06 01 05 00-21 FF-00 -> 45-72-00-00-00-06 01 05 00-21 FF-00


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

45-72-00-00-00-06 01 05 00-20 00-00 -> 45-72-00-00-00-06 01 05 00-20 00-00

 

45-72-00-00-00-06 01 05 00-20 FF-00 -> 45-72-00-00-00-06 01 05 00-20 FF-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-06 01 06 00-13 0B-32 -> 45-72-00-00-00-06 01 06 00-13 0B-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 CODE 1 bajt 0x06
DATA Register Address 2 bajty 0x0000-0xFFFF
Register Value 2 bajty 0x0000-0xFFFF

 

Write Single Register - struktura odpowiedzi
FUNCTION CODE 1 bajt 0x06
DATA Register Address 2 bajty 0x0000-0xFFFF
Register Value 2 bajty 0x0000-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;