Prosta implementacja protokołu komunikacyjnego ADAM ASCII

09.04.2013 How to / Sterowanie i akwizycja danych
Prosta implementacja protokołu komunikacyjnego ADAM ASCII
Wizerunek autora
Producent: Advantech
  • Zakłady przemysłowe
  • Gaz i Paliwa

      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.

      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);

Czyli polegać będzie praktycznie tylko na:

• wyborze urządzenia,
• otwarciu urządzenia,
• odczycie wejścia,
• zamknięciu urządzenia.

Skontaktuj się ze specjalistą Elmark

Masz pytania? Potrzebujesz porady? Zadzwoń lub napisz do nas!