Projects

Modem Restarter

Automatic System Using The ESP8266

Tim Blythman

Issue 2, August 2017

This article includes additional downloadable resources.
Please log in to access.

Log in

Here’s a problem that I’m sure we’ve all experienced - a router that for whatever reason, simply stops supplying the internet we need, and nothing fixes it better than a simple “turn it off and on again”. With Arduino and an ESP8266 Arduino compatible board, this can be done automatically.

It’s the solution repeated by seasoned IT professionals everywhere: the hard reset. A power cycle, AKA “turn it off and on again” that simply does what it says. Resetting a malfunctioning piece of hardware to a known good state. What we’re trying to detect and correct here is the situation that can drive anyone mad - that the internet isn’t working. I wanted a system that will check if the router is connecting to the internet OK, and if not, apply the hard reset that will make it all work again. This project also uploads reports to a phant stream, so that the status can be checked remotely.

The Broad Overview

There’s two main parts to this problem: detecting that the router isn’t doing what it should, and then making the reset happen. Because we’re using WiFi, the sketch first needs to connect to the WiFi network, and then try to connect to a website. I’m using Google, because if Google’s down, that’s pretty much as good as the internet being down. Of course, not being able to connect to the WiFi network is a good reason to ring the alarm bells too, so this needs to be detected as well.

The next step is to reset the router. If you’ve got a router that runs off low voltage, even via a transformer or PSU, then that’s quite easy, but if you’ve got a router (or some other device) that runs off 240V directly, then more hardware is needed to do this safely. Of course, the power can’t just blindly toggle either - it needs to turn the power off for long enough for the router to reset, but also give it long enough after power on to get into a normal operating state.

Because everything should always have more features, I’ve also added some code to upload the status to a phant stream (see article on Power Outage Detector & Arduino UPS). Of course, if the internet is down, an update can’t be done, so the status is either OK, or a reset has recently occurred. If there hasn’t been an OK for a while, there’s something wrong.

How It Works

We originally set out to use an Arduino compatible board plus WiFi Shield for this project, but the project seemed simple enough that I should be able to program the WiFi Shield directly. The main parts of the hardware are the WiFi Shield (operating as an Arduino board) and a 5V relay module. The router power is fed via the relay’s normally closed (NC) contacts, so that to effect a reset, the relay module is energized for a few seconds. Using the NC contacts also means that the default state is “power on”, and things will generally keep running if there is an issue with the Router Restarter.

The other necessary piece of hardware is a USB-Serial converter to do the initial programming. If you don’t have an immediate need to use the USB-Serial converter for another job, then it’s an easy way to power the built project as well. But you may as well keep it for another project, and power the device directly once complete.

Closeup of WiFi Shield
A closeup of the shield. Most of the “pins” on the WiFi module are broken out to headers on the WiFi Shield.
Relay Module
Any 5VDC relay module with Normally Closed (NC) contacts will work.

The Hardware

The code is actually quite basic. The module tries to connect to a WiFi network, and then tries to connect to google.com.au. If it takes too long to do either, the relay module activates, shutting off power to the router for a few seconds, before reapplying power, allowing the router to restart. There’s a timeout to let the router go through its boot process before the checking starts again.

On startup and at regular intervals, a message is also sent to the phant server by a separate function. If a reset occurs, then a different message is sent.

Under the Arduino IDE, connecting to a WiFi network is as simple as issuing the command:

WiFi.begin(SSIDNAME,SSIDPWD);  
  //connect to WiFi network

The code that checks if the board can connect to the internet is below. We're using a counter to detect the number of “fails”, and only tripping the reset if the count gets to three. This gives a bit of robustness in case of occasional glitches that might occur in the internet. In essence, we’re assuming that if the ESP8266 can connect to Google, then everything is fine.

WiFiClient client;
if(client.connect("www.google.com.au",80) {
  // connect to google on port 80- 
  // could be any website
  Serial.print("connection ok:");    
  cnt=0; //reset fail count
}else{
  Serial.print("connection failed:"); 
  //count the fails
  cnt++;
}

These constants (anything shown as a #define) set up what is needed to connect to the phant service (to use this, you would have to fill in the key and stream names with ones you’ve created yourself). I’ve set up the HOSTNAME as a #define for two reasons - firstly, it’s easier to change if it does change in the future; and secondly, it’s actually possible to run your own phant server, and this would have a different address.

#define PHANTPUBLICKEY "_your_public_key_"
#define PHANTPRIVATEKEY "_your_private_key_"
#define PHANTNAME "powerstatus"
#define HOSTNAME "data.sparkfun.com"
#define HOSTPORT (80)

This function is what uploads data to the phant server. The code is identical to what you would use to load a webpage, and it dumps the server’s response back to the serial port for debugging purposes.

void dophant(char* txt){
//upload txt to phant
  Serial.print("Phant:");
  Serial.println(txt);
  if(client.connect(HOSTNAME,HOSTPORT)){
//connect to phant
    client.print("GET /input/"
      PHANTPUBLICKEY "?private_key="
      PHANTPRIVATEKEY "&" PHANTNAME
      "="); //upload via get request
    client.print(txt);
    client.print(" HTTP/1.1rnHost: " 
        HOSTNAME "rnrn");
    delay(5000); 
      //wait for response
    while(client.available()){
    Serial.write(client.read());
      //and dump to serial port
  }  
}
  Serial.println("Phant done");
  client.stop(); 
  //disconnect
}
Parts Required: Jaycar Altronics
1 x ESP8266 WiFi Arduino Compatible Shield XC4614 Z6360
1 x USB to Serial Converter XC4834 D2340B
1 x 5V Relay Module XC4419 Z6325

You’ll also need standard prototyping hardware.

DON'T WANT TO CUT YOUR POWER CABLE? You can easily make up an inline joiner for this project using a DC plug, DC socket, and a short length of cable. Connect the DC plug from your power supply into the socket, and the new plug into your router and you're set. That way your power supply is still in-tact which may be useful for any warranty etc.

Building the Circuit

I found it easier to make the connection between router and relay module first. If your router has a low voltage transformer with a lead and DC plug, you should be able to use this method. On the lead between the plug pack and DC plug, cut and separate one of the wires and bare back the ends about 5mm.

The DC cable after being cut
The DC cable after being cut.

Then screw the bare ends of the wire into the terminals on the relay module. You need to use the normally closed and common connections- the normally closed is usually marked NC and the common will be the middle. On the module we used, they are the two right-most terminals.

Relay module with wires screwed into place.

You can easily test that this is correct by plugging the power supply back into the router. If the normally closed contacts have been correctly wired, the router should turn on and operate as normal.

I cut my relay module in close to the DC plug end of the cable, but in retrospect, I should have put it closer to the mains plug pack, given that I’m plugging the USB power supply for the Router Restarter into the same power board.

Made up programming lead. Note the addition of a lead offcut as a spacer.

The rest of the mechanical build is to hook everything up with jumper wires - there are four from the USB-serial converter and three from the relay module, all going back to the WiFi Shield.

Because I figured I might be connecting the USB-serial converter more than once, I made a plug-in harness out of the jumper leads. After plugging the ends into the respective boards and making sure they worked and were wired correctly, I used a little superglue (sparingly and carefully) to set each end into a permanent arrangement that could still be plugged and unplugged when needed.

Connection diagram for the Modem Restarter

Note that the Relay Module needs 5V to its power input to operate correctly, even though it will activate on a 3.3V signal to a control input it may produce unreliable results.

Code and Configuration

As noted earlier, the code won’t simply work out ‘out of the box’, as there are some parameters that will need to be set to work with your WiFi network and phant stream:

#define SSIDNAME "SSID"
#define SSIDPWD "PASSWORD"
#define PHANTPUBLICKEY "PUBLICKEY"
#define PHANTPRIVATEKEY "PRIVATEKEY"
#define PHANTNAME "FIELDNAME"

At a minimum, replace the text inside the quotes with your own versions. If you are not using the phant server at data.sparkfun.com, you will need to change HOSTNAME and HOSTPORT although HOSTPORT will probably still be 80.

The other #defines are more for finetuning, so can be left for now. If you do not have a phant stream set up, you can just leave the default values - it will just try to upload to a non-existent stream. If you don’t intend to set up a phant stream at all, you can replace the dophant() function with an empty function by removing the code inside the function (so it does nothing):

void dophant(char* txt){  
  //do nothing instead of upload txt phant
}

Assumed Knowledge: Phant Stream

If you haven't setup your own PHANT stream yet check out the article PHANT Stream for a step-by-step guide. PHANT is a free IoT service provided by SparkFun.

Assuming that you’ve set up the Arduino IDE for your ESP8266 board (see our setup article elsewhere in this issue), plug it in and choose the correct serial port.

There are a lot of board profiles available. For the XC4614 WiFi Shield, I chose the ‘ESPDuino’ option as it is based on an ESP-13 module like the shield, and this worked fine. If you have trouble, you can manually change the options - I would start by trying a different Upload Speed. The CPU Frequency and Flash Size should not matter too much, as the sketch is quite small and will operate fine at the slower 80MHz. You might find your module or board has a documented Flash Size that you can input, and if not there is a test sketch that can check the flash size at File>Examples>ESP8266>CheckFlashConfig [1].

Selecting the host board in Arduino IDE
1
Selecting the host board in Arduino IDE.

The next step is to put the board into bootloader mode. On the Duinotech board we used, hold down the “KEY” button, press and release the “RST” button, then release the “KEY” button. If you have one of the all-in-one boards with a USB-serial converter built in, then this might be done automatically. If not, there is more information about how this happens here.

Now you can press upload from the Arduino IDE. To me a least, it appears that this process takes much longer than for other boards. Open the Serial Monitor, and observe the debug data [2].

Serial Monitor Debug Data
2
Serial Monitor Debug Data.

If you get a 0.0.0.0 IP address, then the WiFi settings might not be correct. A HTTP 404 message in the response from the phant server might indicate that the phant stream keys or field are incorrect.

NOTE: It may be habit to set an IP address when using WiFi or Ethernet modules. However it's not a good idea for this project. You actually want the DHCP protocol to assign a valid address. If that doesn't happen then it indicates an issue too. If the IP address isn't assigned correctly, it will also then restart the router. This is also useful for resolving other system bugs that a restart can fix.

Testing the System

Providing everything is working properly, you can now test that it does indeed cut power when there's no internet connection. The simplest way, depending on what type of internet connection you have, is to pull out the hard-wire lead (Cat5 or telephone lead).

If you're in Australia and have an NBN connection with FTTP (Fibre to the Premises) it's not a good idea to remove the fibre optic lead and may require a technician to visit if you do. If you cannot "disrupt the internet", the best option is to simply use the off switch on the router. After a short time, you should hear the mechanical "click" of the relay module trying to restart the router. Under the default settings, it will take about 30 seconds to activate, and will toggle the relay for five seconds. If it doesn’t seem to do this, check the wiring and Serial Monitor to see that the fault condition is detected.

The first thing I did after getting it all working was to make up a permanent power lead that would not require me to plug in the USB-serial converter to run the Router Restarter.

I found an old USB plug with a lead that, I think, came from a hub that stopped working. I found the red and black wires and soldered a small piece of 0.1” header strip to them.

This then plugs into the header where the USB-serial converter is plugged, being sure not to get the polarity incorrect. The pins on the board should be labelled anyway, and you can always check with a multimeter. A few seconds of work can save you a broken module.

A USB donor cable modified for 5V supply to the duinotech board.

WARNING: Don’t assume that black and red are power, or even the right way around. Use a multimeter to double check. In some cases, colour codes have been incorrectly identified, which may lead you to fry your board.

The finished project using a modified USB cable for power, meaning you can save your USB to Serial module for another project.

Where to From Here?

Apart from the settings mentioned above that definitely need to be changed, there are one or two that might need to be tweaked to make the Router Restarter work with your setup. The relay is pulsed for five seconds in the reset routine - this should be enough for most devices, but if you are finding it isn’t working reliably, the duration can be increased. There is also the BOOTTIME constant at the start of the sketch - this is the time that the sketch waits for the router to restart before testing the internet connection. If it is too short, the Router Restarter might get stuck in a loop, as the router doesn’t have enough time to get up and running before it is reset. If you are having trouble, this can be extended.

I also created a small Android app, which monitors a phant stream for changes; this app would work equally well monitoring the stream for this project. Check out the article here.

With the phant capability of the Router Restarter, it can easily be extended to feed more data to the phant stream, or even a second phant stream; for example, you could add a temperature sensor output. Just add a “dophant()” function call with the required value. Perhaps, if your router has a habit of overheating, you could use that to trigger a reset as well.

Another way you could use this project is if you run a server, and you want to check if the server is “up”, and running correctly. In this case, you would use the web address of your server instead of Google. You could also separately test the IP address and URL of the server to discriminate between server outages and DNS issues.

Of course, your server probably doesn’t run off a small plug pack, and to get this project working will probably need a way of controlling 240V. The relay in this project is rated for 10A at 240V, but I wouldn’t recommend modifying any 240V wiring unless you’re qualified and know what you’re doing.

If the server has a low voltage power button (e.g. like an ATX power supply), then the relay could be used to toggle that. In this case, you would probably have to use the normally open contacts, and program the relay to activate for five seconds to do a hard “power off”, then pause and give a brief pulse to turn it back on.

If this doesn’t work and you are not legally qualified to work with 240V, then it might be possible to use a remote controlled wireless power point to do the switching. For example, a pair of relays could be connected to “press” the off and on buttons on the remote to initiate a power cycle.

There are a few projects descibed online to solve this pointy issue of mains power switching, and it's something we'll probably tackle in greater depth too.