Smart Switch with Motion Detection Using an ESP-12F

ESP-12F-based smart switch for two relays and motion detection. Two-way operation hard wired + Android app. Voice control also possible.

IntermediateFull instructions providedOver 1 day251
Smart Switch with Motion Detection Using an ESP-12F

Things used in this project

Hardware components

Prototype PCB
Voltage Regulator 5VDC to 3.3VDC
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
Grove - 4-Channel SPDT Relay
Seeed Grove - 4-Channel SPDT Relay
Optocoupler, Transistor Output
Optocoupler, Transistor Output
PC817 opcocoupler
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
i have used Raspberry PI 3B+
ESP8266 ESP-12E
Espressif ESP8266 ESP-12E
I have used ESP 12 F with 4MB flesh memory

Software apps and online services

Arduino IDE
Arduino IDE
Raspberry Pi Raspbian

Hand tools and fabrication machines

Helping Hand Tool, with Magnifying Glass
Helping Hand Tool, with Magnifying Glass
Solder Wire, Lead Free
Solder Wire, Lead Free
Soldering iron (generic)
Soldering iron (generic)


Read more


PCB circuit diagram

PCB circuit. Relayboard is seprate.


Smart Switch

This code can used as it is. only Wifi setting need to be changed and MQTT broker setting need to be changed. For more detail visit youtube video. almost all line of code is commented for easy undestanding.
//XXXXX Flow diagram XXXXXX
//Include Library
//Variable dcleration
  //Serial port initalised
  //Inputs & Outputs Setup
  //Outputs initialised
  //Reading initial input values & store in placeholder
  //Setup WIFI & connectin to WIFI network
  //Connecting MQTT server
      //Checking MQTT connectivity & reconnect if not connected
      //Checking Switch01 input & call funciton for relay 01
      //Checking Switch02 input & call funciton for relay 02
      //Checking PIR input & call function for trun on or or relay 02
      //Checking MQTT message & turn on/off relay accordingly

//Library Include
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network
const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxx";
const char* mqtt_server = "";
const char* mqttUser = "xxxxxxx"; //in case you dont set MQTT username & Password comment this line
const char* mqttPassword = "xxxxxxxx"; //in case you dont set MQTT username & Password comment this line
//Output defination
byte Switch_01 = 4 ; // Input pin for switch 01
byte Switch_02 = 5 ; // Input pin for switch 01
byte PIR_01  = 14 ; // Input pin for PIR sernsor deetection
//Input defination
byte Rly_1 = 12 ; // Output pin for Relay 01
byte Rly_2 = 13 ; // Output pim for Relay 02
byte Sts_led  = 16  ;
//Input Bit Status
byte Switch_01_sts;
byte Switch_02_sts;
byte Pir_01_sts;
//Input debounse delay
unsigned long Switch_01_dly;
unsigned long Switch_02_dly;
unsigned long Pir_on_dly;
unsigned long Pir_off_dly;
//Output Place Holder
byte Rly_01_sts;
byte Rly_02_sts;
//Wifi Client instance declaration
WiFiClient espClient3;
PubSubClient client(espClient3);
//Generic Variables
long lastMsg = 0;
char msg[50];
long value ;
void setup() {
  //Output Setup
  pinMode ( Rly_1  , OUTPUT  );
  pinMode ( Rly_2  , OUTPUT  );
  pinMode ( LED_BUILTIN , OUTPUT );
  //Output initialised
  digitalWrite ( Rly_1  , HIGH );
  digitalWrite ( Rly_2 , HIGH );
  //Input Setup
  pinMode ( Switch_01 , INPUT  );//Internal Pullup not used as hardware pullup implemented in PCB
  pinMode ( Switch_02 , INPUT  );// Internal Pullup not used as hardware pullup implemented in PCB
  pinMode ( PIR_01    , INPUT  );// Internal Pullup not used as hardware pullup implemented in PCB
  //Initialise Serial Port & read input status
  Serial.begin(115200 );
  //Storing initial state of inputs
  Switch_01_sts = digitalRead(Switch_01);
  Switch_02_sts = digitalRead(Switch_02);
  Pir_01_sts = digitalRead(PIR_01);
  //Printing initial state of inputs
  Serial.print  ("Switch_01_sts  "); Serial.println    ( Switch_01_sts  );
  Serial.print  ("Switch_02_sts "); Serial.println    ( Switch_02_sts );
  Serial.print  ("Pir_sts  "); Serial.println    ( Pir_01_sts  );
  //Setup WiFI
  setup_wifi(); //Call of Wifi setup function
  //MQTT client setup
  client.setServer(mqtt_server, 1883);
  //Read millis value & store in to debounce place holder
  Switch_01_dly = millis();
  Switch_02_dly = millis();
  Pir_on_dly = millis();
  Pir_off_dly = millis();
void setup_wifi() {//Connecting WIFI network
  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  //WIFI connection begin with SSID & Password
  WiFi.begin(ssid, password);
  IPAddress ip(192, 168, 1, 103);//Fix ip assigned to ESP12F , For each new module we have to change this address.
  IPAddress gateway(192, 168, 1, 1);//Gateway setting of ESP12F & it will remain same for all other modules on same network
  IPAddress subnet(255, 255, 255, 0); //Subnet mask , it will remain same for all other modules on same network
  WiFi.config(ip, gateway, subnet); //Assign Above three setting to ESP12F module
  //Connection initilased
  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Led blinks untill connection not established
  //Printing connection status after successful connection of ESP12F
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
void callback(char* topic, byte* payload, unsigned int length) { //This function read MQTT messages & convert its payload into integer value
  String payloadval_str;
  int payloadval_int, payload_pwm;
  for (int i = 0; i < length; i++) payloadval_str += (char)payload[i];
  payloadval_int = payloadval_str.toInt();
  if (payloadval_int == 100) payload_pwm = 1;
  else if (payloadval_int == 0) payload_pwm = 0;
  else payload_pwm = 0;
  recieved_cmd(topic, payloadval_int, payload_pwm);//Checking Recivied MQTT command & its payload & generate outputs accordingly.
void reconnect() { // This function provide connectivity with MQTT server
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("UID_1", mqttUser, mqttPassword ))//Different UID required for each module other wise we will face problem. Comment this line if you have un secure MQTT broker.
    //if (client.connect("UID_1", mqttUser, mqttPassword ))//If MQTT broker USER name & Password not set then uncomment this line & Comment above line.
      digitalWrite(Sts_led, !digitalRead(Sts_led));
      digitalWrite(Sts_led, !digitalRead(Sts_led));
      digitalWrite(Sts_led, !digitalRead(Sts_led));
    else {
      Serial.print("failed, rc=");
      Serial.println(" try again in 5 seconds");
  Serial.println("Pub start");//MQTT connection establihsed
void loop() {
//Checking MQTT connectivity & reconnect if connection failed  
  if (!client.connected()) {//checking if MQTT server connection status
    reconnect();// if MQTT server not connected then try to reconnect
  else client.loop();
//Switch 1 input chekcing
  if (digitalRead(Switch_01) != Switch_01_sts) { //Switch_01 input changed/toggled deetection
  else Switch_01_dly = millis();//Switch_01 on delay time rollout if not activated deetected
//Switch 2 input checking 
  if (digitalRead(Switch_02) != Switch_02_sts) {//Switch_02 input changed/toggled deetection
  else Switch_02_dly = millis();//Switch_02 on delay roolout if no activity deetected
//PIR input checking  
  if (!digitalRead(PIR_01) &  Pir_01_sts) 
    Pir_01_on_call();//PIR deetected motion
  else Pir_on_dly = millis();//PIR_01 on delay timer rollout if no motion deetected
  if ( digitalRead(PIR_01) & !Pir_01_sts) 
    Pir_01_off_call();//PIR not deetected motion
  else Pir_off_dly = millis();//PIR_01 off delay time rollout if no motion deetected
void recieved_cmd(String in_str, int in_int1, int in_int2) { // in_str :- Topic string ,in_int1 :- Payload Value 0 to 100, in_int2 :- Mapped Payload value 0 to 1
  if (in_str == "ashish/bed1/Washroom/sb/cmd/Switch_01") {
    Serial.print("Switch_01 >> Rly_01_sts "); Serial.println(in_int1);
    Rly_01_sts = in_int2;
    snprintf (msg, 5, "#%ld", in_int1);
    client.publish("ashish/bed1/Washroom/sb/sts/Switch_01", msg);
    Serial.print("Switch_01 status "); Serial.println(Switch_01_sts);
  if (in_str == "ashish/bed1/Washroom/sb/cmd/Switch_02") {
    Serial.print("Switch_02 >> Rly_02_sts "); Serial.println(in_int1);
    Rly_02_sts = in_int2;
    snprintf (msg, 5, "#%ld", in_int1);
    client.publish("ashish/bed1/Washroom/sb/sts/Switch_02", msg);
    Serial.print("Switch_02 status "); Serial.println(Switch_02_sts);
void Switch_01_call() { //Switch_01 toggle funciton. if Input pin state cahgned mor ethen 200  milli second then output toggled
  if (millis() - Switch_01_dly > 200) { //Debounce filteration time
    Switch_01_sts = ! Switch_01_sts;
    Rly_01_sts = !Rly_01_sts;
    if (Rly_01_sts == 1) client.publish("ashish/bed1/Washroom/sb/sts/Switch_01", "100");
    if (Rly_01_sts == 0) client.publish("ashish/bed1/Washroom/sb/sts/Switch_01", "0");
    Serial.print("Switch_01 Status "); Serial.println(Switch_01_sts);
void Switch_02_call() { //Switch_01 toggle funciton. if Input pin state cahgned mor ethen 200  milli second then output toggled
  if (millis() - Switch_02_dly > 200) {//Debounce Fileration time
    Switch_02_sts = ! Switch_02_sts;
    Rly_02_sts = !Rly_02_sts;
    if (Rly_02_sts == 1) client.publish("ashish/bed1/Washroom/sb/sts/Switch_02", "100");
    if (Rly_02_sts == 0) client.publish("ashish/bed1/Washroom/sb/sts/Switch_02", "0");
    Serial.print("Switch_02 Status "); Serial.println(Switch_02_sts);
void Pir_01_on_call() { //If PIR sensor activated then Relay2 started after 200 milli seconds
  if (millis() - Pir_on_dly > 200) {
    client.publish("ashish/bed1/Washroom/sb/sts/PIR", "100");
    Serial.print("Switch_02 >PIR> Motion "); Serial.println("1");
    Pir_01_sts = LOW;
    Rly_02_sts = 1;
    client.publish("ashish/bed1/Washroom/sb/sts/Switch_02", "100");
void Pir_01_off_call() { //If PIR sensor deactivated then Relay2 stopped after 3 second
  if (millis() - Pir_off_dly > 3000) {
    client.publish("ashish/bed1/Washroom/sb/sts/PIR", "0");
    Serial.print("Switch_02 >PIR> Motion "); Serial.println("0");
    Pir_01_sts = HIGH;
    Rly_02_sts = 0;
    client.publish("ashish/bed1/Washroom/sb/sts/Switch_02", "0");
void output_writ() {
  digitalWrite(Rly_1, !Rly_01_sts);
  digitalWrite(Rly_2, !Rly_02_sts);
  Serial.print(", Relay_01/02 Status "); Serial.print(Rly_01_sts); Serial.print(" / "); Serial.println(Rly_02_sts);




6 projects • 15 followers


Add projectSign up / Login