UNICON - True Home Automation Controller

by PADMALAYA RAWAL in Circuits > Microcontrollers

577 Views, 10 Favorites, 0 Comments

UNICON - True Home Automation Controller

Real life use

So, when it comes to controlling home appliances we usually smartphone as the only option because it has Bluetooth and wifi inbuilt, right? You picked up your smartphone to control an appliance, pin pong! New Instagram notification and you got distracted. So, an appliance control has converted into a regret. Sounds familiar, right?


But not anymore, introducing UNICON, a truly portable and rechargeable home automation controller that allows you to control appliances. But that's not it, it can simultaneously control appliances of multiple rooms. In this build, we will control 1 appliance of two different rooms, but you can extend it further as per your needs. ENJOY!

Supplies

6cbaa87806cd483dfd2744a30a3376c5.jpg
  1. UNIHIKER - 1Pc
  2. ESP32 C3 Mini (or any other ESP Board) - 2Pcs
  3. Wireless charging coil - 1Pc
  4. TP4056 module - 1Pc
  5. Slide Button- 1Pc
  6. Boost converter - 1Pc
  7. LEDs (Just for prototype) - 2 Pcs
  8. Potentiometer (Just for prototype) - 2Pcs
  9. Brass threaded inserts(M3*6mm) - 3 Pcs
  10. Allen Countersunk screws(M3*6mm) - 3 Pcs
  11. Circular Magnets(8mm * 1.3mm) - 8 Pcs
  12. USB C breakout - 1 Pc
  13. Relay Module (Single channel) - 2 Pcs
  14. LM35 Temperature sensor - 2 Pcs

Prototyping Setup

Circuit diagram.png

But why to prototype? This is to save time debugging at the later stages. As it is the crude form of our project so it allows to make changes faster. We will first begin by prototyping our setup on a breadboard to meet our expectations. For prototyping, I am using two ESP32 boards with one LED and one potentiometer connected to both of them. But why?

 

I want to keep the prototype as simple as possible and wanted to test out whether I can trigger a digital device connected to one pin that will later act as a relay controller, along with whether I can receive analog value from the ESP32 board connected to an analog pin on the UNIHIKER which will later act as Temperature sensor(or any other analog sensor of your choice)

 

Here, I am using one ESP32 WROOM Dev board and one ESP32 C3 Mini Bettle. You can use any of the ESP32 and they should work fine too. Here are the connection diagrams that I am following for this prototype setup.

Firmware Development

Here is the firmware for the ESP32 development boards and the UNIHIKER board. I tried to add comments as much as I could so that you can understand why I did what I did.



//This is for DF ROBOT ESP32 Bettle board
#include <WiFi.h> //Make sure to download this library
#include <WebServer.h> //Make sure to download this library

// WiFi credentials
const char* ssid = "Padmalaya Rawal"; //Change with your WiFi Name
const char* password = "PureCon"; //Change with your WiFi Password

// Static IP configuration
IPAddress local_IP(192,168,1,50); // Set your static IP
IPAddress gateway(192,168,1,1); // Set your router’s gateway IP
IPAddress subnet(255,255,255,0); // Set subnet mask
WebServer server(80); // Create a web server on port 80

const int ledPin = 2; // change to pin on which you are connecting LED
const int sensorPin = 1; // change to pin on which your connecting sensor

// Function to handle turning the LED ON
void handleLedOn() {
digitalWrite(ledPin, HIGH); // Turn the LED ON
Serial.println("LED turned ON");
server.send(200, "text/plain", "LED is ON");
}

// Function to handle turning the LED OFF
void handleLedOff() {
digitalWrite(ledPin, LOW); // Turn the LED OFF
Serial.println("LED turned OFF");
server.send(200, "text/plain", "LED is OFF");
}

// Function to handle invalid URLs
void handleNotFound() {
server.send(404, "text/plain", "Invalid Command");
}

void sensread(){
int sensorValue = analogRead(sensorPin);
server.send(200, "text/plain", String(sensorValue));
}

void setup() {
Serial.begin(115200); // Start Serial communication
pinMode(ledPin, OUTPUT); // Set LED pin as output
pinMode(sensorPin, INPUT);
digitalWrite(ledPin, LOW); // Ensure LED is OFF initially

// Connect to Wi-Fi with static IP
if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("Static IP Configuration Failed");
}

Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);

// Wait until connected to WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}

// Once connected
Serial.println("\nWiFi connected!");
Serial.print("ESP32 IP address: ");
Serial.println(WiFi.localIP()); // Print static IP address

// Define the routes for LED ON and OFF
server.on("/control/led/on", handleLedOn); // Route to turn LED ON
server.on("/control/led/off", handleLedOff); // Route to turn LED OFF
server.on("/read/sensor", sensread);
server.onNotFound(handleNotFound); // Route for invalid commands

// Start the web server
server.begin();
Serial.println("HTTP server started");
}

void loop() {
server.handleClient(); // Handle incoming client requests
}



//This is for ESP32 dev. board

#include <WiFi.h> //Make sure to download this library
#include <WebServer.h> //Make sure to download this library

// WiFi credentials
const char* ssid = "Padmalaya Rawal"; //Change with your WiFi Name
const char* password = "PureCon"; //Change with your WiFi Password

// Static IP configuration
IPAddress local_IP(192,168,1,51); // Set your static IP
IPAddress gateway(192,168,1,1); // Set your router’s gateway IP
IPAddress subnet(255,255,255,0); // Set subnet mask

WebServer server(80); // Create a web server on port 80

const int ledPin = 2; // change to pin on which you are connecting LED
const int sensorPin = 34; // change to pin on which your connecting sensor

// Function to handle turning the LED ON
void handleLedOn() {
digitalWrite(ledPin, HIGH); // Turn the LED ON
Serial.println("LED turned ON");
server.send(200, "text/plain", "LED is ON");
}

// Function to handle turning the LED OFF
void handleLedOff() {
digitalWrite(ledPin, LOW); // Turn the LED OFF
Serial.println("LED turned OFF");
server.send(200, "text/plain", "LED is OFF");
}

// Function to handle invalid URLs
void handleNotFound() {
server.send(404, "text/plain", "Invalid Command");
}

void sensread(){
int sensorValue = analogRead(sensorPin);
server.send(200, "text/plain", String(sensorValue));
}

void setup() {
Serial.begin(115200); // Start Serial communication
pinMode(ledPin, OUTPUT); // Set LED pin as output
pinMode(sensorPin, INPUT);
digitalWrite(ledPin, LOW); // Ensure LED is OFF initially

// Connect to Wi-Fi with static IP
if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("Static IP Configuration Failed");
}

Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);

// Wait until connected to WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}

// Once connected
Serial.println("\nWiFi connected!");
Serial.print("ESP32 IP address: ");
Serial.println(WiFi.localIP()); // Print static IP address

// Define the routes for LED ON and OFF
server.on("/control/led/on", handleLedOn); // Route to turn LED ON
server.on("/control/led/off", handleLedOff); // Route to turn LED OFF
server.on("/read/sensor", sensread);
server.onNotFound(handleNotFound); // Route for invalid commands

// Start the web server
server.begin();
Serial.println("HTTP server started");
}

void loop() {
server.handleClient(); // Handle incoming client requests
}


What's the difference between the two codes for ESP32s?

Difference 1:

In Line 11, 1st code has

IPAddress local_IP(192,168,1,51); // Set your static IP


Whereas the 2nd code has

IPAddress local_IP(192,168,1,50); // Set your static IP

 

Difference 2:

In Line 18, 1st code has

const int sensorPin = 34; // change to pin on which your connecting sensor

 

whereas the 2nd code has

const int sensorPin = 1; // change to pin on which your connecting sensor

 

Also, please don't forget to change the Wifi credentials in both the codes

const char* ssid = "Padmalaya Rawal"; //Change with your WiFi Name

const char* password = "PureCon"; //Change with your WiFi Password

 

Replace the name “Padmalaya Rawal” with the name of your WiFi and “PureCon” with the password. And now it's time for UNIHIKER. Now let's have a look at the UNIHIKER's firmware which is written in Python.

# For UNIHIKER Board

import requests
from unihiker import GUI
import time

from pinpong.board import Board # Import the Board module from the pinpong.board package
from pinpong.extension.unihiker import * # Import all modules from the pinpong.extension.unihiker package


# Instantiate a GUI object.
gui = GUI()

# ESP32's static IP addresses
esp32_ip = "192.168.1.50"
esp32_ip2 = "192.168.1.51"

img_image = gui.draw_image(x=120, y=30, w=400, h=250, image='logo.png', origin='center', onclick=lambda: print("image clicked"))


# URLs to control the LEDs and read the sensor
url_led_on = f"http://{esp32_ip}/control/led/on"
url_led_off = f"http://{esp32_ip}/control/led/off"
url_sensor = f"http://{esp32_ip}/read/sensor" # Fetch sensor data

url_led_on2 = f"http://{esp32_ip2}/control/led/on"
url_led_off2 = f"http://{esp32_ip2}/control/led/off"
url_sensor2 = f"http://{esp32_ip2}/read/sensor" # Fetch sensor data


# Function to turn on the LED on ESP32 No.1
def turn_led_on():
try:
response = requests.get(url_led_on)
print("LED ON Response:", response.text)
except Exception as e:
print("Error turning LED ON:", e)

# Function to turn off the LED on ESP32 No.1
def turn_led_off():
try:
response = requests.get(url_led_off)
print("LED OFF Response:", response.text)
except Exception as e:
print("Error turning LED OFF:", e)

# Function to turn on the LED on ESP32 No.2
def turn_led_on2():
try:
response = requests.get(url_led_on2)
print("LED ON Response:", response.text)
except Exception as e:
print("Error turning LED ON:", e)

# Function to turn off the LED on ESP32 No.2
def turn_led_off2():
try:
response = requests.get(url_led_off2)
print("LED OFF Response:", response.text)
except Exception as e:
print("Error turning LED OFF:", e)

# Function to fetch the analog sensor value from ESP32 No.1
def fetch_sensor_data():
try:
response = requests.get(url_sensor)
sensor_value = response.text
print(f"Sensor Value: {sensor_value}")
value.config(text=sensor_value) # Update the displayed light value

except Exception as e:
print("Error fetching sensor data:", e)

# Function to fetch the analog sensor value from ESP32 No.2
def fetch_sensor_data2():
try:
response = requests.get(url_sensor2)
sensor_value = response.text
print(f"Sensor Value: {sensor_value}")
value2.config(text=sensor_value) # Update the displayed light value

except Exception as e:
print("Error fetching sensor data:", e)


# Add GUI components
gui.draw_text(x=120, y=110, w=200, text='ROOM 1 Control:', origin='bottom')
button_on = gui.add_button(text="ON", x=40, y=120, w=80, h=40, onclick=turn_led_on)
button_off = gui.add_button(text="OFF", x=120, y=120, w=80, h=40, onclick=turn_led_off)
gui.draw_text(x=103, y=180, font_size = 10, text='Temperature:', origin='bottom')
value = gui.draw_text(x=153, y=164, text='0', font_size=10) # Display the initial light value


gui.draw_text(x=120, y=240, w=200, text='ROOM 2 Control:', origin='bottom')
button_on2 = gui.add_button(text="ON", x=40, y=250, w=80, h=40, onclick=turn_led_on2)
button_off2 = gui.add_button(text="OFF", x=120, y=250, w=80, h=40, onclick=turn_led_off2)
gui.draw_text(x=103, y=310, w=200, font_size = 10, text='Temperature:', origin='bottom')
value2 = gui.draw_text(x=154, y=293, text='0', font_size=10) # Display the initial light value


# Main loop to keep the GUI running and fetch sensor data
while True:
fetch_sensor_data()
fetch_sensor_data2()
time.sleep(1) # Delay between fetching sensor data

Note that the IP address in lines 15 and 16 is the same as we added in Code 1 and Code 2. If you wish to change it, make sure to do it all the mentioned lines in all 3 codes to avoid any errors.

Firmware Uploading

You can skip this step if you have already completed the ESP32 boards set up in ARDUINO IDE, but if not, stick with me, this is to make your life easier. Follow along:

 

1. Download Arduino IDE from https://www.arduino.cc/en/software as per your machine(PC).


 

2. Simply follow the instructions and install it. Once installed, fire it up


 

3. ESP32 boards setup, add the below link in preference:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json



4. Install ESP32 boards from the boards' manager

 

6. Select board - DF ROBOT bettle and upload code

 

7. Select board - ESP32 Dev board and follow the above steps again, press boot button when the code starts uploading (not compiling) or you can add a 10uF cap b/w GND and EN pin. 

 

UNIHIKER SETUP:

Now Let's set up UNIHIKER, there are various methods by which you can program UNIHIKER but the one that I prefer needs the least time to start uploading code. I hope you don't want to skip this step because there is not much detailed tutorial available on UNIHIKER that can guide you through.

 

1. Connect UNIHIKER board to your PC via TYPE-C data cable included in the package.

2. Once UNIHIKER booted up, visit http://10.1.2.3 in your browser that will open up the following window:

3. Go to Network settings and add your Wi-Fi credentials. This will allow UNIHIKER to connect to the network. Make sure it's the same Wi-Fi as used in ESP32 codes, else it won't work.

 

4. Now go to toggle service and click “Open Page” under Jupyter section

 

You will see the below page:

 

5. Let's make a new python file, rename it and upload the code to UNIHIKER.

 

Click here to rename the file.

 

In the highlighted section, we will write our code.

 

Now copy and paste the code mentioned above and after pasting the code & renaming the file it should look something like this. Notice that, “NOT CONNECTED” should not appear on the top, it indicates that UNIHIKER is not connected with your PC. If it appears, double check that you are using Data cable (preferably the one included in the kit) not the power cable. Once verified, hit “NOT CONNECTED” Label and it will connect successfully which in indicated in next image.

 

6. Now in a new tab open the below homepage, you can follow the steps listed above and upload DF ROBOT logo named as "logo.png" using the button as shown below. Once uploaded, move back to the previous tab.

 

Download this image and rename it as “logo” and it should be in .png extension:

 

7. Hit the “RUN” button and boom, you will see UI on UNIHIKER. You will be able to control the LED on both ESP32s and also you will see values changing if you rotate the potentiometer.





Final Schematic Explanation

1.png
2.png

DO NOT MISS THIS STEP ELSE IT MIGHT BURN UP YOUR UNIHIKER

If you are using the same Boost convertor Module, make sure to remove resistors A and B to get 5V on output.


When the receiver coil is energized by the transmitter coil, it begins charging the battery via the TP4056 charging module. When the button is turned on, it turns on the boost converter and powers up UNIHIKER. Please do not connect cable to UNIHIKER When it is powered by battery else you may end up burning your UNIHIKER board.

CAD & 3D Printing

DF ROBOT article part 1.png

The CAD is designed using Fusion 360 and the whole project is divided into two parts, one is the UNIHIKER case and the other is the charging Dock. The parts are designed in such as way that you don't need to waste a single gram of filament on support material. I used Black PLA+ filament for all the parts.


Important Specs that you might for setting up your 3D printer:

  1. Printer: AnyCubic Kobra Neo
  2. Layer height: 0.2mm
  3. Nozzle Size: 0.4mm
  4. Slicer: Prusa Slicer
  5. Infill- 60%
  6. Support - No
  7. Print one part at a time - yes


Here are all the 3D-printed parts needed for this build


Assembly


 

 

 

 



 

Remember to solder the sufficiently large wires so that you can open the LID without breaking connections but not too much because that might reduce the current delivered to UNIHIKER. Here is the assembled view of the UNIHIKER Case. Place the 2 mounts and screw them in place before closing the LID. I have kept the tolerance of the Case LOW so that the LID can stay in place without the use of any screws or glue. 

Final Look & Working With Prototype Setup

Working Demo with prototype setup

Here is the final look of our project:






Final Implementation

Real life use

for the final implementation, replace LED with a relay module and potentiometer with LM35 temperature sensor by following the below circuit diagrams. If you want to use any other sensor instead of LM35, make sure to change the code on all three devices by adding the required libraries.

 

There is no change required for UNIHIKER. I have installed this setup in the switch box of two rooms at my home.

Conclusion and Future Improvemts

In a world full of distractions, UNICON will help you to stay distraction-free while staying smart. Control and monitor multiple rooms of your home, office, or arsenal altogether just at your fingertips. This is what we call the true smart home automation setup. 


Future improvements

The device can be made even more compact by replacing all the modules with a custom-designed PCB. Also, I have planned a lot of features for the next version which are as follows

 

1. When the USB is plugged in, UNIHIKER should not be powered by the Boost converter

2. When USB is not connected, UNIHIKER should be powered by a Boost converter

3. When UNIHIKER is on the charging Dock, UNHIKER should not be powered by a boost convertor instead it should be powered by a Wireless coil.

4. When UNIHIKER is on the charging Dock, and USB is plugged in, it should only be powered by USB cable while the battery keeps on charging via Wireless charging. 

5. Addition of more buttons to control more appliances 

6. Addition of more room controls and a drop-down menu to select the room

7. Sleep mode, shutdown screen to save power when the device is inactive for a specific time and wakes up when the device is moved which is detected by the inbuilt IMU.

 

 

We have just scratched the surface, possibilities are endless.

Happy Learning!