/**********************************************************************************
* TITLE: ESPAlexa + Bluetooth + IR + Switch control 4 Relays using ESP32 (Real time feedback + no WiFi control + EEPROM)
* Click on the following links to learn more.
* YouTube Video: https://youtu.be/IHD8jsJuJdQ
* Related Blog : https://iotcircuithub.com/esp32-projects/
*
* This code is provided free for project purpose and fair use only.
* Please do mail us to [email protected] if you want to use it commercially.
* Copyrighted © by Tech StudyCell
*
* Preferences--> Aditional boards Manager URLs :
* https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json
*
* Download Board ESP32 (2.0.11) : https://github.com/espressif/arduino-esp32
*
* Download the libraries
* Espalexa Library (2.7.0): https://github.com/Aircoookie/Espalexa
* IRremote Library (3.6.1): https://github.com/Arduino-IRremote/Arduino-IRremote
* AceButton Library (1.9.2): https://github.com/bxparks/AceButton
**********************************************************************************/
// WiFi Credentials
const char* ssid = "alessa";
const char* password = "fawzi7148";
// device names (change names as per requirement)
String Device_1_Name = "Night Lamp";
String Device_2_Name = "Room Light";
String Device_3_Name = "Studio Light";
String Device_4_Name = "Outdoor Light";
//Update the HEX code of IR Remote buttons 0x<HEX CODE>
#define IR_Button_1 0x1FEE01F
#define IR_Button_2 0x1FE10EF
#define IR_Button_3 0x1FE906F
#define IR_Button_4 0x1FE50AF
#define IR_All_On 0x1FE807F
#define IR_All_Off 0x1FE48B7
#include <WiFi.h>
#include <Espalexa.h>
#include "BluetoothSerial.h"
#include <IRremote.h>
#include <Preferences.h>
#include <AceButton.h>
using namespace ace_button;
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run
`make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
Espalexa espalexa;
Preferences pref;
// define the GPIO connected with Relays and switches
#define RelayPin1 23 //D23
#define RelayPin2 22 //D22
#define RelayPin3 21 //D21
#define RelayPin4 19 //D19
#define SwitchPin1 13 //D13
#define SwitchPin2 12 //D12
#define SwitchPin3 14 //D14
#define SwitchPin4 27 //D27
#define wifiLed 2 //D2
#define IR_RECV_PIN 35 // D35 (IR receiver pin)
#define WiFiResetButton 0 //BOOT button
// Relay State
bool toggleState_1 = LOW; //Define integer to remember the toggle state for relay 1
bool toggleState_2 = LOW; //Define integer to remember the toggle state for relay 2
bool toggleState_3 = LOW; //Define integer to remember the toggle state for relay 3
bool toggleState_4 = LOW; //Define integer to remember the toggle state for relay 4
ButtonConfig config1;
AceButton button1(&config1);
ButtonConfig config2;
AceButton button2(&config2);
ButtonConfig config3;
AceButton button3(&config3);
ButtonConfig config4;
AceButton button4(&config4);
void handleEvent1(AceButton*, uint8_t, uint8_t);
void handleEvent2(AceButton*, uint8_t, uint8_t);
void handleEvent3(AceButton*, uint8_t, uint8_t);
void handleEvent4(AceButton*, uint8_t, uint8_t);
int wifiFlag = 0;
char bt_data ; // variable for storing bluetooth data
IRrecv irrecv(IR_RECV_PIN);
decode_results results;
// prototypes
boolean connectWifi();
//callback functions
void firstLightChanged(uint8_t brightness);
void secondLightChanged(uint8_t brightness);
void thirdLightChanged(uint8_t brightness);
void fourthLightChanged(uint8_t brightness);
boolean wifiConnected = false;
//our callback functions
//our callback functions
void firstLightChanged(uint8_t brightness)
{
//Control the device
if (brightness == 255)
{
digitalWrite(RelayPin1, LOW);
Serial.println("Device1 ON");
toggleState_1 = 1;
}
else
{
digitalWrite(RelayPin1, HIGH);
Serial.println("Device1 OFF");
toggleState_1 = 0;
}
pref.putBool("Relay1", toggleState_1);
}
void secondLightChanged(uint8_t brightness)
{
//Control the device
if (brightness == 255)
{
digitalWrite(RelayPin2, LOW);
Serial.println("Device2 ON");
toggleState_2 = 1;
}
else
{
digitalWrite(RelayPin2, HIGH);
Serial.println("Device2 OFF");
toggleState_2 = 0;
}
pref.putBool("Relay2", toggleState_2);
}
void thirdLightChanged(uint8_t brightness)
{
//Control the device
if (brightness == 255)
{
digitalWrite(RelayPin3, LOW);
Serial.println("Device3 ON");
toggleState_3 = 1;
}
else
{
digitalWrite(RelayPin3, HIGH);
Serial.println("Device3 OFF");
toggleState_3 = 0;
}
pref.putBool("Relay3", toggleState_3);
}
void fourthLightChanged(uint8_t brightness)
{
//Control the device
if (brightness == 255)
{
digitalWrite(RelayPin4, LOW);
Serial.println("Device4 ON");
toggleState_4 = 1;
}
else
{
digitalWrite(RelayPin4, HIGH);
Serial.println("Device4 OFF");
toggleState_4 = 0;
}
pref.putBool("Relay4", toggleState_4);
}
void addDevices(){
// Define your devices here.
espalexa.addDevice(Device_1_Name, firstLightChanged); //simplest definition, default state off
espalexa.addDevice(Device_2_Name, secondLightChanged);
espalexa.addDevice(Device_3_Name, thirdLightChanged);
espalexa.addDevice(Device_4_Name, fourthLightChanged);
espalexa.begin();
}
void sendFeedback(int relay, int value){
EspalexaDevice* d = espalexa.getDevice(relay); //the index is zero-based
if(relay == 4){
d->setPercent(map(value, 0, 4, 0, 100)); //set value "brightness" in percent
}
else{
d->setPercent(value);
}
}
void ir_remote(){
if (irrecv.decode(&results)) {
switch(results.value){
case IR_Button_1:
digitalWrite(RelayPin1, toggleState_1);
toggleState_1 = !toggleState_1;
pref.putBool("Relay1", toggleState_1);
(toggleState_1 == false) ? sendFeedback(0, 0) : sendFeedback(0, 100);
delay(100);
break;
case IR_Button_2:
digitalWrite(RelayPin2, toggleState_2);
toggleState_2 = !toggleState_2;
pref.putBool("Relay2", toggleState_2);
(toggleState_2 == false) ? sendFeedback(1, 0) : sendFeedback(1, 100);
delay(100);
break;
case IR_Button_3:
digitalWrite(RelayPin3, toggleState_3);
toggleState_3 = !toggleState_3;
pref.putBool("Relay3", toggleState_3);
(toggleState_3 == false) ? sendFeedback(2, 0) : sendFeedback(2, 100);
delay(100);
break;
case IR_Button_4:
digitalWrite(RelayPin4, toggleState_4);
toggleState_4 = !toggleState_4;
pref.putBool("Relay4", toggleState_4);
(toggleState_4 == false) ? sendFeedback(3, 0) : sendFeedback(3, 100);
delay(100);
break;
case IR_All_Off:
all_SwitchOff();
break;
case IR_All_On:
all_SwitchOn();
break;
default : break;
}
//Serial.println(results.value, HEX);
irrecv.resume();
}
}
void bluetooth_control()
{
if (SerialBT.available()){
bt_data = SerialBT.read();
Serial.println(bt_data);
delay(20);
switch(bt_data)
{
case 'A': digitalWrite(RelayPin1, LOW); toggleState_1 = 1; sendFeedback(0, 100); pref.putBool("Relay1", toggleState_1); break; // if 'A' received Turn on Relay1
case 'a': digitalWrite(RelayPin1, HIGH); toggleState_1 = 0; sendFeedback(0, 0); pref.putBool("Relay1", toggleState_1); break; // if 'a' received Turn off Relay1
case 'B': digitalWrite(RelayPin2, LOW); toggleState_2 = 1; sendFeedback(1, 100); pref.putBool("Relay2", toggleState_2); break; // if 'B' received Turn on Relay2
case 'b': digitalWrite(RelayPin2, HIGH); toggleState_2 = 0; sendFeedback(1, 0); pref.putBool("Relay2", toggleState_2); break; // if 'b' received Turn off Relay2
case 'C': digitalWrite(RelayPin3, LOW); toggleState_3 = 1; sendFeedback(2, 100); pref.putBool("Relay3", toggleState_3); break; // if 'C' received Turn on Relay3
case 'c': digitalWrite(RelayPin3, HIGH); toggleState_3 = 0; sendFeedback(2, 0); pref.putBool("Relay3", toggleState_3); break; // if 'c' received Turn off Relay3
case 'D': digitalWrite(RelayPin4, LOW); toggleState_4 = 1; sendFeedback(3, 100); pref.putBool("Relay4", toggleState_4); break; // if 'D' received Turn on Relay4
case 'd': digitalWrite(RelayPin4, HIGH); toggleState_4 = 0; sendFeedback(3, 0); pref.putBool("Relay4", toggleState_4); break; // if 'd' received Turn off Relay4
case 'Z': all_SwitchOn(); break; // if 'Z' received Turn on all Relays
case 'z': all_SwitchOff(); break; // if 'z' received Turn off all Relays
default : break;
}
}
}
void all_SwitchOn(){
toggleState_1 = 1; digitalWrite(RelayPin1, LOW); pref.putBool("Relay1", toggleState_1); sendFeedback(0, 100); delay(100);
toggleState_2 = 1; digitalWrite(RelayPin2, LOW); pref.putBool("Relay2", toggleState_2); sendFeedback(1, 100); delay(100);
toggleState_3 = 1; digitalWrite(RelayPin3, LOW); pref.putBool("Relay3", toggleState_3); sendFeedback(2, 100); delay(100);
toggleState_4 = 1; digitalWrite(RelayPin4, LOW); pref.putBool("Relay4", toggleState_4); sendFeedback(3, 100); delay(100);
}
void all_SwitchOff(){
toggleState_1 = 0; digitalWrite(RelayPin1, HIGH); pref.putBool("Relay1", toggleState_1); sendFeedback(0, 0); delay(100);
toggleState_2 = 0; digitalWrite(RelayPin2, HIGH); pref.putBool("Relay2", toggleState_2); sendFeedback(1, 0); delay(100);
toggleState_3 = 0; digitalWrite(RelayPin3, HIGH); pref.putBool("Relay3", toggleState_3); sendFeedback(2, 0); delay(100);
toggleState_4 = 0; digitalWrite(RelayPin4, HIGH); pref.putBool("Relay4", toggleState_4); sendFeedback(3, 0); delay(100);
}
// connect to wifi – returns true if successful or false if not
boolean connectWifi()
{
boolean state = true;
int i = 0;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("Connecting to WiFi");
// Wait for connection
Serial.print("Connecting...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (i > 20) {
state = false; break;
}
i++;
}
Serial.println("");
if (state) {
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
else {
Serial.println("Connection failed.");
}
return state;
}
void getRelayState()
{
//Serial.println("reading data from NVS");
toggleState_1 = pref.getBool("Relay1", 0);
digitalWrite(RelayPin1, !toggleState_1);
(toggleState_1 == false) ? sendFeedback(0, 0) : sendFeedback(0, 100);
delay(200);
toggleState_2 = pref.getBool("Relay2", 0);
digitalWrite(RelayPin2, !toggleState_2);
(toggleState_2 == false) ? sendFeedback(1, 0) : sendFeedback(1, 100);
delay(200);
toggleState_3 = pref.getBool("Relay3", 0);
digitalWrite(RelayPin3, !toggleState_3);
(toggleState_3 == false) ? sendFeedback(2, 0) : sendFeedback(2, 100);
delay(200);
toggleState_4 = pref.getBool("Relay4", 0);
digitalWrite(RelayPin4, !toggleState_4);
(toggleState_4 == false) ? sendFeedback(3, 0) : sendFeedback(3, 100);
delay(200);
}
void setup()
{
Serial.begin(115200);
//Open namespace in read-write mode
pref.begin("Relay_State", false);
btStart(); //Serial.println("Bluetooth On");
SerialBT.begin("ESP32_BT"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
delay(5000);
pinMode(RelayPin1, OUTPUT);
pinMode(RelayPin2, OUTPUT);
pinMode(RelayPin3, OUTPUT);
pinMode(RelayPin4, OUTPUT);
pinMode(wifiLed, OUTPUT);
pinMode(SwitchPin1, INPUT_PULLUP);
pinMode(SwitchPin2, INPUT_PULLUP);
pinMode(SwitchPin3, INPUT_PULLUP);
pinMode(SwitchPin4, INPUT_PULLUP);
//During Starting all Relays should TURN OFF
digitalWrite(RelayPin1, !toggleState_1);
digitalWrite(RelayPin2, !toggleState_2);
digitalWrite(RelayPin3, !toggleState_3);
digitalWrite(RelayPin4, !toggleState_4);
digitalWrite(wifiLed, LOW);
config1.setEventHandler(button1Handler);
config2.setEventHandler(button2Handler);
config3.setEventHandler(button3Handler);
config4.setEventHandler(button4Handler);
button1.init(SwitchPin1);
button2.init(SwitchPin2);
button3.init(SwitchPin3);
button4.init(SwitchPin4);
irrecv.enableIRIn(); // Enabling IR sensor
// Initialise wifi connection
wifiConnected = connectWifi();
if (wifiConnected)
{
addDevices();
}
else
{
Serial.println("Cannot connect to WiFi. So in Manual Mode");
}
delay(1000);
getRelayState(); //fetch data from NVS Flash Memory
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
//Serial.print("WiFi Not Connected ");
digitalWrite(wifiLed, LOW); //Turn off WiFi LED
}
else
{
//Serial.print("WiFi Connected ");
digitalWrite(wifiLed, HIGH);
//WiFi Control
if (wifiConnected){
espalexa.loop();
delay(1);
}
else {
wifiConnected = connectWifi(); // Initialise wifi connection
if(wifiConnected){
addDevices();
}
}
}
//Control Switches Manualy
button1.check();
button2.check();
button3.check();
button4.check();
ir_remote(); //IR remote Control
bluetooth_control(); //Bluetooth Control
}
void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT1");
switch (eventType) {
case AceButton::kEventPressed:
toggleState_1 = 1;
digitalWrite(RelayPin1, LOW);
pref.putBool("Relay1", toggleState_1);
sendFeedback(0, 100);
break;
case AceButton::kEventReleased:
toggleState_1 = 0;
digitalWrite(RelayPin1, HIGH);
pref.putBool("Relay1", toggleState_1);
sendFeedback(0, 0);
break;
}
}
void button2Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT2");
switch (eventType) {
case AceButton::kEventPressed:
toggleState_2 = 1;
digitalWrite(RelayPin2, LOW);
pref.putBool("Relay2", toggleState_2);
sendFeedback(1, 100);
break;
case AceButton::kEventReleased:
toggleState_2 = 0;
digitalWrite(RelayPin2, HIGH);
pref.putBool("Relay2", toggleState_2);
sendFeedback(1, 0);
break;
}
}
void button3Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT3");
switch (eventType) {
case AceButton::kEventPressed:
toggleState_3 = 1;
digitalWrite(RelayPin3, LOW);
pref.putBool("Relay3", toggleState_3);
sendFeedback(2, 100);
break;
case AceButton::kEventReleased:
toggleState_3 = 0;
digitalWrite(RelayPin3, HIGH);
pref.putBool("Relay3", toggleState_3);
sendFeedback(2, 0);
break;
}
}
void button4Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("EVENT4");
switch (eventType) {
case AceButton::kEventPressed:
toggleState_4 = 1;
digitalWrite(RelayPin4, LOW);
pref.putBool("Relay4", toggleState_4);
sendFeedback(3, 100);
break;
case AceButton::kEventReleased:
toggleState_4 = 0;
digitalWrite(RelayPin4, HIGH);
pref.putBool("Relay4", toggleState_4);
sendFeedback(3, 0);
break;
}
}