概述
注意:本教程已更新為可與IRLib 2.x一起使用,與以前的版本有顯著差異。
大多數消費電子設備,例如電視,電纜盒,DVD播放器和其他設備,都使用紅外信號進行遠程控制。每個制造商都有自己的協議來對數據進行編碼,以使發送給一臺設備的信號不會干擾另一臺設備。在LadyAdashe的早期教程中,介紹了從遠程讀取IR信號并使用IR LED創建自己的IR信號的內部工作方式。 。她的教程為您提供了IR工作原理的幕后花絮,但是要想弄清楚項目中的所有技術細節都有些困難。
如果您像我一樣,則不知道該怎么做。 NeoPixels可以工作,也不可以在I2C或SPI通信的內部工作,但是您不需要這樣做,因為我們有相應的庫。一個好的代碼庫會將您(應用程序程序員)與硬件細節和設備的內部運作隔離開來,并為您提供一個API,使您可以輕松使用硬件而無需了解或關注幕后情況。
在本教程中,我們將向您展示如何在基于Arduino的項目中使用IRLib接收,解碼和發送IR信號。我們將向您展示如何在NeoPixel上更改顏色,如何使用IR遙控器控制伺服器以及如何從Arduino向電視或電纜盒發送信號。未來的教程將包括IR控制鼠標,物聯網遠程控制和控制機械臂。
關于IR庫
IR信號由一系列稱為“標記”的調制脈沖組成,這些脈沖由稱為“空格”的間隔隔開。通常,每個信號的開頭都有一個長標記和空格,用作標頭。然后,通過改變標記和空格的時序,可以傳輸一系列比特。如果必須存儲整個信號的精確時序,則需要使用最多100個16位整數的數組。為了比較接收到的數據以查看是否是您想要的數據,您同樣需要存儲大量數據。
幸運的是,信號是根據非常特定的協議發送的,您可以使用此協議接收時序數據并將其轉換為最多32位的單個二進制數。 IR庫將時序信息收集到緩沖區中,然后將其轉換為單個32位值。然后,您可以輕松地將該值與所需的值進行比較。
類似地,如果您要發送IR信號,您需要做的就是將32位值傳遞給庫并告訴它要使用哪種協議使用。它將值轉換為帶有適當標題,位編碼和定時的標記和空格流。
IR庫的金標準是“ LIRC”或Linux紅外遙控器,可在http://網站上找到它。/www.lirc.org/。它由驅動程序和有關數百個各種遠程控制的大型信息數據庫組成。如果我們使用的是基于Linux的系統,那么絕對是正確的選擇。我們將不在這里討論該庫,因為我們打算專注于基于Arduino的系統。
2009年8月,Ken Shirrff在他的博客上發布了“ IRremote”,并在GitHub上發布了該庫。然后在2013年1月,我根據Ken的早期工作發布了IRLib。此修訂版重新組織了代碼,使使用C ++中的面向對象編程設計可以更輕松地添加新協議。
有關IRLib的詳細信息,請參見我的博客,網址為:http://tech.cyborg5.com/irlib/。 。它包括一個詳盡的用戶手冊,該手冊也可以在該庫的“ manuals”文件夾中找到。。在本教程中,我們將使用IRLib來幫助您入門。
2016年9月,我們發布了主要的重寫IRLib的名稱稱為IRLib 2.0。它與原始IRLib不完全向后兼容。本教程已更新為使用IRLib 2.0。以前的IRLib 1.x將不再受支持。最近發布的IRLib 2.03增加了對32位SAMD 21處理器的支持,例如Arduino Zero,Adafruit Feather M0和即將推出的Circuit Playground Express中使用的處理器。
接收和解碼IR
軟件安裝
IRLib庫的安裝如下:
訪問GitHib上的IRLib2頁面。
選擇“下載ZIP”按鈕,或簡單地單擊此鏈接直接下載。
下載完成后解壓縮ZIP文件。
生成的文件夾應命名為“ IRLib2-master”,并將包含5個單獨的文件夾。這是因為IRLib 2.x實際上是5個可一起使用的庫的集合。有時在Windows中,您會得到一個中級文件夾,并且需要四處移動。
將所有五個文件夾與其他Arduino庫一起復制到Arduino庫文件夾中,通常在(主文件夾)/Documents/Arduino/Libraries文件夾。庫不應該與Arduino應用程序本身一起安裝。
如果當前正在運行Arduino IDE,請重新啟動
此存儲庫由總共五個庫組成,每個庫它必須在您的arduino/libraries/文件夾中。因此,例如,應按以下方式安裝它……
arduino/libraries/IRLib2
arduino/libraries/IRLibFreq
arduino/libraries/IRLibProtocols
arduino/libraries/IRLibRecv
arduino/libraries/IRLibRecvPCI
請勿將它們安裝在這樣的單個文件夾中……
arduino/libraries/IRLib2_master
IRLib2
IRLibFreq
IRLib協議
IRLibRecv
IRLibRecvPCI
這是一個教程,指導您正確安裝Arduino庫。
所需的硬件
IRLib在基于8位AVR的Arduino板上運行,例如Uno,Leonardo,Mega和Micro。它也可以在Arduino Yun的Leonardo部分上運行。我們最近增加了對Arduino Zero,Feather M0和Circuit Playground Express中使用的32位ARM SAMD 21處理器的支持。但是,我們不支持Arduino Due或其他類似Arduino的系統。不幸的是,目前它不能在Adafruit Trinket和Adafruit Gemma之類的ATtiny85基礎系統上運行,但對它的支持在工作罐中,并且應在不久的將來以精簡版本提供給那些平臺。在撰寫本文時,它尚未在Adafruit Trinket Pro上進行過測試,但是由于它與Uno基于相同的ATmega328處理器,因此應該可以正常工作。因此,您需要的第一件事是Arduino Uno或其他兼容板。
您將需要一個IR接收器。例如,右列顯示在特色產品下的TSOP38238。該設備結合了一個紅外敏感光電管,一個38 kHz帶通濾波器和自動增益控制。它可以在多種電源電壓下工作,包括3.3v和5v。它可以對接收到的IR信號進行解調,并在電源電壓水平上為您提供一個清晰的開,關脈沖方波。這意味著它是將其輸出直接饋送到Arduino的數字輸入引腳的理想選擇。
最后,您將需要一個IR遙控器,例如用于控制電視,電纜盒或DVD播放器的遙控器。我們所有的示例都將使用右側所示的Adafruit迷你遙控器,但是,我們將向您展示如何檢測自己的電視遙控器正在使用的協議,如果IRLib支持該協議,則可以使用它。
連接紅外接收器非常簡單。將左側的引腳連接到Arduino上的任何數字輸入引腳。在我們的示例中,我們將使用引腳2。將中心引腳接地,將右側引腳連接至+ 5v。
請注意,該設備的帶通濾波器已調至38 kHz,這是大多數協議的典型頻率。但是,某些協議會使用從36 kHz一直到57 kHz的頻率。但是,該濾波器不是非常特定,我們在使用38 kHz接收器接收36-40 kHz范圍內的信號方面取得了成功。 Panasonic_Old協議使用56 kHz。 Adafruit出售的TSOP38238很難解碼該頻率。但是,盡管Radio Shack出售的接收器是38 kHz的設備,但我還是取得了不錯的成績。 Radio Shock沒有列出部件號,但我們認為它是TSOP4438。令人遺憾的是,這可能不再是一個選擇:-(
這些設備是由Vishay制造的,具有多種包裝樣式,頻率和AGC方法。如果Adafruit設備不適用于您并且您需要56 kHz時,您可以參考以下指南。
Vishay的IR接收器選擇指南(PDF格式)
有關接收器和原理圖的更多信息有關使用多個接收器的信息,請參見IRLib手冊第1.4.3節。
解碼紅外數據
加載以下草圖,它是庫示例文件夾中“轉儲”草圖的略微修改版本。所有示例草圖均位于文件夾“ IRLib2/examples”。
下載:文件
復制代碼
#include “IRLibAll.h”
//Create a receiver object to listen on pin 2
IRrecvPCI myReceiver(2);
//Create a decoder object
IRdecode myDecoder;
void setup() {
Serial.begin(9600);
delay(2000); while (!Serial); //delay for Leonardo
myReceiver.enableIRIn(); // Start the receiver
Serial.println(F(“Ready to receive IR signals”));
}
void loop() {
//Continue looping until you get a complete signal received
if (myReceiver.getResults()) {
myDecoder.decode(); //Decode it
myDecoder.dumpResults(true); //Now print results. Use false for less detail
myReceiver.enableIRIn(); //Restart receiver
}
} #include “IRLibAll.h”
//Create a receiver object to listen on pin 2
IRrecvPCI myReceiver(2);
//Create a decoder object
IRdecode myDecoder;
void setup() {
Serial.begin(9600);
delay(2000); while (!Serial); //delay for Leonardo
myReceiver.enableIRIn(); // Start the receiver
Serial.println(F(“Ready to receive IR signals”));
}
void loop() {
//Continue looping until you get a complete signal received
if (myReceiver.getResults()) {
myDecoder.decode(); //Decode it
myDecoder.dumpResults(true); //Now print results. Use false for less detail
myReceiver.enableIRIn(); //Restart receiver
}
}
在加載草圖之后,打開串行監視器并確保將其設置為9600波特。接收者然后按下一個按鈕。在此示例中,我們按下Adafruit Mini Remote上的“播放/暫停”按鈕。結果如下:
Decoded NEC(1): Value:FD807F (32 bits)
Raw samples(68): Gap:40826
Head: m8850 s4450
0:m500 s600 1:m550 s550 2:m500 s600 3:m550 s600
4:m500 s600 5:m500 s600 6:m500 s600 7:m550 s550
8:m500 s1750 9:m500 s1700 10:m500 s1700 11:m550 s1650
12:m550 s1700 13:m500 s1700 14:m500 s600 15:m550 s1700
16:m500 s1700 17:m500 s600 18:m500 s600 19:m500 s600
20:m550 s600 21:m450 s650 22:m500 s600 23:m500 s600
24:m500 s600 25:m500 s1700 26:m550 s1700 27:m500 s1700
28:m500 s1700 29:m550 s1700 30:m500 s1700 31:m500 s1700
32:m500
Extent=65850
Mark min:450 max:550
此轉儲的重要部分是第一行。這告訴我們檢測到的協議是“ NEC”,在IRLib支持的協議中是協議號“ 1”。接收到的數據值為32位十六進制值FD807F。其余信息是接收到的實際標記和空格的原始計時數據。該信息對于嘗試理解和支持協議很有用。
此32位數字唯一標識您按下的按鈕。如果我們按下此遙控器上的“降低音量”和“提高音量”按鈕,我們將獲得0xFD00FF和0xFD40BF值。
嘗試按一下電視或DVD遙控器上的各種按鈕,您可能躺在家里。如果頂行顯示:
Decoded Unknown(0): Value:0 (0 bits)
,則表明IRLib無法理解您的遙控器使用的協議。以下是其他遙控器的一些典型值。我是從Sony DVD播放器上的電源按鈕以及科學大西洋DVR/電纜盒上的播放按鈕獲得的。
Decoded Sony(2): Value:74BCA (20 bits)
Decoded Panasonic Old(5): Value:37990C (22 bits)
這表明DVD播放機使用了Sony協議,該協議是2號協議,并且是20位協議。電纜盒使用22位的Panasonic_Old協議5。大多數協議始終使用相同數量的位,但是某些協議(例如Sony)具有不同的版本,除了20外還可以使用8、12或15位。
工作原理
讓我們看看這里發生了什么。接收器對象偵聽紅外傳感器,當它看到信號時,便開始測量標記和空格的時間。如果經過特定時間沒有其他信號,則認為數據已完成,并且當您調用My_Receiver.GetResults時,它將返回“ true”。它將數據傳遞到您的解碼器對象。解碼器使用時序信息和位數來查看它是否與所支持的協議之一匹配。如果成功,則返回“ true”,盡管在此草圖中我們無需費心檢查。
您可以訪問My_Decoder.protocolNum中的協議號,My_Decoder.bits中的位數和
在草圖的頂部,我們將解碼器對象創建為“ IRdecode”類型。此類包含所有11種受支持的協議。如果您正在使用該庫來控制諸如伺服之類的設備,或者打開和關閉繼電器,則可能要使用具有一種協議的一個遙控器。一旦知道要使用的協議,您可能希望使用僅適用于您特定協議的其他解碼器類。它可以在您的草圖中節省寶貴的程序空間。例如,如果我們使用的是使用NEC協議的Adafruit Mini Remote,則會將第7行更改為:
下載:文件
復制代碼
IRdecodeNEC My_Decoder; IRdecodeNEC My_Decoder;
特定于協議的問題
IRLib直接支持11種協議,并且可能包含有關如何實現其他協議的示例代碼。如前所述,庫的工作之一是將應用程序程序員與處理內部問題的需求隔離開來。但是,您可能需要處理一些特定于協議的問題。
IRLibProtocols/IRLibProtocols.h中的大約第14行枚舉了這些協議,如下所示。
下載:文件
復制代碼
#define UNKNOWN 0
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define PANASONIC_OLD 5
#define JVC 6
#define NECX 7
#define SAMSUNG36 8
#define GICABLE 9
#define DIRECTV 10
#define RCMM 11
#define UNKNOWN 0
#define NEC 1
#define SONY 2
#define RC5 3
#define RC6 4
#define PANASONIC_OLD 5
#define JVC 6
#define NECX 7
#define SAMSUNG36 8
#define GICABLE 9
#define DIRECTV 10
#define RCMM 11
您可能需要處理一些協議特定的問題。
NEC重復代碼
NEC協議使用特殊的標記和空格序列,表示“我按下了按鈕,因此您應該重復上次發送給您的內容”。由您決定是要允許重復代碼還是要強制操作員每次按下和釋放按鈕。 IRLib返回0xFFFFFFFF的值,以告訴您已收到特殊的重復序列。您可以忽略使用戶每次都釋放并按下按鈕的順序,或者可以存儲先前收到的代碼并在看到特殊的重復消息時對其進行處理。
Sony三重消息
Sony協議的技術規范規定,每次按鍵時,您應該連續3次發送每個代碼。 IRLib會為您發送三遍,因此您無需執行任何特殊操作。但是,在接收Sony時,請注意,每次用戶按下按鈕時,您將獲得三份數據副本。如果您正在忙于處理第一個序列,則可能會錯過其他兩個序列,所以沒關系。但是,如果您要計算按鍵或其他應用程序的數量,則需要意識到這一點。
RC5和RC6切換位
菲利普斯(Phillips)發明的RC5和RC6協議使用特殊的切換位來告知您是否通過按住按鈕生成了代碼,或者是一個獨立的按鍵。例如,我有一臺使用RC5協議的電視,“調高音量”的代碼是0x1010。如果我按住該按鈕,它將重復發送相同的代碼。但是,如果我釋放按鈕并再次按下它,則會得到0x1810。每隔一次按鍵一次0x0800將關閉或打開。您可以通過掩蓋該特定位來確保忽略此功能。當您從該協議收到解碼后的值時,您可以執行以下操作:
下載:文件
復制代碼
My_Decoder.value &=0xf7ff; My_Decoder.value &=0xf7ff;
這將確保切換位始終處于關閉狀態。 RC6協議還具有一個標題位,即0x10000。因此,要掩蓋它,您可以執行以下操作:
下載:文件
復制代碼
My_Decoder.value &=0xfeffff; My_Decoder.value &=0xfeffff;
使用IR控制NeoPixels
在這個非常簡單的示例中,我們將通過按遙控器上的按鈕來更改NeoPixel的顏色。我們使用的是單個像素,但是您可以修改草圖以控制整個條帶或矩陣。有關NeoPixels的更多信息,請訪問Adafruit學習系統中的本指南。這是代碼:
下載:文件
復制代碼
#include
#include
IRrecv myReceiver(2);//receiver on pin 2
IRdecode myDecoder;//Decoder object
//One NeoPixel connected to pin 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1,6,NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to ‘off’
myReceiver.enableIRIn(); // Start the receiver
}
void loop() {
if (myReceiver.getResults()) {
myDecoder.decode();
if (myDecoder.protocolNum == NEC) {
switch(myDecoder.value) {
case 0xfd00ff: //Volume Down
strip.setPixelColor(0,255,0,0);//Red
break;
case 0xfd807f: //Play/Pause
strip.setPixelColor(0,0,255,0);//Green
break;
case 0xfd40bf: //Volume Up
strip.setPixelColor(0,0,0,255);//Blue
break;
}
strip.show();
myReceiver.enableIRIn(); //Restart the receiver
}
}
} #include
#include
IRrecv myReceiver(2);//receiver on pin 2
IRdecode myDecoder;//Decoder object
//One NeoPixel connected to pin 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1,6,NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to ‘off’
myReceiver.enableIRIn(); // Start the receiver
}
void loop() {
if (myReceiver.getResults()) {
myDecoder.decode();
if (myDecoder.protocolNum == NEC) {
switch(myDecoder.value) {
case 0xfd00ff: //Volume Down
strip.setPixelColor(0,255,0,0);//Red
break;
case 0xfd807f: //Play/Pause
strip.setPixelColor(0,0,255,0);//Green
break;
case 0xfd40bf: //Volume Up
strip.setPixelColor(0,0,0,255);//Blue
break;
}
strip.show();
myReceiver.enableIRIn(); //Restart the receiver
}
}
}
我們創建一個NeoPixel帶,其中一個像素連接到引腳6。還創建一個連接到引腳11的接收器對象和一個解碼器對象。在設置例程中重新初始化像素帶和IR接收器。然后在主環路中連續測試接收器,以查看其是否已接收到許多IR信號。如果myReceiver.getResults返回true,則我們解碼數據。我們正在使用之前使用的Adafruit Mini Remote。它使用了NEC協議,因此我們確保確實收到了NEC協議數據。然后,我們使用switch語句針對My_Decoder.value中的解碼數據測試各種32位十六進制值。
根據接收到的值設置像素顏色后,我們需要調用strip.show ()實際更改顏色,然后myReceiver.enableIRIn()重置接收器,以便它可以收集其他代碼。
上載草圖并嘗試按調低音量,播放/暫停和調高音量按鈕。您應該看到像素變為紅色,綠色或藍色。您可以輕松添加其他case語句和顏色,或者使其中一種case調用動畫例程來對整個像素帶進行動畫處理。遙控器上的不同按鈕會選擇不同的動畫模式。
如果使用其他遙控器,則必須修改此草圖。將協議類型更改為:
下載:文件
復制代碼
if (myDecoder.protocolNum==SONY) if (myDecoder.protocolNum==SONY)
,例如,如果您使用的是Sony遙控器。當然,您必須在每個case語句中替換適當的代碼。可以在IRLib.h的第60行找到用于比較解碼類型的可用協議的枚舉列表。
使用IR控制伺服器
設置
在此示例中,我們將使用紅外遙控器控制伺服器。我們可以調整伺服器的移動速度,并可以選擇單個預設角度來定位伺服器。
這里是顯示如何連接設備的示意圖。像往常一樣,我們將一個IR接收器連接到+ 5v,地和引腳11。我們還有一個帶有三根導線的伺服器。紅線為+ 5v。黑色或暗褐色的電線接地,其余的通常是黃色的電線是我們連接到引腳9的信號線,盡管它可以是任何數字輸出引腳。
i》 注意:上圖顯示了接收器在引腳11上,但是示例代碼使用了引腳2。可以使用任何數字輸入引腳。
上傳代碼
下面是來自“ IRLib2/examples”文件夾。它已被修改為與Adafruit Mini Remote一起使用。如果使用其他遙控器,則必須使用dump.ino收集有關各種按鈕的代碼的信息,并使用正確的協議名稱和代碼來修改草圖。
下載:文件
復制代碼
#include
#include
// You will have to set these values depending on the protocol
// and remote codes that you are using. These are For the Adafruit
// Mini Remote
#define MY_PROTOCOL NEC
#define RIGHT_ARROW 0xfd50af //Move several clockwise
#define LEFT_ARROW 0xfd10ef //Move servo counterclockwise
#define SELECT_BUTTON 0xfd906f //Center the servo
#define UP_ARROW 0xfda05f //Increased number of degrees servo moves
#define DOWN_ARROW 0xfdb04f //Decrease number of degrees servo moves
#define BUTTON_0 0xfd30cf //Pushing buttons 0-9 moves to fixed positions
#define BUTTON_1 0xfd08f7 // each 20 degrees greater
#define BUTTON_2 0xfd8877
#define BUTTON_3 0xfd48b7
#define BUTTON_4 0xfd28d7
#define BUTTON_5 0xfda857
#define BUTTON_6 0xfd6897
#define BUTTON_7 0xfd18e7
#define BUTTON_8 0xfd9867
#define BUTTON_9 0xfd58a7
IRrecv myReceiver(2); //pin number for the receiver
IRdecode myDecoder;
Servo myServo; // create servo object to control a servo
int16_t pos; // variable to store the servo position
int16_t Speed; // Number of degrees to move each time a left/right button is pressed
uint32_t Previous;//handles NEC repeat codes
void setup() {
myServo.attach(9); // attaches the servo on pin 9 to the servo object
pos = 90; // start at midpoint 90 degrees
Speed = 3; // servo moves 3 degrees each time left/right is pushed
myServo.write(pos); // Set initial position
myReceiver.enableIRIn(); // Start the receiver
}
void loop()
{
if (myReceiver.getResults()) {
myDecoder.decode();
if(myDecoder.protocolNum==MY_PROTOCOL) {
if(myDecoder.value==0xFFFFFFFF)
myDecoder.value=Previous;
switch(myDecoder.value) {
case LEFT_ARROW: pos=min(180,pos+Speed); break;
case RIGHT_ARROW: pos=max(0,pos-Speed); break;
case SELECT_BUTTON: pos=90; break;
case UP_ARROW: Speed=min(10, Speed+1); break;
case DOWN_ARROW: Speed=max(1, Speed-1); break;
case BUTTON_0: pos=0*20; break;
case BUTTON_1: pos=1*20; break;
case BUTTON_2: pos=2*20; break;
case BUTTON_3: pos=3*20; break;
case BUTTON_4: pos=4*20; break;
case BUTTON_5: pos=5*20; break;
case BUTTON_6: pos=6*20; break;
case BUTTON_7: pos=7*20; break;
case BUTTON_8: pos=8*20; break;
case BUTTON_9: pos=9*20; break;
}
myServo.write(pos); // tell servo to go to position in variable ‘pos’
Previous=myDecoder.value;
}
myReceiver.enableIRIn();
}
} #include
#include
// You will have to set these values depending on the protocol
// and remote codes that you are using. These are For the Adafruit
// Mini Remote
#define MY_PROTOCOL NEC
#define RIGHT_ARROW 0xfd50af //Move several clockwise
#define LEFT_ARROW 0xfd10ef //Move servo counterclockwise
#define SELECT_BUTTON 0xfd906f //Center the servo
#define UP_ARROW 0xfda05f //Increased number of degrees servo moves
#define DOWN_ARROW 0xfdb04f //Decrease number of degrees servo moves
#define BUTTON_0 0xfd30cf //Pushing buttons 0-9 moves to fixed positions
#define BUTTON_1 0xfd08f7 // each 20 degrees greater
#define BUTTON_2 0xfd8877
#define BUTTON_3 0xfd48b7
#define BUTTON_4 0xfd28d7
#define BUTTON_5 0xfda857
#define BUTTON_6 0xfd6897
#define BUTTON_7 0xfd18e7
#define BUTTON_8 0xfd9867
#define BUTTON_9 0xfd58a7
IRrecv myReceiver(2); //pin number for the receiver
IRdecode myDecoder;
Servo myServo; // create servo object to control a servo
int16_t pos; // variable to store the servo position
int16_t Speed; // Number of degrees to move each time a left/right button is pressed
uint32_t Previous;//handles NEC repeat codes
void setup() {
myServo.attach(9); // attaches the servo on pin 9 to the servo object
pos = 90; // start at midpoint 90 degrees
Speed = 3; // servo moves 3 degrees each time left/right is pushed
myServo.write(pos); // Set initial position
myReceiver.enableIRIn(); // Start the receiver
}
void loop()
{
if (myReceiver.getResults()) {
myDecoder.decode();
if(myDecoder.protocolNum==MY_PROTOCOL) {
if(myDecoder.value==0xFFFFFFFF)
myDecoder.value=Previous;
switch(myDecoder.value) {
case LEFT_ARROW: pos=min(180,pos+Speed); break;
case RIGHT_ARROW: pos=max(0,pos-Speed); break;
case SELECT_BUTTON: pos=90; break;
case UP_ARROW: Speed=min(10, Speed+1); break;
case DOWN_ARROW: Speed=max(1, Speed-1); break;
case BUTTON_0: pos=0*20; break;
case BUTTON_1: pos=1*20; break;
case BUTTON_2: pos=2*20; break;
case BUTTON_3: pos=3*20; break;
case BUTTON_4: pos=4*20; break;
case BUTTON_5: pos=5*20; break;
case BUTTON_6: pos=6*20; break;
case BUTTON_7: pos=7*20; break;
case BUTTON_8: pos=8*20; break;
case BUTTON_9: pos=9*20; break;
}
myServo.write(pos); // tell servo to go to position in variable ‘pos’
Previous=myDecoder.value;
}
myReceiver.enableIRIn();
}
}
注意:如果使用Leonardo,Micro或Yun或其他ATmega32u4系統,請參閱本頁末尾的特殊說明。
上傳草圖,然后嘗試按左右箭頭按鈕。伺服器應左右旋轉。按下輸入按鈕應使伺服器居中。按下向上或向下箭頭按鈕不會產生任何可見效果,但是會改變您向左或向右推動的移動速度。從零到九的編號按鈕以20°的間隔將伺服器移動到10個不同的固定位置。
如果伺服器行為異常,則可能是電源問題。一些USB端口無法提供足夠的電流來驅動Arduino和移動伺服器。您可能需要添加一個外部5伏電源。以下是演示此示例的視頻。
暫時無法加載嵌入的內容:
暫時無法加載嵌入的內容:
暫時無法加載嵌入的內容:
工作原理
程序在對象,解碼器對象和伺服對象上創建接收器。您可以在此處找到有關標準Arduino伺服庫的更多信息。設置功能附加了伺服器,啟用了IR輸入,并初始化了幾個變量。
循環功能獲取一個IR代碼,并根據其值將其傳遞給switch語句。 switch語句的每種情況處理根據需要移動伺服器的不同功能。
由于使用的是NEC協議,因此需要處理一點開銷。該協議具有獨特的功能,可讓您查看是否按住了遙控器上的按鈕以發送相同值的重復實例。它具有特殊的標記和空格序列,表示“重復您上次所做的操作”。當IRLib看到特殊序列時,它將返回值0xFFFFFFFF。我們通過將先前的值存儲在switch語句的底部來處理這種特殊情況,以便如果我們得到重復的代碼,則下次可以替換它。 NEC協議是唯一使用此特定方法檢測重復代碼的協議。其他協議具有其他系統,有關這些系統的詳細信息,請參見IRLib文檔。
基于ATmega32u4的系統的特殊說明
此處提供的示例在Arduino Uno或Mega上應該可以正常工作,但是如果您使用的是Arduino Leonardo,Arduino Micro,Arduino Yun或其他基于ATmega32u4的示例系統,您必須對IRLib進行一些修改。
IRLib使用Arduino的內置硬件計時器每隔50μs產生一次中斷,以便它可以輪詢輸入引腳以查看是否已更改。默認情況下,它使用TIMER2。 Arduino伺服庫還通過TIMER1使用硬件中斷。但是,ATmega32u4處理器沒有TIMER2,因此IRLib在使用該處理器的系統上默認為TIMER1。您將必須修改“ IRLibProtocols/IRLibHardware.h”以更改默認計時器。在該文件的大約第56行,您將看到類似以下內容的文件:
下載:文件
復制代碼
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it‘s Teensy 2.0
//#define IR_SEND_TIMER1 14
//#define IR_SEND_TIMER3 9
#define IR_SEND_TIMER4_HS 10
#else
/* it’s probably Leonardo */
#define IR_SEND_TIMER1 9
//#define IR_SEND_TIMER3 5
//#define IR_SEND_TIMER4_HS 13
#endif
#elif defined(__AVR_ATmega32U4__)
#ifdef CORE_TEENSY
// it‘s Teensy 2.0
//#define IR_SEND_TIMER1 14
//#define IR_SEND_TIMER3 9
#define IR_SEND_TIMER4_HS 10
#else
/* it’s probably Leonardo */
#define IR_SEND_TIMER1 9
//#define IR_SEND_TIMER3 5
//#define IR_SEND_TIMER4_HS 13
#endif
您需要將//放在#define IR_SEND_TIMER1前面,以注釋掉該行。然后從其他兩個選項之一TIMER3或TIMER4_HS前面的斜杠上刪除。請注意,這些定義說“ IR_SEND_TIMERxx”。在文件的后面,我們將該值復制為也用作接收計時器。如果您使用的是Leonardo,后來又使用IRLib發送IR信號,則需要在這些定義之后記下數字。盡管我們可以將接收器連接到任何數字輸入引腳,但是IRLib要求您根據使用的計時器使用特定的輸出引腳。稍后將在發送部分中介紹。
發送IR代碼
硬件問題
IRLib不僅接收和解碼IR信號,但它也可以使用IR LED和驅動器電路傳輸它們。該庫已用于控制電視,電纜盒,DVD,VCR和諸如直升機和恐龍機器人之類的IR控制玩具。
它還可以用于控制某些家庭自動化設備。一些用戶試圖控制空調和風扇,但是用于空調的協議非常難以實現,并且由于它們很少見,我們還沒有直接支持這種協議。
通常,Arduino的輸出引腳無法提供足夠的電流來驅動LED和IR LED,因此您將需要使用NPN晶體管實現一個簡單的驅動器電路,并在此處顯示一個470歐姆的電阻:
請確保正確設置了LED的極性。兩條引線中的較短的一根連接到晶體管,而一根較長的一根連接到正電源。請注意,流經LED的電流很可能會超過最大連續電流額定值。但是,由于信號被調制并且發送的脈沖序列僅持續幾毫秒,因此電路將正常工作。
IRLIb手冊的第1.4節“硬件注意事項”中提供了更多高級驅動器電路原理圖。/p》
雖然我們可以將IR接收器連接到任何可用的數字輸入引腳,但您只能使用非常特定的引腳進行輸出。該庫使用PWM引腳并修改定時參數以更改該引腳的默認頻率。
Arduino Uno和Arduino Mega的默認計時器為TIMER2。在Leonardo上的是TIMER1。針腳編號為Uno的針腳3,并為Leonardo和Mega使用針腳9。如果已將庫修改為使用其他計時器,例如更改Leonardo上的計時器編號以避免與伺服庫發生沖突,那么您將需要使用其他特定的引腳。有關顯示硬件計時器和引腳號之間關系的表,請參見IRLib用戶手冊中的1.4.1支持的平臺部分。
加載軟件
我們假設您已經按照本教程前面所述安裝了IRLib庫。讓我們加載一個簡單的草圖,看看它是如何工作的。這是來自示例文件夾的IRsendDemo草圖。
下載:文件
復制代碼
#include
IRsend mySender;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.read() != -1) {
//send a code every time a character is received from the serial port
//Sony DVD power A8BCA
mySender.send(SONY,0xa8bca, 20);
}
} #include
IRsend mySender;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.read() != -1) {
//send a code every time a character is received from the serial port
//Sony DVD power A8BCA
mySender.send(SONY,0xa8bca, 20);
}
}
在這個簡單的示例中,每次您鍵入a時,我們都會發送代碼以打開和關閉Sony DVD播放器。字符插入串行監視器。我們創建一個發送對象mySender。除了初始化串行端口外,沒有其他設置。在循環中,我們檢查輸入的字符,如果有,請發送代碼。
send方法具有三個參數:協議類型,數據和位數。
我們創建的IRsend對象是一個支持所有11種支持協議的通用例程。但是在這種情況下,由于我們僅使用一種協議,因此可以使用以下對象創建對象:
下載:文件
復制代碼
IRsendSony mySender; IRsendSony mySender;
在循環內,發送命令將為:
下載:文件
復制代碼
mySender.send(0xa8bca, 20); mySender.send(0xa8bca, 20);
某些協議(例如NEC)始終使用相同的位數,因此您無需將其指定為附加參數。請參閱用戶手冊以了解是否需要extra bits參數。
用戶手冊還為您提供有關如何創建僅使用受支持協議的特定子集的解碼和發送例程的信息。在IRLib 2.0中,這比原始版本要容易得多。
在同一程序中發送和接收
在同一程序中進行發送和接收時,有一些特殊注意事項。發送和接收都使用建筑物硬件計時器。但是,計時器用于兩個不同的目的。發送代碼時,它將重新配置計時器并禁用接收。因此,您必須在每次發送后重新啟用接收器。例如:
下載:文件
復制代碼
mySender.send(Protocol, Data, Bits);
myReceiver.enableIRIn(); // Re-enable receiver mySender.send(Protocol, Data, Bits);
myReceiver.enableIRIn(); // Re-enable receiver
通常,您只需要調用myReceiver.enableIRIn();即可。在設置例程中一次,但是如果您同時在發送和接收,則必須在每次發送之后調用它。
有關如何在同一程序中發送和接收的完整示例,請查看record.ino “ IRLib2/examples”文件夾中的示例草圖。加載草圖時,請打開串行監視器,將遙控器指向接收器,然后按一個按鈕。該程序將捕獲該代碼。然后,每當字符類型進入串行監視器時,它將通過LED重復該代碼。
責任編輯:wv
-
Arduino
+關注
關注
188文章
6478瀏覽量
188139
發布評論請先 登錄
相關推薦
如何在MATLAB中使用DeepSeek模型

評論