Web Server Access Point (AP) Mode with MKR 1000

Learn how to set up your board as an access point, allowing other devices to connect to it.

Introduction

In this tutorial, we will be creating something called an Access Point. An access point is practically a wireless local area network, which in this tutorial will not be connected to the Internet. This can be a practical setup for projects that have no access to the internet, but we still want to control and monitor our MKR 1000 board wirelessly. We will be using functionalities from the WiFi101 library, and we will set up a basic configuration that allows us to control an LED (on or off) and do a reading on one of the analog pins.

Hardware & Software Needed

Circuit

Follow the wiring diagram below to connect the LED to the MKR 1000 board.

Circuit with board, resistor and LED.
Circuit with board, resistor and LED.

Schematic

This is the schematic of our circuit.

Schematic of our circuit.
Schematic of our circuit.


Let's Start

This tutorial barely uses any external hardware: we only need an LED that we will control remotely. But the most interesting aspects lie in the library we are going to use: WiFi101. This library can be used for many different connectivity projects, where we can both connect to WiFi, make GET requests and - as we will explore in this tutorial - create an access point (AP) and hosting a web server that we can connect to.

We will go through the following steps in order to create a web server on our MKR 1000:

  • First, we need to initialize the WiFi101 library.
  • Then, we need to create the credentials of our access point by entering a name for our network.
  • Once the program is running, it will create an access point, start hosting a server, and wait for a client to connect.
  • On our phone or laptop, we can now find the access point in the list of available Wi-Fi networks.
  • Once connected to the Wi-Fi, we can connect to the board's specific IP address using our regular browser (e.g. Chrome, Firefox).
  • As long as we are connected, the program detects it, and enters a
    while()
    loop.
  • In the
    while()
    loop, two links are simply printed in HTML format, which is visible in the browser.
  • These links control the LED we connected to the board, simply "ON" or "OFF".
  • If we press the "ON" link, the program is configured to add an "H" to the end of the URL, or if we press the "OFF" link, we add an "L" to the end of the URL.
  • If the URL ends with "H", it will turn on the LED, and if it ends with "L" it turns it off. H stands for "HIGH" and L stands for "LOW".
  • There is also a field displaying the value read from analog pin 1 (A1). Since we have nothing connected, we will read random values.

And that is the configuration we will be using in this tutorial. There are a few other functionalities, such as checking if we have the latest firmware and that we are using the right board, and these potential errors will be printed in the Serial Monitor.

Programming the Board

  1. First, let's make sure we have the drivers installed. If we are using the Web Editor, we do not need to install anything. If we are using an offline editor, we need to install it manually. This can be done by navigating to Tools > Board > Board Manager.... Here we need to look for the Arduino SAMD boards (32-bits ARM Cortex M0+) and install it.

  2. Now, we need to install the library needed. If we are using the Web Editor, there is no need to install anything. If we are using an offline editor, simply go to Tools > Manage libraries.., and search for WiFi101 and install it.

  3. We can now take a look at some of the core functions of this sketch:

  • char ssid[] = ""
    - stores network name.
  • WiFi.begin(ssid)
    - creates an open network.
  • WiFiServer server(80)
    - creates a server that listens for incoming connections on the specified port.
  • WiFiClient client
    - creates a client that can connect to to a specified internet IP address.
  • server.begin()
    - tells the server to begin listening for incoming connections.
  • client.connected
    - checks for connected clients.
  • client.available
    - checks for available data.
  • client.read
    - reads the available data.
  • client.print()
    - print something to the client (e.g. html code).
  • client.stop()
    - closes the connection.

Note: both

ssid
and
pass
needs to be a minimum of 8 characters long

Upload the code to the board, and make sure the right board and port are selected.

1#include <SPI.h>
2#include <WiFi101.h>
3
4char ssid[] = "yourNetwork"; // your network SSID (name)
5int keyIndex = 0; // your network key Index number (needed only for WEP)
6
7int led = LED_BUILTIN;
8int status = WL_IDLE_STATUS;
9WiFiServer server(80);
10
11void setup() {
12 //Initialize serial and wait for port to open:
13 Serial.begin(9600);
14 while (!Serial) {
15 ; // wait for serial port to connect. Needed for native USB port only
16 }
17
18 Serial.println("Access Point Web Server");
19
20 pinMode(led, OUTPUT); // set the LED pin mode
21
22 // print the network name (SSID);
23 Serial.print("Creating access point named: ");
24 Serial.println(ssid);
25
26 // Create open network. Change this line if you want to create an WEP network:
27 status = WiFi.beginAP(ssid);
28 if (status != WL_AP_LISTENING) {
29 Serial.println("Creating access point failed");
30 // don't continue
31 while (true);
32 }
33
34 // wait 10 seconds for connection:
35 delay(10000);
36
37 // start the web server on port 80
38 server.begin();
39
40 // you're connected now, so print out the status
41 printWiFiStatus();
42}
43
44
45void loop() {
46 // compare the previous status to the current status
47 if (status != WiFi.status()) {
48 // it has changed update the variable
49 status = WiFi.status();
50
51 if (status == WL_AP_CONNECTED) {
52 // a device has connected to the AP
53 Serial.println("Device connected to AP");
54 } else {
55 // a device has disconnected from the AP, and we are back in listening mode
56 Serial.println("Device disconnected from AP");
57 }
58 }
59
60 WiFiClient client = server.available(); // listen for incoming clients
61
62 if (client) { // if you get a client,
63 Serial.println("new client"); // print a message out the serial port
64 String currentLine = ""; // make a String to hold incoming data from the client
65 while (client.connected()) { // loop while the client's connected
66 if (client.available()) { // if there's bytes to read from the client,
67 char c = client.read(); // read a byte, then
68 Serial.write(c); // print it out the serial monitor
69 if (c == '\n') { // if the byte is a newline character
70
71 // if the current line is blank, you got two newline characters in a row.
72 // that's the end of the client HTTP request, so send a response:
73 if (currentLine.length() == 0) {
74 // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
75 // and a content-type so the client knows what's coming, then a blank line:
76 client.println("HTTP/1.1 200 OK");
77 client.println("Content-type:text/html");
78 client.println();
79
80 // the content of the HTTP response follows the header:
81 client.print("Click <a href=\"/H\">here</a> turn the LED on<br>");
82 client.print("Click <a href=\"/L\">here</a> turn the LED off<br>");
83
84 int randomReading = analogRead(A1);
85 client.print("Random reading from analog pin: ");
86 client.print(randomReading);
87
88 // The HTTP response ends with another blank line:
89 client.println();
90 // break out of the while loop:
91 break;
92 }
93 else { // if you got a newline, then clear currentLine:
94 currentLine = "";
95 }
96 }
97 else if (c != '\r') { // if you got anything else but a carriage return character,
98 currentLine += c; // add it to the end of the currentLine
99 }
100
101 // Check to see if the client request was "GET /H" or "GET /L":
102 if (currentLine.endsWith("GET /H")) {
103 digitalWrite(led, HIGH); // GET /H turns the LED on
104 }
105 if (currentLine.endsWith("GET /L")) {
106 digitalWrite(led, LOW); // GET /L turns the LED off
107 }
108 }
109 }
110 // close the connection:
111 client.stop();
112 Serial.println("client disconnected");
113 }
114}
115
116void printWiFiStatus() {
117 // print the SSID of the network you're attached to:
118 Serial.print("SSID: ");
119 Serial.println(WiFi.SSID());
120
121 // print your WiFi shield's IP address:
122 IPAddress ip = WiFi.localIP();
123 Serial.print("IP Address: ");
124 Serial.println(ip);
125
126 // print where to go in a browser:
127 Serial.print("To see this page in action, open a browser to http://");
128 Serial.println(ip);
129
130}

Upload Sketch and Testing the Program

Once the code has been successfully uploaded, open the Serial Monitor and it should look like the following image.

Serial Monitor output of board's IP address.
Serial Monitor output of board's IP address.

This means that we successfully created an access point. To connect to it, we can either use a laptop or a smartphone that can connect to Wi-Fi. We will need to disconnect from our current Wi-Fi network, so it is easier to use a phone to connect. Go to your phone's settings, and open the list of Wi-Fi networks. The name of the network we created earlier should show up now.

Finding the access point.
Finding the access point.

Once we are connected to the Wi-Fi, we can enter the URL (IP address of the board) in the browser. This is the one printed in the Serial Monitor. Now, we should see an almost empty page with two links at the top left that say "Click here to turn the LED on" and "Click here to turn the LED off", and a text saying: "Random reading from analog pin: xxx". Depending on if you are using a computer or a phone, they will look like the image below.

Different browser views.
Different browser views.

When interacting with the links, you should see the LED, connected to pin 2, turn on and off depending on what you click, and now we have successfully created a way of interacting with our MKR 1000 board remotely. Whenever we click on these links, the Serial Monitor will print information regarding the requests, as the image below shows.

Serial Monitor output of a client connecting.
Serial Monitor output of a client connecting.

Troubleshoot

If the code is not working, there are some common issues we might need to troubleshoot:

  • We have not updated the latest firmware for the board.
  • We have not installed the core required for the board.
  • We have not installed the WiFi101 library.
  • We have not selected the right port to upload: depending on what computer we use, sometimes the board is duplicated. By simply restarting the editor, this issue can be solved.

Conclusion

In this tutorial, we learned how to create an access point, and how to host a web server that we can connect to. We learned how to control an LED remotely, as well as how to display the value of an analog pin in the browser. This method can be very useful when creating a wireless system of sensors and actuators. If you have more than one Wi-Fi compatible board, we can also connect these to the same access point.