紅外線控制簡介

紅外線控制廣泛用於電視、冷氣機、風扇、音響等裝置,一般有效距離約 5~10 公尺,遙控器與接收器之間應保持對準,避免遮擋。工作原理如下:

  1. 遙控器發送紅外線信號,每個按鍵都有獨立的編碼信號。
  2. 接收器接收紅外線信號,並轉成數位信號。
  3. 將數位信號解碼後,判斷是哪個按鍵被按下,再賦予相對應的任務。
紅外線控制電路示意圖
紅外線控制電路實際接線

基本範例1:透過IRremote函式庫取得按鍵編碼。

#include "IRremote.hpp"       // 引用IRremote函式庫
const int irReceiverPin = 15; // 紅外線接收器接腳

void setup() {
  Serial.begin(9600);   // 啟動串列埠監看視窗
  IrReceiver.begin(irReceiverPin , ENABLE_LED_FEEDBACK);    // 建立IrReceiver物件,並開啟LED閃爍功能
}

void loop() {
  if (IrReceiver.decode())    // 若接收到紅外線訊號並成功解碼
  {
    Serial.println(IrReceiver.decodedIRData.command);   // 印出這次接收到的按鍵編碼
    IrReceiver.resume();      // 重設紅外線接收器狀態,準備接收下一個訊號
  }
}

基本範例2:取得按鍵編碼,並加入按鍵簡易防彈跳功能。

//------------------------------------------------------------
#include "IRremote.hpp"             // 引用IRremote函式庫
const int irReceiverPin = 15;       // 紅外線接收器接腳
//------------------------------------------------------------
unsigned long previousMillis = 0;   // 前一次的millis()時間
const long interval = 300;          // 防彈跳時間為 300ms
//------------------------------------------------------------

void setup() {
  Serial.begin(9600);   // 啟動串列埠監看視窗
  IrReceiver.begin(irReceiverPin , ENABLE_LED_FEEDBACK);  // 建立IrReceiver物件,並開啟LED閃爍功能
}

void loop() {
  if (IrReceiver.decode())    // 若接收到紅外線訊號並成功解碼
  {
    unsigned long currentMillis = millis();          // 當前的millis()時間
    if (currentMillis - previousMillis >= interval)  // 若達到預設計時的時間
    {
      //---------------------------------------------------------------------
      // 每經過一個interval的時間,要做的事
      //---------------------------------------------------------------------
      Serial.println(IrReceiver.decodedIRData.command);  // 印出這次接收到的按鍵編碼
      //---------------------------------------------------------------------

      previousMillis = currentMillis;  // 更新前一次的millis()時間
    }

    IrReceiver.resume();  // 重設紅外線接收器狀態,準備接收下一個訊號
  }
}

基本範例3:取得按鍵編碼,判讀接收值,再賦予相對應的任務。

//------------------------------------------------------------
#include "IRremote.hpp"             // 引用IRremote函式庫
const int irReceiverPin = 15;       // 紅外線接收器接腳
//------------------------------------------------------------
unsigned long previousMillis = 0;   // 前一次的millis()時間
const long interval = 300;          // 防彈跳時間為 300ms
//------------------------------------------------------------

void setup() {
  Serial.begin(9600);   // 啟動串列埠監看視窗
  IrReceiver.begin(irReceiverPin , ENABLE_LED_FEEDBACK);  // 建立IrReceiver物件,並開啟LED閃爍功能
}

void loop() {
  if (IrReceiver.decode())    // 若接收到紅外線訊號並成功解碼
  {
    unsigned long currentMillis = millis();          // 當前的millis()時間
    if (currentMillis - previousMillis >= interval)  // 若達到預設計時的時間
    {
      //---------------------------------------------------------------------
      // 每經過一個interval的時間,要做的事
      //---------------------------------------------------------------------
      switch (IrReceiver.decodedIRData.command)  // 判讀接收值
      {
        case 69:
          Serial.println("CH-");
          break;
        case 70:
          Serial.println("CH");
          break;
        case 71:
          Serial.println("CH+");
          break;
        case 68:
          Serial.println("PREV");
          break;
        case 64:
          Serial.println("NEXT");
          break;
        case 67:
          Serial.println("PLAY/PAUSE");
          break;
        case 7:
          Serial.println("VOL-");
          break;
        case 21:
          Serial.println("VOL+");
          break;
        case 9:
          Serial.println("EQ");
          break;
        case 22:
          Serial.println("0");
          break;
        case 25:
          Serial.println("100+");
          break;
        case 13:
          Serial.println("200+");
          break;
        case 12:
          Serial.println("1");
          break;
        case 24:
          Serial.println("2");
          break;
        case 94:
          Serial.println("3");
          break;
        case 8:
          Serial.println("4");
          break;
        case 28:
          Serial.println("5");
          break;
        case 90:
          Serial.println("6");
          break;
        case 66:
          Serial.println("7");
          break;
        case 82:
          Serial.println("8");
          break;
        case 74:
          Serial.println("9");
          break;
        default:
          Serial.println("undefined");
          break;
      }
      //---------------------------------------------------------------------

      previousMillis = currentMillis;  // 更新前一次的millis()時間
    }

    IrReceiver.resume();  // 重設紅外線接收器狀態,準備接收下一個訊號
  }
}

範例4:利用紅外線遙控RGB LED燈。

//------------------------------------------------------------
#include "IRremote.hpp"             // 引用IRremote函式庫
const int irReceiverPin = 15;       // 紅外線接收器接腳
//------------------------------------------------------------
unsigned long previousMillis = 0;   // 前一次的millis()時間
const long interval = 300;          // 防彈跳時間為 300ms
//------------------------------------------------------------
int rgbPin[3] = {5,18,19};          // R,G,B接腳
int color[10][3] = {
  {0,0,0},            // Black 0
  {255,255,255},      // White 1
  {255,0,0},          // Red 2
  {0,255,0},          // Green 3
  {0,0,255},          // Blue 4 
  {255,255,0},        // Yellow 5
  {255,127,0},        // Orange 6
  {160,32,240},       // Purple 7
  {128,42,42},        // Brown 8
  {255,0,255}         // Pink 9
};
//------------------------------------------------------------

void setup() {
  //-------------------------
  Serial.begin(9600);   // 啟動串列埠監看視窗
  //-------------------------
  IrReceiver.begin(irReceiverPin , ENABLE_LED_FEEDBACK);  // 建立IrReceiver物件,並開啟LED閃爍功能
  //-------------------------
  pinMode(rgbPin[0],OUTPUT);
  pinMode(rgbPin[1],OUTPUT);
  pinMode(rgbPin[2],OUTPUT);
  //-------------------------
}

void loop() {
  if (IrReceiver.decode())    // 若接收到紅外線訊號並成功解碼
  {
    unsigned long currentMillis = millis();          // 當前的millis()時間
    if (currentMillis - previousMillis >= interval)  // 若達到預設計時的時間
    {
      //---------------------------------------------------------------------
      // 每經過一個interval的時間,要做的事
      //---------------------------------------------------------------------
      switch (IrReceiver.decodedIRData.command)  // 判讀接收值
      {
        case 69:
          Serial.println("CH-");
          break;
        case 70:
          Serial.println("CH");
          break;
        case 71:
          Serial.println("CH+");
          break;
        case 68:
          Serial.println("PREV");
          break;
        case 64:
          Serial.println("NEXT");
          break;
        case 67:
          Serial.println("PLAY/PAUSE");
          break;
        case 7:
          Serial.println("VOL-");
          break;
        case 21:
          Serial.println("VOL+");
          break;
        case 9:
          Serial.println("EQ");
          break;
        case 22:
          Serial.println("0");
          Serial.println("Black");
          show_color(0);
          break;
        case 25:
          Serial.println("100+");          
          break;
        case 13:
          Serial.println("200+");
          break;
        case 12:
          Serial.println("1");
          Serial.println("White");
          show_color(1);
          break;
        case 24:
          Serial.println("2");
          Serial.println("Red");
          show_color(2);
          break;
        case 94:
          Serial.println("3");
          Serial.println("Green");
          show_color(3);
          break;
        case 8:
          Serial.println("4");
          Serial.println("Blue");
          show_color(4);
          break;
        case 28:
          Serial.println("5");
          Serial.println("Yellow");
          show_color(5);
          break;
        case 90:
          Serial.println("6");
          Serial.println("Orange");
          show_color(6);
          break;
        case 66:
          Serial.println("7");
          Serial.println("Purple");
          show_color(7);
          break;
        case 82:
          Serial.println("8");
          Serial.println("Brown");
          show_color(8);
          break;
        case 74:
          Serial.println("9");
          Serial.println("Pink");
          show_color(9); 
          break;
        default:
          Serial.println("undefined");
          break;
      }
      //---------------------------------------------------------------------

      previousMillis = currentMillis;  // 更新前一次的millis()時間
    }

    IrReceiver.resume();  // 重設紅外線接收器狀態,準備接收下一個訊號
  }
}

void show_color(int x)
{
  for(int i=0; i<=2; i++)
  {
    analogWrite(rgbPin[i],color[x][i]);
  }  
}

作業練習:

  • 請使用ESP32、紅外線遙控器、紅外線接收器,控制一個RGB LED燈,並將狀態顯示在LCD上。
  • 功能:
    • 啟動時,LCD上顯示”Press the IR remote’s button”。
    • LCD上可顯示目前按下的按鍵名稱。
    • LCD上可顯示目前的亮度百分比。
    • LCD上可顯示目前的顏色名稱,當隨機產生顏色時,則顯示”random”。
    • 按下0-9數字鍵,可直接顯示對應的顏色。(請自行定義0~9對應的顏色)
    • 按下PREV、NEXT鍵,可切換前一個或下一個顏色,可在顏色0~9之間循環切換。
    • 按下VOL+、VOL-鍵,可控制RGB LED的亮度增減,亮度範圍在0%到100%之間,每次調整5%。
    • 按下EQ鍵,可自動且持續隨機產生不同的顏色,每按一下按鈕可啟動或停止。
    • 程式需作防彈跳處理,確保單次按鍵只觸發一次顏色切換或亮度調整等動作。
作業練習操作影片