Khalid Abdulla
Published © GPL3+

Wi-Fi Power Toggler

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

IntermediateFull instructions provided2 hours4,238
Wi-Fi Power Toggler

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
×1
DFRobot DF Robot Lithium Polymer Battery (1000mAh, 3.7V)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
N-Channel Power Mosfet (STP36NF06L)
×1
Linear Regulator (7805)
Linear Regulator (7805)
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 100k ohm
Resistor 100k ohm
×2
Resistor 221k ohm
Resistor 221k ohm
×1
PCB terminal block (3-way)
×1
Breadboard (generic)
Breadboard (generic)
×1

Software apps and online services

pushingbox
Google Sheets
Google Sheets

Story

Read more

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).

Code

WiFi Power Toggler Sketch

Arduino
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");
}

Credits

Khalid Abdulla

Khalid Abdulla

1 project • 2 followers
Engineer and self-confessed tinkerer. Currently also a PhD student. More here: http://people.eng.unimelb.edu.au/kabdulla/

Comments