Project tutorial

Smart Home Electrical Distribution for Floods © GPL3+

This hack is a proof of concept that shuts off power only to the level of the house that has been flooded, allowing for normal use elsewhere

  • 2,244 views
  • 4 comments
  • 15 respects

Components and supplies

Nodemcu
NodeMCU ESP8266 Breakout Board
×1
Extension Cord
There's one per floor, representing the electrical grid of each floor of the house. In this case I'm assuming 3 floors in the house. Make sure the two cables inside are separable.
×3
Water Sensor
×3
Relay Module
The one I used is a 4 channel relay module as it's cheaper than buying 3 single channel modules.
×1
Small Plastic Box
Any box will do, as it's just to house the project.
×1
Usbcable
Micro-USB to USB Cable (Generic)
To power the ESP8266
×1
11026 02
Jumper wires (generic)
×1

Apps and online services

Ide web
Arduino Web Editor
FileZilla
000Webhost
Just used as a host and server, feel free to use your own service.
Freenom
Used to get a free.tk domain for a year, feel free to use your own service.

About this project

I recently got to know a person from Fredericton, New Brunswick, Canada. Just this past year, there was a record breaking flood there, and when I asked her about it, she gave me an eye-opening account about how it has affected her life. As global warming continues to progress, flooding has gone from a rare occurrence to a commonplace issue in New Brunswick. This past May, the water level rose around 5.8 meters, which was never seen since 1973. Citizens were stranded, public services were cancelled, and many had to relocate for weeks.

What struck me was the fact that a huge number of people were negatively impacted even if their home was still partially flood-free. Out of fear of electrocution, the city shuts off power to grids at a time, blacking out whole areas. Given the fact that it takes weeks for a flood to subside, many families are forced to move out as their phones die out or when their food turns bad, even if most of their home is still inhabitable.

To tackle this issue, this proof of concept system uses water sensors to check for flooding at each level of the house, and only shuts off power to the flooded level. This allows families with a secondary power supply to safely access their homes' built-in electrical grid and maintain a decent quality of life during a flood. Moreover, the control unit uses is connected to the internet so that in case of flooding, the homeowner can be notified immediately. This system is made with the assumption that the homeowner is willing to waterproof their circuit breaker and rewire the home so that there aren't any multi-floor sections of wiring.

Demo of Hydrosafe shutting off lights to specific grids automatically

How It Works

Flooding is detected by a water level sensor placed at a level below the wall socket. A constant voltage is applied, and as water touches the sensor, it shorts the cathodes, creating a current and outputting HIGH on the signal pin. The sensor is connected to a NodeMCU ESP8266, which registers the voltage and shuts off the power to the floor by applying a HIGH voltage to the corresponding relay module. It also sends a POST request to a PHP server, updating the status of the sensors. This data is accessed by a landing page, giving the user on the clock information about the state of their home. My live demo can be checked out at www.hydrosafe.tk, before it expires 23/07/2019.

0. Preparing the Enclosure (Optional)

I didn't want HydroSafe to look like a dying octopus, so I made a basic enclosure for all the parts to be housed in. Take a reasonable box and cut a hole big enough for the extension cord to fit through.

Here, the project is made with 3 floors in mind. As such, 3 holes were cut on the front side to fit the water sensors and 3 holes on the lid for. If the box isn't tall enough for cups to fit snugly under the water sensors, give it some encouragement and prop it up with a Popsicle stick frame.

1. Connecting the Components

If using an enclosure, thread all the cables and wires through before connecting them. At about 15cm from the plug, split the extension cable in two, cut one side in half, and strip the cut ends. Screw them into the common and normally open pins of the relay module.

If your module does not have a built-in rectifier diode for protection, add your own between the relay and ESP8266, by connecting a diode facing the relay between the ESP's 5V pin and the relay's VCC pin. Repeat this for the number of independent circuits you want, which in this case is 3. Connect the sensors and relay modules as shown in the schematic.

Note: the sensors are cheap and erode quickly, but it isn't a problem due to the fact that flooding should happen relatively rarely.

2. Setting Up Server and Domain

To store the data collected into a server, and access the state of the sensors live on a webpage, you will need to get a domain and a server. In this project, I decided to get a free domain off freenom. Keep in mind that the free plan lasts only a year, so the domain will expire if you don't renew it. Here I registered the domain name hydrosafe.tk.

Now to host the domain and get database functionality, you have to find a host. I used 000webhost as it gives me free hosting along with a free database of up to 1GB. It uses FTP to transfer files to the server, which something I am familiar with. You can also use hosts like Heroku or AWS, but for this tutorial will cover how to set up hosting on 000webhost.

To host your domain on your server, you need to point it to the server. Navigate to the nameserver section of your domain registrar control panel and enter the nameservers of your host. For 000webhost, the nameservers are NS01.000WEBHOST.COM and NS02.000WEBHOST.COM. On freenom, do this by logging in with the account used to register the domain, and going to Services > My Domains and clicking on the Manage Domain button, then navigating to Management Tools > Nameservers. Then click the Use Custom Nameservers radio button and enter the nameservers. Click the Change Nameservers button at the bottom of the page.

Now that your domain is pointing to your server, you need to park the domain to your server on the server control panel. This allows the server to redirect your custom domain name to its default domain, which in my case is shadproject.000webhostapp.com. Create a free account on 000webhost and create a new project and name it whatever you like. Remember the username and password, as it'll be used step 4. Click the red Manage Website button, then click the Set Web Address button at the top. At the bottom, click Add Domain > Park Domain. Enter your custom domain address. Finally click Manage > Link Website and choose your default domain.

Congrats! After a few hours (24-48 max) the domain should be linked to your server.

3. Setting Up a Database

To store the data that the ESP is sending to the server, you must create a database to save and organize the data. On 000webhost, click Manage Databases at the top, then click the New Database button. Name it, set a user and password, and create it. Remember the logins for step 4. Then click Manage > PhpMyAdmin.

Click on the top database that you just named, then click New. This creates a new table where the data shall be stored. Name it data and set # of columns to 4. You can change this for more sensors if you'd like. Name the columns and set the types as shown below.

The number in the parenthesis is the value to enter in the Length/Values field. Leave everything after the Length/Values field as default. Click Save, and your table has been created!

4. Creating a Data Collector and Landing Page

Copy the index.php file and dataCollector.php file as linked below. Follow the instructions to change the variables.

Download FileZilla or use any FTP client app you'd like, and connect to the server. This tutorial will cover the use of FileZilla. Open the app and click File > Site Manager. Click New Site and name it however you'd like.

Fill in the fields as shown above, and enter your webpage username and password that you've set in step 2. Click Connect.

Navigate to the public_h folder on the server (right side) and navigate to the folder containing your changed dataCollector.php and index.php files on your computer's navigator (left side). Add both files to the server by double clicking them.

5. Setting Up the ESP8266

Now that we have the server side set up, we can work on the client, which is the ESP module. First, we need to install the ESP8266 add-on with the Arduino boards manager. To do this, open up the Arduino IDE, go to File>Preferences, and paste the link below in the "Additional Board Manager URLs" text box:

http://arduino.esp8266.com/stable/package_esp8266com_index.json

Hit OK, and go to Tools > Boards > BoardsManager. Type esp8266 in the search field, click on the entry, and install it. Now, you can select the NodeMCU 1.0 board by going to the Tools > Boards menu.

Copy the Arduino code attached below and follow the instructions on the description. Customize the code for the number of water sensors and relays. In this basic tutorial, there is no security or credential setup for posting to the datacollector.php page. Connect the ESP to your computer via the micro-USB cable, and upload the code. Make sure you selected the port the board is connected to (in Tools > Port).

After uploading the code, the ESP should regularly monitor the water sensors and post the data to the server if there is a change in the status of the sensors. You can now plug the USB to a power supply (eg charger or bank) and the system should work autonomously. Now, you can plug your devices to any of the protruding extension cords, and plug your main cord into a wall socket (double check your wiring before doing so as you are messing with 120V ac).

Congrats! You have replicated a smart flooding power management system. You can use the extension cords as a normal source of power to emulate the home's outlets, and view the status of the sensors on your domain.

Note on Feasibility

Though this proof of concept does carry out the key features of the HydroSafe solution, it needs to be improved in many ways to make it commercially viable. The main box as well as the circuit breaker would need waterproofing, and the sensor modules would need be be installed in their respective locations in the house. The relays would also need to be much higher duty to handle the greater current of controlling the home's existing grid, and the circuit breaker would need to take 3 or more inputs instead of the single utility line that it was designed to handle. Moreover, it is recognized that extensive rewiring of the home will also have to be done if the electrical system isn't separated by floors. High barriers to entry and legal challenges with hydro companies will have to be faced if this is truly to be implemented.

Future Steps

In the future, the sensor aspect of the system can also be combined with the capability of remotely controlling the breaker box, allowing for greater use of this product on a day to day basis. Also, if modules are installed in many homes, the data collection could be crowdsourced to allow local municipalities to actively track a flood's impact on the community, thus increasing the efficiency of first responders.

Ultimately, though the complexity grows and feasibility decreases as this solution is utilized in the real world, I hope that HydroSafe can be of some use to those who are trying to improve communities' resilience in the face of natural disasters.

Code

Arduino code for ESP8266Arduino
This is the code for the ESP module, to be pasted in the Arduino IDE and uploaded to the board. Replace every CHANGE_THIS label, in order, with your domain name, wifi name, wifi password, and domain name respectively (there are 4 labels to be changed).
#include <ESP8266WiFi.h>
//Pin declarations
int s1pin = 15;
int s2pin = 14;
int s3pin = 16;
int r1pin = 5;
int r2pin = 4;
int r3pin = 0;
//Sensor variable declarations
int sensor1, sensor2, sensor3;
int sen1prev = 0, sen2prev = 0, sen3prev = 0;
//Networking vars
const char server[] = "CHANGE_THIS";
const char* MY_SSID = "CHANGE_THIS";
const char* MY_PWD =  "CHANGE_THIS";
WiFiClient client;
void setup() {
 Serial.begin(9600);
 //Pin setup
 pinMode(s1pin, INPUT);
 pinMode(s2pin, INPUT);
 pinMode(s3pin, INPUT);
 pinMode(r1pin, OUTPUT);
 pinMode(r2pin, OUTPUT);
 pinMode(r3pin, OUTPUT);
 digitalWrite(r1pin, HIGH);
 digitalWrite(r2pin, HIGH);
 digitalWrite(r3pin, HIGH);
 //Connecting to wifi
 Serial.print("Connecting to " + *MY_SSID);
 WiFi.begin(MY_SSID, MY_PWD);
 Serial.println("going into wl connect");
 while (WiFi.status() != WL_CONNECTED) { //not connected,  ...waiting to connect
   delay(1000);
   Serial.print(".");
 }
 Serial.println("wl connected");
 Serial.println("");
 Serial.println("Credentials accepted! Connected to wifi\n ");
 Serial.println("");
}
void loop() {
 delay(500);
 //Collect data
 sensor1 = digitalRead(s1pin) == HIGH;
 sensor2 = digitalRead(s2pin) == HIGH;
 sensor3 = digitalRead(s3pin) == HIGH;
 //Serial output
 Serial.print("Sensor 1: ");
 Serial.print(sensor1);
 Serial.print("     Sensor 2: ");
 Serial.print(sensor2);
 Serial.print("     Sensor 3: ");
 Serial.println(sensor3);
 //Relay control
 if (sensor1 == 1) {
   digitalWrite(r1pin, LOW);
 } else {
   digitalWrite(r1pin, HIGH);
 }
 if (sensor2 == 1) {
   digitalWrite(r2pin, LOW);
 } else {
   digitalWrite(r2pin, HIGH);
 }
 if (sensor3 == 1) {
   digitalWrite(r3pin, LOW);
 } else {
   digitalWrite(r3pin, HIGH);
 }
 //Sensor state changed
 if ((sensor1 != sen1prev) || (sensor2 != sen2prev) || (sensor3 != sen3prev)) {
   Serial.println("Something changed!");
   sen1prev = sensor1;
   sen2prev = sensor2;
   sen3prev = sensor3;
   //Connect to server
   Serial.println("\nStarting connection to server...");
   if (client.connect(server, 80)) {
     Serial.println("Connected to server");
     //POST request
     String data = "Floor1="
                   + (String) sensor1
                   + "&Floor2="  + (String) sensor2
                   + "&Floor3=" + (String) sensor3;
     client.println("POST /dataCollector.php HTTP/1.1");
     client.println("Host: CHANGE_THIS");                 //change this if using your Domain
     client.println("User-Agent: ESP8266/1.0");
     client.println("Connection: close");
     client.println("Content-Type: application/x-www-form-urlencoded");
     client.print("Content-Length: ");
     client.print(data.length());
     client.print("\n\n");
     client.print(data);
     //Output debug to serial
     Serial.println("\n");
     Serial.println("My data string im POSTing looks like this: ");
     Serial.println(data);
     Serial.println("And it is this many bytes: ");
     Serial.println(data.length());
     //Server confirmation, uncomment if you'd like to see the collector's response
     /*
     Serial.println("Server Resopnse:");
     Serial.println("--------------------");
     while (client.connected()) {
       if (client.available()) {
         String line = client.readStringUntil('\n');
         Serial.println(line);
       }
     }
     Serial.println("--------------------");
     */
   } else {                                        //If not connected to a server
     Serial.println("Connection failure");
     client.stop();
   }
 } else {                                          //If nothing changed
   Serial.println("Nothing changed.");
 }
}
dataCollector.phpPHP
The code for the dataCollector.php file. There are 4 CHANGE_THIS variables. Replace them with the DB Host, DB User, DB password, and DB Name. For 000webhost you can find them in your Manage Databases page. You can customize the timezone and variables for the # of floors.
<?php
  //Timestamp creation
   date_default_timezone_set("America/Toronto");
   $timeStamp = date("Y-m-d H:i:s");

  //If data is sent in from ESP
  if(isset($_REQUEST["Floor1"]) && isset($_REQUEST["Floor2"]) && isset($_REQUEST["Floor3"])){
    //Variable declarations
    $floor1 = $_REQUEST["Floor1"];
    $floor2 = $_REQUEST["Floor2"];
    $floor3 = $_REQUEST["Floor3"];

    echo "Timestamp: " . $timeStamp . "%<br>";
    echo "Floor 1: " . $floor1 . "%<br>";
    echo "Floor 2: " . $floor2 . "%<br>";
    echo "Floor 3: " . $floor3 . "%<br>";

    //Connect to MySQL
    $con = mysqli_connect("CHANGE_THIS", "CHANGE_THIS", "CHANGE_THIS")
     or die('Could not connect: ' . mysqli_error());

    $db_select = mysqli_select_db($con, "CHANGE_THIS") or die
    ("Database selection failed: " . mysqli_error());

     //Tells script to stop executing if articles aren't booleans
     if ( !(is_numeric($floor1) && is_numeric($floor1) && is_numeric($floor1)) ){
         die('invalid article id');
     }

    //Write request
    $sql = "
    INSERT INTO `data` (`datetime`, `floor1`, `floor2`, `floor3`) VALUES ('$timeStamp', '$floor1', '$floor2', '$floor3');
     ";

     if ($con->query($sql) === TRUE) {
         echo "New record created successfully";
     } else {
         echo "Error: " . $sql . "<br>" . $conn->error;
     }
  } else {
    echo "Nothing sent or not all parameters met";
  }
?>
index.phpPHP
This is the code for index.php, the landing page of your domain. There are 4 CHANGE_THIS variables. Replace them with the DB Host, DB User, DB password, and DB Name. For 000webhost you can find them in your Manage Databases page. Code is customizable to accommodate # of floors.

Edit- It's messy code but it gets the job done :')
<html>
  <head>
    <title>HydroSafe Water Detection</title>
  <style type="text/css">
    body {
      background: linear-gradient(141deg, #0fb8ad 0%, #1fc8db 51%, #2cb5e8 75%);
    }

    h1 {
    font-family: Century Gothic, CenturyGothic, AppleGothic, sans-serif;
    font-size: 70px;
    font-weight: 500;
    text-align: center;
    color: #F9F9F9;
    }

  h2 {
    color: #333;
    font-size: 20px;
    font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
    }

  h3 {
    font-family: Candara,Calibri,Segoe,Segoe UI,Optima,Arial,sans-serif;
    text-align: center;
    font-size: 30px;
    color: #ffffff;
  }

  p {
    font-size: 35px;
    font-family: Georgia, "Times New Roman", Times, serif;
    color: #DEDEDE;
    padding-left: 50px;
    padding-right: 50px;
    line-height: 200%;
  }

  #translation1 {
    font-size: 35px;
    font-family: Georgia, "Times New Roman", Times, serif;
    color: #DEDEDE;
    padding-left: 50px;
    padding-right: 50px;
    line-height: 200%;
  }

  #translation2 {
    font-size: 35px;
    font-family: Georgia, "Times New Roman", Times, serif;
    color: #DEDEDE;
    padding-left: 50px;
    padding-right: 50px;
    line-height: 200%;
  }

  #translation3 {
    font-size: 35px;
    font-family: Georgia, "Times New Roman", Times, serif;
    color: #DEDEDE;
    padding-left: 50px;
    padding-right: 50px;
    line-height: 200%;
  }

  </style>

  </head>
  <body>
  <center><img src="https://i.imgur.com/HumUAOA.png" width = "30%"></center>
    <?php
      //Connect to MySQL
      $con = mysqli_connect("CHANGE_THIS", "CHANGE_THIS", "CHANGE_THIS")
       or die('Could not connect: ' . mysqli_error());

      $db_select = mysqli_select_db($con, "CHANGE_THIS") or die
      ("Database selection failed: " . mysqli_error());

      //Store table in array
      $query = "SELECT * FROM `data` ORDER BY `data`.`datetime` ASC ";
      $result = mysqli_query($con, $query);
      $data = array();
      while($row = mysqli_fetch_assoc($result) ){
        $data[]= $row;
      }
      mysqli_free_result($result);

      //Create arrays for each column
      $datetime = array();
      $floor1 = array();
      $floor2 = array();
      $floor3 = array();
      foreach ($data as $row) {
        $phpdate = strtotime( $row['datetime'] );//Make datetime legible
        $datetime[] = $phpdate;
        $floor1[] = $row['floor1'];
        $floor2[] = $row['floor2'];
        $floor3[] = $row['floor3'];
      }
    ?>
    <h1>Water Detection Status</h1>

    <p>Timestamp: <?php echo date( 'Y-m-d H:i:s', end($datetime) ); ?></p>

    <p>Floor 1:</p> 
    <div id ="translation1"><?php echo end($floor1);?></div>
    <br>

    <p>Floor 2:</p> 
    <div id ="translation2"><?php echo end($floor2);?></div>
    <br>

    <p>Floor 3:</p> 
    <div id ="translation3"><?php echo end($floor3);?></div>
    <br>


  <script type="text/javascript">

      if (document.getElementById("translation1").innerHTML == 0) {
      document.getElementById("translation1").innerHTML = "Dry";
      }
      
      else if (document.getElementById("translation1").innerHTML == 1) {
        document.getElementById("translation1").innerHTML = "Flooded";
      }

      if (document.getElementById("translation2").innerHTML == 0) {
        document.getElementById("translation2").innerHTML = "Dry";
      }
      
      else if (document.getElementById("translation2").innerHTML == 1) {
        document.getElementById("translation2").innerHTML = "Flooded";
      }

      if (document.getElementById("translation3").innerHTML == 0) {
        document.getElementById("translation3").innerHTML = "Dry";
      }
      
      if (document.getElementById("translation3").innerHTML == 1) {
        document.getElementById("translation3").innerHTML = "Flooded";
      }

  </script>

  </body>
</html>

Schematics

Wiring Schematic for Control Module
Connect the parts as shown using jumper cables. This setup is made for 3 floors but can be customized.
Hydro bb otlcwv3lp9

Comments

Similar projects you might like

Arduino Bluetooth Basic Tutorial

by Mayoogh Girish

  • 455,961 views
  • 44 comments
  • 242 respects

Home Automation Using Raspberry Pi 2 And Windows 10 IoT

Project tutorial by Anurag S. Vasanwala

  • 289,583 views
  • 96 comments
  • 677 respects

Security Access Using RFID Reader

by Aritro Mukherjee

  • 230,682 views
  • 38 comments
  • 240 respects

OpenCat

Project in progress by Team Petoi

  • 197,202 views
  • 154 comments
  • 1,371 respects
Add projectSign up / Login