2026年2月8日 星期日

ESP32 NODEMCU-32S 發送遙控器紅外線訊號

目的:

將之前從電風扇紅外線遙控器讀取的訊號:
ESP32 NODEMCU-32S 讀取遙控器紅外線訊號
在 Arduino IDE 的 Serial Monitor 用鍵盤輸入1~7,讓紅外線發射器發送遙控器上 7 個按鈕的訊號,控制電風扇。

環境:

Win10、Arduino IDE 2.3.7、ESP32 NODEMCU-32S、紅外線發射器(電壓:1.4V~1.6V,電流:20mA)、電阻(90 歐姆)


[關於紅外線接收]

紅外線發射器是一種 LED,發出的光是紅外線。
我看到有兩種紅外線發射器,一種是長短兩隻腳的紅外線 LED,一種是做成做成插上就可使用的電路板模組。
我想自己接電組,所以使用兩隻腳的紅外線 LED。
遙控器發出的紅外線,常用波長有 850nm、940nm 兩種,我不確定原本遙控器是哪種,所以都買來測試。
我買時看到有外觀有 3mm、5mm 兩種大小,也都買來測試。

先講測試結果

  • 850nm、940nm,兩種都可以正常發送紅外線,遙控電風扇。
    個人感覺 940nm 在我的電風扇似乎稍微好一點。
  • 3mm、5mm 兩種大小,兩種都可以正常發送紅外線,遙控電風扇。
    比較大顆的 5mm 感覺有效角度大些,比較不用對準電風扇。




引腳線路接法:

  • GPIO27 (ESP32)  ---------- 電阻(90歐姆) ---------- 正極(+)  (紅外線 LED 長腳)
  • GND (ESP32)  ----------   負極(-) (紅外線 LED 短腳)


安裝 IRremote library:

使用 IRremote 這個 library 處理紅外線訊號,
先到「Tools」->「Manage Libraries...」確認已安裝 IRremote 。


紅外線訊號:

之前讀取的紅外線訊號如後,可知是用 NEC 通訊協議。
用 IrSender.sendNEC(<aAddress>,  <aCommand>, <numberOfRepeats>) 發射訊號。

電源開關
14:32:44.974 -> EF1FEFE
14:32:44.974 -> Protocol=NEC Address=0xFEFE Command=0xF1 Raw-Data=0xEF1FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:32:45.041 -> Send with: IrSender.sendNEC(0xFEFE, 0xF1, <numberOfRepeats>);

減風量
14:23:42.992 -> FB04FEFE
14:23:42.992 -> Protocol=NEC Address=0xFEFE Command=0x4 Raw-Data=0xFB04FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:23:43.100 -> Send with: IrSender.sendNEC(0xFEFE, 0x4, <numberOfRepeats>);

加風量
14:25:02.445 -> F906FEFE
14:25:02.445 -> Protocol=NEC Address=0xFEFE Command=0x6 Raw-Data=0xF906FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:02.576 -> Send with: IrSender.sendNEC(0xFEFE, 0x6, <numberOfRepeats>);

指示燈開關
14:25:50.912 -> CF3FEFE
14:25:50.912 -> Protocol=NEC Address=0xFEFE Command=0xF3 Raw-Data=0xCF3FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:25:50.997 -> Send with: IrSender.sendNEC(0xFEFE, 0xF3, <numberOfRepeats>);

轉頭開關
14:27:12.477 -> DF2FEFE
14:27:12.477 -> Protocol=NEC Address=0xFEFE Command=0xF2 Raw-Data=0xDF2FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:27:12.584 -> Send with: IrSender.sendNEC(0xFEFE, 0xF2, <numberOfRepeats>);

關機定時
14:28:15.624 -> AF5FEFE
14:28:15.624 -> Protocol=NEC Address=0xFEFE Command=0xF5 Raw-Data=0xAF5FEFE 32 bits LSB first Gap=3276750us Duration=75100us
14:28:15.701 -> Send with: IrSender.sendNEC(0xFEFE, 0xF5, <numberOfRepeats>);

開機定時
14:29:05.835 -> 9F6FEFE
14:29:05.835 -> Protocol=NEC Address=0xFEFE Command=0xF6 Raw-Data=0x9F6FEFE 32 bits LSB first Gap=3276750us Duration=75150us
14:29:05.913 -> Send with: IrSender.sendNEC(0xFEFE, 0xF6, <numberOfRepeats>);


程式碼:

後面是 IRremote 4.x 版本的寫法,若版本不同,可到官網 https://github.com/Arduino-IRremote/Arduino-IRremote 查對應的寫法。
若要關閉發送紅外訊號時,開發板內建LED燈閃爍的效果,可在 #include <IRremote.hpp> 之前 #define NO_LED_SEND_FEEDBACK_CODE 或 #define NO_LED_FEEDBACK_CODE
//設定發送訊號時, LED_BUILTIN 這顆 LED 不閃爍
//#define NO_LED_SEND_FEEDBACK_CODE
//#define NO_LED_FEEDBACK_CODE
#include <IRremote.hpp>  // include the library

// 發送紅外線的 GPIO 引腳
const int IR_SEND_PIN = 27;

//要發送的紅外線訊號
int sCmdArrCnt = 7;
uint8_t sCmdArr[7] = {
  0xF1,  //1.電源開關
  0xF2,  //2.轉頭開關
  0xF3,  //3.指示燈開關
  0x4,   //4.減風量
  0xF5,  //5.關機定時
  0xF6,  //6.開機定時
  0x6    //7.加風量
};
String sCmdStrArr[7] = {
  "電源開關",
  "轉頭開關",
  "指示燈開關",
  "減風量",
  "關機定時",
  "開機定時",
  "加風量"
};


void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);

  //version 4.5: LED feedback is always enabled for sending.
  //It can only be disabled by using #define NO_LED_SEND_FEEDBACK_CODE or #define NO_LED_FEEDBACK_CODE.
  IrSender.begin(IR_SEND_PIN);
}

/*
 * Set up the data to be sent.
 * For most protocols, the data is build up with a constant 8 (or 16 byte) address
 * and a variable 8 bit command.
 * There are exceptions like Sony and Denon, which have 5 bit address.
 */
uint16_t sAddress = 0xFEFE;
uint8_t sCommand = 0xF1;
int_fast8_t sRepeats = 0;

void loop() {

  if (Serial.available()) {

    String readString = Serial.readStringUntil('\n');  // Read until newline
    Serial.print("[readString]:");
    Serial.println(readString);

    //轉成整數
    //若用 Serial.parseInt() 讀取整數,讀到換行,會轉成0,導致多執行一次
    int readInt = atoi(readString.c_str());
    Serial.print("[readInt]:");
    Serial.println(readInt);
    if (readInt >= 1 && readInt <= sCmdArrCnt) {
      //7個功能,分別輸入1~7代表,轉成 array index
      int idx = readInt - 1;
      //印出16進位紅外線指令
      Serial.print("0x");
      Serial.println(sCmdArr[idx], HEX);
      Serial.println(sCmdStrArr[idx]);  //文字說明
      IrSender.sendNEC(sAddress, sCmdArr[idx], sRepeats);
    }
    Serial.println("===================");
  }
}
結果



參考:





沒有留言:

張貼留言