India Automation Challenge 2021
OR
Normally we are facing problems with the IR Remote sometimes it may not work and regularly we need to change the Batteries, so thought of replacing this IR Remote with Voice Assistant (Alexa). This is very helpfull to all the people for changing the channels, for volume control, changing to channels directly by single word (Alexa, change channel to 4 on TV). By using this device we can save more time in searching for Remote, for buying the Batteries, by focusing Remote exactly to TV for changing, etc., for this no need of an any external power supply, directly we can connect this device USB port of Set-Up Box.
ESP8266 Chip, IR LED, Opto-Coupler (PC817), Transistor(BC547), 1K Ohm Resistor, AMS117-3.3, Micro USB Connector
Arduino, Sinric Pro
I have selected ESP8266(ESP-01) Chip which is the smallest microcontroller which comes with default wifi connectivity and also we can design small PCB using this ESP8266 Chip. Next main component is IR Transmitter to communicate with the set-up box, next component is transistor for switching purpose, next component is opto-coupler, which is mainly used for isolating the two regions, here I have used for safe switching and transfering of signal. Next coming to software section, Arduino IDE is the best user-friendly Environment for Arduino, and next, I have used Sinric Pro Skill to communicate with Alexa, as it is default skills available in Alexa so, no need of any 3rd party Voice Assistant Applications. Finally, we can control the channels using Alexa via Sinric Pro Skill directly.
This is the simple circuit diagram has designed for smart control of set-up box channels using Alexa, very simple design and power supply is given from Micro USB Port but for ESP Chip is capable of only 3.3V so, we have used AMS1117-3.3 Voltage Regulator.
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#endif
#include "SinricPro.h"
#include "SinricProTV.h"
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
decode_results results;
const uint16_t kIrLed = 2 ; //Pin you wish to send IR on
IRsend irsend(kIrLed);
#define WIFI_SSID "GPONWIFI_1970" //WIFI Name
#define WIFI_PASS "123456123456" // WIFI Password
#define APP_KEY "6d29d25c-e4fc-4b10-8a9c-8837a00c7ecd" //Sinric App Key, should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "19db7e4f-f787-4a20-be49-78dee5f65621-7beb3e43-1323-4bfd-b6d4-1d00829de6e0" // Sinric App Secret, should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define TV_ID "610b8ed6bab19d4058190f9a" // Sinric TV Device ID Should look like "5dc1564130xxxxxxxxxxxxxx"
#define TV_ID_2 "6107a515fc89cf405088cb37" // Sinric TV Device ID Should look like "5dc1564130xxxxxxxxxxxxxx"
#define BAUD_RATE 115200
bool tvPowerState;
unsigned int tvVolume;
unsigned int tvChannel;
bool tvMuted;
String channel;
const char* channelNames[] = {
"0", //(Alexa only reconises Netflix written like this, i believe its a Virgin Media thing. However saying "Change channel to Netflix on TV" works fine)
"one",
"two",
"three",
"four",
"five",
"six",
"twenty two",
"fourty seven",
"one one nine",
"one one eight",
"Zee Telugu",
"E TV",
"Maa TV",
"ETV Plus",
"ETV Abhiruchi",
"Zee Cinemalu",
"Movies",
"AP Local",
"win six",
};
#define MAX_CHANNELS sizeof(channelNames) / sizeof(channelNames[0]) // just to determine how many channels are in channelNames array
// map channelNumbers used to convert channelName into channelNumber
// This map is initialized in "setupChannelNumbers()" function by using the "channelNames" array
std::map<String, unsigned int> channelNumbers;
void setupChannelNumbers() {
for (unsigned int i=0; i < MAX_CHANNELS; i++) {
channelNumbers[channelNames[i]] = i;
}
}
// TV device callbacks
bool onAdjustVolume(const String &deviceId, int &volumeDelta, bool volumeDefault) {
if (volumeDelta > 0) {irsend.sendNEC(0x8877D22D, 32);delay(250);irsend.sendNEC(0x8877D22D, 32);delay(250);irsend.sendNEC(0x8877D22D, 32);delay(250);irsend.sendNEC(0x8877D22D, 32);delay(250);irsend.sendNEC(0x8877D22D, 32);} //Insert IR for Volume Up here.
if (volumeDelta < 0) {irsend.sendNEC(0x887738C7, 32);delay(250);irsend.sendNEC(0x887738C7, 32);delay(250);irsend.sendNEC(0x887738C7, 32);delay(250);irsend.sendNEC(0x887738C7, 32);delay(250);irsend.sendNEC(0x887738C7, 32);} //Insert IR for Volume Down here.
tvVolume += volumeDelta; // calcualte new absolute volume
Serial.printf("Volume changed about %i to %i\r\n", volumeDelta, tvVolume);
volumeDelta = tvVolume; // return new absolute volume
return true;
}
bool onChangeChannel(const String &deviceId, String &channel) {
tvChannel = channelNumbers[channel]; // save new channelNumber in tvChannel variable
Serial.printf("Change channel blah to \"%s\" (channel number %d)\r\n", channel.c_str(), tvChannel);
Serial.println(tvChannel);
Serial.println(channel);
if ((channel) == ("ETV")) {
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....11");
}// irsend.sendNEC(0x8877827D, 32); delay (250); irsend.sendNEC(0x8877827D, 32);} //Change IR sequence inside of {} for each channel.
if (channel == "zee telugu") {
irsend.sendNEC(0x887702FD, 32);
Serial.println("Hi....22");
}//irsend.sendNEC(0xFD00FF, 32); delay (250); irsend.sendNEC(0XFD807F, 32);}
if ((channel) == ("TV")) {
irsend.sendNEC(0x8877A25D, 32);
Serial.println("Hi....33");
}
if (channel == "ETV Plus") {
irsend.sendNEC(0x8877629D, 32);
Serial.println("Hi....44");
}
if (channel == "ETV Abhiruchi") {
irsend.sendNEC(0x887722DD, 32);
Serial.println("Hi....55");
}
if (channel == "zee cinemalu") {
irsend.sendNEC(0x8877827D, 32);
delay(250);
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....66");
}
if (channel == "movies") {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x8877A25D, 32);
Serial.println("Hi....77");
}
if (channel == "ap 24x7") {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877926D, 32);
Serial.println("Hi....88");
}
if (channel == "win tv") {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887712ED, 32);
Serial.println("Hi....99");
}
return true;
}
bool onChangeChannelNumber(const String& deviceId, int channelNumber, String& channelName) {
tvChannel = channelNumber; // update tvChannel to new channel number
if (tvChannel < 0) tvChannel = 0;
if (tvChannel > MAX_CHANNELS-1) tvChannel = MAX_CHANNELS-1;
delay(250);
channelName = channelNames[tvChannel]; // return the channelName
Serial.print("channelNumber: ");
Serial.println(channelNumber);
Serial.print("channelName: ");
Serial.println(channelName);
if ((channelName) == "one") {
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....11");
}// irsend.sendNEC(0x8877827D, 32); delay (250); irsend.sendNEC(0x8877827D, 32);} //Change IR sequence inside of {} for each channel.
if (channelNumber == 2) {
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....22");
}//irsend.sendNEC(0xFD00FF, 32); delay (250); irsend.sendNEC(0XFD807F, 32);}
if ((channelNumber) == 3) {
irsend.sendNEC(0x887702FD, 32);
Serial.println("Hi....33");
}
if (channelNumber == 4) {
irsend.sendNEC(0x8877629D, 32);
Serial.println("Hi....44");
}
if (channelNumber == 5) {
irsend.sendNEC(0x8877A25D, 32);
Serial.println("Hi....55");
}
if (channelNumber == 6) {
irsend.sendNEC(0x887722DD, 32);
delay(250);
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....66");
}
if (channelNumber == 7) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x8877A25D, 32);
Serial.println("Hi....77");
}
if (channelNumber == 8) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877926D, 32);
Serial.println("Hi....88");
}
if (channelNumber == 9) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887712ED, 32);
Serial.println("Hi....99");
}
if (channelNumber == 22) {
irsend.sendNEC(0x8877827D, 32);
delay(250);
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....22");
}
if (channelNumber == 47) {
irsend.sendNEC(0x8877629D, 32);
delay(250);
irsend.sendNEC(0x887752AD, 32);
Serial.println("Hi....47");
}
if (channelNumber == 119) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887712ED, 32);
Serial.println("Hi....119");
}
if (channelNumber == 118) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877926D, 32);
Serial.println("Hi....118");
}
if (channelNumber == 104) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x8877629D, 32);
Serial.println("Hi....104");
}
if (channelNumber == 103) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x887702FD, 32);
Serial.println("Hi....103");
}
if (channelNumber == 102) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x8877827D, 32);
Serial.println("Hi....103");
}
if (channelNumber == 105) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x8877A25D, 32);
Serial.println("Hi....105");
}
if (channelNumber == 106) {
irsend.sendNEC(0x887742BD, 32);
delay(250);
irsend.sendNEC(0x8877B24D, 32);
delay(250);
irsend.sendNEC(0x887722DD, 32);
Serial.println("Hi....106");
}
Serial.printf("Change to channel to %d (channel name \"%s\")\r\n", tvChannel, channelName.c_str());
return true;
}
bool onMute(const String &deviceId, bool &mute) {
if(deviceId=="TV_ID"){
Serial.printf("TV volume is %s\r\n", mute?"muted":"unmuted");
tvMuted = mute; // set tvMuted state
if(mute){
irsend.sendNEC(0x8877E21D, 32); //Insert Mute button IR for Mute
}
else{
irsend.sendNEC(0x8877E21D, 32); //Insert Mute button IR for unmute (Normally the same as above)
}
}
return true;
}
bool onSetVolume(const String &deviceId, int &volume) {
Serial.printf("Volume set to: %i\r\n", volume);
tvVolume = volume; // update tvVolume
return true;
}
// setup function for WiFi connection
void setupWiFi() {
irsend.begin()
Serial.printf("\r\n[Wifi]: Connecting");
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
Serial.printf(".");
delay(250);
}
IPAddress localIP = WiFi.localIP();
Serial.printf("connected!\r\n[WiFi]: IP-Address is %d.%d.%d.%d\r\n", localIP[0], localIP[1], localIP[2], localIP[3]);
}
void dump(decode_results *results) {
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
uint16_t count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.print("Unknown encoding: ");
} else if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
} else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
} else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
} else if (results->decode_type == RC5X) {
Serial.print("Decoded RC5X: ");
} else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
} else if (results->decode_type == RCMM) {
Serial.print("Decoded RCMM: ");
} else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->address, HEX);
Serial.print(" Value: ");
} else if (results->decode_type == LG) {
Serial.print("Decoded LG: ");
} else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
} else if (results->decode_type == AIWA_RC_T501) {
Serial.print("Decoded AIWA RC T501: ");
} else if (results->decode_type == WHYNTER) {
Serial.print("Decoded Whynter: ");
} else if (results->decode_type == NIKAI) {
Serial.print("Decoded Nikai: ");
}
serialPrintUint64(results->value, 16);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): {");
for (uint16_t i = 1; i < count; i++) {
if (i % 100 == 0)
yield(); // Preemptive yield every 100th entry to feed the WDT.
if (i & 1) {
Serial.print(results->rawbuf[i] * kRawTick, DEC);
} else {
Serial.print(", ");
Serial.print((uint32_t) results->rawbuf[i] * kRawTick, DEC);
}
}
Serial.println("};");
}
// setup function for SinricPro
void setupSinricPro() {
// add device to SinricPro
SinricProTV& myTV = SinricPro[TV_ID];
// set callback functions to device
myTV.onAdjustVolume(onAdjustVolume);
myTV.onChangeChannel(onChangeChannel);
myTV.onChangeChannelNumber(onChangeChannelNumber);
myTV.onMute(onMute);
myTV.onSetVolume(onSetVolume);
// setup SinricPro
SinricPro.onConnected([](){ Serial.printf("Connected to SinricPro\r\n"); });
SinricPro.onDisconnected([](){ Serial.printf("Disconnected from SinricPro\r\n"); });
SinricPro.begin(APP_KEY, APP_SECRET);
}
// main setup function
void setup() {
Serial.begin(BAUD_RATE); Serial.printf("\r\n\r\n");
Serial.printf("%d channels configured\r\n", MAX_CHANNELS);
// irrecv.enableIRIn();
setupWiFi();
setupSinricPro();
setupChannelNumbers();
}
void loop() {
SinricPro.handle();
}