Building a Voice Controlled Home Automation System with Arduino

Published  February 14, 2024   0
Voice Controlled Home Automation Using Arduino

Voice Controlled Home Automation Using Arduino is an exciting project that aims to automate home appliances with the power of voice commands. In this project, voice instructions will be recognised, and text-to-speech conversion will be performed using an Android app. The HC-05 module will then be used to transmit the text data via Bluetooth to an Arduino microcontroller. This system is very practical and user-friendly because it enables users to simply control and manage home appliances using basic voice commands. This idea offers a new degree of automation and efficiency in managing home appliances thanks to the integration of modern technology.

We previously built many Home automation projects including few voice controlled home appliances projects.

How Does the Voice Controlled Home Automation Work?

As mentioned in the intro we will be using an android app to detect the voice command. Once the voice commands are recognised the command will be converted to text using the same app, this text data will then send to the Arduino nano using Bluetooth. For that we have used the famous HC-05 Bluetooth module. The HC-05 module will communicate with the phone using Bluetooth SPP(Serial Port Profile). Once a data is received the module will transfer the data to Arduino nano over the UART line. Here we have used the default serial, but you can also use software serial over any other pins. Once the data is received the Arduino nano will decode it and perform tasks accordingly.

Components Required to Voice Controlled Home Automation

All the parts you will require to build the voice-controlled home automation project are listed below,

  • Arduino Nano - x1
  • HC-05 Bluetooth Module - x1
  • Hi-link 5V 3W Power Supply Module - x1
  • VS1838 IR Sensor - x1
  • 5MM IR LED - x1
  • S8050 NPN Transistor - x5
  • 5V Relays - x4
  • 1N4007 Diode - x4
  • 5MM LED - x4
  • 1 KOhms Resistor - x5
  • 470 Ohms Resistor - x4
  • 10A screw terminal 2 Pin - x5
  • Perfboard
  • WiresCable sleeve
  • Connectors and pin headers
  • Pref board
  • Other necessary tools

Voice Controlled Home Automation Using Arduino - Circuit Diagram

The complete circuit diagram for the Voice Controlled Home Automation Using Arduino is shown below.

Voice Controlled Home Automation Using Arduino - Circuit Diagram

The schematic diagram for the project is very simple. A Hi-Link 5V AC-DC module is used as the power source. The AC input is directly connected to the power supply module. The 5V output from it will be used to power the entire control circuit. You can also find 4 separate relays with their respective driver circuits. The relay driver circuit is built around the S8050 NPN transistor. One coil terminal of the relay is connected to the 5V supply line. When a high pulse is applied to the base of the driver transistor, it will pull the other coil terminal to the ground line. A 1N4007 diode is used as freewheeling diode to protect the circuitry from any potential flyback voltages. An LED with current limit resistor is used to indicate the status of each relay.

The Bluetooth module is connected to the Arduino using the UART line. There is no configuration is required with the Bluetooth module, it communicates with the Arduino in its default baud rate. You can also use other similar Bluetooth module with SPP profile support. But make sure to set the baud rate to 9600. The IR sensor VS1838 is interfaced using the pin D2. Since the IR decoder library is depending on hardware interrupt, make sure to use the same pin. Once in the learning mode, when a IR signal is detected, it will trigger the interrupt routine and decode the IR signals. The IR transmitter LED is driven using a S8050 NPN transistor and is driven with the pin D3. Similar to the sensor pin this pin also cannot be changed because of the library dependency. We will use the PWM out from this pin to send the IR signals. Lastly, the RGB neopixel LEDs are interfaced via the pin D3. Make sure to change the number of LEDs in the code as per your use case. Also makes sure to power the RGB led externally if the number of LEDs are high.

Voice Controlled Home Automation Circuit

Arduino Code for Voice Controlled Home Automation

As a first step make sure to install all the necessary Arduino libraries, and they are namely IRMP library for IR sensing and transmission and the FastLED library for controlling the RGB LEDs. Once You can install them directly from Arduino Library manager or you can manually install them by downloading them from our GitHub repo. Once installed, download, and open the Arduino code we have provided. Now let’s look at the code.

#include <Arduino.h>
#include <FastLED.h>
#include <EEPROM.h>
#define DATA_PIN 12        //Define led data pin in
#define LED_TYPE NEOPIXEL  //define type of led
#define NUM_LEDS 16        //num of leds in strip
#define IRMP_INPUT_PIN 2   // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#define IRSND_IR_FREQUENCY 38000
#define IRMP_PROTOCOL_NAMES 1         // Enable protocol number mapping to protocol strings - needs some program memory ~ 420 bytes here
#define IRMP_USE_COMPLETE_CALLBACK 1  // Enable callback functionality
// Decode protocol list!disable unwanted     Enable  Remarks      F_INTERRUPTS            program memory
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1         // Sony SIRCS           >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1           // NEC + APPLE + ONKYO  >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1       // Samsung + Samsg32    >= 10000                 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1      // Kaseikyo             >= 10000                 ~250 bytes
#define IRMP_SUPPORT_JVC_PROTOCOL 1           // JVC                  >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL 1         // NEC16                >= 10000                 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL 1         // NEC42                >= 10000                 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1    // Matsushita           >= 10000                  ~50 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1         // DENON, Sharp         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 1           // RC5                  >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1           // RC6 & RC6A           >= 10000                 ~250 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL 1          // IR60 (SDA2008)       >= 10000                 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1       // Grundig              >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1       // Siemens Gigaset      >= 15000                 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL 1         // Nokia                >= 10000                 ~300 bytes
#define IRMP_SUPPORT_BOSE_PROTOCOL 1          // BOSE                 >= 10000                 ~150 bytes
#define IRMP_SUPPORT_KATHREIN_PROTOCOL 1      // Kathrein             >= 10000                 ~200 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL 1        // NUBERT               >= 10000                  ~50 bytes
#define IRMP_SUPPORT_FAN_PROTOCOL 0           // FAN (ventilator)     >= 10000                  ~50 bytes     conflicts with NUBERT
#define IRMP_SUPPORT_SPEAKER_PROTOCOL 1       // SPEAKER (~NUBERT)    >= 10000                  ~50 bytes
#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 1  // Bang & Olufsen       >= 10000                 ~200 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL 1        // RECS80 (SAA3004)     >= 15000                  ~50 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 1     // RECS80EXT (SAA3008)  >= 15000                  ~50 bytes
#define IRMP_SUPPORT_THOMSON_PROTOCOL 1       // Thomson              >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NIKON_PROTOCOL 1         // NIKON camera         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NETBOX_PROTOCOL 1        // Netbox keyboard      >= 10000                 ~400 bytes (PROTOTYPE!)
#define IRMP_SUPPORT_ORTEK_PROTOCOL 0         // ORTEK (Hama)         >= 10000                 ~150 bytes     conflicts with FDC and NETBOX
#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 1    // Telefunken 1560      >= 10000                 ~150 bytes
#define IRMP_SUPPORT_FDC_PROTOCOL 1           // FDC3402 keyboard     >= 10000 (better 15000)  ~150 bytes (~400 in combination with RC5)
#define IRMP_SUPPORT_RCCAR_PROTOCOL 1         // RC Car               >= 10000 (better 15000)  ~150 bytes (~500 in combination with RC5)
#define IRMP_SUPPORT_ROOMBA_PROTOCOL 0        // iRobot Roomba        >= 10000                 ~150 bytes     conflicts with RC6
#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0        // RUWIDO, T-Home       >= 15000                 ~550 bytes     conflicts with DENON
#define IRMP_SUPPORT_A1TVBOX_PROTOCOL 1       // A1 TV BOX            >= 15000 (better 20000)  ~300 bytes
#define IRMP_SUPPORT_LEGO_PROTOCOL 1          // LEGO Power RC        >= 20000                 ~150 bytes
#define IRMP_SUPPORT_RCMM_PROTOCOL 1          // RCMM 12,24, or 32    >= 20000                 ~150 bytes
#define IRMP_SUPPORT_LGAIR_PROTOCOL 1         // LG Air Condition     >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 1     // Samsung48            >= 10000                 ~100 bytes (SAMSUNG must be enabled!)
#define IRMP_SUPPORT_MERLIN_PROTOCOL 1        // Merlin               >= 15000 (better 20000)  ~300 bytes (requires IRMP_32_BIT=1)
#define IRMP_SUPPORT_PENTAX_PROTOCOL 1        // Pentax               >= 10000 <=17000         ~150 bytes (<= 17000 due to 8 bit timing overflow issue)
#define IRMP_SUPPORT_S100_PROTOCOL 0          // S100                 >= 10000                 ~250 bytes     conflicts with RC5
#define IRMP_SUPPORT_ACP24_PROTOCOL 0         // ACP24                >= 10000                 ~250 bytes     conflicts with DENON
#define IRMP_SUPPORT_TECHNICS_PROTOCOL 1      // TECHNICS             >= 10000                 ~250 bytes
#define IRMP_SUPPORT_PANASONIC_PROTOCOL 0     // PANASONIC Beamer     >= 10000                 ~250 bytes     conflicts with KASEIKYO
#define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0   // Mitsubishi Aircond   >= 10000                 ~250 bytes     conflicts with KASEIKYO
#define IRMP_SUPPORT_VINCENT_PROTOCOL 1       // VINCENT              >= 10000                 ~250 bytes
#define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 1     // SAMSUNG AH           >= 10000                 ~250 bytes
#define IRMP_SUPPORT_IRMP16_PROTOCOL 0        // IRMP specific        >= 15000                 ~250 bytes
#define IRMP_SUPPORT_GREE_PROTOCOL 1          // GREE CLIMATE         >= 10000 <=17000         ~250 bytes
#define IRMP_SUPPORT_RCII_PROTOCOL 0          // RCII T+A             >= 15000                 ~250 bytes     conflicts with GRUNDIG and NOKIA
#define IRMP_SUPPORT_METZ_PROTOCOL 1
#define IRMP_SUPPORT_MELINERA_PROTOCOL 1  // MELINERA (Lidl)      >= 10000
// Encode protocol list!disable unwanted    Enable  Remarks        F_INTERRUPTS            program memory
#define IRSND_SUPPORT_SIRCS_PROTOCOL 1         // Sony SIRCS           >= 10000                 ~200 bytes
#define IRSND_SUPPORT_NEC_PROTOCOL 1           // NEC + APPLE          >= 10000                 ~100 bytes
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1       // Samsung + Samsung32  >= 10000                 ~300 bytes
#define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1      // Kaseikyo             >= 10000                 ~300 bytes
#define IRSND_SUPPORT_JVC_PROTOCOL 1           // JVC                  >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NEC16_PROTOCOL 1         // NEC16                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NEC42_PROTOCOL 1         // NEC42                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1    // Matsushita           >= 10000                 ~200 bytes
#define IRSND_SUPPORT_DENON_PROTOCOL 1         // DENON, Sharp         >= 10000                 ~200 bytes
#define IRSND_SUPPORT_RC5_PROTOCOL 1           // RC5                  >= 10000                 ~150 bytes
#define IRSND_SUPPORT_RC6_PROTOCOL 1           // RC6                  >= 10000                 ~250 bytes
#define IRSND_SUPPORT_RC6A_PROTOCOL 1          // RC6A                 >= 10000                 ~250 bytes
#define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1       // Grundig              >= 10000                 ~300 bytes
#define IRSND_SUPPORT_SIEMENS_PROTOCOL 1       // Siemens, Gigaset     >= 15000                 ~150 bytes
#define IRSND_SUPPORT_NOKIA_PROTOCOL 1         // Nokia                >= 10000                 ~400 bytes
#define IRSND_SUPPORT_IR60_PROTOCOL 0          // IR60 (SDA2008)       >= 10000                 ~250 bytes // IR frequency 30 kHz
#define IRSND_SUPPORT_BOSE_PROTOCOL 1          // BOSE                 >= 10000                 ~100 bytes
#define IRSND_SUPPORT_KATHREIN_PROTOCOL 0      // Kathrein             >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_NUBERT_PROTOCOL 1        // NUBERT               >= 10000                 ~100 bytes
#define IRSND_SUPPORT_FAN_PROTOCOL 1           // FAN (ventilator)     >= 10000                 ~100 bytes
#define IRSND_SUPPORT_SPEAKER_PROTOCOL 1       // SPEAKER              >= 10000                 ~100 bytes
#define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0  // Bang&Olufsen         >= 10000                 ~250 bytes // IR frequency 455 kHz
#define IRSND_SUPPORT_RECS80_PROTOCOL 1        // RECS80               >= 15000                 ~100 bytes
#define IRSND_SUPPORT_RECS80EXT_PROTOCOL 1     // RECS80EXT            >= 15000                 ~100 bytes
#define IRSND_SUPPORT_THOMSON_PROTOCOL 1       // Thomson              >= 10000                 ~250 bytes
#define IRSND_SUPPORT_NIKON_PROTOCOL 1         // NIKON                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NETBOX_PROTOCOL 0        // Netbox keyboard      >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ORTEK_PROTOCOL 0         // ORTEK (Hama)         >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 1    // Telefunken 1560      >= 10000                 ~150 bytes
#define IRSND_SUPPORT_FDC_PROTOCOL 1           // FDC IR keyboard      >= 10000 (better 15000)  ~150 bytes
#define IRSND_SUPPORT_RCCAR_PROTOCOL 1         // RC CAR               >= 10000 (better 15000)  ~150 bytes
#define IRSND_SUPPORT_ROOMBA_PROTOCOL 1        // iRobot Roomba        >= 10000                 ~150 bytes
#define IRSND_SUPPORT_RUWIDO_PROTOCOL 1        // RUWIDO, T-Home       >= 15000                 ~250 bytes
#define IRSND_SUPPORT_A1TVBOX_PROTOCOL 1       // A1 TV BOX            >= 15000 (better 20000)  ~200 bytes
#define IRSND_SUPPORT_LEGO_PROTOCOL 1          // LEGO Power RC        >= 20000                 ~150 bytes
#define IRSND_SUPPORT_RCMM_PROTOCOL 0          // RCMM 12,24, or 32    >= 20000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_LGAIR_PROTOCOL 1         // LG Air Condition     >= 10000                 ~150 bytes.
#define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 1     // Samsung48            >= 10000                 ~100 bytes
#define IRSND_SUPPORT_PENTAX_PROTOCOL 1        // Pentax               >= 10000                 ~150 bytes
#define IRSND_SUPPORT_S100_PROTOCOL 1          // S100                 >= 10000                 ~150 bytes
#define IRSND_SUPPORT_ACP24_PROTOCOL 1         // ACP24                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_TECHNICS_PROTOCOL 1      // TECHNICS             >= 10000                 ~200 bytes
#define IRSND_SUPPORT_PANASONIC_PROTOCOL 1     // PANASONIC Beamer     >= 10000                 ~150 bytes
#define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 1   // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer
#define IRSND_SUPPORT_IRMP16_PROTOCOL 0        // IRMP specific        >= 15000                 ~250 bytes
#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND
#include <irmp.hpp>
#include <irsnd.hpp>
IRMP_DATA irmp_data;
IRMP_DATA irsnd_data;
int Prortocol_Index[58] = { IRMP_UNKNOWN_PROTOCOL, IRMP_SIRCS_PROTOCOL, IRMP_NEC_PROTOCOL, IRMP_SAMSUNG_PROTOCOL, IRMP_MATSUSHITA_PROTOCOL, IRMP_KASEIKYO_PROTOCOL, IRMP_RECS80_PROTOCOL, IRMP_RC5_PROTOCOL, IRMP_DENON_PROTOCOL, IRMP_RC6_PROTOCOL, IRMP_SAMSUNG32_PROTOCOL, IRMP_APPLE_PROTOCOL, IRMP_RECS80EXT_PROTOCOL, IRMP_NUBERT_PROTOCOL, IRMP_BANG_OLUFSEN_PROTOCOL, IRMP_GRUNDIG_PROTOCOL, IRMP_NOKIA_PROTOCOL, IRMP_SIEMENS_PROTOCOL, IRMP_FDC_PROTOCOL, IRMP_RCCAR_PROTOCOL, IRMP_JVC_PROTOCOL, IRMP_RC6A_PROTOCOL, IRMP_NIKON_PROTOCOL, IRMP_RUWIDO_PROTOCOL, IRMP_IR60_PROTOCOL, IRMP_KATHREIN_PROTOCOL, IRMP_NETBOX_PROTOCOL, IRMP_NEC16_PROTOCOL, IRMP_NEC42_PROTOCOL, IRMP_LEGO_PROTOCOL, IRMP_THOMSON_PROTOCOL, IRMP_BOSE_PROTOCOL, IRMP_A1TVBOX_PROTOCOL, IRMP_ORTEK_PROTOCOL, IRMP_TELEFUNKEN_PROTOCOL, IRMP_ROOMBA_PROTOCOL, IRMP_RCMM32_PROTOCOL, IRMP_RCMM24_PROTOCOL, IRMP_RCMM12_PROTOCOL, IRMP_SPEAKER_PROTOCOL, IRMP_LGAIR_PROTOCOL, IRMP_SAMSUNG48_PROTOCOL, IRMP_MERLIN_PROTOCOL, IRMP_PENTAX_PROTOCOL, IRMP_FAN_PROTOCOL, IRMP_S100_PROTOCOL, IRMP_ACP24_PROTOCOL, IRMP_TECHNICS_PROTOCOL, IRMP_PANASONIC_PROTOCOL, IRMP_MITSU_HEAVY_PROTOCOL, IRMP_VINCENT_PROTOCOL, IRMP_SAMSUNGAH_PROTOCOL, IRMP_IRMP16_PROTOCOL, IRMP_GREE_PROTOCOL, IRMP_RCII_PROTOCOL, IRMP_METZ_PROTOCOL, IRMP_ONKYO_PROTOCOL };
struct CRGB leds[NUM_LEDS];  // Initialize LED array
const int Relay1 = 5;        // Relay pin 1 (IN1)
const int Relay2 = 4;        // Relay pin 2 (IN2)
const int Relay3 = 6;        // Relay pin 3 (IN3)
const int Relay4 = 7;        // Relay pin 4 (IN4)
int irrec = 0;
String data;  //Variable for storing received data
int proto;
uint16_t addr, cmd, temp;
int eeadr;
void handleReceivedIRData();
void IRDecoder();
void SerialDecoder();
bool volatile sIRMPDataAvailable = false;

At the start, as usual we included all the necessary libraries. And enabled all the IR protocols we needed. At this code we have enabled all the IR protocols, about 40 of them. If you don’t need it you can disable them by commenting out the respective definition, it will reduce the code size and RAM usage. After that we have created two instances for IR sensor for receiving and sending IR signals along with the instance for FastLED library. And we have also declared all the global variables for the code in this section.

void setup() {
  Serial.begin(9600);  //Sets the baud for serial data transmission
  FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
  // Set Relay pins as OUTPUT
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  pinMode(Relay3, OUTPUT);
  pinMode(Relay4, OUTPUT);
  // Init all relays to off
  digitalWrite(Relay1, LOW);
  digitalWrite(Relay2, LOW);
  digitalWrite(Relay3, LOW);
  digitalWrite(Relay4, LOW);
  irmp_init();
  irmp_irsnd_LEDFeedback(true);  // Enable receive signal feedback at LED_BUILTIN
  irmp_register_complete_callback_function(&handleReceivedIRData);
  irsnd_init();
}

In the setup function we have initialized the serial port with a baud rate of 9600. Ii is the default baud rate of HC-05 module. If you change the baud rate of HC-05 module, make sure to change it in the setup function too. Then we have initialized the FastLED library, along with initialized the relay control pins as output and set them to LOW at the startup. Later we have initialized the IRMP library instances and the interrupt handler.

void loop() {
  // Read data from Bluetooth Module
  char ch = 0;
  data = "";
  while (1) { // When there is no command received the MCU will be in this loop.
    while (Serial.available() <= 0) {
      if (irrec > 0) {
        IRDecoder();// Call IR decoder function when a valid command is detected
      }
      digitalWrite(13, irrec);
    };
    ch = Serial.read();
    if (ch == '#')
      break; // break the loop when a command is received
    data += ch;
  }
  SerialDecoder();// call serial Decoder function
}

In the loop function we have created two other loops. The Arduino will check if there is a data in the UART buffer. When there is a data available, it will be loaded into a variable and will break the loop as soon as the end character is detected. After breaking out of the loop, it will call the SerialDecoder function for decode the prompt. After that it will goback to the previous loop. In the loop if the command was to record a certain IR signal it will listen for new IR signal by calling IRDecoder function.

void SerialDecoder() {
  // Print Bluetooth Module data on serial monitor
  Serial.print(data);
  Serial.print("\n");
  // Control the devices using voice command
  if (data.startsWith("*turn on light"))  // turn on Device1 {
    digitalWrite(Relay1, HIGH);
    Serial.println("  :   light on");
    delay(200);
  } else if (data.startsWith("*turn off light"))  // turn off Device1
  {
    digitalWrite(Relay1, LOW);
    Serial.println("  :   light off");
    delay(2000);
  } else if (data.startsWith("*turn on TV"))  // turn on Device2
  {
    digitalWrite(Relay2, HIGH);
    Serial.println("  :   TV on");
    delay(200);
  }
  else if (data.startsWith("*turn off TV"))  // turn off Device2
  {
    digitalWrite(Relay2, LOW);
    Serial.println("  :   TV off");
    delay(200);
  } else if (data.startsWith("*turn on fan"))  // turn on Device3
  {
    digitalWrite(Relay3, HIGH);
    Serial.println("  :   fan on");
    delay(200);
  } else if (data.startsWith("*turn off fan"))  // turn off Device3
  {
    digitalWrite(Relay3, LOW);
    Serial.println("  :   fan off");
    delay(200);
  } else if (data.startsWith("*turn on music"))  // turn on Device4
  {
    digitalWrite(Relay4, HIGH);
    Serial.println("  :   music on");
    delay(200);
  } else if (data.startsWith("*turn off music"))  // turn off Device4
  {
    digitalWrite(Relay4, LOW);
    Serial.println("  :   music off");
    delay(200);
  } else if (data.startsWith("*turn on all"))  // turn on all Device
  {
    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2, HIGH);
    digitalWrite(Relay3, HIGH);
    digitalWrite(Relay4, HIGH);
    Serial.println("  :   All Relays on");
    delay(200);
  } else if (data.startsWith("*turn off all"))  // turn off all Device
  {
    digitalWrite(Relay1, LOW);
    digitalWrite(Relay2, LOW);
    digitalWrite(Relay3, LOW);
    digitalWrite(Relay4, LOW);
    Serial.println("  :   All Relays off");
    delay(200);
  } else if (data.startsWith("*RGB red"))  // set the RGB leds to red
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Red;  //set the RGB leds to red
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB green"))  //set the RGB leds to green
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Green;  //set the RGB leds to green
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB blue"))  // set the RGB leds to blue
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Blue;  //set the RGB leds to blue
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB yellow"))  // set the RGB leds to yellow
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Yellow;  //set the RGB leds to yellow
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB white"))  // // set the RGB leds to  white
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::White;  //set the RGB leds to white
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*turn off RGB"))  // turn off all RGB LEDS
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Black;  //turn off all RGB LEDS
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*record power"))  // record and save remote power button
  {
    irrec = 12;
    IRDecoder();
    irrec = 1;
    delay(200);
  } else if (data.startsWith("*record volume up"))  // record and save remote volume up button
  {
    irrec = 12;
    IRDecoder();
    irrec = 2;
    delay(200);
  } else if (data.startsWith("*record volume down"))  // record and save remote volume down button
  {
    irrec = 12;
    IRDecoder();
    irrec = 3;
    delay(200);
  } else if (data.startsWith("*record next"))  // record and save remote next button
  {
    irrec = 12;
    IRDecoder();
    irrec = 4;
    Serial.print("irrec :");
    Serial.println(irrec);
    delay(200);
  } else if (data.startsWith("*record previous"))  /// record and save remote previous button
  {
    irrec = 12;
    IRDecoder();
    irrec = 5;
    delay(200);
  }
  else if (data.startsWith("*remote power"))  // Recall and send remote power button signal
  {
    eeadr = 10;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote volume up"))  // Recall and send remote volume up button signal
  {
    eeadr = 20;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote volume down")) // Recall and send remote volume down button signal
  {
    eeadr = 30;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote next"))  // Recall and send remote next button signal
  {
    eeadr = 40;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote previous"))  // Recall and send remote previous button signal
  {
    eeadr = 50;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  }
}

The SerialDecoder function is responsible for decoding all the voice prompts as well as executing them. The function will compare the received prompt with predefined once using an if else ladder and when it detects a match it will execute the corresponding function. If you want to customize the voice prompts or you want to add additional voice prompts modify this function.

void Rotary() {
  delay(75);
  if (digitalRead(PinCLK))
    rotationdirection = digitalRead(PinDT);
  else
    rotationdirection = !digitalRead(PinDT);
  TurnDetected = true;
  delay(75);
}

The Rotary function will execute as soon as an interrupt occurs at the D3 pin, which is connected to the CLK pin of the rotary encoder. When this function is executed, it will detect the rotation direction and will set the rotationdirection flag accordingly. It will also set another flag called TurnDetected to let the loop function know that a turn is detected.

void IRDecoder() {
  if (sIRMPDataAvailable) {
    int eepaddr = irrec;
    irrec = 0;
    int rpt;
    sIRMPDataAvailable = false;
    irmp_result_print(&irmp_data);
    proto = irmp_data.protocol;
    addr = irmp_data.address;
    cmd = irmp_data.command;
    // save signal data to EEPROM
    if (eepaddr < 10) {
      if (proto == 0) {
        EEPROM.write(eepaddr * 10, 0x0);
      } else {
        EEPROM.write(eepaddr * 10, proto);
      }
      if (addr == 0) {
        EEPROM.write((eepaddr * 10) + 1, 0);
        EEPROM.write((eepaddr * 10) + 2, 0);
      } else {
        EEPROM.write((eepaddr * 10) + 1, addr);
        EEPROM.write((eepaddr * 10) + 2, addr >> 8);
      }
      if (cmd == 0) {
        EEPROM.write((eepaddr * 10) + 3, 0x0);
        EEPROM.write((eepaddr * 10) + 4, 0x0);
      } else {
        EEPROM.write((eepaddr * 10) + 3, cmd);
        EEPROM.write((eepaddr * 10) + 4, cmd >> 8);
      }
    }
  }
}

The IR decoder function will listen for new IR signals and when it detects a valid signal it will decode the signal into protocol, address and command. Once decoded it will store these values to the EEPROM in the respective addresses. With this function you don’t need to hard code any IR signal data , you can save or re program them as you wish with voice prompt.

void handleReceivedIRData() {
  irmp_get_data(&irmp_data);
  sIRMPDataAvailable = true;
}

The handleReceivedIRData function is the interrupt handler function responsible for detecting the IR signals. This function works in the background and stores the received signal in the buffer for processing.

How to Use the Voice Controlled Home Automation?

To use the project first you need to install an app called BT Voice Control for Arduino (AMR_voice). You can find the app from the GitHub repo linked below this article or you can download it directly from Play Store. Once downloaded and installed, Enable the Bluetooth, Pair the HC-05 module and open the app. In the app, select Connect Robot option from the menu and it will list all the paired Bluetooth devices. Select the HC-05 module from the list and the app will establish connection with the module.

Home Automation Application

Once connected all you have to do is press the microphone button and it will bring up the voice prompt option. Say the correct prompt and enjoy controlling your device with voice prompts. Here are the default voice prompts in the given program.

You can download all the necessary files from the Circuit Digest GitHub repo, from the following link.

 And here are a few projects related to Arduino, Bluetooth, and Home automation you might find interesting

Code
#include <Arduino.h>
#include <FastLED.h>
#include <EEPROM.h>
#define DATA_PIN 12        //Define led data pin in
#define LED_TYPE NEOPIXEL  //define type of led
#define NUM_LEDS 16        //num of leds in strip
#define IRMP_INPUT_PIN 2   // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#define IRSND_IR_FREQUENCY 38000
#define IRMP_PROTOCOL_NAMES 1         // Enable protocol number mapping to protocol strings - needs some program memory ~ 420 bytes here
#define IRMP_USE_COMPLETE_CALLBACK 1  // Enable callback functionality
// Decode protocol list!disable unwanted     Enable  Remarks      F_INTERRUPTS            program memory
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1         // Sony SIRCS           >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1           // NEC + APPLE + ONKYO  >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1       // Samsung + Samsg32    >= 10000                 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1      // Kaseikyo             >= 10000                 ~250 bytes
#define IRMP_SUPPORT_JVC_PROTOCOL 1           // JVC                  >= 10000                 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL 1         // NEC16                >= 10000                 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL 1         // NEC42                >= 10000                 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1    // Matsushita           >= 10000                  ~50 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1         // DENON, Sharp         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 1           // RC5                  >= 10000                 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1           // RC6 & RC6A           >= 10000                 ~250 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL 1          // IR60 (SDA2008)       >= 10000                 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1       // Grundig              >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1       // Siemens Gigaset      >= 15000                 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL 1         // Nokia                >= 10000                 ~300 bytes
#define IRMP_SUPPORT_BOSE_PROTOCOL 1          // BOSE                 >= 10000                 ~150 bytes
#define IRMP_SUPPORT_KATHREIN_PROTOCOL 1      // Kathrein             >= 10000                 ~200 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL 1        // NUBERT               >= 10000                  ~50 bytes
#define IRMP_SUPPORT_FAN_PROTOCOL 0           // FAN (ventilator)     >= 10000                  ~50 bytes     conflicts with NUBERT
#define IRMP_SUPPORT_SPEAKER_PROTOCOL 1       // SPEAKER (~NUBERT)    >= 10000                  ~50 bytes
#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 1  // Bang & Olufsen       >= 10000                 ~200 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL 1        // RECS80 (SAA3004)     >= 15000                  ~50 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 1     // RECS80EXT (SAA3008)  >= 15000                  ~50 bytes
#define IRMP_SUPPORT_THOMSON_PROTOCOL 1       // Thomson              >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NIKON_PROTOCOL 1         // NIKON camera         >= 10000                 ~250 bytes
#define IRMP_SUPPORT_NETBOX_PROTOCOL 1        // Netbox keyboard      >= 10000                 ~400 bytes (PROTOTYPE!)
#define IRMP_SUPPORT_ORTEK_PROTOCOL 0         // ORTEK (Hama)         >= 10000                 ~150 bytes     conflicts with FDC and NETBOX
#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 1    // Telefunken 1560      >= 10000                 ~150 bytes
#define IRMP_SUPPORT_FDC_PROTOCOL 1           // FDC3402 keyboard     >= 10000 (better 15000)  ~150 bytes (~400 in combination with RC5)
#define IRMP_SUPPORT_RCCAR_PROTOCOL 1         // RC Car               >= 10000 (better 15000)  ~150 bytes (~500 in combination with RC5)
#define IRMP_SUPPORT_ROOMBA_PROTOCOL 0        // iRobot Roomba        >= 10000                 ~150 bytes     conflicts with RC6
#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0        // RUWIDO, T-Home       >= 15000                 ~550 bytes     conflicts with DENON
#define IRMP_SUPPORT_A1TVBOX_PROTOCOL 1       // A1 TV BOX            >= 15000 (better 20000)  ~300 bytes
#define IRMP_SUPPORT_LEGO_PROTOCOL 1          // LEGO Power RC        >= 20000                 ~150 bytes
#define IRMP_SUPPORT_RCMM_PROTOCOL 1          // RCMM 12,24, or 32    >= 20000                 ~150 bytes
#define IRMP_SUPPORT_LGAIR_PROTOCOL 1         // LG Air Condition     >= 10000                 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 1     // Samsung48            >= 10000                 ~100 bytes (SAMSUNG must be enabled!)
#define IRMP_SUPPORT_MERLIN_PROTOCOL 1        // Merlin               >= 15000 (better 20000)  ~300 bytes (requires IRMP_32_BIT=1)
#define IRMP_SUPPORT_PENTAX_PROTOCOL 1        // Pentax               >= 10000 <=17000         ~150 bytes (<= 17000 due to 8 bit timing overflow issue)
#define IRMP_SUPPORT_S100_PROTOCOL 0          // S100                 >= 10000                 ~250 bytes     conflicts with RC5
#define IRMP_SUPPORT_ACP24_PROTOCOL 0         // ACP24                >= 10000                 ~250 bytes     conflicts with DENON
#define IRMP_SUPPORT_TECHNICS_PROTOCOL 1      // TECHNICS             >= 10000                 ~250 bytes
#define IRMP_SUPPORT_PANASONIC_PROTOCOL 0     // PANASONIC Beamer     >= 10000                 ~250 bytes     conflicts with KASEIKYO
#define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0   // Mitsubishi Aircond   >= 10000                 ~250 bytes     conflicts with KASEIKYO
#define IRMP_SUPPORT_VINCENT_PROTOCOL 1       // VINCENT              >= 10000                 ~250 bytes
#define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 1     // SAMSUNG AH           >= 10000                 ~250 bytes
#define IRMP_SUPPORT_IRMP16_PROTOCOL 0        // IRMP specific        >= 15000                 ~250 bytes
#define IRMP_SUPPORT_GREE_PROTOCOL 1          // GREE CLIMATE         >= 10000 <=17000         ~250 bytes
#define IRMP_SUPPORT_RCII_PROTOCOL 0          // RCII T+A             >= 15000                 ~250 bytes     conflicts with GRUNDIG and NOKIA
#define IRMP_SUPPORT_METZ_PROTOCOL 1
#define IRMP_SUPPORT_MELINERA_PROTOCOL 1  // MELINERA (Lidl)      >= 10000

// Encode protocol list!disable unwanted    Enable  Remarks        F_INTERRUPTS            program memory
#define IRSND_SUPPORT_SIRCS_PROTOCOL 1         // Sony SIRCS           >= 10000                 ~200 bytes
#define IRSND_SUPPORT_NEC_PROTOCOL 1           // NEC + APPLE          >= 10000                 ~100 bytes
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1       // Samsung + Samsung32  >= 10000                 ~300 bytes
#define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1      // Kaseikyo             >= 10000                 ~300 bytes
#define IRSND_SUPPORT_JVC_PROTOCOL 1           // JVC                  >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NEC16_PROTOCOL 1         // NEC16                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NEC42_PROTOCOL 1         // NEC42                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1    // Matsushita           >= 10000                 ~200 bytes
#define IRSND_SUPPORT_DENON_PROTOCOL 1         // DENON, Sharp         >= 10000                 ~200 bytes
#define IRSND_SUPPORT_RC5_PROTOCOL 1           // RC5                  >= 10000                 ~150 bytes
#define IRSND_SUPPORT_RC6_PROTOCOL 1           // RC6                  >= 10000                 ~250 bytes
#define IRSND_SUPPORT_RC6A_PROTOCOL 1          // RC6A                 >= 10000                 ~250 bytes
#define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1       // Grundig              >= 10000                 ~300 bytes
#define IRSND_SUPPORT_SIEMENS_PROTOCOL 1       // Siemens, Gigaset     >= 15000                 ~150 bytes
#define IRSND_SUPPORT_NOKIA_PROTOCOL 1         // Nokia                >= 10000                 ~400 bytes
#define IRSND_SUPPORT_IR60_PROTOCOL 0          // IR60 (SDA2008)       >= 10000                 ~250 bytes // IR frequency 30 kHz
#define IRSND_SUPPORT_BOSE_PROTOCOL 1          // BOSE                 >= 10000                 ~100 bytes
#define IRSND_SUPPORT_KATHREIN_PROTOCOL 0      // Kathrein             >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_NUBERT_PROTOCOL 1        // NUBERT               >= 10000                 ~100 bytes
#define IRSND_SUPPORT_FAN_PROTOCOL 1           // FAN (ventilator)     >= 10000                 ~100 bytes
#define IRSND_SUPPORT_SPEAKER_PROTOCOL 1       // SPEAKER              >= 10000                 ~100 bytes
#define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0  // Bang&Olufsen         >= 10000                 ~250 bytes // IR frequency 455 kHz
#define IRSND_SUPPORT_RECS80_PROTOCOL 1        // RECS80               >= 15000                 ~100 bytes
#define IRSND_SUPPORT_RECS80EXT_PROTOCOL 1     // RECS80EXT            >= 15000                 ~100 bytes
#define IRSND_SUPPORT_THOMSON_PROTOCOL 1       // Thomson              >= 10000                 ~250 bytes
#define IRSND_SUPPORT_NIKON_PROTOCOL 1         // NIKON                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_NETBOX_PROTOCOL 0        // Netbox keyboard      >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ORTEK_PROTOCOL 0         // ORTEK (Hama)         >= 10000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 1    // Telefunken 1560      >= 10000                 ~150 bytes
#define IRSND_SUPPORT_FDC_PROTOCOL 1           // FDC IR keyboard      >= 10000 (better 15000)  ~150 bytes
#define IRSND_SUPPORT_RCCAR_PROTOCOL 1         // RC CAR               >= 10000 (better 15000)  ~150 bytes
#define IRSND_SUPPORT_ROOMBA_PROTOCOL 1        // iRobot Roomba        >= 10000                 ~150 bytes
#define IRSND_SUPPORT_RUWIDO_PROTOCOL 1        // RUWIDO, T-Home       >= 15000                 ~250 bytes
#define IRSND_SUPPORT_A1TVBOX_PROTOCOL 1       // A1 TV BOX            >= 15000 (better 20000)  ~200 bytes
#define IRSND_SUPPORT_LEGO_PROTOCOL 1          // LEGO Power RC        >= 20000                 ~150 bytes
#define IRSND_SUPPORT_RCMM_PROTOCOL 0          // RCMM 12,24, or 32    >= 20000                 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_LGAIR_PROTOCOL 1         // LG Air Condition     >= 10000                 ~150 bytes.
#define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 1     // Samsung48            >= 10000                 ~100 bytes
#define IRSND_SUPPORT_PENTAX_PROTOCOL 1        // Pentax               >= 10000                 ~150 bytes
#define IRSND_SUPPORT_S100_PROTOCOL 1          // S100                 >= 10000                 ~150 bytes
#define IRSND_SUPPORT_ACP24_PROTOCOL 1         // ACP24                >= 10000                 ~150 bytes
#define IRSND_SUPPORT_TECHNICS_PROTOCOL 1      // TECHNICS             >= 10000                 ~200 bytes
#define IRSND_SUPPORT_PANASONIC_PROTOCOL 1     // PANASONIC Beamer     >= 10000                 ~150 bytes
#define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 1   // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer
#define IRSND_SUPPORT_IRMP16_PROTOCOL 0        // IRMP specific        >= 15000                 ~250 bytes

#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND
#include <irmp.hpp>
#include <irsnd.hpp>
IRMP_DATA irmp_data;
IRMP_DATA irsnd_data;
int Prortocol_Index[58] = { IRMP_UNKNOWN_PROTOCOL, IRMP_SIRCS_PROTOCOL, IRMP_NEC_PROTOCOL, IRMP_SAMSUNG_PROTOCOL, IRMP_MATSUSHITA_PROTOCOL, IRMP_KASEIKYO_PROTOCOL, IRMP_RECS80_PROTOCOL, IRMP_RC5_PROTOCOL, IRMP_DENON_PROTOCOL, IRMP_RC6_PROTOCOL, IRMP_SAMSUNG32_PROTOCOL, IRMP_APPLE_PROTOCOL, IRMP_RECS80EXT_PROTOCOL, IRMP_NUBERT_PROTOCOL, IRMP_BANG_OLUFSEN_PROTOCOL, IRMP_GRUNDIG_PROTOCOL, IRMP_NOKIA_PROTOCOL, IRMP_SIEMENS_PROTOCOL, IRMP_FDC_PROTOCOL, IRMP_RCCAR_PROTOCOL, IRMP_JVC_PROTOCOL, IRMP_RC6A_PROTOCOL, IRMP_NIKON_PROTOCOL, IRMP_RUWIDO_PROTOCOL, IRMP_IR60_PROTOCOL, IRMP_KATHREIN_PROTOCOL, IRMP_NETBOX_PROTOCOL, IRMP_NEC16_PROTOCOL, IRMP_NEC42_PROTOCOL, IRMP_LEGO_PROTOCOL, IRMP_THOMSON_PROTOCOL, IRMP_BOSE_PROTOCOL, IRMP_A1TVBOX_PROTOCOL, IRMP_ORTEK_PROTOCOL, IRMP_TELEFUNKEN_PROTOCOL, IRMP_ROOMBA_PROTOCOL, IRMP_RCMM32_PROTOCOL, IRMP_RCMM24_PROTOCOL, IRMP_RCMM12_PROTOCOL, IRMP_SPEAKER_PROTOCOL, IRMP_LGAIR_PROTOCOL, IRMP_SAMSUNG48_PROTOCOL, IRMP_MERLIN_PROTOCOL, IRMP_PENTAX_PROTOCOL, IRMP_FAN_PROTOCOL, IRMP_S100_PROTOCOL, IRMP_ACP24_PROTOCOL, IRMP_TECHNICS_PROTOCOL, IRMP_PANASONIC_PROTOCOL, IRMP_MITSU_HEAVY_PROTOCOL, IRMP_VINCENT_PROTOCOL, IRMP_SAMSUNGAH_PROTOCOL, IRMP_IRMP16_PROTOCOL, IRMP_GREE_PROTOCOL, IRMP_RCII_PROTOCOL, IRMP_METZ_PROTOCOL, IRMP_ONKYO_PROTOCOL };

struct CRGB leds[NUM_LEDS];  // Initialize LED array
const int Relay1 = 5;        // Relay pin 1 (IN1)
const int Relay2 = 4;        // Relay pin 2 (IN2)
const int Relay3 = 6;        // Relay pin 3 (IN3)
const int Relay4 = 7;        // Relay pin 4 (IN4)
int irrec = 0;
String data;  //Variable for storing received data
int proto;
uint16_t addr, cmd, temp;
int eeadr;

void handleReceivedIRData();
void IRDecoder();
void SerialDecoder();
bool volatile sIRMPDataAvailable = false;

void setup() {
  Serial.begin(9600);  //Sets the baud for serial data transmission
  FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
  // Set Relay pins as OUTPUT
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  pinMode(Relay3, OUTPUT);
  pinMode(Relay4, OUTPUT);
  // Init all relays to off
  digitalWrite(Relay1, LOW);
  digitalWrite(Relay2, LOW);
  digitalWrite(Relay3, LOW);
  digitalWrite(Relay4, LOW);
  irmp_init();
  irmp_irsnd_LEDFeedback(true);  // Enable receive signal feedback at LED_BUILTIN
  irmp_register_complete_callback_function(&handleReceivedIRData);
  irsnd_init();
}

void loop() {

  // Read data from Bluetooth Module
  char ch = 0;
  data = "";
  while (1) { // When there is no command received the MCU will be in this loop. 
    while (Serial.available() <= 0) {
      if (irrec > 0) {
        IRDecoder();// Call IR decoder function when a valid command is detected
      }
      digitalWrite(13, irrec);
    };
    ch = Serial.read();
    if (ch == '#')
      break; // break the loop when a command is received
    data += ch;
  }
  SerialDecoder();// call serial Decoder function
}

//Decode received serial command
void SerialDecoder() { 
  // Print Bluetooth Module data on serial monitor
  Serial.print(data);
  Serial.print("\n");

  // Control the devices using voice command
  if (data.startsWith("*turn on light"))  // turn on Device1
  {
    digitalWrite(Relay1, HIGH);
    Serial.println("  :   light on");
    delay(200);
  } else if (data.startsWith("*turn off light"))  // turn off Device1
  {
    digitalWrite(Relay1, LOW);
    Serial.println("  :   light off");
    delay(2000);
  } else if (data.startsWith("*turn on TV"))  // turn on Device2
  {
    digitalWrite(Relay2, HIGH);
    Serial.println("  :   TV on");
    delay(200);
  }

  else if (data.startsWith("*turn off TV"))  // turn off Device2
  {
    digitalWrite(Relay2, LOW);
    Serial.println("  :   TV off");
    delay(200);
  } else if (data.startsWith("*turn on fan"))  // turn on Device3
  {
    digitalWrite(Relay3, HIGH);
    Serial.println("  :   fan on");
    delay(200);
  } else if (data.startsWith("*turn off fan"))  // turn off Device3
  {
    digitalWrite(Relay3, LOW);
    Serial.println("  :   fan off");
    delay(200);
  } else if (data.startsWith("*turn on music"))  // turn on Device4
  {
    digitalWrite(Relay4, HIGH);
    Serial.println("  :   music on");
    delay(200);
  } else if (data.startsWith("*turn off music"))  // turn off Device4
  {
    digitalWrite(Relay4, LOW);
    Serial.println("  :   music off");
    delay(200);
  } else if (data.startsWith("*turn on all"))  // turn on all Device
  {
    digitalWrite(Relay1, HIGH);
    digitalWrite(Relay2, HIGH);
    digitalWrite(Relay3, HIGH);
    digitalWrite(Relay4, HIGH);
    Serial.println("  :   All Relays on");
    delay(200);
  } else if (data.startsWith("*turn off all"))  // turn off all Device
  {
    digitalWrite(Relay1, LOW);
    digitalWrite(Relay2, LOW);
    digitalWrite(Relay3, LOW);
    digitalWrite(Relay4, LOW);
    Serial.println("  :   All Relays off");
    delay(200);
  } else if (data.startsWith("*RGB red"))  // set the RGB leds to red
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Red;  //set the RGB leds to red
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB green"))  //set the RGB leds to green
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Green;  //set the RGB leds to green
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB blue"))  // set the RGB leds to blue
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Blue;  //set the RGB leds to blue
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB yellow"))  // set the RGB leds to yellow
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Yellow;  //set the RGB leds to yellow
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*RGB white"))  // // set the RGB leds to  white
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::White;  //set the RGB leds to white
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*turn off RGB"))  // turn off all RGB LEDS
  {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Black;  //turn off all RGB LEDS
    }
    FastLED.show();
    delay(200);
  } else if (data.startsWith("*record power"))  // record and save remote power button
  {
    irrec = 12;
    IRDecoder();
    irrec = 1;
    delay(200);
  } else if (data.startsWith("*record volume up"))  // record and save remote volume up button
  {
    irrec = 12;
    IRDecoder();
    irrec = 2;
    delay(200);
  } else if (data.startsWith("*record volume down"))  // record and save remote volume down button
  {
    irrec = 12;
    IRDecoder();
    irrec = 3;
    delay(200);
  } else if (data.startsWith("*record next"))  // record and save remote next button
  {
    irrec = 12;
    IRDecoder();
    irrec = 4;
    Serial.print("irrec :");
    Serial.println(irrec);
    delay(200);
  } else if (data.startsWith("*record previous"))  /// record and save remote previous button
  {
    irrec = 12;
    IRDecoder();
    irrec = 5;
    delay(200);
  }

  else if (data.startsWith("*remote power"))  // Recall and send remote power button signal
  {
    eeadr = 10;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote volume up"))  // Recall and send remote volume up button signal
  {
    eeadr = 20;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found")); 
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote volume down")) // Recall and send remote volume down button signal
  {
    eeadr = 30;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote next"))  // Recall and send remote next button signal
  {
    eeadr = 40;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  } else if (data.startsWith("*remote previous"))  // Recall and send remote previous button signal
  {
    eeadr = 50;
    irsnd_data.protocol = EEPROM.read(eeadr);
    temp = (EEPROM.read(eeadr + 2) << 8);
    temp |= EEPROM.read(eeadr + 1);
    irsnd_data.address = temp;
    temp = (EEPROM.read(eeadr + 4) << 8);
    temp |= EEPROM.read(eeadr + 3);
    irsnd_data.command = temp;
    irsnd_data.flags = 0;  // repeat frame 1 time
    Serial.print(F("Sending data  "));
    Serial.println(proto);
    if (!irsnd_send_data(&irsnd_data, true)) {
      Serial.println(F("Protocol not found"));  
    }
    irsnd_data_print(&Serial, &irsnd_data);
  }
}

//Decode and save IR signals
void IRDecoder() {
  if (sIRMPDataAvailable) {
    int eepaddr = irrec;
    irrec = 0;
    int rpt;
    sIRMPDataAvailable = false;
    irmp_result_print(&irmp_data);
    proto = irmp_data.protocol;
    addr = irmp_data.address;
    cmd = irmp_data.command;
    // save signal data to EEPROM
    if (eepaddr < 10) {
      if (proto == 0) {
        EEPROM.write(eepaddr * 10, 0x0);
      } else {
        EEPROM.write(eepaddr * 10, proto);
      }
      if (addr == 0) {

        EEPROM.write((eepaddr * 10) + 1, 0);
        EEPROM.write((eepaddr * 10) + 2, 0);
      } else {
        EEPROM.write((eepaddr * 10) + 1, addr);
        EEPROM.write((eepaddr * 10) + 2, addr >> 8);
      }
      if (cmd == 0) {
        EEPROM.write((eepaddr * 10) + 3, 0x0);
        EEPROM.write((eepaddr * 10) + 4, 0x0);
      } else {
        EEPROM.write((eepaddr * 10) + 3, cmd);
        EEPROM.write((eepaddr * 10) + 4, cmd >> 8);
      }
    }
  }
}

//IR interrupt handle routine
void handleReceivedIRData() {
  irmp_get_data(&irmp_data);
  sIRMPDataAvailable = true;
}
Video

Have any question realated to this Article?

Ask Our Community Members