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
Moduły ADAM-6000 w naszej serwerowni
Czyli maksymalnie uproszczona obsługa Modbus/TCP z poziomu języka PHP

      Dzięki wbudowanej komunikacji w oparciu o łącze sieciowe Ethernet i zaimplementowanemu protokołowi Modbus/TCP moduły serii ADAM-6000 mają bardzo szeroki zakres zastosowań. Na potrzeby niniejszego krótkiego artykułu rozważmy np. możliwości ich zastosowania w prostym układzie monitorowania szafy serwerowej. Z dużym prawdopodobieństwem założyć możemy, iż przynajmniej jeden z naszych serwerów jest serwerem www (na potrzeby internetu lub intranetu) z zainstalowanym modułem PHP. W sytuacji takiej nie musimy już szukać żadnego dodatkowego oprogramowania służącego do prostej obsługi modułów serii ADAM-6000 - możemy to zorganizować we własnym zakresie. I to na dodatek przy stosunkowo niskim nakładzie pracy!

      Podstawowym parametrem, który powinniśmy monitorować jest oczywiście temperatura. Najważniejszą będzie tu oczywiście temperatura panująca wewnątrz naszej szafy serwerowej, opcjonalnie monitorować możemy także temperaturę otoczenia panującą w pomieszczeniu, w którym szafa została umieszczona. Do tego celu zastosować możemy jeden z modułów specjalizowanych do pomiaru temperatury, np:

ADAM-6015 - przeznaczony do bezpośredniej współpracy czujnikami oporowymi (RTD),
ADAM-6018 - przeznaczony do bezpośredniej współpracy z czujnikami termoelektrycznymi (termoparami).

      Wykorzystać możemy także uniwersalny moduł wejść analogowych ADAM-6017. Wadą takiego rozwiązania będzie oczywiście konieczność zastosowania dodatkowego przetwornika temperatury z wyjściem w standardzie napięciowym (np. 0÷10V) lub prądowym (np. 4÷20mA). Jednak rozwiązanie takie będzie też miało pewną zaletę: do modułu podłączyć będziemy mogli przetwornik dowolnej wielkości fizycznej, co okazać się może bardzo pomocne np. w przypadku, gdy dodatkowo zechcemy monitorować poziom wilgotności, zadymienia itp.

      Dla włączonego w sieć i odpowiednio skonfigurowanego modułu musimy sobie teraz napisać funckję pozwalającą na odczyt wartości danego wejścia analogowego. Skorzystamy oczywiście z zaimplementowanej w moduł PHP obsługi gniazd. Jedyne co musimy zrobić to:

• nawiązać połączenie TCP na porcie 502 z naszym modułem,
• wysłać do niego odpowiednią ramkę z zapytaniem w protokole Modbus/TCP,
• odebrać odpowiedź z modułu,
• z uzyskanej ramki Modbus/TCP wyekstrahować wartość rejestru i przeliczyć ją na wartość fizyczną.

      W momencie, gdy chcemy to zrobić w możliwie najprostszy sposób nie musimy się oczywiście dokładnie "wgryzać" w całą specyfikację protokołu. Skorzystamy po prostu z funkcji 0x04 - czyli Read Input Registers. Przy założeniu, że za każdym razem odczytywać będziemy tylko jeden (odpowiedni) rejestr przyjąć możemy praktycznie stałą strukturę naszego zapytania, w którym zmianiał się będzie tylko jeden bajt - wskazujący na numer rejestru w module ADAM. Pozostałe bajty (czyli zawartość pól Transaction Identifier, Protocol Identifier, Length Field, Unit Identifier, Function Code i Quantity of Input Registers) będą miały zawsze tę samą wartość. Nasze zapytanie Modbus/TCP będzie więc zawierało następujące wartości:

00 00 00 00 00 06 01 04 00 numer kanału 00 01

      Dla modułu ADAM-6017 odczytywać będziemy mogli w ten sposób wartości z kanałów 0÷7, co odpowiadało będzie odczytom rejestrów 40001÷40008. Po wysłaniu zapytania musimy odebrać i przynajmniej pobieżnie przeanalizować odpowiedź modułu. W tym momencie także możemy przyjąć pewne uproszczenie: prawidłowa odpowiedź na zapytanie o wartość pojedynczego 16-o bitowego rejestru (wliczając także nagłówek MBAP Header) powinna mieć długość 11 bajtów, a zawartość odczytywanego rejestru reprezentowana jest przez ostatnie dwa bajty. Teraz pozostaje nam już tylko przeliczenie otrzymanej w ten sposób wartości na rzeczywistą wartość wielkości fizycznej. Dla modułów serii ADAM będzie to liniowa zależność pomiędzy zakresem 0÷65535 zwracanym przez rejestr, a ustawionym przy konfiguracji modułu zakresem pomiarowym (np. -10÷10V). Na tej podstawie obliczyć więc możemy np. wartość zmierzonego przez moduł napięcia, a na podstawie charakterystyki podłączonego do modułu przetwornika możemy już obliczyć wartość rzeczywistą mierzonej wielkości fizycznej (temperatury, wilgotności, itp). Nasza bardzo prosta funkcja może więc mieć następującą strukturę:

function MTCPReadAnalogInput($H,$Ch,$R1,$R2)
{
$fp=@fsockopen($H,502,$errno,$errstr,1);
$value="ERR";
if ($fp)
     {
     $Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(4).chr(0).chr($Ch).chr(0).chr(1);
     fwrite($fp,$Query,strlen($Query));
     set_socket_blocking($fp,true);
     stream_set_timeout($fp,0,20000);
     $Answer=fread($fp,255);
     fclose($fp);
     if (strlen($Answer)==11) $value=sprintf("%.3f",(ord($Answer[9])*256+ord($Answer[10]))/65535*($R2-$R1)+$R1);
     }
return $value;
}

gdzie:

$H to adres IP naszego modułu pomiarowego ADAM-6017,
$Ch to numer kanału pomiarowego (0÷7),
$R1 to dolna wartość zakresu pomiarowego (np. -10V),
$R2 to górna wartość zakresu pomiarowego (np. +10V),
• w przypadku wystąpienia błędu (brak połączenia, brak lub błędna odpowiedź) zwracana jest wartość "ERR".

      Nasz hipotetyczny monitoring szafy serwerowej rozszerzyć możemy także o sygnały dyskretne pozwalające np. na detekcję i rejestrację sygnału otwarcia szafy, sprawdzenie stanu czujnika przeciwpożarowego itp. W tym celu wykorzystać możemy np. moduł ADAM-6060 wyposażony w 6 wejść cyfrowych i 6 wyjść przekaźnikowych. Do odczytu stanu poszczególnych wejść skorzystamy z funkcji 0x01 - Read Coils. Struktura naszej funkcji będzie bardzo zbliżona. Za jej pomocą będziemy mogli odczytać stan wejść 0÷5. Stan danego wejścia cyfrowego reprezentowany będzie przez odpowiedni bit w ostatnim bajcie otrzymanej 10-o bajtowej odpowiedzi z modułu, który ostatecznie będzie naszym wynikiem:

function MTCPReadDiscreteInput($H,$Ch)
{
$fp=@fsockopen($H,502,$errno,$errstr,1);
$value="ERR";
if ($fp)
     {
     $Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(1).chr(0).chr(0).chr(0).chr(6);
     fwrite($fp,$Query,strlen($Query));
     set_socket_blocking($fp,true);
     stream_set_timeout($fp,0,20000);
     $Answer=fread($fp,255);
     fclose($fp);
     if (strlen($Answer)==10) $value=(ord($Answer[9])&(1<<$Ch))>>$Ch;
     }
return $value;
}

gdzie:

$H to adres IP naszego modułu pomiarowego ADAM-6060,
$Ch to numer kanału wejściowego (0÷5),
• zwracana jest wartość 0 lub 1,
• w przypadku wystąpienia błędu (brak połączenia, brak lub błędna odpowiedź) zwracana jest wartość "ERR".

      W przypadku zaproponowanego modułu ADAM-6060 wykorzystać możemy także jego wyjścia cyfrowe. Pozwolą nam np. na załączenie wentylatora - w przypadku przekroczenia temperatury granicznej, lub np. na załączenie jakiegoś urządzenia alarmowego w przypadku wykrycia aktywnego sygnału z czujki przeciwpożarowej. W tym celu skorzystamy z funkcji 0x05 - Write Single Coil. Parametrami naszej funkcji będą: po raz kolejny - numer kanału (0÷5; co tutaj odpowiada rejestrom 00017÷00022), oraz dodatkowo zapisywany stan dla danego wyjścia (0 lub 1):

function MTCPWriteDiscreteOutput($H,$Ch,$S)
{
$fp=@fsockopen($H,502,$errno,$errstr,1);
$value="ERR";
if ($fp)
     {
     $Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(5).chr(0).chr(16+$Ch).chr($S*255).chr(0);
     fwrite($fp,$Query,strlen($Query));
     set_socket_blocking($fp,true);
     stream_set_timeout($fp,0,20000);
     $Answer=fread($fp,255);
     fclose($fp);
     if ((strlen($Answer)==12)&&(ord($Answer[10])==($S*255))) $value="OK";
     }
return $value;
}

      Przedstawione powyżej bardzo proste funkcje (w miarę możliwości i czasu do ewentualnego dopracowania; szczególnie jeśli chodzi o bardziej wnikliwą kontrolę prawidłowości otrzymywanych danych) mogą stanowić szkielet naszego prostego skryptu wykonywanego cyklicznie (np. z wykorzystaniem cron'a) przez serwer, służącego do monitorowania serwerowni. Dodatkowo:

  • W przypadku szybkozmiennych sygnałów cyfrowych i przy wykonywaniu skryptu z jakąś ściśle określoną, ale niestety ograniczoną częstotliwością musimy się liczyć z tym, że nie każdą chwilową zmianę sygnału wychwycimy. W takim przypadku skorzystać możemy np. z trybu "Low to high latch" lub "High to low latch", lub nawet z trybu licznikowego (Counter). Wymaga to odpowiedniej konfiguracji modułu oraz oczywiście dopisania nowych funkcji korzystających z odpowiednich rejestrów (odczyt zawartości licznika, kasowanie statusu latch) przypisanych do tych trybów pracy. Będzie to na pewno konieczne rozwiązanie przy monitorowaniu czujnika otwarcia szafy.

  • Dzięki zastosowaniu konwerterów serii EKI-122X ("Modbus TCP/RTU Data Gateways") zamiast modułów serii ADAM-6000 wykorzystać możemy także moduły serii ADAM-4000, wyposażone w obsługę protokołu Modbus/RTU.

  • No i oczwiście nie musimy ograniczać się tylko do naszego hipotetycznego monitoringu serwerowni. Korzystając z modułów ADAM i modułu PHP zintergowanego z serwerem www możemy pokusić się o zbudowanie całkowicie we własnym zakresie układu "małej automatyki" z dostępem za pośrednictwem przeglądarki internetowej...