In this post we are going to learn how to make a Smart relay using ESP32 and a relay board module. This is usefull to control your apliances or lightning. Also in some websites like alixpress there are avaliable for purchase some boards that includes both relay and ESP32 as well as a power supply. Or maybe you want to desingn your own board. The devices can be controlled independently with Alexa or Google home

Let's get started

What you need

Procedure

Setting Arduino Cloud

First, if you don´t have one, you need to create an Arduino cloud account. If you have one already just log in.

This is is the screen that will appear once we have logged in.

Now, in the left sidebar, select devices.

Your devices will be listed here. If you have not added any before, it will appear empty. To add a new device click on the +device button.

This screen will show up. Now, select “Third party device”.

Now click on the ESP32 option and in the box below select the type of board you have.

Give it the name of your choice

This steep is very important. Now this screen will appear with the unique identifier of your ESP32, that we’re going to need later. You can download the pdf with the ID and the key to keep a copy in your computer.

Once the configuration is complete, you should be able to see the device on the devices screen.

Now, in the left taskbar, go to “things” and then click on the “+thing” button.

If we enter the entry we have just created, we will see the following screen. Here we must first choose the board we are going to use from the task bar on the right hand side.

Now we will add the variables. These are the final devices, in this case the relays, which we are going to control from the board.

To add a variable press the add button and the next screen will show up.

Enable the Smart home tag and select the light option in this case.

We name the variable as shown in the image, otherwise you need to change the name in the Arduino code too. The name should be the same in both files or it won’t work.

Create as many variables as the relays you have. The free version only allows you to create up to 5 variables.

Now we need to create a dashboard to interact with the outputs.

Go to dashboards in the left dashboard and click in the +dashboard button.

Now we are going to add the virtual switches that will allow to control the outputs. To do this, we will click on the add button

Select the switch.

Now we need to link the switch to its corresponding output. To do this we press the variable link button and select the output we want to activate that switch.

You will need to create as many switches as outputs you have.

The code

Now, It´s time for the code. Open arduino IDE and upload the following code to your ESP32 board. You will need to add your wifi credentials and the ID and key that we mentioned before. Also you can change the GPIO ports for another that is more suitable for you.

Arduino IDE code

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

const char DEVICE_LOGIN_NAME[]  = "DEV. ID"; //Enter DEVICE ID

const char SSID[]               = "SSID";    //Enter WiFi SSID (name)
const char PASS[]               = "PASSWORD";    //Enter WiFi password
const char DEVICE_KEY[]         = "DEV. KEY";    //Enter Secret device password (Secret Key)



// define the GPIO connected with Relays and switches
#define RelayPin1 23  //D23
#define RelayPin2 19  //D19
#define RelayPin3 18  //D18
#define RelayPin4 5  //D5

#define SwitchPin1 13  //D13
#define SwitchPin2 12  //D12
#define SwitchPin3 14  //D14
#define SwitchPin4 27  //D27

#define wifiLed    2   //D2


int toggleState_1 = 0; //Define integer to remember the toggle state for relay 1
int toggleState_2 = 0; //Define integer to remember the toggle state for relay 2
int toggleState_3 = 0; //Define integer to remember the toggle state for relay 3
int toggleState_4 = 0; //Define integer to remember the toggle state for relay 4

// Switch State
bool SwitchState_1 = LOW;
bool SwitchState_2 = LOW;
bool SwitchState_3 = LOW;
bool SwitchState_4 = LOW;

int   reconnectFlag = 0;

void onLight1Change();
void onLight2Change();
void onLight3Change();
void onLight4Change();

CloudSwitch light1;
CloudSwitch light2;
CloudSwitch light3;
CloudSwitch light4;

void initProperties(){

  ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME);
  ArduinoCloud.setSecretDeviceKey(DEVICE_KEY);
  ArduinoCloud.addProperty(light1, READWRITE, ON_CHANGE, onLight1Change);
  ArduinoCloud.addProperty(light2, READWRITE, ON_CHANGE, onLight2Change);
  ArduinoCloud.addProperty(light3, READWRITE, ON_CHANGE, onLight3Change);
  ArduinoCloud.addProperty(light4, READWRITE, ON_CHANGE, onLight4Change);
  
}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);


void relayOnOff(int relay) {

  switch (relay) {
    case 1:
      if (toggleState_1 == 0) {
        digitalWrite(RelayPin1, LOW); // turn on relay 1
        toggleState_1 = 1;
        Serial.println("Device1 ON");
      }
      else {
        digitalWrite(RelayPin1, HIGH); // turn off relay 1
        toggleState_1 = 0;
        Serial.println("Device1 OFF");
      }
      delay(100);
      break;
    case 2:
      if (toggleState_2 == 0) {
        digitalWrite(RelayPin2, LOW); // turn on relay 2
        toggleState_2 = 1;
        Serial.println("Device2 ON");
      }
      else {
        digitalWrite(RelayPin2, HIGH); // turn off relay 2
        toggleState_2 = 0;
        Serial.println("Device2 OFF");
      }
      delay(100);
      break;
    case 3:
      if (toggleState_3 == 0) {
        digitalWrite(RelayPin3, LOW); // turn on relay 3
        toggleState_3 = 1;
        Serial.println("Device3 ON");
      } else {
        digitalWrite(RelayPin3, HIGH); // turn off relay 3
        toggleState_3 = 0;
        Serial.println("Device3 OFF");
      }
      delay(100);
      break;
    case 4:
      if (toggleState_4 == 0) {
        digitalWrite(RelayPin4, LOW); // turn on relay 4
        toggleState_4 = 1;
        Serial.println("Device4 ON");
      }
      else {
        digitalWrite(RelayPin4, HIGH); // turn off relay 4
        toggleState_4 = 0;
        Serial.println("Device4 OFF");
      }
      delay(100);
      break;
    default : break;
  }
}

void manual_control()
{
  if (digitalRead(SwitchPin1) == LOW && SwitchState_1 == LOW) {
    digitalWrite(RelayPin1, LOW);
    toggleState_1 = 1;
    SwitchState_1 = HIGH;
    light1 = toggleState_1;
    Serial.println("Switch-1 on");
  }
  if (digitalRead(SwitchPin1) == HIGH && SwitchState_1 == HIGH) {
    digitalWrite(RelayPin1, HIGH);
    toggleState_1 = 0;
    SwitchState_1 = LOW;
    light1 = toggleState_1;
    Serial.println("Switch-1 off");
  }
  if (digitalRead(SwitchPin2) == LOW && SwitchState_2 == LOW) {
    digitalWrite(RelayPin2, LOW);
    toggleState_2 = 1;
    SwitchState_2 = HIGH;
    light2 = toggleState_2;
    Serial.println("Switch-2 on");
  }
  if (digitalRead(SwitchPin2) == HIGH && SwitchState_2 == HIGH) {
    digitalWrite(RelayPin2, HIGH);
    toggleState_2 = 0;
    SwitchState_2 = LOW;
    light2 = toggleState_2;
    Serial.println("Switch-2 off");
  }
  if (digitalRead(SwitchPin3) == LOW && SwitchState_3 == LOW) {
    digitalWrite(RelayPin3, LOW);
    toggleState_3 = 1;
    SwitchState_3 = HIGH;
    light3 = toggleState_3;
    Serial.println("Switch-3 on");
  }
  if (digitalRead(SwitchPin3) == HIGH && SwitchState_3 == HIGH) {
    digitalWrite(RelayPin3, HIGH);
    toggleState_3 = 0;
    SwitchState_3 = LOW;
    light3 = toggleState_3;
    Serial.println("Switch-3 off");
  }
  if (digitalRead(SwitchPin4) == LOW && SwitchState_4 == LOW) {
    digitalWrite(RelayPin4, LOW);
    toggleState_4 = 1;
    SwitchState_4 = HIGH;
    light4 = toggleState_4;
    Serial.println("Switch-4 on");
  }
  if (digitalRead(SwitchPin4) == HIGH && SwitchState_4 == HIGH) {
    digitalWrite(RelayPin4, HIGH);
    toggleState_4 = 0;
    SwitchState_4 = LOW;
    light4 = toggleState_4;
    Serial.println("Switch-4 off");
  }
}  

void doThisOnConnect(){
  /* add your custom code here */
  Serial.println("Board successfully connected to Arduino IoT Cloud");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  digitalWrite(wifiLed, HIGH); //Turn on WiFi LED
}
void doThisOnSync(){
  /* add your custom code here */
  Serial.println("Thing Properties synchronised");
}

void doThisOnDisconnect(){
  /* add your custom code here */
  Serial.println("Board disconnected from Arduino IoT Cloud");
  digitalWrite(wifiLed, LOW); //Turn off WiFi LED
}

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500);

  // Defined in thingProperties.h
  initProperties();
 
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, doThisOnConnect);
  ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, doThisOnSync);
  ArduinoCloud.addCallback(ArduinoIoTCloudEvent::DISCONNECT, doThisOnDisconnect);

  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  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, HIGH);
  digitalWrite(RelayPin2, HIGH);
  digitalWrite(RelayPin3, HIGH);
  digitalWrite(RelayPin4, HIGH);
}

void loop() {

  ArduinoCloud.update();
  
  manual_control();     //Manual Control
 
}

void onLight1Change() {
  //Control the device
  if (light1 == 1)
  {
    digitalWrite(RelayPin1, LOW);
    Serial.println("Device1 ON");
    toggleState_1 = 1;
  }
  else
  {
    digitalWrite(RelayPin1, HIGH);
    Serial.println("Device1 OFF");
    toggleState_1 = 0;
  }
}

void onLight2Change() {
  if (light2 == 1)
  {
    digitalWrite(RelayPin2, LOW);
    Serial.println("Device2 ON");
    toggleState_2 = 1;
  }
  else
  {
    digitalWrite(RelayPin2, HIGH);
    Serial.println("Device2 OFF");
    toggleState_2 = 0;
  }
}

void onLight3Change() {
  if (light3 == 1)
  {
    digitalWrite(RelayPin3, LOW);
    Serial.println("Device3 ON");
    toggleState_3 = 1;
  }
  else
  {
    digitalWrite(RelayPin3, HIGH);
    Serial.println("Device3 OFF");
    toggleState_3 = 0;
  }
}

void onLight4Change() {
  if (light4 == 1)
  {
    digitalWrite(RelayPin4, LOW);
    Serial.println("Device4 ON");
    toggleState_4 = 1;
  }
  else
  {
    digitalWrite(RelayPin4, HIGH);
    Serial.println("Device4 OFF");
    toggleState_4 = 0;
  }
}

If everything went well, you should notice that the ESP32 is now shown as online.

You can also test the outputs using the dashboard switches and the arduino IDE serial monitor.

Works with Alexa / Google home

Google Home implementation

 

At this point we are ready to link an Alexa/Google home account to control our devices. This allows a simpler control of the devices as well as the creation of routines or the convenience of voice control if you have a smart speaker.

To connect our Google or Alexa account, we must first go back to the things tab and choose the project in which we have previously configured the outputs.

Once here in the taskbar on the right hand side, scroll down to the Smart Home integration option and click on configure.

Now this screen will appear where we can choose whether we want to use Alexa or Google home. In my case I will use google home to link the account.

Once linked, the Google home or Alexa icon will appear next to the devices.

Now we must finish the configuration from our smartphone. Open the Google home app and go to the devices tab.

‎ ‎ ‎

‎ ‎ ‎ ‎

Then press + add button.

‎ ‎ ‎

‎ ‎ ‎ ‎

Now choose the option ‘Works with Google Home’.

‎ ‎ ‎

‎ ‎ ‎ ‎

Look for Arduino and click on it.

‎ ‎ ‎

‎ ‎ ‎ ‎

Select all the apliances and click on “Add to a room”.

‎ ‎ ‎

‎ ‎ ‎ ‎

Now click on done. All devices should appear in the room you have selected.

‎ ‎ ‎

Final steps

Now is time to connect all and enjoy the project.

Conections diagram

Final result

In our case will be using an 8 relay board, but the code is only compatible with up to 4 relays.