Project tutorial
Wi-Fi Power Toggler

Wi-Fi Power Toggler © GPL3+

Restores your Wi-Fi connection for you, so you don't have to, and keeps a track of how often this is done.

  • 2,990 views
  • 2 comments
  • 14 respects

Components and supplies

Apps and online services

About this project

Our Wi-Fi connection at home tends to fail 2-3 times per week. The usual remedy is to turn the Wi-Fi router off and on again; which normally fixes it. When we are at home this is a pain, as we have to excavate the router from under a mass of twisted cables. When we are out, this is not possible; which is annoying as it prevents any remote desktoping to machines at our flat, and means any IoT devices/projects go belly up.

This project documents the design and build of an automated Wi-Fi power toggler which:

  • Detects a drop-out in the Wi-Fi internet connection
  • Disconnects power, waits and reconnects power to the Wi-Fi router
  • Automatically fills out and submits a web log-in form (required with the internet connection we have in our apartment)
  • Records these drop-outs, whether the power was out during the drop-out and whether the power-cycling restored internet access, in an online spreadsheet.

Build Instructions

The basic steps for the build are as follows:

1) Buy/find/salvage/scavenge the necessary hardware; other that the MKR1000 board it's mostly stuff you might have lying around.

2) Find your Wi-Fi router (it is probably under a twisted mess of cables under a desk somewhere)

3) Check the DC wall-wart for what voltage and current it puts out. Mine is rated to output 12V at 1A, but when I measured it with no load attached it was outputting about 16V.

4) Provided the voltage is below 35V, and the current below about 3A (I'd be surprised if they weren't); the hardware described in this project should work

5) Cut the DC-jack off-of the wall-wart, leaving a few centimeters of cable (to allow the jack to be plugged back into the Wi-Fi router later). This is a point of no return so you might want to put the other bits together first to check you've got it sorted. Also if there is no visible marking, use some tape to keep track of which of the two short wires from the DC-jack came from each of the two longer wires to the wall-wart.

6) Use a multi-meter to check the polarity of the wires coming from the wall-wart, and label them

7) Assemble the circuit as indicated on the schematic on the hardware page. PCB header terminals like these, are a good way of connecting the larger wires from the wall-wart and to the DC-jack onto the breadboard.

8) Customize the Arduino script (see below and the software page for details) to have the details of your Wi-Fi connection, etc. and then upload it to the MKR1000 board.

9) Turn on the wall-wart and enjoy never having to manually power-cycle your router ever again! And also have the satisfaction of a record being kept of the number of times this power-cycling has been necessary!

Customizing the Arduino Code

The hardware and software sections provide details of the hardware required, and the software which needs to be programmed onto the MKR1000 board. There are two additional steps that are required to get the full functionality.

The first is setting up a Google Form, and PushingBox account to allow the Arduino to report information about connection drop-outs and recoveries. For this project I have followed the excellent instructions here. There are quite a few steps, but if you follow them carefully you should get a PushingBox 'DeviceID' which you can paste into the Arduino sketch, and 'hey-presto' your Ardunio can upload stuff into a google docs spreadsheet.

The second is log-in details which may be required for your ISP (we have such a requirement in our apartment). To find these details, go to the landing page where you normally enter your login information. A screenshot of our log-in page is given below:

You then need to navigate to the source code of this page (most browsers will have an option to do so under the 'View' or 'Tools' menu). You are looking for the action which is taken when you submit the form (click the login button). The image below shows the source code for our landing page:

Highlighted in the above source code are the action which is taken when the web login form is submitted (in this case an HTTP POST to login.spirit.com.au/login), and also the fields which are passed as part of this POST (namely 'username' and 'password').

Depending what you find you may need to modify the Arduino code a little beyond the section I've highlighted for editing, but if it's a similar set-up you simply need to replace the:

char serverLogin[] = "login.your.isp.name";

With an appropriate host name (in above example "login.spirit.com.au"), and the:

char loginSubPage[] = "/login";

With an appropriate URL extension (in the above example it is indeed just "/login"). As well as entering your landing page username and password.

A Word of Warning

If you include a 3.7V Li-Po battery in your version of this project you need to be careful about the heat dissipation in the linear regulator. I found that without a battery being charged the MKR1000 drew only about 20mA, so the dissipation in the linear regulator is about (16V in - 5V out) x 0.02A = 0.22W. The total thermal resistance between the junction and ambient for the TO-220 package from the data-sheet is about 55 degrees C / W; so this will cause a temperature rise of about 10 degrees C (just noticeable).

However, when the battery was connected and charging at the same time, the MKR1000 drew about 200mA, this will cause a temperature rise of around 100 degrees C, which on top of an ambient of 20 degrees C is only just within the maximum ratings for the device. If you are going to include a battery and allow it to be charged from the 5V regulated supply I would recommend fitting a decent heat-sink (or better still use a switch-mode-power supply).

Questions & Comments

It would be great to hear your thoughts on how I could improve the project, or make the description clearer. An obvious one would be moving it over to solder-board, and putting it in an enclosure; I do plan to do that (because this project is actually going to be put to use on my Wi-Fi router), but wasn't able to within time constraints of the MKR1000 competition.

Code

WiFi Power Toggler SketchArduino
This is the main sketch to be loaded onto the Arduino MKR1000. Please note that you will need to change a number of variables in the code to get it to work for you. These are highlighted with comments:
- Need to enter the SSID (name) and password for your wifi network
- Need to provide details of any web log-in page of your ISP (see Story page for details)
- Need to provide details of the pushing box account you have set up (see Story page for details)
/*
  WiFi Power Toggler

  This sketch is intended for an Arduino MKR1000 used as a Wi-Fi power toggler:
  https://www.hackster.io/khalidaabdulla/wi-fi-power-toggler-0ed04a
  
  Circuit:
  Detailed schematics can be found at the URL above.
  Pin 0 connects (via 1k resistor) to the gate of power mosfet
  Pin 1 connects (via 100k, 220k potential divider) to the 5V output of 7805 linear regulator
  5V pin connects to output of 7805 linear regulator
  GND pin connects to ground of 7805 linear regulator
  3.7V Li-Po battery connects via the 2-pin JST connector
  
  created 31 March 2016
  by Khalid Abdulla
  
  This code is in the public domain.
*/

#include <SPI.h>
#include <WiFi101.h>

//////////////////////////////////
///// VALUES TO BE EDITED ////////
//////////////////////////////////

// WIFI SETTINGS:
char ssid[] = "YOUR_NETWORK_NAME";          // <== Insert your network SSID (name) HERE
char pass[] = "YOUR_WIFI_PASSWORD";         // <== Your Wi-Fi password goes here
int keyIndex = 0;                           // <== Your network key Index number goes here (needed only for WEP)

// WIFI Web-Login (if Required):
char serverLogin[] = "login.your.isp.name";       // <== If you need to auto-fill a web-login page; the root URL for that page goes here
char webLoginUsername[] = "YourUserName@YourIsp"; // <== Username for ISP web login
char webLoginPass[] = "YOUR_WEBLOGIN_PASSWORD";   // <== Password for ISP web 
char loginSubPage[] = "/login";                   // <== sub-page of web log-in host URL

// Pushing Box Settings:
char devid[] = "yourDeviceID_fromPushingBox";    // <= The device ID from Pushing Box goes here (see https://www.hackster.io/khalidaabdulla/wi-fi-power-toggler-0ed04a)

//////////////////////////////////
////////// EDITING DONE //////////
//////////////////////////////////


int status = WL_IDLE_STATUS;
boolean connStatus = false;         // to track connectivity
boolean powerOnAtDisconn = false;   // to track if power was off when connection failed
int failedReconnAttempts = 0;
char tempString[50];                // used for assembling varios chracter arrays (without resorting to Strings)

// Initialize the Wifi client library
WiFiClient client;

// Variables for google-form upload:
char postmsg[250];
char serverUpload[] = "api.pushingbox.com";

// Variables for checking internet connectivity
char serverCheck[] = "www.google.com";

// Variables for timing etc.
unsigned long lastConnectionCheck = 0;                 // Last time connectivity assessed, in milliseconds
unsigned long timeConnectionFailed = 0;                // Time since connection failure found, in milliseconds
const unsigned long checkInterval = 10L * 60L * 1000L; // Delay between updates, in milliseconds (set to 10 minutes)
const unsigned long timeOff = 20L * 1000L;             // How long to turn router off for (set to 20 seconds)
const unsigned long timeOn = 20L * 1000L;             // How long to wait between turn on and connection test (set to 20 seconds)
int nTogglesMax = 10;                                  // Maximum number of times to attempt power toggling

// Hardware pin definitions
int mosfetPin = 0;
int ledPin = 6;               // Switch on-board LED with mosfet pin to aid debugging
int powerSense = 1;           // Check for presence of mains power on this input pin


void setup() {

  // Set up digital outputs (to driver mosfet, and led for debugging):
  pinMode(mosfetPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

  // Also need to turn on the mosfet (otherwise Wi-Fi set-up below won't work)
  digitalWrite(mosfetPin, HIGH);
  digitalWrite(ledPin, HIGH);

  // Set up digital input (to measure presence of power):
  pinMode(powerSense, INPUT);
  
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect.
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 20 seconds for connection:
    delay(20000);
  }
  // should be connected now, so print out the status:
  printWifiStatus();

  // attempt web log-in in case access not currently logged in:
  webLogin();
}


void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  /*
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }*/

  // If (checkInterval/1000) seconds have passed since we last checked connection,
  // then it needs to be tested again:
  if (millis() - lastConnectionCheck > checkInterval) {

    lastConnectionCheck = millis();
    connStatus = testConnection();

    if (~connStatus) {
      // Connection not working; log status of mains power, and record time of outage
      powerOnAtDisconn = digitalRead(powerSense);
      timeConnectionFailed = millis();

      // Repeatedly try to turn off power, restore power and re-test connection
      // limit to maximum number of iterations to prevent excessive power toggling
      // if for example www.google.com is not available for some reason
      int nToggles = 0;
      while(~connStatus && nToggles <= nTogglesMax) {
        digitalWrite(mosfetPin, LOW);
        digitalWrite(ledPin, LOW);
        delay(timeOff);
        digitalWrite(mosfetPin, HIGH);
        digitalWrite(ledPin, HIGH);
        delay(timeOn);
        connStatus = testConnection();
        nToggles = nToggles + 1;
      }

      // If we have restored connection; upload report to google docs:
      if(connStatus) {
        uploadMsg();
        webLogin();
        failedReconnAttempts = 0;
      } else {
        // Otherwise we will wait again till another connection check is performed
        failedReconnAttempts = failedReconnAttempts + 1;
      }
    }
  }
}

    
// Post message to spreadsheet via Google Form
void uploadMsg() {
  
  if (client.connect(serverUpload, 80)) {
    
    Serial.println("Connected to pushing box");
    sprintf(tempString, "Conn restored, time since disconn [s]:%d, power on at disconn:%d, failed reconn attempts:%d", (millis() - timeConnectionFailed)/1000, powerOnAtDisconn, failedReconnAttempts);
    sprintf(postmsg,"GET /pushingbox?devid=%s&status=%s HTTP/1.1", devid, tempString); 
    client.println(postmsg);

    sprintf(tempString, "Host: %s", serverUpload);
    client.println(tempString);
    client.println("Connection: close");
    client.println();

    // Print output to serial to assist with debugging:
    Serial.println(postmsg);
    Serial.println(tempString);
    Serial.println("Connection: close");
    Serial.println();
 
    delay(1000);
    client.stop();
    
  } else {
    Serial.println("Failed to connect to pusshing box");
    client.stop();
    return;
  }
}


// Test if we have internet connectivity via Wi-Fi
boolean testConnection() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  if (client.connect(serverCheck, 80)) {
    Serial.println("Able to connect to google, internet working!");
    // Make HTTP GET request to double check
    client.println("GET /search?q=arduino HTTP/1.1");
    sprintf(tempString, "Host: %s", serverCheck);
    client.println(tempString);
    client.println("Connection: close");
    client.println();
    return true;
  }
  else {
    // Connection not made, test failed
    Serial.println("connection failed");
    return false;
  }
}


// Log-in to ISP Web-login page (if required)
void webLogin() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  if (client.connect(serverLogin, 80)) {
    Serial.println("Connecting to web log-in page:");

    // send the HTTP POST request to log user in:
    sprintf(tempString, "POST %s HTTP/1.1", loginSubPage);
    client.println(tempString);

    sprintf(tempString, "Host: %s", serverLogin);
    client.println(tempString);
    client.println("Content-Type: application/x-www-form-urlencoded");

    client.println("");
    sprintf(tempString, "Content-Length: %d", sizeof(webLoginUsername) + sizeof(webLoginPass) + 19);
    client.println(tempString);
    
    sprintf(tempString, "username=%s&password=%s", webLoginUsername, webLoginPass);
    client.println(tempString);

    client.println("");
    client.println("Connection: close");
  }
  
  else {
    Serial.println("Connection to web log-in page failed");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Schematics

Wi-Fi Power Toggler Circuit Schematic
This shows the circuit schematic. On the left we have a screw terminal which the +16V and ground of the existing DC power supply (wall-wart) for the Wi-Fi Router connect. Our router put out 16Vdc, but the linear regulator will work with any DC power supply up to 35V.

The wall-wart provides power to the 7805 linear regulator which produces a regulated 5V output to power the MKR1000 board, via the (5V) pin (note the schematic shows the Arduino Nano, as now MKR1000 model was available).

A potential divider (made up of R1 and R2) drops the 5V to ~3.3V to be sensed by digital input (1), to check if mains power is present (MKR1000 will continue to run on battery in the event of a power outage; but the Wi-Fi connection will be dropped).

The MKR 1000 board is connected (via the 2-pin JST connector) to a 3.7V Li-Po battery.

Finally digital output (0) of the MKR 1000 drives the gate of an N-Channel power mosfet (via a 1k resistor, with a 100k pull-down resistor), which switches the ground connection to the Wi-Fi router, turning it on and off.
Bread-Board Layout
This shows an approximate bread-board layout of the circuit. Note that the physical locations of the pins on the MKR1000 board are not correct, but rather the Pin IDs are correct (with the exception of A6, A7 where the battery connects; which in reality is via the 2-pin JST connector).

Comments

Author

Photo
Khalid Abdulla
  • 1 project
  • 2 followers

Additional contributors

Published on

March 30, 2016

Members who respect this project

WillbarkMyavatar6836614LilshredderE27ed531f0bcd3fe3d4381a57690c3beLogo 300x30018581760 1064432770326718 5582761015199642580 nPhoto

and 6 others

See similar projects
you might like

Similar projects you might like

Event Monitor for Independent Senior Citizens

Project tutorial by Rethink IoT

  • 4,028 views
  • 4 comments
  • 27 respects

Programmable Pocket Power Supply with OLED Display

Project tutorial by Shahariar

  • 6,320 views
  • 6 comments
  • 28 respects

Alexa Smart Power Strip with Temperature

Project tutorial by Muhammad Afzal

  • 1,203 views
  • 0 comments
  • 7 respects

Make your own Power Inverter using Arduino

Project showcase by Team Shailza

  • 25,924 views
  • 6 comments
  • 15 respects

Multiple mode Environmental Sensor Deck with MKR1000

Project tutorial by Team ConsoleTeam

  • 11,333 views
  • 13 comments
  • 46 respects
Add projectSign up / Login