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/RTU
Czyli komunikacja na łączu szeregowym RS-485

Przesyłane w obydwie strony wiadomości zorganizowane są w postaci ramek o czterech ściśle określonych polach:

ADDRESS FUNCTION CODE DATA CHECKSUM

W implementacji RTU dla zapytania mamy:

ADDRESS [1 bajt] - określa do którego urządzenia wpiętego w sieć (tu RS-485) adresowane jest zapytanie
FUNCTION CODE [1 bajt] - określa kod funkcji/zapytania
DATA [różnej długości] - przekazuje parametry wejściowe wywoływanej funkcji
CHECKSUM [2 bajty] - stanowi sumę kontrolną

Dla odpowiedzi:

ADDRESS [1 bajt] - określa adres urządzenia slave odpowiadającego na zapytanie
FUNCTION CODE [1 bajt] - określa kod funkcji/zapytania z zapytania
DATA [różnej długości] - przekazuje parametry wynikowe funkcji
CHECKSUM [2 bajty] - stanowi sumę kontrolną

Najczęściej wykorzystywane funkcje (spośród wielu dostępnych ściśle zdefiniowanych w standardzie) przedstawiono w poniższej tabeli:

Function code Function description
0x01Read Coils
0x02Read Discrete Inputs
0x03Read Holding Registers
0x04Read Input Registers
0x05Write Single Coil
0x06Write Single Register
0x08Loopback Diagnostic
0x0FWrite Multiple Coils
0x10Write Multiple Registers

      Oprócz znajomości kodów i struktury poszczególnych funkcji Modbus potrzebne są nam jeszcze adresy rejestrów. W przypadku modułów pomiarowych serii ADAM możemy je znaleźć w dokumentacji lub odczytać za pomocą ADAM.NET Utility. Dla najpopularniejszych modułów serii ADAM-4000 - czyli modułu wejść analogowych ADAM-4017+ i modułu we/wy cyfrowych ADAM-4055 będą to następujące wartości:

ADAM-4017+ ADAM-4055
Analog Inputs Digital Inputs
40001AI-0R 00001DI-0R
40002AI-1R 00003DI-1R
......... ...?...
40008AI-7R 00008DI-7R
Analog Inputs Types Digital Outputs
40201AI-0 typR/W 00017DO-0R/W
40202AI-1 typR/W 00018DO-1R/W
......... ...?...
40208AI-7 typR/W 00024DO-7R/W
Module Info Module Info
40211Name-1R 40211Name-1R
40212Name-2R 40212Name-2R
40213Firmware-1R 40213Firmware-1R
40214Firmware-2R 40214Firmware-2R


Korzystając z tych informacji możemy już budować strukturę naszych zapytań Modbus/RTU. Na początek skorzystamy z funkcji 0x04 - Read input Registers. Struktura jej zapytań i stosownych odpowiedzi, zgodnie ze standardem Modbus wygląda następująco:

Read input Registers - struktura zapytania
FUNCTION CODE1 bajt0x04
DATAStarting Address2 bajty0x0000-0xFFFF
Quantity of Input Registers (N)2 bajty0x0001-0x007D

Read input Registers - struktura odpowiedzi
FUNCTION CODE1 bajt0x04
DATAByte Count1 bajt2xN
Input RegistersNx2 bajtów-

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

• Odczyt nazwy urządzenia i wersji firmware dla modułu ADAM-4017+:

010400-D200-04E4-30 -> 01040840-17-50-00-A2-02-00-00C9-14

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

010400-0000-0131-CA -> 010402E5-F933-E2


Do ustawienia pojedynczego wyjścia cyfrowego skorzystamy z funkcji 0x05 - Write Single Coil:

Write Single Coil - struktura zapytania
FUNCTION CODE1 bajt0x05
DATAOutput Address2 bajty0x0000-0xFFFF
Output Value2 bajty0x0000 / 0xFF00

Write Single Coil - struktura odpowiedzi
FUNCTION CODE1 bajt0x05
DATAOutput Address2 bajty0x0000-0xFFFF
Output Value2 bajty0x0000 / 0xFF00

Przykładowe transakcje - włączenie i wyłączenie wyjścia cyfrowego DO-0 w module ADAM-4055 - będą więc wyglądały następująco:

020500-10FF-008D-CC -> 020500-00FF-008C-09

020500-1000-00CC-3C -> 020500-0000-00CD-F9


Do ustawienia kilku wyjść cyfrowych (jedną transakcją) skorzystamy funkcji 0x0F - Write Multiple Coils:

Write Multiple Coils - struktura zapytania
FUNCTION CODE1 bajt0x0F
DATAStarting Address2 bajty0x0000-0xFFFF
Quantity of Outputs2 bajty0x0001-0x07B0
Byte Count1 bajtN
Outputs ValueN bajtów-

Write Multiple Coils - struktura odpowiedzi
FUNCTION CODE1 bajt0x0F
DATAStarting Address2 bajty0x0000-0xFFFF
Quantity of Outputs2 bajty0x0001-0x07B0

Przykładowe transakcje - włączenie i wyłączenie wszystkich wyjść cyfrowych w module ADAM-4055 - będą więc wyglądały następująco:

020F00-1000-0801FF3F-03 -> 020F00-0000-0854-3E

020F00-1000-0801007F-43 -> 020F00-0000-0854-3E


Do odczytu stanu wejść cyfrowych skorzystamy z funkcji 0x02 - Read Discrete Inputs:

Read Discrete Inputs - struktura zapytania
FUNCTION CODE1 bajt0x02
DATAStarting Address2 bajty0x0000-0xFFFF
Quantity of Inputs2 bajty0x0001-0x007D

Read Discrete Inputs - struktura odpowiedzi
FUNCTION CODE1 bajt0x02
DATAByte Count1 bajtN
Inputs StatusN bajtów-

Przykładowa transakcja - odczyt stanu wszystkich wejść cyfrowych w module ADAM-4055 - będzie więc wyglądała następująco:

020200-0000-0879-FF -> 020201AA21-B3



UWAGA: W przedtawionych wyżej przykładach, w każdej z komend (zgodnie ze standardem Modbus) występują dwa kończące bajty reprezentujące sumę kontrolną CRC. Do jej wygenerowania (algorytm jest bardziej złożony niż np. w przypadku protokołu ADAM-ASCII) skorzystać możemy np. z poniższej funkcji (Pascal/Delph):

procedure GenerateModbusCRC(var modbus_command:string);
var CRC:word;
bajt,bit:byte;
LSB:byte;
begin
  CRC:=$FFFF;
  for bajt:=1 to length(modbus_command) do
    begin
    CRC:=CRC xor ord(modbus_command[bajt]);
    for bit:=1 to 8 do
      begin
      LSB:=CRC and $0001;
      if LSB=1 then CRC:=CRC-1;
      CRC:=CRC shr 1;
      if LSB=1 then CRC:=CRC xor $A001;
      end;
    end;
  modbus_command:=modbus_command+chr(CRC and $00FF)+chr((CRC and $FF00) shr 8);
end;

      Na podstawie przedstawionych powyżej danych i przykładów (oraz oczywiście po sięgnięciu do dokumentacji protokołu Modbus) możemy jak widać we własnym zakresie - od podstaw - zorganizować komunikację naszej aplikacji z modułami pomiarowymi ADAM - w oparciu o bezpośrednią obsługę łącza szeregowego. Nie jest to sprawa trywialna - trzeba pamiętać o pewnych dodatkowych, nie opisanych wyżej właściwościach protokołu Modbus, oraz - co bardzo ważne - odpowiednio zaimplementować obsługę błędów. Na szczęście nie zawsze jesteśmy do tego zmuszeni - z pomocą przychodzi nam zazwyczaj implementacja protokołu w systemach SCADA/HMI, plus szeroka dostępność serwerów OPC (pozycja taka występuje także w ofercie Advantech). Jednakże znajomość struktury tegoż protokołu będzię zapewne pomocna także i w takim przypadku...