Karta przekaźnikowa do routera


Jakiś czas temu pisałem, że przygotowuję system do podlewania ogródka w oparciu o router i OpenWRT. Aby zrealizować projekt, potrzebna była możliwość sterowania urządzeniami elektrycznymi, co sprowadza się tak naprawdę do załączania przekaźników. Przy okazji rozważań stwierdziłem także, że dobrze byłoby mieć dodatkowo możliwość badania stanów pewnych czujników. Wybór padł na kartę przekaźnikową z dodatkowymi wejściami. Dzięki elastyczności i dobramu podejściu do klineta użytkownika jack_62, udało się sprawnie zamówić kartę z wejściem USB wyposażoną w osiem przekaźników i taką samą ilość wejść.

Ponieważ podłączanie karty przekaźników do routera nie jest czynnością popularną, więc stwierdziłem, że warto napisać kilka słów o tym. W komplecie z kartą otrzymałem kabel USB. Skoro mamy interfejs USB, to nic nie stoi na przeszkodzie, żeby wpiąć kartę do huba, podłączonego z kolei do routera. W moim przypadku jest to TPlink TL-MR3420, ale testowałem też z Dlinkiem DIR-320, a pracować powinna z każdym routerem wyposażonym w wejścia USB, do którego da się wgrać OpenWRT.

Po podłączeniu i zainstalowaniu w systemie potrzebnych modułów jądra (kmod-usb-serial i kmod-usb-serial-ftdi), wśród urządzeń pojawia się /dev/ttyUSB0:

root@mr3420:~$ ls -l /dev/ttyUSB0
crw-rw-rw-    1 root     root     188,   0 Jun 11 12:10 /dev/ttyUSB0

Dlaczego akurat te moduły? Karta komunikuje się tak naprawdę przez port szeregowy i zawiera wbudowany konwerter portu szeregowego na USB, oparty o chip FT2232 firmy FTDI. To bardzo dobre rozwiązanie, a dodatkowo upraszcza komunikację od strony programistycznej. Nie potrzebujemy żadnych wyszukanych sterowników, a oprogramowanie portu szeregowego w każdym języku powinno być proste.

Skoro mamy płytkę przekaźnikową podłączoną, warto zastanowić się co nam może ona dać. Podstawowym dobrem dostarczamym nam są przekaźniki i możliwość sterowania nimi. Jak to działa? Każdy z przekaźników daje możliwość podłączenia trzech przewodów. Kiedy wszystko jest wyłączone, to między środkowym stykiem a złączem oznaczonym NC jest zwarcie. Jeżeli natomiast przekaźnik jest załączony to zwarcie jest między środkowym stykiem a NO (a znika oczywiście przy NC). Można więc potraktować przekaźnik jak włącznik. Przekaźniki pozwalają na podłączenie napięcia 230V, ale oczywiście w każdej sytuacji należy pamiętać o zachowaniu ostrożności i potencjalnym ryzyku.

Do wejścia z kolei można podłączyć np. włącznik i sprawdzać kiedy jest załączony. Można też skonfigurować kartę tak, żeby włącznik podłączony do wejścia sterował odpowiednim przekaźnikiem, nawet bez udziału routera. Oczywiście włącznik to nie jest najprzydatniejsza rzecz, którą będziemy wykorzystywać, a sterować będziemy raczej programowo. Jednak taka forma komunikacji też się może kiedyś przydać.

Zamiast włącznika można oczywiście podłączyć coś innego, na przykład kontaktron i sprawdzać otwarcie drzwi lub okna. Może to być także pływak alarmujący o przekroczeniu poziomu wody w studzience, kratce lub szambie. Czujnik zalania czy czujki ruchu też wydają się dobrym pomysłem. Może to być oczywiście dowolne urządzenie, które na przykład potrafi zewrzeć styki (czyli pewnie posiada przekaźnik) w wyniku jakiegoś zdarzenia. Ja w oparciu o tani czujnik zalania planuję sprawdzać czy pada deszcz, co będzie przydatne dla systemu podlewania.

Komunikacja z portem szeregowym urządzenia jest prosta. Ja z rozsądku, wygody lub lenistwa, jakkolwiek to nazwać, postanowiłem użyć języka php (pakiet php5-cli). Aby było jeszcze prościej użyłem gotowej biblioteki, pierwszej zaproponowanej przez google, konkretnie php_serial.class.php. Do właściwego działania z moim środowiskiem wymagała co prawda poprawienia dwóch linijek w kodzie, ale wszystko dało się znaleźć na forum projektu.

Pierwszą rzeczą konieczną do połączenia było ustawienie parametrów portu zgodnie z dokumentacją karty. To tylko kilka linijek:

$serial = new phpSerial;
$serial->deviceClose("/dev/ttyUSB0");
$serial->deviceSet("/dev/ttyUSB0");
$serial->confBaudRate(57600);
$serial->confParity(none); //Set the Parity
$serial->confCharacterLength(8);//Set the word length
$serial->confStopBits(1); //Set Stop Bit
$serial->confFlowControl(none);

Do tej operacji biblioteka potrzebuje programu stty, który także trzeba było zainstalować (pakiet coreutils-stty). Teraz można już dowolnie otwierać port, wysyłać polecenia i odbierać informacje od karty. Na początek otworzymy port, załączymy czwarty przekaźnik, poczekamy 10 sekund, wyłączymy go i zamkniemy port:

$serial->deviceOpen("a+b");
$cmd=chr(0x01)."O".chr(0x03);
$serial->sendMessage( chr(0x55).$cmd.chr(crcmaxim(sbin2ar($cmd))).chr(0xa0) );
sleep(10);
$cmd=chr(0x01)."F".chr(0x03);
$serial->sendMessage( chr(0x55).$cmd.chr(crcmaxim(sbin2ar($cmd))).chr(0xa0) );
$serial->deviceClose();

Co konkretnie zrobiliśmy? Wysłaliśmy do urządzenia ciąg 0x55 0x01, rozpoczynający każdą komunikację (oczywiście zgodnie z dokumentacją protokołu używanego przez kartę przekaźników), następnie znak O, będący poleceniem załączenia przekaźnika (analogicznie F nakazuje wyłączenie). Po polecaniu przychodzi parametr 0x03 wskazujący, że chodzi nam o czwarty przekaźnik (są numerowane od 0). Na koniec wysyłamy kod kontrolny. Jaki? Jak mówi instrukcja: „Suma kontrolna obliczana jest na podstawie funkcji zgodnej z przyjętej przez firmę Dallas-maxim”. Skąd wziąć funkcję wyliczającą CRC wg algorytmu stosowanego przez tę firmę? Ja znalazłem kod w C i go przepisałem na php. Mam nadzieję, że nikt się na mnie nie obrazi, jak zamieszczę swoją wersję.

function crcmaxim(array $ar)
{
  $numBytes=sizeof($ar);
  $byteIndex=0;
  $bitCount=0;
  $CRC=0;
  for($byteIndex=0;$byteIndex<$numBytes; $byteIndex++ )
  {
    $nextByte=$ar[$byteIndex];
    for($bitCount=0;$bitCount<8;$bitCount++)                    
    {                                                           
      $b=($CRC ^ $nextByte)&1;                                  
      $CRC>>=1;
      if($b)
      {
        $CRC^=0x8c;
      }
      $nextByte>>=1;
    }
  }
  return $CRC;
}

Funkcja sbin2ar przekształca natomiast string w tablicę bitów.

function sbin2ar($sbin)
{
  $ar=array();
  $ll=strlen($sbin);
  for ($i=0; $i<$ll; $i++) $ar[]=ord(substr($sbin,$i,1));
  return $ar;
}

To już wszystko co potrzebne, aby karta przekaźnikowa na USB stała się całkowicie posłuszna naszym poleceniom. Nic też nie stoi na przeszkodzie, żeby wysłać polecenie, które sprawdzi stan przekaźników lub wejść. Wszystko szczegółowo i przejrzyście opisuje dokumentacja, która dołączona jest do produktu. Co więcej nawet gdy nie będziemy pytać o stan wejść, to w przypadku, gdy któryś ulegnie zmianie, karta sama wyśle odpowiedni ciąg znaków do routera.

Podsumowując – karta jest w 100% tym czego szukałem i świetnie spełnia swoje funkcje. W tej chwili działa u mnie, oparty o nią, system do podlewania ogródka. Do tej pory nie miałem najmniejszych problemów ze stabilnością działania.

Ten wpis został opublikowany w kategorii Majsterkowanie i oznaczony tagami , , . Dodaj zakładkę do bezpośredniego odnośnika.

0 odpowiedzi na Karta przekaźnikowa do routera

  1. Dudzio pisze:

    Witam.
    Chciałem pogratulować super pomysłów i świetnego bloga. Również chcę u siebie wdrożyć coś w stylu ineligentnego sterowania piecem i takie tam i zastanawiam się nad zakupem karty przekaźnikowej.

    Którą kartę według Pana lepiej kupić tą z wejściami czy bez?

    Co można podpiąć do tych wejść?

    Można odczytywać z poziomu routera stany wartości tych wejść?

    Zastanawiam się czy można podpiąć do nich czujkę temperatury, czy lepiej odczyt temp zrealizować na czymś innym?(Konwerter USB/1-Wire albo Andruino)

    Z niecierpliwością czekam na dalszy rozwój projektu 🙂

    Pozdrawiam.

    • techniczny pisze:

      Do wejścia podpiąć można wiele rzeczy, które zwracają stan 0/1 – czyli np. kontaktrony, czujniki zalania, itp. (ważne, żeby czujnik miał wyjście przekaźnikowe lub open collector). Wybór karty moim zdaniem powinien zależeć od potrzeb.

      • Gilu pisze:

        Kod, który wkleileś wydaje sie fragmentami przycięty, mógłbym prosić o kompletne przykłady kodu PHP które używałeś u siebie?

  2. Dudzio pisze:

    Czyli żadnego czujnika temp nie podepnę 🙁 szkoda.

    Ale chyba zdecyduję się na ten z wejściami bo można zawsze coś pomodzić,

  3. Witam. Czy ta karta przekaźnikowa obsługuje napięcia od 3-12V?

  4. equinoxe pisze:

    Witam. Mam pytanie odnośnie tych dwóch poprawionych linijek w bibliotece php_serial.class.php. Które to linijki? Mam identyczną kartę przekaźników i router z OpenWRT. Zrobiłem wszystko według wskazówek i jedyne co udało mi się osiągnąć to zaświecanie czerwonej diody informującej o komunikacji (RxTx). Przekaźniki nie włączają się. Co może być problemem?
    Pozdrawiam

    • techniczny pisze:

      Przejrzałem kod biblioteki i widzę zmianę w funkcji confFlowControl. Konkretnie w przypisaniu $linuxModes = array(
      zmieniłem
      „none” => „clocal -crtscts -ixon -ixoff”,
      na
      „none” => „clocal -crtscts -ixon -ixoff raw”,
      Nie wiem czy nie było czegoś jeszcze, ale chyba nie…

  5. Dudzio pisze:

    Próbowałeś może sterować tą kartą przekaźnikową z poziomu telefonu z androidem?

    Ostatnio pojawiła się taka aplikacja na stronie allegro sprzedającego ją.

    Jak byś mógł to bardzo bym prosił o sprawdzenie jak to działa.

    Z góry dzięki.

  6. konopka pisze:

    Witam.Proszę o pomoc,bo z linuxa jestem zielony.Otóż wgrałem do Asua WL500gp v2 openwrt,zrobiłem update i konfigurację pod moduł 1-wire,jest widoczny przez putty.Chciałbym jeszcze podłączyć moduł przekażnikowy /taki jw/ i nie mogę ruszyć z miejsca.Poza tym chcę mieć podgląd temperatur i sterowanie przekażnikami z poziomu windowsa.Bardzo proszę o pomoc!

  7. kamillo pisze:

    Witam
    Funkcja do liczenia CRC jest nieco przycięta. Brakuje w niej jednego z argumentów dla for:
    for($bitCount=0;$bitCount>=1;
    Bardzo prosiłbym o podanie co powinno się tam znaleźć bo niestety nie moge ruszyć z miejsca z tego powodu….

  8. pimowo pisze:

    W jaki sposób to odczytywać w PHP?

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *