Arduino Network Tester

How many times you wanted to know if an Ethernet plug or port has internet connectivity and you had to bring your laptop or a cable from the next room to check? And how many times the only tools available were the simple Network Cable tester and your provider’s Modem or Router? For me that was a common issue and of course there was no easy, "plug and play" solution (at a reasonable price!!). Taking these into consideration I decided to give a solution by making a simple optimization to the most common Network tool. Arduino Network Tester, extends the functionality of the well-known Network Cable tester by adding DHCP, DNS and Internet connectivity tests using an Arduino Pro Mini and a W5500 Ethernet Shield with an overall cost of less than €15!
Arduino Network Tester

How it works

When turned on, the Power LED is ON and the Status LED is flashing, until you connect an RJ45 (Ethernet Cable) from an OSI Layer 3 device (e.g. router) to the W5500 ethernet port. Following this, the device runs the tests one by one starting with DHCP where it requests an IP address. If configuration from a DHCP Server is successfully received then the DHCP LED turns on. As a next step the device tries to resolve the url www.example.com to the appropriate IP and if successful then the DNS LED turns ON. Finally,it makes an HTTP request to the domain www.example.com and parse the result. If the returned HTTP Status Code equals to 200 then the Internet Connectivity LED turns ON. Once the Status LED turns ON then all the checks have been completed, either successfully or unsuccessfully.

Bill of Materials

1) Double Side Thru-Hole Prototype PCB Board (at least 70*90mm)
2) Arduino Pro Mini 3.3v 8MHz
3) W5500 Ethernet Shield
4) 5 LEDs (SMD 0805)
5) 5 330 Ohm Resistors (SMD 0805)
6) Battery Charger (TC4056A)
7) 3.7V 100mah LIPO battery with XH 2.5mm connector
8) B2B-XH-A 2 Pins connector
9) On-Off switch (SS-12F15G)
10) 2.54 mm Pin headers

Burn optiboot Bootloader

When the ethernet cable is disconnected from the tester, the device resets using the WatchDog Timer (WDT). The default bootloader of Arduino Pro Mini has an annoying bug which actually keeps the tester in a reset loop after calling WDT_reset(). To solve this issue you have to burn the Optiboot Bootloader. You can find how to burn a new Bootloader to Arduino Pro mini using an Arduino UNO here. Follow the instructions and before burning the bootloader to Arduino Pro Mini use the following settings in Arduino IDE:

ArduinoProMiniBootloader

Pinouts

W5500 Ethernet Shield to Arduino

Arduino PIN W5500 Ethernet Shield
10 CS
11 MO (MOSI)
12 MI (MISO)
13 SCK
GND G
VCC V

TP4056 Power and Charging

The Power Switch handles the battery’s connection. On the one side of the switch the battery connects to the charger and on the other side it provides power to the tester. In the current implementation you can’t charge the battery and power the tester at the same time. To enable this functionality a load sharing circuit must be used.

Prototype PCB Board Design

Arduino Network Tester is consisted of two double sided thru-hole prototype PCB boards:
1) the top with the LED Indicators
2) the bottom, with the rest circuit.

Prototype Board

The two PCBs are then stacked together, using 2.54mm connectors to distribute the power and the signals to the LEDs. The battery can be replaced using the XH 2.5mm connector, and the switch is removable in order to be positioned on the 3d printed cover.

Arduino Network Tester PCB

Code

Use Arduino IDE and a USB-to-TTL serial converter to upload the following sketch to Arduino Pro Mini. If this is the first time you are doing this, you can follow the official instructions.

#include <SPI.h>
#include <Ethernet.h>
#include <Dns.h>
#include <avr/wdt.h>

#define PWR_LED 6
#define DHCP_LED 5
#define DNS_LED 4
#define INT_LED 3
#define STATUS_LED 2

//Here you can set your own mac address
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

DNSClient dns_client;
EthernetClient eth_client;

char server_url[] = "www.example.com";
// www.example.com resolves to 93.184.216.34
// if you change server_url you must also change server_ip
byte server_ip[] = { 93, 184, 216, 34 };

//the resolved ip from the DNS query
IPAddress server_ip_resolved;

boolean dns_resolved = false;
boolean http_responded = false;

long last_blink = 0;

void init_leds() {
  pinMode(PWR_LED, OUTPUT);
  pinMode(DHCP_LED, OUTPUT);
  pinMode(DNS_LED, OUTPUT);
  pinMode(INT_LED, OUTPUT);
  pinMode(STATUS_LED, OUTPUT);

  digitalWrite(PWR_LED, HIGH);
  digitalWrite(DHCP_LED, HIGH);
  digitalWrite(DNS_LED, HIGH);
  digitalWrite(INT_LED, HIGH);
  digitalWrite(STATUS_LED, HIGH);
  delay(500);
  digitalWrite(DHCP_LED, LOW);
  digitalWrite(DNS_LED, LOW);
  digitalWrite(INT_LED, LOW);
  digitalWrite(STATUS_LED, LOW);
}

void reset_leds() {
  digitalWrite(DHCP_LED, LOW);
  digitalWrite(DNS_LED, LOW);
  digitalWrite(INT_LED, LOW);
  digitalWrite(STATUS_LED, LOW);
}

void flash_led(int led, int blink_delay) {
  if (millis() - blink_delay > last_blink) {
    if (digitalRead(led) == HIGH) {
      digitalWrite(led, LOW);
    } else {
      digitalWrite(led, HIGH);
    }
    last_blink = millis();
  }
}

void setup() {
  // Open serial communications and wait for port to open:
  init_leds();

  //while no cable is connected wait
  while (Ethernet.linkStatus() != LinkON) {
    flash_led(STATUS_LED, 1000);
  }
  //A cable has been connected, stop flashing Status LED
  digitalWrite(STATUS_LED, LOW);
  // Obtain an IP using DHCP
  if (Ethernet.begin(mac) == 0) {
  // Static Configuration: comment the previous line, 
  // uncomment the following line and set appropriate values:
  // if (Ethernet.begin(mac, ip, dns, gateway, subnet)==0) {
    while (true) {
      //Failed to configure Ethernet using DHCP      
      flash_led(DHCP_LED, 1000);
      digitalWrite(STATUS_LED, HIGH);
    }
  } else {
    //DHCP Configuration completed 
    digitalWrite(DHCP_LED, HIGH);
    // give the Ethernet shield a second to initialize:
    delay(1000);

    //Check DNS
    dns_client.begin(Ethernet.dnsServerIP());
    if (dns_client.getHostByName(server_url, server_ip_resolved) == 1 && server_ip_resolved == server_ip) {
      //DNS is working
      digitalWrite(DNS_LED, HIGH);
      dns_resolved = true;
    } else {
      //DNS failed
    }

    //Check Internet Connectivity
    if (eth_client.connect(server_url, 80)) {
      http_responded = false;
      eth_client.println("GET http://" + String(server_url) + " HTTP/1.1");
      eth_client.println("Host: " + String(server_url));
      eth_client.println("Connection: close");
      eth_client.println(); // end HTTP request header      
    } else {
      //Unable to establish an http connection
      digitalWrite(STATUS_LED, HIGH);
    }
  }
}

void reset_WDT() {
  wdt_enable(WDTO_15MS);
  while (1) {};
}

void loop() {
  //If cable unplugged reset
  if (Ethernet.linkStatus() != LinkON) {
    reset_WDT();
  }

  // Handle HTTP Client response
  String response = "";
  while (eth_client.available() && !http_responded) {
    char c = eth_client.read();
    response = response + c;
    //Find the first carriage return, this line returns the status code of the HTTP server
    if (c == '\r') {
      http_responded = true;
      eth_client.stop();
      //if page loaded then internet connectivity exists
      if (response.indexOf("200") > 0) {
        digitalWrite(INT_LED, HIGH);
        digitalWrite(STATUS_LED, HIGH);
      } else {
        //Failed to load the page, Internet connectivity does not exist
        digitalWrite(STATUS_LED, HIGH);
      }
      break;
    }
  }
}

The code is available on github

3d Files

Arduino Network Tester consists of 4 seperate 3d printed parts:

Network Tester Parts

  • Outer Shell
  • Back Cover where pcb is mounted
  • Power Module LED Indicators Separator
  • LED Indicators Separator
    All parts are available on thingverse

Assembled and Operational!

Future Updates

  • Code optimization to allow Arduino to sleep for less Power Consumption
  • Battery Level Indicator

Customization – Local Network Testing

With simple code changes, the Arduino Network Tester could be used to check the configuration of isolated local networks, using local Web Server/Router page instead of example.com and/or Static DHCP configuration (uncomment the appropriate line) in the case of a local network without DHCP Server.

Leave a Reply