Introduction: Smart Plug

About: I like to learn, like to make, like to share.

A smart plug is a home automation device and is a hot new thing. Several types of the smart plug are available in the market but they are quite expensive. Besides, as a hobbyist, I always like to make my own thing and I think you are same.

Generally, smart plugs are compact device and plug into traditional wall sockets, upgrading them with remote control, scheduling, and power usage monitoring via smartphone apps. In this tutorial I will show you how I build my smart plug using ESP8266 wifi module which has the following features:

  • Local and Remote Control - The device is made based on Cayenne and you can easily on/off the plug using Cayenne smartphone app or Cayenne Web app.
  • Motion Control - You can automatically on/off the plug with your presence and can enable or disable the option from Cayenne app.
  • Voice Control - You can turn on or off the plug by using Alexa voice assistant.
  • Power Scheduling – Easily create on/off schedules for your devices and you can easily set the timer from Cayenne app.
  • Thermal Protection – A built-in temperature sensor will automatically turn off overheating appliances and notify you through SMS or E-mail.
  • Remote Monitoring - Using Cayenne app you can easily monitor voltage, current, temperature and state of the plug (either it is on or off).
  • Energy Usage Statistics – You can monitor power consumption of connected devices and get notified.

Demo video:

Step 1: Components List

1. ESP8266-12E Module

2. DC5V Adapter

3. 3.3V Regulator IC

4. Triac (BT134)

5. Opto-isolated triac driver (EL3021)

6. Temperature Sensor (DS18B20)

7. Current Sensor (ACS712)

8. A generic AC Plug

9. Some Resistors and jumper wire from your parts box.

Tools Required

1. Soldering Iron

2. Multimeter

3. Cutter

4. Glue Gun

5. Screw Driver

Step 2: Preparing Cayenne Environment

Cayenne is an easy to build IoT platform where you can connect you IoT devices very easily. Cayenne support real-time data visualization, remote monitoring, SMS and email notification and trigger. To connect your device with Cayenne platform you first need to sign up from https://mydevices.com/cayenne/signup/. You will get some credentials to connect with cayenne from your device. To visualize the data and control your device you just need to add an appropriate widget using drag and drop method. First, you need to determine the parameters you like to monitor. Cayenne use a separate channel for every parameter and you need to define it when setup the widget. Current Cayenne support Raspberry Pi, Arduino, ESP8266 and lots of sensors and actuators.

Before going further you may give a quick look in this getting started guide:

https://www.theengineeringprojects.com/2016/09/get...

In my case I added:

  • Two Value Display Widgets for showing Current and Temperature.
  • One Gauge Display Widget for showing Voltage.
  • One 2 State Display Widget for monitoring the state of the Plug
  • Three Button Controller Widget for turning On and Off the plug, Enabling/Disabling proximity, and Enabling/Disabling timer.
  • One Slider Controller Widget to set the time.
  • One Line Chart Display Widget to show the energy consumption rate.
  • Two triggers, one for automatic off if overheats and another for email and SMS notification.

Follow the pictures and provide the asking information to prepare your own dashboard.

Step 3: Mobile View

After preparing your own Cayenne environment you can access the dashboard from web application as well as from mobile application. Both Andriod and Iphone app are available. I added some screenshot from my Android phone. Cayenne retains the last data sent from any device.

Step 4: Making Power Supply

The power supply is a very important thing for your device and the operation of your device depends on the performance of the power supply. I used ESP8266-12E as a main controlling unit for my smart plug. The esp module requires 3.3V regulated supply for stable operation. A 3.3V power supply is very uncommon but you can easily manage a 5V power supply. All smartphone charger has a 5V output with enough current capacity. You can easily use one but required a 3.3V regulator.

I used an old mobile phone charger. For converting 5V to 3.3V I made a regulator circuit using AMS1117 regulator IC. As I have a plan to measure the inside temperature of the plug so I soldered a DS18B20 temperature sensor on the regulator board.

After making the regulator circuit I connected the output of the charger board to the input of the regulator circuit.

Step 5: Making Solid State Relay

As you know, to control AC load using a DC signal a relay is required. There are two types of relay available.

1. Electro-mechanical relay

2. Solid state relay

Solid state relay has some advantages over mechanical relay. They require much lesser current and operate for a wide voltage range compare to mechanical relay. As solid state relay required less current they can be driven directly from a microcontroller pin without using any transistor. This is the reason I am using solid state relay fro my smart plug.

To make one I used a triac (BT134) and an optoisolated triac driver (EL3021). The schematic is added with the step. I don't use any snubber circuit but if you like to drive a high inductive load using the relay it is highly recommended.

Step 6: Soldering ESP Module and Uploading Program

The esp8266-12e board has no header pin, so it is hard to solder in PCB board or connecting sensors. For the reason, I use a thin jumper wire from an HDD IDE cable to solder the board in PCB. Then I added some basic resistor and 5 header pin with it. The FTDI board will be connected to the esp module using this header at the time of programming.

After making it ready upload the following sketch into the esp module. Don't forget to select "NodeMCU 1.0(ESP8266-12E" board before uploading the sketch.

 
/*
 * This code is for smart plug 
 * Author: Md. Khairul Alam
 * Hackster: www.hackster.io/taifur
 * Date: 01 October, 2017
 * Under GPL licence
 * 
 */
 
//used for sending data to Cayenne cloud
#include  
// Include the libraries for DS18B20 Temeperature sensor
#include 
#include 

//Enabling Alexa voice
#include "WemoSwitch.h"
#include "WemoManager.h"
#include "CallbackFunction.h"

WemoManager wemoManager;
WemoSwitch *light = NULL;

//set up cayenne debug
#define CAYENNE_PRINT Serial
// Data types
#define TYPE_DIGITAL_SENSOR "digital_sensor" 
#define TYPE_VOLTAGE "voltage" 
#define TYPE_CURRENT "current" 
// Unit types
#define UNIT_DIGITAL "d" 
#define UNIT_VOLTS "v" 
#define UNIT_AMP "a" 

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

#define PLUG 5
#define pirPin 4

//variables
int timer_flag = 0;
int timer_time = 120;
int pir_flag = 0;
long timer_millis = 0;
int calibrationTime = 30;
long unsigned int lowIn;
long unsigned int pause = 60000;
boolean lockLow = true;
boolean takeLowTime;
int PIRValue = 0;
unsigned long lastMillis = 0;


int mVperAmp = 185; // use 100 for 20A Module and 66 for 30A Module
int RawValue= 0;
int ACSoffset = 500; //for esp8266 only
double Voltage = 0;
double current = 0;

float temp = 0;
// WiFi network info.
const char ssid[] = "taifur&mafi";
const char wifiPassword[] = "University";

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
const char username[] = "4f245760-6f09-11e7-8942-2bfc58a71315";
const char password[] = "b5f6214d8a77d9cb35410a81e7224ec189e3ce8c";
const char clientID[] = "1a8c0230-a1e7-11e7-98fe-97ee227ec16c";


void setup() {
	Serial.begin(9600);
  pinMode(PLUG, OUTPUT); 
  pinMode(pirPin, INPUT);
  //configure cayenne
	Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  // Start up the temperature sensor library
  sensors.begin();
  //start up wemo library
  wemoManager.begin();
  // Format: Alexa invocation name, local port no, on callback, off callback
  light = new WemoSwitch("Smart Plug", 80, plugOn, plugOff);
  wemoManager.addDevice(*light);
  
  delay(100);
  digitalWrite(PLUG, LOW); 
}

void loop() {
	Cayenne.loop();
  wemoManager.serverLoop();
  if(timer_flag){
    check_time();
    }
  if(pir_flag){
    PIRSensor();
    }
  read_temperature();
  int voltage = 220; //Standard voltage   
  read_current();
  
  float energy = 0.7 * voltage * current * millis()/(1000 * 60); //in kWh, assuming power factor 0.7

	if (millis() - lastMillis > 10000) {
		lastMillis = millis();
		//Write data to Cayenne here. This example just sends the current uptime in milliseconds.
	  Cayenne.virtualWrite(1, voltage, TYPE_VOLTAGE, UNIT_VOLTS);
    Cayenne.virtualWrite(2, current, TYPE_CURRENT, UNIT_AMP);
    Cayenne.virtualWrite(3, temp, TYPE_TEMPERATURE, UNIT_CELSIUS);
		Cayenne.virtualWrite(4, energy, TYPE_ENERGY, UNIT_KW_PER_H);  
	} 
}

CAYENNE_IN(5) //data receive from channel 5 (on/off) switch
{
   int value = getValue.asInt(); //accept and convert value to Int
   Serial.println(value);
   digitalWrite(PLUG, value); //change valve state
   Cayenne.virtualWrite(7, value, TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);

}

CAYENNE_IN(6) //data receive from channel 6 on/off time value
{
   int value = getValue.asInt(); //accept and convert value to Int
   Serial.println(value);
   timer_time = value;
   
}

CAYENNE_IN(8) //data receive from channel 6 on/off proximity
{
   int value = getValue.asInt(); //accept and convert value to Int
   Serial.println(value);
   pir_flag = value;
   
}

CAYENNE_IN(10) //data receive from channel 6 on/off timer enable
{
   int value = getValue.asInt(); //accept and convert value to Int
   Serial.println(value);
   timer_flag = value;
   timer_millis = millis();   
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
	CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
	//Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

void read_temperature(){
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  temp = sensors.getTempCByIndex(0);
  Serial.println(temp); 
}

void read_current(){
  for(int i = 0; i < 1000; i++) { // 1000 analogue readings for averaging
      RawValue = RawValue + analogRead(A0); // add each A/D reading to a total
  }
  Voltage = ((RawValue / 1000) / 1023.0) * 1000; // Gets you mV, max is 1000mV
  current = ((Voltage - ACSoffset) / mVperAmp);
}

void check_time() {
  if(((millis()-timer_millis)/60000) > timer_time){
    digitalWrite(PLUG, !digitalRead(PLUG));
    Cayenne.virtualWrite(7, !digitalRead(PLUG), TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);
    timer_flag = 0;
    }
 }

void PIRSensor() {
   if(digitalRead(pirPin) == HIGH) {
      if(lockLow) {
         PIRValue = 1;
         lockLow = false;
         Serial.println("Motion detected.");
         digitalWrite(PLUG, HIGH);
         Cayenne.virtualWrite(7, 1, TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);
         delay(50);
      }
      takeLowTime = true;
   }
   if(digitalRead(pirPin) == LOW) {
      if(takeLowTime){
         lowIn = millis();takeLowTime = false;
      }
      if(!lockLow && millis() - lowIn > pause) {
         PIRValue = 0;
         lockLow = true;
         Serial.println("Motion ended.");
         digitalWrite(PLUG, LOW);
         Cayenne.virtualWrite(7, 0, TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);
         delay(50);
      }
   }
}

void plugOn() {
    Serial.print("Switch 1 turn on ...");
    digitalWrite(PLUG, HIGH);
    Cayenne.virtualWrite(7, 1, TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);
}

void plugOff() {
    Serial.print("Switch 1 turn off ...");
    digitalWrite(PLUG, LOW);
    Cayenne.virtualWrite(7, 0, TYPE_DIGITAL_SENSOR, UNIT_DIGITAL);
}

Step 7: Connecting Altogether

After making all the circuit I connected altogether according to the schematic. The schematic was designed in Fritzing and I use Sparkfun ESP Thing Dev Board instead of ESP8266-12E module. The pinout for both the board is same. So, you can easily replace it with ESP module. Relay and the current sensors are connected in series with between supply and the plug.

I used a PIR motion sensor to activate motion control in the plug. PIR sensor is connected to the pin #4 of the esp module.

Step 8: Placing All Inside the Box

After connecting all the units it is the right time to put all the thing inside a box. The plug I bought was included a switch at the top right corner. I replaced the switch with the PIR sensor because a manual switch is no more required for the smart plug. I attached the sensor with the plug using hot glue. Then I joined the power adapter board and the relay circuit. After that, I fixed the regulator circuit with the plug. Finally, I attached the current sensor and the esp board.

Step 9: Final Product

After putting all the thing inside the box I screwed the bottom part of the box with the top part which contains all the component with the two screws provided with the plug.

If you followed all the steps then Congratulation!!!

You successfully made your own smart plug. Test and use.

Automation Contest 2017

Participated in the
Automation Contest 2017