How to Build a Smart Home Automation System with Blynk and ESP32 Part 2.

Ayodeji Taofeek Khalid
8 min readJul 26, 2023

--

The first part gave a detailed breakdown about home automation and the things needed to make one. This section covers the code and circuit breakdown to make your own smart home automation system.

The circuit below shows the connections of the system which was design using the proteus simulation software. If you are using a 4-channel relay module, the power pin for the four relays will be interconnected together with 4 signal pins for each relay.

The battery coupled with the charge regulator serves as the power supply for the system.

A quick recap of the function of the libraries installed. TinyGsmClient and BlynkSimpleTinyGSM are used to interface with the GSM module for Internet connectivity, while LiquidCrystal is used to work with the LCD display. After installing all libraries needed, its time to write some codes for our smart home automation system. The link to the code is right after the explanation.

Below is a step-by-step guide on the explanation of the code:

#define TINY_GSM_MODEM_SIM800

#include <TinyGsmClient.h>

#include <BlynkSimpleTinyGSM.h>

#include <LiquidCrystal.h>

In this part, the Blynk template ID, name, and authorization token are defined. These parameters are necessary to connect the hardware with the Blynk platform and template.

#define BLYNK_TEMPLATE_ID “*************”

#define BLYNK_TEMPLATE_NAME “HOME AUTOMATION”

#define BLYNK_AUTH_TOKEN “*************************”

This line sets the Serial port as the output for Blynk debug messages. By defining BLYNK_PRINT as Serial, debug information will be printed to the Serial Monitor.

#define BLYNK_PRINT Serial

This part creates a HardwareSerial object named sim for communication with the SIM800 GSM module. It is using Serial2 (UART2) of the ESP32 board for communication. The TinyGsm library is then initialized with the sim object to handle GSM communication.

HardwareSerial sim(2);

TinyGsm modem(sim);

Auth: The Blynk authorization token is a unique key that identifies the hardware (ESP32) and the corresponding Blynk project.

Apn: The Access Point Name (APN) is the address used by the GSM module to connect to the Internet. This specific APN is for MTN Nigeria.

User and pass: These are empty strings. If your mobile carrier requires authentication, you can specify the username and password here.

char auth[] = “********************************”;

char apn[] = “web.gprs.mtnnigeria.net”;

char user[] = “”;

char pass[] = “”;

PointIndex: A variable used to keep track of the data point index in the Blynk platform.

int pointIndex = 1;

LiquidCrystal lcd(22,21,2,4,23,19); : Initializes the LCD display object, specifying the LCD’s pins (RS, E, D4, D5, D6, and D7) connected to the ESP32.

LiquidCrystal lcd(22,21,2,4,23,19);

BlynkTimer: An object that provides a simple way to schedule periodic tasks, which can be useful for automating actions at specified intervals.

BlynkTimer timer;

These #define statements assign the pin numbers on the ESP32 board to control each relay.

#define Relay_1 27

#define Relay_2 14

#define Relay_3 12

#define Relay_4 13

These #define statements assign Virtual Pin numbers from the Blynk platform to the buttons. When a button in the Blynk platform is pressed, the corresponding virtual pin is updated.

#define Button_VirtualPin_1 V1

#define Button_VirtualPin_2 V2

#define Button_VirtualPin_3 V3

#define Button_VirtualPin_4 V4

These variables are used to keep track of the button states for each relay. buttonCondition_X stores the state of the relay (1 for on and 0 for off), while pushButtonXState stores the current state of the physical push button.

int buttonCondition_1 = 1;

int pushButton1State = HIGH;

int buttonCondition_2 = 1;

int pushButton2State = HIGH;

int buttonCondition_3 = 1;

int pushButton3State = HIGH;

int buttonCondition_4 = 1;

int pushButton4State = HIGH;

This relay_state() function is responsible for controlling the state of the relays based on the relay number passed to it as an argument. It uses a switch statement to handle each relay separately.

· For each relay, the function checks the corresponding buttonCondition_X variable to determine if the relay is currently off (buttonCondition_X is 0) or on (buttonCondition_X is 1).

· If the relay is off, the function turns it on by setting the corresponding relay’s pin to HIGH and updating the buttonCondition_X variable to 1 to indicate that the relay is now on.

· If the relay is already on, the function turns it off by setting the corresponding relay’s pin to LOW and updating the buttonCondition_X variable to 0 to indicate that the relay is now off.

· A delay of 200 milliseconds is added after each relay state change to debounce the relay switch and avoid rapid toggling.

The function covers four relays (relay numbers 1 to 4), and if an invalid relay number is passed, it does nothing.

void relay_state(int relay) {

switch(relay) {

// For relay 1

case 1:

if(buttonCondition_1 == 0) {

digitalWrite(Relay_1, HIGH); // Turn on relay 1 by setting its pin to HIGH

buttonCondition_1 = 1; // Update buttonCondition_1 to indicate relay is now on

}

else {

digitalWrite(Relay_1, LOW); // Turn off relay 1 by setting its pin to LOW

buttonCondition_1 = 0; // Update buttonCondition_1 to indicate relay is now off

}

delay(200); // Add a delay to debounce the relay switch

break;

// For relay 2

case 2:

if(buttonCondition_2 == 0) {

digitalWrite(Relay_2, HIGH); // Turn on relay 2 by setting its pin to HIGH

buttonCondition_2 = 1; // Update buttonCondition_2 to indicate relay is now on

}

else {

digitalWrite(Relay_2, LOW); // Turn off relay 2 by setting its pin to LOW

buttonCondition_2 = 0; // Update buttonCondition_2 to indicate relay is now off

}

delay(200); // Add a delay to debounce the relay switch

break;

// For relay 3

case 3:

if(buttonCondition_3 == 0) {

digitalWrite(Relay_3, HIGH); // Turn on relay 3 by setting its pin to HIGH

buttonCondition_3 = 1; // Update buttonCondition_3 to indicate relay is now on

}

else {

digitalWrite(Relay_3, LOW); // Turn off relay 3 by setting its pin to LOW

buttonCondition_3 = 0; // Update buttonCondition_3 to indicate relay is now off

}

delay(200); // Add a delay to debounce the relay switch

break;

// For relay 4

case 4:

if(buttonCondition_4 == 0) {

digitalWrite(Relay_4, HIGH); // Turn on relay 4 by setting its pin to HIGH

buttonCondition_4 = 1; // Update buttonCondition_4 to indicate relay is now on

}

else {

digitalWrite(Relay_4, LOW); // Turn off relay 4 by setting its pin to LOW

buttonCondition_4 = 0; // Update buttonCondition_4 to indicate relay is now off

}

delay(200); // Add a delay to debounce the relay switch

break;

// If an invalid relay number is passed, do nothing

default : break;

}

}

These functions use the BLYNK_WRITE macro to handle changes in the virtual pins in the Blynk platform. When a button state changes in the platform, the corresponding BLYNK_WRITE function is executed, updating the relay state and displaying the current state on the LCD. This way, you can remotely control the state of each relay and see their status on the LCD display.

BLYNK_WRITE(Button_VirtualPin_1) {

buttonCondition_1 = param.asInt();

digitalWrite(Relay_1, buttonCondition_1);

lcd.setCursor (0,0);

lcd.print(“PORT1=”);

lcd.setCursor (6,0);

lcd.print(buttonCondition_1);

}

BLYNK_WRITE(Button_VirtualPin_2) {

buttonCondition_2 = param.asInt();

digitalWrite(Relay_2, buttonCondition_2);

lcd.setCursor (9,0);

lcd.print(“PORT2=”);

lcd.setCursor (15,0);

lcd.print(buttonCondition_2);

}

BLYNK_WRITE(Button_VirtualPin_3) {

buttonCondition_3 = param.asInt();

digitalWrite(Relay_3, buttonCondition_3);

lcd.setCursor (0,1);

lcd.print(“PORT3=”);

lcd.setCursor (6,1);

lcd.print(buttonCondition_3);

}

BLYNK_WRITE(Button_VirtualPin_4) {

buttonCondition_4 = param.asInt();

digitalWrite(Relay_4, buttonCondition_4);

lcd.setCursor (9,1);

lcd.print(“PORT4=”);

lcd.setCursor (15,1);

lcd.print(buttonCondition_4);

}

This function is designed to check the status of the Blynk platform’s connection to the server. It starts by checking if the Blynk platform is currently connected to the server by calling the Blynk.connected() function and storing the result in the boolean variable isconnected.

If the Blynk platform is not connected (isconnected == false), the function attempts to reconnect using Blynk.begin() with the provided authentication credentials (auth, modem, apn, user, and pass). This is an attempt to re-establish the connection in case it was lost.

If the Blynk platform is connected to the server (isconnected == true), the function prints “Connected” to the serial monitor using Serial.println(“ Connected”). This message indicates that the ESP32 successfully reconnected to the Blynk server or that the connection was already established.

The function is often called by a SimpleTimer object to periodically check and maintain the Blynk platform ‘s connection to the server, ensuring reliable communication between the ESP32 and the Blynk platform.

void checkBlynkStatus() { // This function is called every 3 seconds by SimpleTimer

bool isconnected = Blynk.connected();

if (isconnected == false) {

Blynk.begin (auth, modem, apn, user, pass); // Reconnect to the Blynk server using the provided authentication credentials

}

if (isconnected == true) {

Serial.println(“ Connected”); // Print “Connected” to the serial monitor

}

}

This setup() function is called once at the beginning of the Arduino sketch. It performs the following tasks:

  • Initializes the serial communication with a baud rate of 9600 to enable debugging and monitoring messages through the serial monitor.
  • Initializes the LCD display with 16 columns and 2 rows to display the welcome message for the home automation system.
  • Prints the welcome message “HOME AUTOMATION SYSTEM” on the LCD display, with the second line indicating “SYSTEM.”
  • Waits for 2 seconds to display the welcome message before proceeding.
  • Configures the relay pins (Relay_1, Relay_2, Relay_3, and Relay_4) as output pins and sets their initial state based on the buttonCondition variables (buttonCondition_1, buttonCondition_2, buttonCondition_3, and buttonCondition_4).
  • Initializes the SIM800 GSM module with a baud rate of 9600, 8 data bits, no parity, and 1 stop bit for communication with the cellular network.
  • Begins the Blynk connection with the specified parameters (authentication token, GSM modem, APN, username, and password) to establish communication between the ESP32 and the Blynk server.
  • Sets the BlynkTimer interval to 3 seconds to periodically check the Blynk server connection status using the checkBlynkStatus() function.
  • Waits for 2 seconds before proceeding.
  • Clears the LCD display to prepare for displaying real-time data.
  • Waits for 1 second before finishing the setup function.

void setup() {

Serial.begin(9600);

lcd.begin(16, 2);

lcd.setCursor (0,0);

lcd.print(“ HOME AUTOMATION “);

lcd.setCursor (5,1);

lcd.print(“SYSTEM”);

delay(2000);

pinMode(Relay_1, OUTPUT);

digitalWrite(Relay_1, buttonCondition_1);

pinMode(Relay_2, OUTPUT);

digitalWrite(Relay_2, buttonCondition_2);

pinMode(Relay_3, OUTPUT);

digitalWrite(Relay_3, buttonCondition_3);

pinMode(Relay_4, OUTPUT);

digitalWrite(Relay_4, buttonCondition_4);

sim.begin(9600, SERIAL_8N1, 16, 17);

Blynk.begin(auth, modem, apn, user, pass);

timer.setInterval(3000L, checkBlynkStatus);

delay(2000);

lcd.clear();

delay(1000);

}

The loop() function is a crucial part of every Arduino sketch. It is called repeatedly and indefinitely after the setup() function has been executed. In this specific code, the loop() function serves the purpose of handling Blynk communication and ensuring data transmission with the Blynk server. Here’s the explanation of the code:

Blynk.run() : This function is the core of Blynk’s functionality. It continuously listens for incoming commands from the Blynk server and executes corresponding actions, such as updating the state of virtual pins or sending data back to the Blynk platform. It ensures that any actions triggered by the Blynk p;atform (e.g., pressing virtual buttons) are detected and processed in real-time, allowing for a smooth and responsive interaction between the hardware and the Blynk platform.

void loop() {

// Run Blynk to oversee the communication and transmission with the Blynk server

Blynk.run();

}

Congratulations on completing Part 2 of “Building a Home Automation System with Blynk and ESP32”!

In this section, we delved into the code and circuit breakdown to create your very own smart home automation system. From understanding the relay states to exploring Blynk communication, you’ve gained valuable insights to control your devices remotely.

Now, with the power of technology and DIY, you can seamlessly transform your home into a connected haven. Keep exploring and innovating with your home automation journey.

The link to the code : popmonac/Home-Automation: The project requires an ESP32 board, SIM800 GSM module, relays, a compatible LCD, and the Blynk app installed on an Android or iOS device. The Arduino IDE should be installed, along with the necessary libraries (TinyGsmClient, BlynkSimpleTinyGSM, and LiquidCrystal). (github.com)

--

--

Ayodeji Taofeek Khalid

Embedded system developer | Stem advocate | Renewable Energy advocate | IoT | Blockchain Advocate | Open Source Contributor | Writer | Brand strategist |