Arduino – wszystko o  sterowaniu przez podczerwień IR

Arduino – wszystko o sterowaniu przez podczerwień IR

INFORMACJA: Poniższy post nie wydostał się z Poczekalni :(

Witam!  To jest mój pierwszy artykuł. Chciałbym przedstawić jak wprowadzać dane do Arduino przez zwykły pilot od telewizora.

Nazwy elementów są jednocześnie linkami do  artykułów w sklepie Botland.

Wstęp

Porównanie komunikacji przez podczerwień, radiowej i przez moduły XBee

Lp. Komunikacja przez podczerwień Komunikacja radiowa Xbee
Cena (Nadajnik + odbiornik/moduł) Od 5zł do 20zł Od 10zł do 50zł Od 50zł do 250zł
Polecane produkty TSOP31236 (odbiornik), IR LIRED3B 3mm 940nm (nadajnik) HC-12 433MHz

 

Zależne od potrzeby i budżetu
Zasięg (metry) 5-20 100-1000 100-1500
Szybkość transmisji Mała Średnia Bardzo duża
Zalecane miejsce użycia Mieszkania, biura Teren otwarty, duże hale, rzadziej małe pomieszczenia Raczej mieszkania, biura
Co wywołuje zakłócenia Światło słoneczne Inne moduły radiowe w tym Wi-Fi
Przeznaczenie Raczej zdalne sterowanie, rzadko komunikacja Komunikacja i zdalnie sterowanie Raczej komunikacja, rzadko zdalne sterowanie

Komunikacja przez podczerwień

Płytka Arduino np. Uno, MegaCo będzie nam potrzebne:

Biblioteka

Najpierw konieczne będzie pobranie biblioteki z strony:http://www.dfrobot.com/image/data/DFR0107/IRremote.zip. Plik rozpakowujemy do folderu Libraries. Po włączeniu Arduino Ide w Szkic/Importuj bibliotekę… na dole listy powinna pojawić się biblioteka “IRremoute”. Jeżeli nie ma jej musimy ją ręcznie dodać: Szkic/Importuj bibliotekę…/Dodaj bibliotekę… znajdujemy folder “Rremoute” i klikamy Open.

Sterowanie Arduino przez pilot od telewizora

Schemat

Podłączmy według schematu:

Schemat

Jeżeli posiadamy moduł należy go podłączyć: czerwony – 5V, czarny – GND, zielony – pin cyfrowy nr 2. Numer pinu cyfrowego można zmienić, ale trzeba to uwzględnić w kodzie.

Przypisywanie przycisków na pilocie do numerów

Zgrywamy kod na płytkę Arduino:

#define receiverpin = 2;       // pin Arduino, do którego został podłączony odbiornik IR
#include <IRremote.h>       // biblioteka
IRrecv irrecv(receiverpin); 
decode_results results;

void setup()
{
Serial.begin(9600);
   irrecv.enableIRIn(); // uruchamia odbiornik podczerwieni
}

void loop()
{
if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygnał IR
   {
Serial.print(results.value);
      Serial.println(" ");
irrecv.resume(); // odbiera następną wartość
      delay(100);
}
]

Włączmy monitor portu szeregowego. Wciskamy po kolei potrzebne do naszej komunikacji przyciski i zapisujemy liczbę, która wyświetli nam się w monitorze portu szeregowego. Przykład:

Monitor portu szeregowego 1

4105841032 – POWER

3261853764 – PRZYCISK  DO GÓRY

3305092678 – PRZYCISK W DÓŁ

1400905448 – PRZYCISK W PRAWO

1972149634 – PRZYCISK W LEWO

Funkcje i program

Wykorzystując te dane możemy teraz napisać przykładową funkcję:

int irRemoute ()
{
 int dane;
if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygna� IR
  {

   unsigned long odczyt = results.value; // sygnał zapisuje jako odczyt
switch (odczyt)
   {
case 4105841032: //power
    dane = 11;
break;
    case 2331063592: //eneter
dane = 12;
    break;
case 3261853764: // góra
    dane = 13;
break;
    case 3305092678: // dół
dane = 14;
    break;
case 1400905448: // prawo
    dane = 15;
break;
    case 1972149634: // lewo
dane = 16;
    break; 
case 3778927144: // 1
    dane = 1;
break;
    case 2908251746: // 2
dane = 2;
    break;
case 657459652: // 3
    dane = 3;
break;
    case 4120482440: // 4 
dane = 4;
    break;
   case 1931099650: // 5
    dane = 5;
break;
    case 742730860: // 6
dane = 6;
    break;
case 1167253836: // 7
    dane = 7;
break;
    case 1747313982: // 8
dane = 8;
    break;
case 2340753640: // 9
    dane = 9;
break;
    case 3119867746: // 0
dane = 10;
    break;
default:
    dane=0;
}
  }
else
  {
dane=0;
  }
irrecv.resume(); // resetuje czujnik
return dane ;
}.

W miejsca liczb należy wpisać własne używając danych z poprzedniego programu. Zbędne wiersze trzeba usunąć, pamiętając że po każdej liczbie jest dwukropek. Dodatkowo na końcu pętli switch-case znajduje się: default: dane=0; oraz cała pętla switch-case zamknięta jest klamrą. Dotyczy to wszystkich programów i funkcji, które są zaprezentowane w tym artykule.

 

Pętla sprawdza odczyt, a następnie porównuje go z różnymi wartościami i przypisuje mu odpowiednią wartość zmiennej “dane”, która zostaje zwrócona przez funkcję. Funkcja ta nie blokuje programu, ale jeżeli chcemy być obsypani ogromną ilością danych możemy wprowadzić drobną modyfikację:

byte irRemoute ()
{
byte dane=0;
  while(dane==0)
{
   if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygna� IR
{
       unsigned long odczyt = results.value; // sygnał zapisuje jako odczyt
switch (odczyt)
       {
case 4105841032: //power
         dane = 11;
break;
         case 2331063592: //eneter
dane = 12;
         break;
case 3261853764: // góra
         dane = 13;
break;
         case 3305092678: // dół
dane = 14;
         break;
case 1400905448: // prawo
         dane = 15;
break;
         case 1972149634: // lewo
dane = 16;
         break;   
case 3778927144: // 1
         dane = 1;
break;
         case 2908251746: // 2
dane = 2;
         break;
case 657459652: // 3
         dane = 3;
break;
         case 4120482440: // 4 
dane = 4;
         break;
case 1931099650: // 5
         dane = 5;
break;
         case 742730860: // 6
dane = 6;
         break;
case 1167253836: // 7
         dane = 7;
break;
         case 1747313982: // 8
dane = 8;
         break;
case 2340753640: // 9
         dane = 9;
break;
         case 3119867746: // 0
dane = 10;
         break;
default:
         dane=0;
}
      irrecv.resume(); // reseruje czujnik  
}
   else 
{
    dane=0;
}
  }
return dane ;
}

W powyższym kodzie nie tylko zmieniłem typ zmiennej z int na byte, aby zajmowała mniej miejsca. W większych programach może to być konieczne. Ponadto liczba zapisana w zmiennej byte jest o wiele łatwiejsza do przesłania np. do innego Arduino niż int. W powyższej funkcji dodałem też pętlę while, która powtarza się dopóki, dopóty czujnik nie odbierze wartości, z której  korzystamy. Ta funkcja może być wykonywana czasem bardzo długo, więc Arduino nie może odbierać w tym czasie danych z innych źródeł, co może być uciążliwe w zaawansowanych projektach. W takich przypadkach lepiej jest zastosować pierwszą funkcję i polecenie if w pętli głównej:

void loop()
{

byte check = irRemoute();
 if (check != 0)
{
  // Tutaj podajemy co ma wykonać dalej z zmienną check jeżeli nie jest ona zerem   
}

}

Jednak w większości projektów nie będziemy korzystać z tak wielu danych. Czasami będziemy chcieli się zatrzymać i poczekać na dane z czujnika podczerwieni, a czasami będziemy chcieli korzystać wyłącznie ze sterowania przez IR. Wtedy polecenie if nie będzie miało sensu. A oto przykładowy program:

#include <IRremote.h>       // biblioteka
IRrecv irrecv(2); //numer pinu 
decode_results results;

void setup()
{
Serial.begin(9600);
   irrecv.enableIRIn(); // uruchamia odbiornik podczerwieni
}

void loop()
{
Serial.println(irRemoute());
 delay(100);
}


byte irRemoute ()
{
  byte dane=0;
while(dane==0)
  {
if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygna� IR
    {
unsigned long odczyt = results.value; // sygnał zapisuje jako odczyt
       switch (odczyt)
{
         case 4105841032: //power
dane = 11;
         break;
case 2331063592: //eneter
         dane = 12;
break;
         case 3261853764: // góra
dane = 13;
         break;
case 3305092678: // dół
         dane = 14;
break;
         case 1400905448: // prawo
dane = 15;
         break;
case 1972149634: // lewo
         dane = 16;   
break;
         case 3778927144: // 1
dane = 1;
         break;
case 2908251746: // 2
         dane = 2;
break;
         case 657459652: // 3 
dane = 3;
         break;
case 4120482440: // 4
         dane = 4;
break;
         case 1931099650: // 5
dane = 5;
         break;
case 742730860: // 6
         dane = 6;
break;
         case 1167253836: // 7
dane = 7;
         break;
case 1747313982: // 8
         dane = 8;
break;
         case 2340753640: // 9
dane = 9;
         break;
case 3119867746: // 0
         dane = 10;
break;
         default:
dane=0;
       }
irrecv.resume(); // reseruje czujnik
    }
else
    {
dane=0;
    }
}
return dane ;
}

Otwieramy monitor portu szeregowego i wciskamy po kolei przyciski na pilocie. Oto efekt:

Bez tytułu4

Sterowanie światłami – mały SmartHome

Jeżeli chcemy sterować przykładowo światłami w domu, trzeba z powrotem zamienić dane na konkretny sygnał. Przykładowy schemat (układy z przekaźnikami zastąpiłem  LED-ami):Bez tytułu15

Wiem, że takie diody najlepiej podłączyć do tranzystorów, ale w naszym projekcie nie jest to istotne. Odbiornik podczerwieni podłączmy do pinu nr 11.

Schemat przekaźnika

Jeżeli chodzi o układy z przekaźnikami można je zrobić samemu lub kopić gotowe płytki np. Moduł z przekaźnikiem v3.1 5V 277V/10A – DFRobot lub zbudować własne w oparciu o ich schemat:Bez tytułu11

Z powyższego schematu można usunąć LED. Na schemacie są pokazane Przekaźnik JQC-3FF-S-Z-5V – cewka 5V, styki 10A/250VAC. Proponuję użyć tranzystora  NPN BC338-40 25V/0.8A. Pin oznaczony numerem 3 z listwy J1 należy podłączyć do masy, 2 z J1 do 5V, 1 z J1 do pinu cyfrowego Arduino, 1 z J2 do napięcia sieciowego, 3 z J2 do zasilania np. lampy.

UWAGA! BEZPOŚREDNI KONTAKT CZŁOWIEKA Z PRĄDEM 230V 50Hz POWODUJE BOLESNE SKURCZE MIĘŚNI, MIGOTANIE KOMÓR SERCA I ŚMIERĆ.

Program:

#include <IRremote.h> // biblioteka
IRrecv irrecv(14);
decode_results results;

boolean jeden = 0;
boolean dwa = 0;
boolean trzy = 0;
boolean cztery = 0;
boolean piec = 0;
boolean szesc = 0;
boolean siedem = 0;
boolean osiem = 0;
boolean dziewiec = 0;


void setup()
{
Serial.begin(9600);
 irrecv.enableIRIn(); // uruchamia odbiornik podczerwieni
}

void loop()
{
if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygnał IR
 {
unsigned long odczyt = results.value; // sygnał zapisuje jako odczyt
 switch (odczyt)
{
 case 3778927144: // 1
jeden = change(jeden);
 digitalWrite(2,jeden);
break;
 case 2908251746: // 2
dwa = change(dwa);
 digitalWrite(3,dwa);
break;
 case 657459652: // 3 
trzy = change(trzy);
 digitalWrite(4,trzy);
break;
 case 4120482440: // 4 
cztery = change(cztery);
 digitalWrite(5,cztery);
break;
 case 1931099650: // 5
piec = change(piec);
 digitalWrite(6,piec);
break;
 case 742730860: // 6
szesc = change(szesc);
 digitalWrite(7,szesc);
break;
 case 1167253836: // 7
siedem = change(siedem);
 digitalWrite(8,siedem);
break;
 case 1747313982: // 8
osiem = change(osiem);
 digitalWrite(9,osiem);
break;
 case 2340753640: // 9
dziewiec = change(dziewiec);
 digitalWrite(10,dziewiec);
break;
 
}
 irrecv.resume(); // reseruje czujnik 
}
 delay(1000);
}



byte change (boolean otrz)
{
return (!otrz);
}

A oto film jak to działa (film dodany na moim kanale gdzie znajdują też inne filmiki z Arduino i Lego Mindstorms):

Wysyłanie wiadomości przez IR z jednego Arduino do drugiego Arduino i funkcja “Random”

Arduino działające jako odbiornik

Schemat z poprzedniego projektu:

Bez tytułu15

Program:

#include <IRremote.h>       // biblioteka
IRrecv irrecv(14);
decode_results results;

boolean jeden = 0;
boolean dwa = 0;
boolean trzy = 0;
boolean cztery = 0;
boolean piec = 0;
boolean szesc = 0;
boolean siedem = 0;
boolean osiem = 0;
boolean dziewiec = 0;


void setup()
{
   Serial.begin(9600);
irrecv.enableIRIn(); // uruchamia odbiornik podczerwieni
}

void loop()
{
 if (irrecv.decode(&results)) // sprawdza, czy otrzymano sygna� IR
{
       byte odczyt = (byte) results.value; // sygnał zapisuje jako odczyt
/*
       odczyt = constrain(odczyt,1,9); 
  • /
switch (odczyt) { case 1: // 1 jeden = change(jeden); digitalWrite(2,jeden); break; case 2: // 2 dwa = change(dwa); digitalWrite(3,dwa); break; case 3: // 3 trzy = change(trzy); digitalWrite(4,trzy); break; case 4: // 4 cztery = change(cztery); digitalWrite(5,cztery); break; case 5: // 5 piec = change(piec); digitalWrite(6,piec); break; case 6: // 6 szesc = change(szesc); digitalWrite(7,szesc); break; case 7: // 7 siedem = change(siedem); digitalWrite(8,siedem); break; case 8: // 8 osiem = change(osiem); digitalWrite(9,osiem); break; case 9: // 9 dziewiec = change(dziewiec); digitalWrite(10,dziewiec); break; } irrecv.resume(); // resetuje czujnik } } byte change (boolean otrz) { return (!otrz); }

Na początku pętli loop znajduje się kod, który zamknąłem w komentarzu:

/*
       odczyt = constrain(odczyt,1,9); 
  • /

Powyższy fragment kodu (gdyby nie był w komentarzu) zamienia wszelkie liczby większe od 9 otrzymane w wyniku zakłóceń na 9.  Jest to opcjonalny fragment kodu i jego celem jest zmienianie stanu on/off LEDu podłączonego do pinu nr 10 przy wystąpieniu zakłóceń.

Arduino działające jako nadajnik

Schemat:

AD Bez tytułu

Program:

#include <IRremote.h>
IRsend irsend;

void setup(){}
void loop() 
{
  
byte dane = random(1,10);
  irsend.sendSony(dane, 18); // Wysyła wylosowaną liczbę w przedziale od 1 do 10
delay(2500);
}

Efekty

Czas zapalania się i gaśnięcia poszczególnych LEDów jest chaotyczny, ale ilość takich cykli dla każdego z nich jest porównywalny.

Komunikacja radiowa lub przez XBee

Jeżeli mówimy o komunikacji radiowej zapewne mamy na myśli radio FM albo zachwalane moduły o częstotliwości 2,4 GHz stosowany w samochodach RC i dronach. Radio FM jest świetnym wynalazkiem, ale nie nadaje się do komunikacji robotów. Moduły 2,4 GHz byłyby wręcz idealne, ale jeżeli chodzi nam o jak najdokładniejszy przekaz (bardzo zakłóca np. Wi-Fi) lepiej wybrać częstotliwość trochę mniejszą np 433MHz lub 868MHz. Jest prawdą fakt, że są co najmniej 2,5 do 5 razy wolniejsze, ale  433 milionów stanów zegarowych na sekundę to wystarczająco nawet dla bardziej złożonych komunikacji.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Dalsze działanie

Całość można wgrać na mikrokontroler np. ATTINY2313 za pomocą ARDUINO IDE  (link do artykułu) . Daje nam to możliwość zbudowania taniego i trwałego układu.

 

INFORMACJA: Poniższy post nie wydostał się z Poczekalni :(

Ocena: 3.67/5 (głosów: 3)

Podobne posty

12 komentarzy do “Arduino – wszystko o sterowaniu przez podczerwień IR

    • Faktycznie. Poprawiłem schemat (każda dioda powinna mieć swój rezystor). Jednak zastosowałem wszędzie rezystor 220Ω dlatego, że przy takich diodach można przyjąć, że napięcie LED równe jest 2V

      Odpowiedz
    • Po zapoznaniu się z tym artykułem uważam, że pierwsza część mojego artykułu jest ściśle powiązana z drugą, a biblioteka ta jest z tego co wiem jedną z najprostszych i najwyraźniej najbardziej popularnych do sterowania IR

      Odpowiedz
  • Dla mnie wporzo. A co do tego że już było to mi to nie przeszkadza a wręcz przeciwnie. Dobrze jest poczytać wiele poradników odnoszących się do jednego problemu bo żaden nie jest idealny no i powtarzamy sobie wiadomości i przyswajamy co dla początkującego jest wskazane. 5.

    Odpowiedz
  • a mnie drażni w takich projektach brak wykończenia -robione na płytkach stykowych, kilka ledow i tyle
    a gdzie zrobiona płytka (wytrawiona lub chociaz polutowane na uniwersalnej, gdzie obudowa? wszędzie tylko pajęczynki na płytce stykowej
    tak jakby ktoś robił poradnik pt “jak zrobić stół’ ale podal tylko wymiary, ucial blat i deski i położył jedno na drugim mówiąc “a potem sobie posklejajcie/skręccie, pomalujcie” itd
    takie to wszystko niedokończone…

    Odpowiedz
    • Rozumiem Krapi co masz na myśli. Według mnie przerabianie takiego prostego układu z LEDami, który ma właściwie sprawdzić działanie programu jest trochę bez sensu. Pokazując natomiast jak zrobić małe SmartHome sterowane podczerwienią jest może ciekawe, ale ten projekt ma bardziej charakter zabawy ze względu na wady sterowania IR – podatność na zakłócenia, mały zasięg i mały kąt nadawania.

      Odpowiedz
  • cześć,
    mam pewien problem i znajomy mi podesłał ten artykuł z myślą że może to jest rozwiązanie dla mnie.
    Jeśli mogli byś przeczytać w czym problem i mi odpowiedzieć czy ma rację i czy ktoś się tego podejmie.
    Mam ramkę cyfrową (dokładnie 20 szt.) która ma sterowani przyciskami ale też pilotem. Wyświetlany na niej jest zapętlony film.
    Ma zaprogramowany czas włączenia i wyłączenia się.
    Niestety sklepy w których stoją te ramki mają na noc centralnie wyłączany prąd i po ponownym włączeniu prądu ramka nie startuje filmem tylko swoim ekranem startowym z ikonami typy VIDEO, ZDJĘCIA KALENDARZ. Oczywiście można uruchomić wyświetlanie filmu pilotem ale chodzi o to aby ramka była bezobsługowa czyli żeby film startował sam.
    Pytanie czy tego typu rozwiązanie jak w powyższym artykule można by było zastosować.
    Może macie inny pomysł?
    Uprzedzę pytania że ups’y i power banki nie są rozwiązaniem. Już to przerobiliśmy.

    Odpowiedz
  • Witam. A co gdybym chciał żeby dioda/diody świeciły się tylko w momencie przyciskania przycisku na pilocie? Próbuje to ogarnąć ale bez efektu. Proszę o pomoc

    Odpowiedz
  • Wszystko pięknie tylko jedno ‘ale’.
    Na końcu pętli CASE dajesz “dane=0” jako wartość gdy nie jest odbierany żaden kod, a wcześniej jest przypisanie że gdy z pilota odebrany zostanie kod klawisza ‘ZERO’ to przypisujesz wartość ’10’. Dla mnie to trochę zamieszane.

    Niech kod ‘ZERO’ z pilota przypisuje wartość ‘0’, a wartość gdy nie jest odbierany żaden kod np. wynosi ‘255’.

    Na pierwszy rzut oka wtedy widać że odbieramy kod ‘ZERO’ bo ma wartość ‘0’ i łatwiej to wtedy opanować.

    Gdybyś chciał do urządzenia wprowadzić np. jakąś wartość w postaci ciągu cyfr, dajmy na to jakiś np. PIN i w nim byłaby cyfra ‘0’ (np. 6083) to łatwiej połączyć w całość odczytane zmienne 6, 0, 8, 3, a niżeli zmienne 6, 10, 8, 3.

    To tylko moja taka uwaga bardziej stylistyczna bo oczywiście w samym wyniku działania programu nic nie zmieni.

    Odpowiedz

Odpowiedz

anuluj

Masz uwagi?