2023年8月10日 星期四

ESP32 Infrared Universal Decoder - IR Application

Purpose:

The universal infrared remote control is an example of a helpful device for daily use. You can remotely control household appliances from the smartphone screen by turning such a remote control into an Internet of Things device. For example, turn on the air conditioner in advance when returning home on a hot summer day.

We must first understand the code of the remote control before transmitting.

This project is to use ESP32 to make a Infrared Universal Decoder for home appliance remote control
Fundamental:


圖一: 波長分類

圖二:紅外線發射訊號定義
圖三: oscilloscope signal waveform

圖四: oscilloscope signal waveform meaning
Circuit:


YouTubeDemo:

CodeIntroduce:
#include <BluetoothSerial.h>
#include <IRremote.h>
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t L298NFlag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t BMP180Flag = 0;
  uint8_t DS18B20Flag = 0;
  uint8_t initial_Flag = 0;
  uint8_t Tone_Flag = -1;
  uint8_t IR_RECV_Flag=0;
  uint8_t IR_SEND_Flag=0;
  uint8_t FunctionFlag = 3;
  uint8_t SendFlag = 0;
  uint8_t BMPCnt = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;

//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//---------BT--------------------
BluetoothSerial SerialBT;
//---------IR----------------------------
//Platform     IR input    IR output   Tone      Core/Pin schema
//ESP32        15          4           27
//----- IR define --------------
//const int IR_RECEIVE_PIN = 15;
//const uint16_t IR_SEND_PIN = 4;
#define IR_RECEIVE_PIN          15  // D15
#define IR_SEND_PIN              4  // D4
IRrecv irrecv(IR_RECEIVE_PIN);
IRsend irsend(IR_SEND_PIN);
decode_results results;
//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  //SerialBT.begin("BT_IR");  //worwi no support
  irrecv.enableIRIn();  // Start the receiver
  //irsend.begin();

}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          processCommand(Uart.line); // do something with the command
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    //檢查藍芽內是否有資料
    while (SerialBT.available())
    {
      flag.L298NFlag=1;
      String BTdata = SerialBT.readString();
      //顯示在序列視窗
      Serial.println(BTdata);
      BTprocessCommand(BTdata); // do something with the command
    }//while (BT.available())

    if(flag.IR_RECV_Flag==1)
    {
      if (irrecv.decode(&results))// 接收紅外線訊號並解碼
      {
        Serial.println(results.value, HEX);
        //serialPrintUint64(results.value, HEX);
        dump(&results);
        //translateIR();
        irrecv.resume();
      }
    }

    if(flag.IR_RECV_Flag==2)
    {
      if (irrecv.decode())
      {
        translateIR();
        irrecv.resume();  // Receive the next value
      }
    }

    if(flag.IR_SEND_Flag==1)
    {
      irsend.sendNEC(0x84FBD02F, 32); // 輸出紅外線訊號
    }
  }
}
//-------------------BT-----------------
void BTprocessCommand(String data)
{
  if (data =="F")
  {
    Serial.println(F("Forward"));
    //Forward();
  }
 
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230801"));
  }
  //---------------------------------------
  if (strstr(data, "IR_RECV") != NULL)
  {
    flag.IR_RECV_Flag=1;
    Serial.println(F("IR_RECV"));
  }
  if (strstr(data, "IR_WOKWI") != NULL)
  {
    flag.IR_RECV_Flag=2;
    Serial.println(F("IR_WOKWI"));
  }
  //---------------------------------------
  if (strstr(data, "IR_SEND") != NULL)
  {
    flag.IR_SEND_Flag=1;
    Serial.println(F("IR_SEND"));
  }
}
//-----------------------------------------
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print(F("Unknown encoding: "));
  }
  else if (results->decode_type == NEC) {
    Serial.print(F("Decoded NEC: "));
  }
  else if (results->decode_type == SONY) {
    Serial.print(F("Decoded SONY: "));
  }
  else if (results->decode_type == RC5) {
    Serial.print(F("Decoded RC5: "));
  }
  else if (results->decode_type == RC6) {
    Serial.print(F("Decoded RC6: "));
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print(F("Decoded PANASONIC - Address: "));
    //Serial.print(results->panasonicAddress,HEX);
    Serial.print(F(" Value: "));
  }
  else if (results->decode_type == JVC) {
     Serial.print(F("Decoded JVC: "));
  }
  Serial.print(results->value, HEX);
  Serial.print(F(" ("));
  Serial.print(results->bits, DEC);
  Serial.println(F(" bits)"));
  Serial.print(F("unsigned int YourVariableName ["));
  Serial.print(count-1, DEC);
  Serial.print(F("]={"));
 
  for (int i = 1; i < count; i++) {//ingore data of i=0
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(abs(-(int)results->rawbuf[i]*USECPERTICK), DEC);
    }
    if(i<count-1){
    Serial.print(F(","));
    }
  }
  Serial.println(F("};"));
}
//-----------------------------------------
void translateIR()
{
  // Takes command based on IR code received
  switch (irrecv.decodedIRData.command)
  {
    case 162:
      Serial.println("POWER");
      break;
    case 226:
      Serial.println("MENU");
      break;
    case 34:
      Serial.println("TEST");
      break;
    case 2:
      Serial.println("PLUS");
      break;
    case 194:
      Serial.println("BACK");
      break;
    case 224:
      Serial.println("PREV.");
      break;
    case 168:
      Serial.println("PLAY");
      break;
    case 144:
      Serial.println("NEXT");
      break;
    case 104:
      Serial.println("num: 0");
      break;
    case 152:
      Serial.println("MINUS");
      break;
    case 176:
      Serial.println("key: C");
      break;
    case 48:
      Serial.println("num: 1");
      break;
    case 24:
      Serial.println("num: 2");
      break;
    case 122:
      Serial.println("num: 3");
      break;
    case 16:
      Serial.println("num: 4");
      break;
    case 56:
      Serial.println("num: 5");
      break;
    case 90:
      Serial.println("num: 6");
      break;
    case 66:
      Serial.println("num: 7");
      break;
    case 74:
      Serial.println("num: 8");
      break;
    case 82:
      Serial.println("num: 9");
      break;
    default:
      break;

  }
}
//------------------------------------------------------





end

沒有留言:

張貼留言