background image

Protokół ADAM-ASCII 

Czyli prosta implementacja protokołu komunikacyjnego 

      Komunikacja modułów serii ADAM-4000/5000 wyposażonych w interfejs RS-485 z innymi 
urządzeniami pełniącymi funkcje jednostek nadrzędnych w systemie pomiarowym oparta jest w głównej 
mierze o prosty protokół w formacie komend ASCII opracowany przez producenta (wszystkie moduły 
wejść/wyjść w serii ADAM-4000 oraz kasety komunikacyjne bez wbudowanych kontrolerów w serii 
ADAM-5000 wyposażone w port szeregowy RS-485). Każda z komend protokołu składa się praktycznie z 
czterech części: 
 
• znak początku, 
• adres modułu, 
• kod komendy, 
• znak kończący. 

      Znakiem poczatku jest zazwyczaj $ lub #. Adres modułu (do którego wysyłamy komendę) określany jest 
za pomocą dwóch znaków odpowiadających reprezentacji jego adresu w systemie szesnastkowym 
(wymagane są duże litery). W zależności od typu komendy, jej kod składa się z jednego do kilku znaków. 
Znakiem kończącym jest zawsze znak powrotu karetki <cr>=0x13. W przypadku odpowiedzi sytuacja jest 
podobna. Rozpoczyna się znakiem potwierdzenia (jest to zazwyczaj > lub !), po którym występuje (np. w 
przypadku odpowiedzi na komendy typu "Read...") wartość zwracana przez moduł, a kończy się także 
znakiem powrotu karetki. 

      Specyfikacja całości protokołu zawiera łącznie kilkadziesiąt komend (wśród których występują te 
odpowiedzialne za samą konfigurację i diagnostykę sprzętu oraz komendy wykorzystywane już podczas 
samej pracy modułów) i została oczywiście zawarta w instrukcji użytkownika sprzętu. Kilka przykładów 
zawarto w poniższej tabeli: 

Typ komendy 

Format zapytania 

Format odpowiedzi 

Przykład 

zapytania 

Przykład 

odpowiedzi 

Read Module 
Name 

$AAM<cr> 

!AA(ModuleName)<cr> 

$01M<cr> 
$02M<cr> 

!014017P<cr> 
!024055<cr> 

Read Firmware 
Version 

$AAF<cr> 

!AA(Version)<cr> 

$01F<cr> 
$02F<cr> 

!01A2.02<cr> 
!02A2.04<cr> 

Read Conf. Status 

$AA2<cr> 

!AATTCCFF<cr> 

$012<cr> 

!01FF0600<cr> 

Set Configuration 

%AANNTTCCFF<cr> 

!AA<cr> 

%0112050600<cr> 

!12<cr> 

... 

... 

... 

... 

... 

Read Analog Input 

#AAN<cr> 

>(data)<cr> 

#010<cr> 

>+04.416<cr> 

Digital Data In 

$AA6<cr> 

!(dataout)(datain)00<cr> 

$026<cr> 

!FCFC00<cr> 

Digital Data Out 

#AABB(data)<cr> 

><cr> 

#02003A<cr> 

><cr> 

      Wymieniona na pierwszym miejscu komenda "Read Module Name" jest najprostszą, bardzo ważną i 
pomocną komendą, pozwalającą na sprawdzenie poprawności komunikacji z danym modułem. 
Wykorzystywana jest także np. przez program narzędziowy Adam Utility do wyszukiwania wszystkich 
modułów (z aktywowanym protokołem ADAM-ASCII) włączonych do danej sieci RS-485. Komendą dość 
rozbudowaną jest np. ostatnia z wymienionych - "Digital Data Out", więc dla przykładu przeanalizujemy 
jej strukturę. Dokładny opis komendy znajdujemy oczywiście w dokumentacji do serii ADAM-4000: 

• # is a delimiter character. 
• AA (range 00-FF) represents the 2-character hexadecimal address of the output value. 
• BB is used to indicate whether all channels will be set or a single channel will be set. In the last case, BB will also 
indicate which channel it is. Writing data (a byte) to all channels should make both characters to be zero (BB=00). 
Writing data (a bit) to a single channel; however, will make the first character 1 and the second character ranging from 
0 to B. The second character indicates the channel number. 
• (data) is the hexadecimal representation of the digital output value(s). Two characters are for ADAM-4050, 4055, 
4060 and 4068. Four characters are for ADAM-4056S and 4056SO. 

background image

      Okazuje się więc, że wygenerowanie odpowiedniej zawartości komendy nie jest wcale aż tak 
skomplikowane. Pierwszy znak musi być znakiem rozpoczynającym #. Dwa kolejne znaki muszą 
reprezentować adres modułu w formacie heksadecymalnym (np. 21 dla modułu o adresie 33). Dwa kolejne 
znaki określają czy chcemy zapisać całą paczkę danych, czy tylko jeden bit. A ostatnie znaki (2 lub 4 - w 
zależności od ilości wyjść cyfrowych w danym module; przed kończącym komendę znakiem powrotu 
karetki) reprezentować muszą heksadecymalną wartość odpowiadającą wymuszanemu stanowi wyjść 
cyfrowych. I tak na przykład: 
 
• #140005<cr> - to zapis wartosci 05h (00000101, odpowiednio dla wszystkich wyjść CH7÷Ch0) w module 
o adresie 20, 
• #211201<cr> - to zapis wartości 01 (ustawienie stanu wysokiego) dla wyjścia CH2 w module o adresie 33. 

UWAGA: Opisywany protokół umożliwia także korzystanie z sumy kontrolnej. Zgodnie z dokumentacją producenta: 

"The checksum is represented by a 2-character ASCII hexadecimal format and is transmitted just prior to the carriage 
return. The checksum equals to the result after performing modulus-256 (100h) of all the ASCII values sum preceding 
the checksum. If the checksum is missing or incorrect, the module will not respond."

 Jeżeli chcemy skorzystać z tej 

możliwości to: 
 
• sumę kontrolną musimy włączyć przy konfiguracji danego modułu (ta opcja tylko w trybie INIT), 
• i oczywiście dwa znaki reprezentujące tę sumę kontrolną dodawać musimy do każdej wysyłanej komendy. 
 
Algorytm jej generowania jest bardzo prosty - przykładowa implementacja w języku Pascal/Delphi może wyglądać 
następująco: 
 
function ADAMCHECKSUM(komenda:string):byte; 
var i,suma:integer; 
begin 
   suma:=0; 
   for i:=1 to length(komenda) do suma:=suma+ord(komenda[i]); 
   suma:=suma mod 256; 
   ADAMCHECKSUM:=suma; 
end; 

      Korzystając z opisu protokołu zawartego w dokumentacji do modułów ADAM, komunikację z 
urządzeniami można więc implementować we własnym zakresie w oparciu o bezpośrednią obsługę łącza 
szeregowego (zarówno w przypadku współpracy modułów z komputerem, jak i innym urządzeniem typu 
sterownik PLC itp). W przypadku komunikacji modułów kontrolno-pomiarowych z komputerem 
wykorzystać można także bezpłatne biblioteki dll dostarczane przez producenta. W tym celu należy: 
 
• zainstalować pakiet menadżera urządzeń (devmgr.exe), 
• zainstalować pakiet bibliotek (adamdll.exe), 
• opcjonalnie: zainstalować pakiet przykładowych programów (examples.exe), 
• w konfiguracji urządzeń dodać i odpowiednio skonfigurować: 
     • port szeregowy, 
     • podłączone do niego moduły pomiarowe, 
• w tworzonej aplikacji wykorzystać odpowiedni plik nagłówkowy (np. w przypadku Delphi będzie to 
driver.pas), 
• wykorzystać odpowiednie funkcje biblioteczne do obsługi sprzętu. 

Przykładowy kod programu (Delphi) pozwalający na opdczyt wejścia analogowego będzie bardzo prosty:  

DRV_SelectDevice(Handle,true,DeviceNumber,@szbuffer[0]); 
DRV_DeviceOpen(DeviceNumber,DeviceHandle); 
ptAIVoltageIn.chan:=0; 
ptAIVoltageIn.voltage:=@Voltage; 
DRV_AIVoltageIn(DeviceHandle,ptAIVoltageIn); 
DRV_DeviceClose(DeviceHandle); 

background image

Czyli polegać będzie praktycznie tylko na: 
 
• wyborze urządzenia, 
• otwarciu urządzenia, 
• odczycie wejścia, 
• zamknięciu urządzenia.