ESP32 (EP.8) ESP32 ควบคุมอุปกรณ์ไฟฟ้าในห้อง

วันนี้จะขอเสนอเรื่องการใช้งานประยุกต์ใช้ ESP32 กับรีโมทคอนโทรลในการควบคุมอุปกรณ์ไฟฟ้าในห้อง

การใช้งาน ESP32 ในการควบคุมอุปกรณ์ไฟฟ้าต่าง ๆ ในห้องจะมีความสะดวกมาก  เนื่องจาก ESP32 มีขา GPIO จำนวนมาก (สูงสุดถึงประมาณ 15 ขาในการใช้งานแบบ digital ON/OFF)  และรีโมท 1 อันก็จะมีทั้งแป้นตัวเลขและปุ่มอื่นจำนวนมากเช่นกัน  นั่นก็หมายความว่าเราสามารถควบคุมอุปกรณ์ได้นับสิบอย่างที่มีในห้องโดยที่เรานั่งอยู่กับโต๊ะหรือนอนอยู่บนเตียงก็ได้ครับ

project นี้ค่อนข้างจะง่ายมาก …. ขั้นตอนจะมี 2 อย่างเท่านั้น

ขั้นแรกก็คือเราจะต้องหา code ที่ตัวรีโมทคอนโทรลส่งสัญญาณ Infrared ออกมาก่อน  ซึ่งสัญญาณ infrared ที่รีโมทส่งออกมาจะเป็น pulse train แบบภาพนี้

ซึ่งก็แน่นอนว่าทุกปุ่มของรีโมทคอนโทรลจะมี code ต่างกัน  ลักษณะของ code นี้เมื่อรับโดย ESP32 มันจะแปลง pulse train ที่ซับซ้อนออกมาเป็นชุด data ในรูปแบบ HEX (Hexadecimal numbers) จะต้องทำงานร่วมกับ library ครับ …. ซึ่ง library ใหม่สุดที่แนะนำก็คือ “IRremote” library (พัฒนาโดย shirriff / z3t0 / ArminJo)  ตัวล่าสุดนี้ทำงานได้ดีและให้ HEX data สั้นที่สุด  ดูได้จากคลิปด้านล่างนี้เลยครับ

จากคลิปนี้จะเห็นว่าเมื่อเรากดปุ่มตัวเลข 1 2 3 และอื่น ๆ มันจะให้ HEX data ที่สั้นมาก  เราก็เอา HEX data นี้ไปใส่ใน code ของ ESP32 เพื่อที่จะสั่งงาน GPIO ให้ ON / OFF ตามปุ่มของรีโมทที่เรากดได้

Code ทั้งหมด

#include <Arduino.h>
#include <IRremote.hpp>

// Hardware Pin Definitions
const int IR_RECEIVE_PIN = 15;
const int PIN_BTN1 = 21;
const int PIN_BTN2 = 38;
const int PIN_BTN3 = 39;
const int PIN_BTN4 = 47;
const int PIN_BUZZER = 4;

// Captured IR Raw Data Constants
const uint32_t IR_BTN_1 = 0x7308CF;
const uint32_t IR_BTN_2 = 0xB304CF;
const uint32_t IR_BTN_3 = 0x330CCF;
const uint32_t IR_BTN_4 = 0xD302CF;

// Variables to track output states
bool statePin21 = LOW;
bool statePin38 = LOW;
bool statePin39 = LOW;
bool statePin47 = LOW;

// Non-blocking Buzzer Timing Variables
bool buzzerActive = false;
unsigned long buzzerStartTime = 0;
const unsigned long BUZZER_DURATION = 200; // 0.5 second beep duration

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

  // Initialize GPIO outputs
  pinMode(PIN_BTN1, OUTPUT);
  pinMode(PIN_BTN2, OUTPUT);
  pinMode(PIN_BTN3, OUTPUT);
  pinMode(PIN_BTN4, OUTPUT);
  pinMode(PIN_BUZZER, OUTPUT);

  digitalWrite(PIN_BTN1, LOW);
  digitalWrite(PIN_BTN2, LOW);
  digitalWrite(PIN_BTN3, LOW);
  digitalWrite(PIN_BTN4, LOW);
  digitalWrite(PIN_BUZZER, LOW);

  // Initialize IR Receiver
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  Serial.println("ESP32-S3 IR Control System Ready.");
}

void loop() {
  // 1. Process Incoming IR Commands
  if (IrReceiver.decode()) {
    // Ignore repeat hold signals to prevent accidental fast toggling
    if (!(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
      uint32_t rawData = IrReceiver.decodedIRData.decodedRawData;

      // Trigger Buzzer for 0.5 sec upon receiving any IR command
      digitalWrite(PIN_BUZZER, HIGH);
      buzzerActive = true;
      buzzerStartTime = millis();

      switch (rawData) {
        case IR_BTN_1:
          statePin21 = !statePin21;
          digitalWrite(PIN_BTN1, statePin21);
          Serial.print("Button 1 pressed -> GPIO 21 state: ");
          Serial.println(statePin21 ? "ON" : "OFF");
          break;

        case IR_BTN_2:
          statePin38 = !statePin38;
          digitalWrite(PIN_BTN2, statePin38);
          Serial.print("Button 2 pressed -> GPIO 38 state: ");
          Serial.println(statePin38 ? "ON" : "OFF");
          break;

        case IR_BTN_3:
          statePin39 = !statePin39;
          digitalWrite(PIN_BTN3, statePin39);
          Serial.print("Button 3 pressed -> GPIO 39 state: ");
          Serial.println(statePin39 ? "ON" : "OFF");
          break;

        case IR_BTN_4:
          statePin47 = !statePin47;
          digitalWrite(PIN_BTN4, statePin47);
          Serial.print("Button 4 pressed -> GPIO 47 state: ");
          Serial.println(statePin47 ? "ON" : "OFF");
          break;

        default:
          // Unmapped IR codes
          break;
      }
    }

    IrReceiver.resume(); // Enable receiving the next signal
  }

  // 2. Non-blocking Buzzer Timer (turns OFF active buzzer after 500ms)
  if (buzzerActive && (millis() - buzzerStartTime >= BUZZER_DURATION)) {
    digitalWrite(PIN_BUZZER, LOW);
    buzzerActive = false;
  }
}

อุปกรณ์ที่ใช้มีเพียงเท่านี้  

LED 4 ดวงในภาพต่ออยู่กับ GPIO ของ ESP32 …. ซึ่งในการประยุกต์ใช้งานจริงเราจะต้องต่อวงจรจาก GPIO ต่าง ๆ เพื่อไปควบคุมอุปกรณ์ซึ่งใช้ไฟ 220 โวลต์  วิธีการต่อที่ง่ายที่สุดก็คือใช้ครับรายละเอียดตามภาพด้านล่าง

ในการหา HEX data ของแต่ละปุ่มในการกดรีโมท  อุปกรณ์ที่ใช้มีเพียงเท่านี้

Code ทั้งหมด

#include <Arduino.h>
#include <IRremote.hpp>

// Define the GPIO pin where your IR receiver module (e.g., VS1838B) OUT pin is connected
const int IR_RECEIVE_PIN = 15; 

void setup() {
  // Initialize Serial communication at 115200 baud
  Serial.begin(115200);
  while (!Serial) delay(10); // Wait for Serial to open

  Serial.println("\n--- ESP32 IR Code Scanner ---");
  Serial.println("Point your remote at the receiver and press any button...\n");

  // Start the IR receiver
  // ENABLE_LED_FEEDBACK blinks the ESP32's built-in LED whenever an IR signal is detected
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
  // Check if an IR signal has been received and decoded
  if (IrReceiver.decode()) {
    
    // Ignore repeat signals (when you hold down a button)
    if (!(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
      
      Serial.print("Protocol: ");
      Serial.print(getProtocolString(IrReceiver.decodedIRData.protocol));
      
      // Print the 8-bit Command in HEX format (Most common for button mapping)
      Serial.print(" | Command (HEX): 0x");
      if (IrReceiver.decodedIRData.command < 0x10) Serial.print("0"); // Leading zero formatting
      Serial.print(IrReceiver.decodedIRData.command, HEX);

      // Print the full Raw Data/Address frame in HEX format for reference
      Serial.print(" | Raw Data: 0x");
      Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
    } 
    else {
      Serial.println("[Button Held Down - Repeat Signal]");
    }

    // Prepare the receiver to accept the next IR signal
    IrReceiver.resume(); 
  }
}

ให้ท่านเปลี่ยน HEX data ตามของรีโมทท่าน