Domofon analogowy 4+n w inteligentnym domu

Opisywałem niedawno popularny, analogowy system domofonowy 4+n. Pora zająć się jego integracją z systemem automatyki domowej. Stworzymy urządzenie (bramkę IP – system 4+n), które będzie pozwalało odczytywać stan wybranych parametrów systemu, jak i wykonywać pewne działania. Ze względu na bezpieczeństwo i fakt, że bramofony zamocowane są do metalowego płotu, zastosujemy pełną izolację elektryczną między systemem domofonowym a elektroniką i siecią ethernet.

Bramka domofon - inteligentny dom

Domofon jest już zainstalowany i sprawdzony w działaniu. Na początku przypomnę jego konfigurację, bo będzie ona miała wpływ na budowę urządzenia. Ponieważ jednak system w moim przypadku jest dość złożony, więc urządzenie będzie w miarę uniwersalne. Będzie można je zastosować do do systemu o podobnej złożoności lub prostszego.

Instalacja, w której uruchomiłem pierwsze urządzenie składa się z 4 unifonów i 2 bramofonów. Bramofony posiadają jeden przycisk wywołania, po którego wciśnięciu dzwonią wszystkie unifony. Poza tym na system składa się zasilacz (zwany centralką) EWD 10 firmy Elfon i przekaźnik domofonowy P1E firmy Miwi-Urmet. O częściach składowych systemu można było już przeczytać na blogu.

Oczekiwania

Pora zastanowić się, czego oczekujemy po integracji systemu domofonowego z automatyką domową. Będziemy realizować kilka funkcji:
1. Wykrywać fakt wciśnięcia przycisku w bramofonie (wraz z określeniem, przy którym stoi gość, aby móc wysłać powiadomienie ze zdjęciem z właściwej kamery)
2. Wykrywać otwarcie rygla przyciskiem przy unifonie
3. Wykrywać wciśnięcie dodatkowego przycisku na unifonie (w celu otwarcia bramy przez system automatyki)
4. Umożliwiać otwarcie furtki przez system automatyki domowej
5. Umożliwiać wywołanie sygnału dzwonienia w unifonach
Dodatkowym założeniem jest, że domofon ma działać poprawnie i realizować podstawowe funkcje przy awarii systemu automatyki. To ogólne założenie, dotyczy nie tylko integracji z systemem domofonowym.

System 4+n

W pierwszej kolejności trzeba zrozumieć jak działa system 4+n. Przyjmiemy pewne uproszczenia i skupimy się na przypadku bez interkomu, który jednak niewiele zmienia w tych rozważaniach. 4+n opiera się na, podłączonych równolegle do urządzeń, liniach sygnałowych i linii masy. Linia głośnika i linia mikrofonu przenosi dźwięk. Zwarcie do masy linii zaczepu (np. przez wciśnięcie przycisku w unifonie) powoduje otwarcie elektrozaczepu przez zasilacz (podanie napięcia, zwykle 12V AC, na odpowiednie zaciski). Wraz z masą mamy już 4 linie, dojdzie nam jeszcze „n” linii wywołań (dzwonienia), a ich liczba zależy od (upraszczając) liczby przycisków na bramofonie, czyli niezależnie wywoływanych unifonów. W naszym przypadku są 4 unifony, ale wszystkie podłączone są pod jedną linię, więc dzwonią w tym samym czasie. Dochodzi natomiast linia dodatkowego przycisku, której zwarcie do masy będzie dawało automatyce sygnał do otwarcia bramy.

Przy okazji warto wiedzieć, że istnieje modyfikacja systemu 4+n, nazywana 3+n, pozwalająca zaoszczędzić jedną żyłę. W tym wypadku sygnałem do otwarcia rygla jest zwarcie do masy linii głośnika lub mikrofonu.

Koncepcja realizacji

Urządzenie zostanie oparte o Arduino Pro Mini. Użyte zostaną optoizolatory PC817, zarówno do badania sygnałów po stronie domofonu (z użyciem podzielników napięcia), jak i sterowania od strony Arduino. Jak zrealizujemy założone funkcje? Po kolei.

Aby wykrywać fakt wciśnięcia przycisku na bramofonie (czyli dzwonienia dzwonków w unifonach) trzeba wykryć pojawiające się napięcie na linii wywołania (na powrocie z bramofonu) lub spadek napięcia na generatorze wywołania. Początkowo ten pierwszy pomysł wydawał się bardziej naturalny i testy na sucho wypadły pozytywnie. Natomiast pierwszy test po zainstalowaniu realnego systemu okazało się, że przy zainstalowanych opornikach, napięcie na wejściu analogowym Arduino wzrasta w stopniu na tyle niewielkim, że zachodziło ryzyko błędów. Linia jest zwierana z masą przez głośniki unifonów, które z natury mają dość małą rezystancję. Można było albo przerobić schemat i podpiąć się do generatora wywołania, natomiast ja zmieniłem rezystory.

Mamy więc informację, że przycisk dzwonka został naciśnięty, ale nie wiadomo, na którym bramofonie. W układzie jest natomiast przekaźnik, który posiada kilka niewykorzystanych styków. Przekaźnik działa tak, że przełącza styk wejściowy (np. 30) między dwa wyjściowe (np. 31 i 32), zależnie od tego, z którego bramofonu przyszedł sygnał dzwonienia. Aby sprawdzić stan przekaźnika można więc sprawdzać czy przez przekaźnik popłynie prąd, gdy podłączymy na wejściu napięcie a na wyjściu masę. Oczywiście przez rezystor, bo nie można zrobić zwarcia. A jak sprawdzić czy płynie prąd? Gdybyśmy podłączyli w szereg diodę, to świeciłaby, gdy w układzie popłynie prąd. Zamiast diody można podłączyć optoizolatora, aby mieć informację po stronie Arduino.

Aby wykryć otwarcie rygla należy monitorować linię elektrozaczepu. Należy wykryć kiedy zostanie zwarta do masy przez wciśnięcie przycisku na którymś z unifonów. Pojawi się wtedy spadek napięcia na linii.

Linię dodatkowego przycisku obsługuje się tak samo jak badanie przekaźnika. Badamy przepływ prądu, bo przycisk zwiera ją do masy.

Rygiel otwierany jest po zwarciu linii elektrozaczepu z masą przez przycisk w unifonie. Możemy to zrobić też niezależnie od unifonu używając tranzystora, sterowanego oczywiście przez optoizolator.

Bardzo podobnie będziemy wywoływać dzwonienie – powodując przepływ prądu między sygnałem generatora a linią wywołania. Do tego też użyjemy tranzystora i optoizolatora.

Dodatek – sterowanie na 433MHz

Dodatkowo do urządzenia zostanie dodany nadajnik i odbiornik sygnałów 433MHz, analogicznie jak w opisywanym już urządzeniu do radiowego sterowania urządzeniami. Zostają nam wolne wejścia, a przy okazji będziemy w stanie obsłużyć bezprzewodowe przyciski (np. dodatkowy przycisk do otwierania furtki) czy urządzenia (oświetlenie, sterowanie bramą czy roletami). Zawsze można nie wlutować tych dwóch niewielkich elementów i ich nie używać.

Projekt elektroniki

Jak już pisałem, sercem urządzenia będzie Arduino Pro Mini. Zasilimy je przez stabilizator napięcia 7805. Za komunikację ze światem będzie odpowiadał moduł ethernet oparty o układ Wiz5100. Do odczytu stanów z optoizolatorów użyjemy wejść analogowych. Do sterowania dzwonieniem i ryglem potrzebne będą dwa wyjścia cyfrowe. Dla układów na 433MHz potrzebujemy wejścia i wyjścia cyfrowego.

Z systemem domofonowym połączymy się w 7 miejscach. Będzie potrzebne połączenie: zasilania i masy, sygnału generatora, linii zaczepu, wywołania, wyjścia na linię dodatkowego przycisku i przekaźnika.

Ostatecznie projekt przekłada się na poniższy schemat.

Bramka do domofonu 4+n - schemat

Płytka PCB

Projektując płytkę należało oddzielić dwie części, między którymi jest izolacja optyczna – domofonową i bliższą Arduino. Optoizolatory zostaną umieszczone na podstawkach, żeby łatwo było je w razie przepięcia po stronie domofonu wymienić. Warto rozdzielić optoizolatory służące do sterowania i odczytu stanu. Są to te same układy, ale zainstalowane odwrotnie. Arduino także będzie odłączane od płytki, dla łatwego programowania, co zapewni także łatwą i szybką podmianę zaprogramowanego układu. Płytka została zaprojektowana jako dwustronna, jednak nieliczne połączenia z jednej ze stron zostaną wykonane przewodami.

Projekt PCB - integracja z domofonem 4+n

Po wykonaniu płytek można przystąpić do lutowania.

Płytka PCB - integracja z 4+n

Obudowa

Kolejnym krokiem jest projekt obudowy. Powinno być w niej miejsce na zaprojektowaną płytkę drukowaną i na moduł ethernetowy. Będą one połączone przewodami z użyciem tzw. złącz goldpin. Trzeba też przewidzieć otwory na wyprowadzenie dwóch przewodów (3 i 4 żyły) wychodzących do domofonu. Obudowę tradycyjnie projektujemy w programie OpenSCAD, który generuje także pliki STL, będące podstawą dla programu przygotowującego wydruk 3D.

OpenSCAD - projekt obudowy

Pozostaje tylko przygotować wydruk, np. używając programu Repetier Host. Dostarczy on plików gcode dla drukarki 3d. Obudowa w tym wypadku powstanie z filamentu PET-G produkcji Devil Design.

Repetier Host - przygotowanie do druku

Płytki pasują dość ściśle do obudowy, a zostaną dodatkowo dociśnięte po przykręceniu jej górnej części.

Oprogramowanie

Gdy mamy już część sprzętową gotową, można zabrać się za programowanie. Bazą będzie program przygotowany dla bramki IP-433MHz. Komunikuje się on ze światem przez pakiety UDP. Do sterowania urządzeniami bezprzewodowymi użyjemny dokładnie takiego samego protokołu. Natomiast dla komunikacji z częścią odpowiedzialną za domofon dostosujemy wcześniej używany protokół komunikacyjny oparty o http, przepisując go tak, żeby wykorzystywał pakiety UDP. Zawartość nie zmieni się, natomiast zamiast łączyć się przez TCP i wysyłać polecania w zapytaniu, będziemy je przesyłać wewnątrz pakietu UDP. Urządzenie jako wynik będzie także odsyłać pakiet UDP, umieszczając w nim zawartość zapytania i odpowiedzi.

#include <RCSwitch.h>
#include <SPI.h>      
#include <Ethernet.h>
#include <EthernetUdp.h>
#define UDP_TX_PACKET_MAX_SIZE 60

RCSwitch mySwitch = RCSwitch();

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0x17, 0x51
};

IPAddress ip(192, 168, 1, 200);
IPAddress master(192,168,1,1);

byte gateway[] = { 192, 168, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };
byte mydns[] = { 8,8,8,8 };

#define ID 'd' // identyfikator urządzenia
#define INPUTDEBOUNCETIME 70

// port na którym słuchamy i na który nadajemy
unsigned int localPort = 8000;
unsigned int remPort = 8000;

// numeracja wyjść cyfrowych i wejść analogowych
#define OTWORZ 0
#define ZADZWON 1
#define ETHRESET 2
#define DZWONEK 0
#define RYGIEL 1
#define PRZYCISK 2
#define BRAMOFON 3

// tablica (domyślnych) stanów wyjść
int output[]={LOW, LOW, HIGH};
int output_pins[]={7,8,9};
unsigned long output_next_change_time[]={0,0,0};
int output_next_change_state[]={LOW, LOW, HIGH};
#define OUTPUT_SIZE 3

// na jak długo ma się zmienić stan (0 - bez limitu)
unsigned long change_time=0;

// tablica wejść analogowych
int analog_state[]={0,0,0,0};
int analog_pins[]={A3, A2, A1, A0};
unsigned long analog_lastchange[]={0,0,0,0};
int analog_level[]={3,300,300,300};
#define ANALOG_SIZE 4 // liczba elementów w tablicy

unsigned long time;

// bufory i zmienne globalne
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
String str;
char cstr[UDP_TX_PACKET_MAX_SIZE];

// do obsługi pakietów UDP
EthernetUDP Udp;

void setup() {
  int w=0; // licznik

  // obsługa modułów radiowych 433MHZ
  mySwitch.enableReceive(0);  // interrupt 0 - pin 2
  mySwitch.enableTransmit(3); // pin 3

  // konfigurujemy wyjścia i ustalamy stany
  for(w=0; w<OUTPUT_SIZE; w++ )
  {
    pinMode(output_pins[w], OUTPUT);
    digitalWrite(output_pins[w], output[w]);
  }

  delay(500);
  
  Ethernet.begin(mac, ip, mydns, gateway, subnet);
  Udp.begin(localPort);

  delay(100);

  sendMessage('r', String(ID) ); // powiadom serwer o restarcie/włączeniu
}

// wysłanie pakietu UDP pod zadany adres (id urządzenia, komenta, paramety)
boolean sendMessageTo(char cmd, String param, IPAddress dest)
{
    int psize=UDP_TX_PACKET_MAX_SIZE;
    Udp.beginPacket(dest, remPort); 
    str = String(String(ID)+String(cmd)+param+String("\n"));
    if( psize>str.length() ) psize=str.length();
    for(int w=0; w<UDP_TX_PACKET_MAX_SIZE; w++) cstr[w]=0;
    str.toCharArray(cstr,UDP_TX_PACKET_MAX_SIZE);
    Udp.write(cstr, psize);
    Udp.endPacket();
}

// do wysyłania zwrodnych pakietów UDP (przyjmuje string)
boolean sendReturnMessageTo(String txt, IPAddress dest)
{
  int psize=UDP_TX_PACKET_MAX_SIZE;
  Udp.beginPacket(dest, remPort);
  if( psize>txt.length() ) psize=txt.length();    
  for(int w=0; w<UDP_TX_PACKET_MAX_SIZE; w++) cstr[w]=0;
  txt.toCharArray(cstr,UDP_TX_PACKET_MAX_SIZE);
  Udp.write(cstr, psize);
  Udp.endPacket();
}

// wysłanie komunikatu pod domyśly adres
int sendMessage(char cmd, String param)
{
  sendMessageTo(cmd, param, master);
}

// czy timer już nadszedł lub minął (jest mniejszy od time); zakładamy, że czasy nie są dłuższe niż kilka dni i sprawdzamy czy nie miało szansy przekroczenie zakresów
boolean isAfter( unsigned long timer )
{
  if(timer<=time && !(time>3000000000L && timer<1000000000L) ) return(true);
  if(timer>3000000000L && time<1000000000L) return(true);
  return(false);
}

// sprawdza czy nie nadszedł czas zaplanowanego przełączenia stanów
void checkOutputTimes()
{
  int w;
  
  for(w=0; w<OUTPUT_SIZE; w++ )
  {
    if( output_next_change_time[w]!=0 )
    {
      if( isAfter( output_next_change_time[w] ) )
      {
        output_next_change_time[w]=0;
        output[w]=output_next_change_state[w];
        digitalWrite(output_pins[w], output[w]);
      }
    }
  }
}


// tłumaczy analogowy odczyt na stan 0-1
int checkAnalogLevel(int inputnum)
{
  int inp;
  
  inp=0;
  if( analogRead(analog_pins[inputnum])>analog_level[inputnum] ) inp=1;

  return(inp);
}

// sprawdza stany wejść, jeżeli nastąpiła zmiana, to powiadamia
void checkAnalogInputs()
{
  int inp, w, q;
  unsigned long changetime;
  
  for(w=0; w<ANALOG_SIZE; w++ )
  {
    inp=checkAnalogLevel(w);
    
    // ponowne odczyty dla pewności czy to nie chwilowa anomalia
    for( q=0; q<15; q++) if(inp!=analog_state[w]) { inp=checkAnalogLevel(w); }
    
    if(inp!=analog_state[w] && isAfter(analog_lastchange[w]+INPUTDEBOUNCETIME) )
    { 
      //puszczono dzwonek, trzeba wysłać, jak długo był trzymany
      //trzeba też wykryć, z którego bramofonu pochodzi sygnał
      if(w==DZWONEK && inp==0)
      {
        changetime=time-analog_lastchange[w];
        q=checkAnalogLevel(BRAMOFON);
        if( q==1 ) sendMessage('f', String(changetime) );
        if( q==0 ) sendMessage('b', String(changetime) );
      }
      
      //zmieniamy stany i wysyłamy informację
      analog_state[w]=inp; 
      analog_lastchange[w]=time;
      sendMessage('a', String(String(w)+inp) );
    }

  }
}

// parsujemy bufor, rozdzielamy na pojedyncze komendy i uruchamiamy
int parseCmd(char buf[], int psize)
{
  int w;
  boolean cmdBegin=true;
  boolean cmdEnd=false;
  boolean cmdToRun=false;
  String cmd("");
  String retval("");

  for(w=0; w<=psize; w++)
  {
    if( (buf[w]==',' || buf[w]=='\n' || w==psize) && cmdBegin )
    {
      cmdToRun=true;
    }
    if( cmdToRun )
    {
      retval+=runCommand(cmd)+String("\n");  
      cmd="";
      cmdToRun=false;
    }
    else if( cmdBegin && !cmdEnd )
    {
      cmd+=buf[w];
    }
  }

  if( psize<UDP_TX_PACKET_MAX_SIZE )buf[psize]=0;
  sendReturnMessageTo(String(String(buf)+String("\n")+retval+String("\n")), master);
  
}

//uruchamia komenda i zwraca czy się udało
String runCommand(String cmdstring)
{
  int w;
  String ret="";
  char charparam[15];
  
  // nie ma co sprawdzać gdy długość < 3
  if( cmdstring.length()<3 ) return("Error");
  
  // podział na kod urządzenia, komendę i jej parametry
  char dest=cmdstring.charAt(0);
  char cmd=cmdstring.charAt(1);
  String param=cmdstring.substring(2);
  
  // nie do mnie
  if( dest!=ID ) return("Error");
  
  switch(cmd)
  {
    case 'o': // pytanie o stan wyjść
      for(w=0; w<OUTPUT_SIZE; w++ )
        if( output[w]==HIGH ) { ret+="1"; } else ret+="0";
      return(ret);
      break;      

    case 'a': // pytanie o stan wejścia analogowego
      w=param.toInt();
      if( w<0 || w>=ANALOG_SIZE ) return("Error");
      return( String(analogRead(analog_pins[w])) );
      break;
      
    case 'h': // ustawienie stanu wyjścia na wysoki
      w=param.toInt();
      if( w<0 || w>OUTPUT_SIZE ) return("Error");
      output[w]=HIGH;
      if( change_time!=0 )
      {
        output_next_change_time[w]=time+change_time;
        output_next_change_state[w]=LOW;
        if( output_next_change_time[w]==0 ) output_next_change_time[w]++;
        change_time=0;
      }
      digitalWrite(output_pins[w], HIGH);
      return("1");
      break;

    case 'l': // ustawienie stanu wyjścia na niski
      w=param.toInt();
      if( w<0 || w>OUTPUT_SIZE ) return("Error");
      output[w]=LOW;
      if( change_time!=0 )
      {
        output_next_change_time[w]=time+change_time;
        output_next_change_state[w]=HIGH;
        if( output_next_change_time[w]==0 ) output_next_change_time[w]++;
        change_time=0;
      }      
      digitalWrite(output_pins[w], LOW);
      return("0");
      break;

    case 'c': // ustawia czas na jaki ma być zmiana wyjścia
      param.toCharArray(charparam, 14);
      change_time=atol(charparam);
      return( String(change_time) );
      break;
    
    default:
      return("Error");
  }
}

// sprawdza czy przyszło coś przez odbiornik 433MHz
void check433()
{
  if (mySwitch.available()) {
    
    int value = mySwitch.getReceivedValue();
    
    if (value == 0) {
      //nieznane kodowanie/błędny odczyt;
    } else 
    {
       str = String(String(mySwitch.getReceivedProtocol())+"."+mySwitch.getReceivedBitlength()+"."+
       String(mySwitch.getReceivedValue()));
       for(int w=0; w<UDP_TX_PACKET_MAX_SIZE; w++) cstr[w]=0;
       str.toCharArray(cstr,UDP_TX_PACKET_MAX_SIZE);

       // wysyłamy pakiet udp
       Udp.beginPacket(master, remPort);
       Udp.write(cstr, UDP_TX_PACKET_MAX_SIZE);
       Udp.endPacket();
    }
    mySwitch.resetAvailable();
  }
}

void parseUdp433(int packetSize)
{
  int mProtocol;
  int mSize;
  unsigned long mValue;

    //pobieramy wartości z ciągu znaków
    mProtocol=packetBuffer[0]-48;
    mSize=packetBuffer[3]-48+10*(packetBuffer[2]-48);
    mValue=String(packetBuffer).substring(5, packetSize).toInt(); 

    // wyłaczamy odbieranie kodów, żeby nie odczytywać wysłaego przez siebie
    mySwitch.disableReceive();

    // wysyłamy polecenie radiowo
    mySwitch.setProtocol(mProtocol);
    mySwitch.send(mValue, mSize);

    // włączamy odbieranie ponownie
    mySwitch.enableReceive(0);

    // odsyłamy potwierdzenie wysłania
    Udp.beginPacket(master, remPort);
    str = String("P:"+String(mProtocol)+"."+String(mSize)+"."+String(mValue)+"...");
    for(int w=0; w<UDP_TX_PACKET_MAX_SIZE; w++) cstr[w]=0;
    String(str).toCharArray(cstr,UDP_TX_PACKET_MAX_SIZE);
    Udp.write(cstr, UDP_TX_PACKET_MAX_SIZE);
    Udp.endPacket();
}

void loop() {

  time=millis();

  checkOutputTimes(); // sprawdzamy czy nie trzeba czegoś wyłączyć
  checkAnalogInputs(); // sprawdzamy wejścia analogowe
 
  int packetSize = Udp.parsePacket();

  //przyszły jakieś dane przez sieć
  if (packetSize) {
    IPAddress remote = Udp.remoteIP();

    if( remote[0]!=192 ) { 
      //tu można dodać autoryzację po adresie źródłowym
    }
    
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);

    // pierwszy bajt pakietu zgadza się z identyfikatorem urządzenia, więc może to być polecenie
    if( packetBuffer[0]==ID )
    {
      parseCmd(packetBuffer, packetSize);
    }
    // jest to polecenie wysłania sygnału radiowego na 433MHz
    else if( (packetBuffer[0]=='1' || packetBuffer[0]=='2') && packetBuffer[1]=='.' )
    {
      parseUdp433(packetSize);
    }

  }

  // sprawdzenie czy przyszło coś radiowo
  check433();
}

W działaniu

Program jest dość długi, natomiast posiada komentarze i opiera się na prezentowanych już przy wcześniejszych okazjach, więc nie będę go dokładnie omawiał. Napiszę natomiast, jak go obsługiwać w systemie automatyki domowej.

W moim przypadku aktualnie sterownik automatyki oparty na Raspberry Pi lub QNAP HS-251+ wykonuje program serwera napisany w NodeJS. Urządzenie może oczywiście współpracować z inną platformą, która musi tylko mieć możliwość wysyłania i odbierania pakietów UDP.

Aby zadzwonić dzwonkiem unifonów przez pół sekundy, należy wysłać pakiet zawierający dc500,dh1. Komenda dc500 ustawia czas dla następnej zmiany na 500ms, a dh1 ustawia stan wysoki wyjścia numer 1, podłączonego do wywołania.

Analogicznie, żeby otworzyć furtkę, na 500ms zwieramy linię elektrozaczepu z masą, przez ustawienie stanu wysokiego na wyjściu 0 – dc500,dh0.

Otrzymując zaś pakiet df100 lub db120 wiemy, że ktoś nacisnął krótko przycisk w bramofonie przy furtce lub bramie. Zareagujemy na to, zapisując stopklatkę z odpowiedniej kamery i wysyłając link do niej e-mailem. Jeżeli telefon odbiera maile na bieżąco przez IMAP, to powiadomienie o wizycie gościa jest właściwie natychmiastowe.

Gdy zaś pojawi się pakiet da20 (domofon, wejście analogowe 2, stan niski), wiemy, że ktoś nacisnął przycisk otwierania bramy. Wtedy powinniśmy na to zareagować i otworzyć bramę (u mnie wysyłając odpowiedni pakiet do innego urządzenia) i może np. zapalić światła wzdłuż wjazdu gdy jest ciemno. Pakiet da10 oznacza, że wyzwolono otwieranie elektrozaczepu.

Dodatkowo możemy spodziewać się pakietów takich jak przy urządzeniu do sterowania w urządzeniami na 433,92MHz. Gdy otrzymamy pakiet 2.24.1111 oznacza to, że taki pakiet został odebrany (np. ktoś nacisnął przycisk w pilocie). Natomiast odsyłając taki pakiet do urządzenia, możemy go nadać (tak, jakbyśmy nacisnęli przycisk w pilocie). Ten temat jednak był już opisywany przy okazji wpisu o tamtym urządzeniu.

Oczywiście nadal możemy używać poleceń znanych z wcześniejszych urządzeń – np. wysłać pakiet da1, żeby odczytać wartość na pierwszym wejściu analogowym.

Podsumowanie

W wielu domach istnieją instalacje 4+n, bo system nie jest nowy. Warto jednak rozważyć system 4+n także w sytuacji gdy dopiero wybiera się domofon. Ma on wiele zalet, o których pisałem przy okazji wcześniejszego opisu. Oczywiście może się wydawać, że w dobie cyfrowych systemów, analogowy 4+n jest przeżytkiem, natomiast warto postawić na prostotę i niezawodność. Tym bardziej, że integracja 4+n z inteligentnym domem jest dużo prostsza, niż w przypadku wielu zamkniętych systemów cyfrowych.

Projekt obudowy i płytki można znaleźć w serwisie thingiverse.

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: