Using HTML Drop-down Select Boxes for Hour and Minute on Arduino Web Server

An Arduino and Ethernet shield with SD card are used as a web server to host a page that allows a user to select hour and minute values from two HTML drop-down select boxes. The time sent to the Arduino can be used to set a real-time clock from a web page or for other time related purposes.

To demonstrate that the Arduino is getting the time values from the web page, they are displayed in the Serial Monitor window of the Arduino IDE. JavaScript in the hosted HTML web page is used to send the hour and minute time values to the Arduino periodically. This allows the code to easily be integrated with the Arduino Ajax web server code. The code could also be adapted to send the time only when a button is clicked.

This video shows the sketch running and the selected time values from the web page being sent to the Serial Monitor window:

 

Web Server Hardware

An Arduino Uno, Ethernet shield and 2GB micro SD card were used for testing the code. Any Arduino board that is compatible with the Ethernet shield should work.

Setting up the Web Server

The Arduino sketch below must be loaded to the Arduino with Ethernet shield. The HTML web page from below must be copied to a file called index.htm on the micro SD card. Insert the micro SD card into the socket on the Ethernet shield.

Arduino Web Server Sketch

Copy this code and paste it to the Arduino IDE for loading to the Arduino board with Ethernet shield and SD card. Change the MAC and IP address to suit your own system.

/*--------------------------------------------------------------
  Program:      drop_down_select

  Description:  Arduino web server that gets hour and
                minute from two drop-down select boxes on an
                HTML page.
                The web page is stored on the micro SD card.
  
  Date:         22 June 2015
 
  Author:       W.A. Smith, http://startingelectronics.org
--------------------------------------------------------------*/

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   60

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
File webFile;               // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer

void setup()
{
    // disable Ethernet chip
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
    
    Serial.begin(115200);       // for debugging
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
    
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
}

void loop()
{
    byte hour;
    byte minute;
    
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // limit the size of the stored received HTTP request
                // buffer first part of HTTP request in HTTP_req array (string)
                // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
                if (req_index < (REQ_BUF_SZ - 1)) {
                    HTTP_req[req_index] = c;          // save HTTP request character
                    req_index++;
                }
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    // remainder of header follows below, depending on if
                    // web page or XML page is requested
                    // Ajax request - send XML file
                    if (StrContains(HTTP_req, "ajax_inputs")) {
                        // send rest of HTTP header
                        client.println("Content-Type: text/xml");
                        client.println("Connection: keep-alive");
                        client.println();
                        // print the received hour and minute to the Serial Monitor window
                        // if received with the incoming HTTP GET string
                        if (GetTime(&hour, &minute)) {
                          Serial.print("Hour: ");
                          Serial.println(hour);
                          Serial.print("Minute: ");
                          Serial.println(minute);
                        }
                    }
                    else {  // web page request
                        // send rest of HTTP header
                        client.println("Content-Type: text/html");
                        client.println("Connection: keep-alive");
                        client.println();
                        // send web page
                        webFile = SD.open("index.htm");        // open web page file
                        if (webFile) {
                            while(webFile.available()) {
                                client.write(webFile.read()); // send web page to client
                            }
                            webFile.close();
                        }
                    }
                    // reset buffer index and all buffer elements to 0
                    req_index = 0;
                    StrClear(HTTP_req, REQ_BUF_SZ);
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

// extract hour and minute from the incoming HTTP GET data string
// returns true only if both the hour and minute have been received
boolean GetTime(byte *hr, byte *mn)
{
  boolean valid_time = false;  // hour and minute received flag
  char *str_part;              // pointer to part of the HTTP_req string
  char str_time[3] = {0};      // used to extract the times from HTTP_req string
  
  // get pointer to the beginning of hour data in string
  str_part = strstr(HTTP_req, "&h=");
  if (str_part != NULL) {
    // get the hour from the string
    str_time[0] = str_part[3];
    str_time[1] = str_part[4];
    *hr = atoi(str_time);
    // get pointer to the beginning of minute data in string
    str_part = strstr(HTTP_req, "&m=");
    if (str_part != NULL) {
      // get the minute from the string
      str_time[0] = str_part[3];
      str_time[1] = str_part[4];
      *mn = atoi(str_time);
      // got the hour and the minute
      valid_time = true;
    }
  }

  return valid_time;
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
    for (int i = 0; i < length; i++) {
        str[i] = 0;
    }
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
    char found = 0;
    char index = 0;
    char len;

    len = strlen(str);
    
    if (strlen(sfind) > len) {
        return 0;
    }
    while (index < len) {
        if (str[index] == sfind[found]) {
            found++;
            if (strlen(sfind) == found) {
                return 1;
            }
        }
        else {
            found = 0;
        }
        index++;
    }

    return 0;
}


Arduino Hosted HTML Page

This code gets copied to the index.htm file on the micro SD card.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Drop-Down Select Box Example</title>
        <script>
        strHour = "";
        strMin = "";
        function GetArduinoIO()
        {
            nocache = "&nocache=" + Math.random() * 1000000;
            var request = new XMLHttpRequest();
            
            // get the values from the drop-down select boxes
            var sel_hour = document.getElementById("selHour");
            if (sel_hour.selectedIndex > 0) {
                strHour = "&h=" + sel_hour.options[sel_hour.selectedIndex].text;
            }
            else {
                // the first item in the drop-down box is invalid text, so clear the string
                strHour = "";
            }
            
            var sel_min = document.getElementById("selMin");
            if (sel_min.selectedIndex > 0) {
                strMin = "&m=" + sel_min.options[sel_min.selectedIndex].text;
            }
            else {
                strMin = "";
            }

            // send HTTP GET request with LEDs to switch on/off if any
            request.open("GET", "ajax_inputs" + strHour + strMin + nocache, true);
            request.send(null);
            setTimeout('GetArduinoIO()', 3000);
        }
    </script>
    </head>

    <body onload="GetArduinoIO()">
        <select id="selHour">
            <option selected="selected" value="">Select Hour</option>
            <option value="00">00</option>
            <option value="01">01</option>
            <option value="02">02</option>
            <option value="03">03</option>
            <option value="04">04</option>
            <option value="05">05</option>
            <option value="06">06</option>
            <option value="07">07</option>
            <option value="08">08</option>
            <option value="09">09</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
        </select>
        <select id="selMin">
            <option selected="selected" value="">Select Minute</option>
            <option value="00">00</option>
            <option value="01">01</option>
            <option value="02">02</option>
            <option value="03">03</option>
            <option value="04">04</option>
            <option value="05">05</option>
            <option value="06">06</option>
            <option value="07">07</option>
            <option value="08">08</option>
            <option value="09">09</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
            <option value="13">13</option>
            <option value="14">14</option>
            <option value="15">15</option>
            <option value="16">16</option>
            <option value="17">17</option>
            <option value="18">18</option>
            <option value="19">19</option>
            <option value="20">20</option>
            <option value="21">21</option>
            <option value="22">22</option>
            <option value="23">23</option>
            <option value="24">24</option>
            <option value="25">25</option>
            <option value="26">26</option>
            <option value="27">27</option>
            <option value="28">28</option>
            <option value="29">29</option>
            <option value="30">30</option>
            <option value="31">31</option>
            <option value="32">32</option>
            <option value="33">33</option>
            <option value="34">34</option>
            <option value="35">35</option>
            <option value="36">36</option>
            <option value="37">37</option>
            <option value="38">38</option>
            <option value="39">39</option>
            <option value="40">40</option>
            <option value="41">41</option>
            <option value="42">42</option>
            <option value="43">43</option>
            <option value="44">44</option>
            <option value="45">45</option>
            <option value="46">46</option>
            <option value="47">47</option>
            <option value="48">48</option>
            <option value="49">49</option>
            <option value="50">50</option>
            <option value="51">51</option>
            <option value="52">52</option>
            <option value="53">53</option>
            <option value="54">54</option>
            <option value="55">55</option>
            <option value="56">56</option>
            <option value="57">57</option>
            <option value="58">58</option>
            <option value="59">59</option>
        </select>
    </body>

</html>

Running the Web Server Drop-down Select Box Project

With the index.htm file on the SD card and the sketch loaded to the Arduino, open the Serial Monitor window and then use a web browser to surf to the IP address that is set in the sketch.

Change the hour and minute values in the drop-down boxes to valid time values to see the hour and minute displayed in the Serial Monitor window. Both the hour and minute must be set to valid values before anything is displayed.

Basic Multi-file Arduino Web Server

This basic Arduino web server hosts HTML web pages and various other files such as CSS, JavaScript, text and image files.

Web pages and other resource files are stored on the SD card inserted into the SD card socket on  Arduino Ethernet shield or Arduino Ethernet board.

The code for the web server can be copied from the project’s page which contains a form that allows parameters such as the MAC, IP and port numbers to be changed. After changes have been made to the settings, a button is clicked to update the Arduino web server sketch. The sketch can then be copied and pasted into the Arduino IDE for loading to the Arduino board with Ethernet shield. Some sample HTML files, JavaScript, CSS, text and image files are also available for download and demonstrate the web server capabilities.

This web server is a supplement to the Arduino Ethernet shield web server tutorial and provides a starting place to design your own web server.

Get the Arduino web server code →

How to Control an LED from an Arduino Web Page Button and an External Push Button

The article on how to control an LED with both a button on a web page from an Arduino web server and a physical hardware button includes the circuit diagram, HTML and JavaScript code and the Arduino code.

I wrote the article after being asked a question on how to control an LED from an HTML button on an Arduino hosted web page and a physical button connected to an Arduino pin.

The image below shows the final project.

Arduino LED Control from Web Page and Push Button Switch

Arduino LED Control from Web Page and Push Button Switch

An Arduino and Ethernet shield is used with a web page hosted on the micro SD card inserted into the Ethernet shield.

When the checkbox or button on the web page is clicked, the corresponding LED will switch on or off. When a push button is pressed, the corresponding LED will switch on or off and the state of the LED will be updated on the web page. Ajax is used to update the LED states on the web page so that there is no page refresh flicker.

Pressing the left push button causes the left LED to switch on and the checkbox on the page to get a check mark. Pushing the left push button again switches the LED off and the check is removed from the checkbox on the web page.

The button on the web page will initially display the text OFF as part of the button text. When the right push button is pressed, the LED will switch on and the HTML button text will be updated to display ON. Pressing the right push button again will switch the LED off and update the button text on the web page to display OFF again.

Go to the project article with video, circuit diagram and HTML, JavaScript and Arduino Code →

Arduino MEGA Ethernet Web Server for Controlling 24 Outputs

In this tutorial, an Arduino MEGA 2560 and Ethernet shield are used to make a web server that hosts a web page that allows 24 outputs to be controlled using checkboxes. The tutorial on the Arduino MEGA web server contains the circuit diagram and all of the source code for the project.

This tutorial was written to answer a question on the blog about the Arduino web server tutorial.

An image of the web server with the web page used to control 24 LEDs is shown below.

24 Output Arduino MEGA Web Server using the Ethernet Shield

24 Output Arduino MEGA Web Server using the Ethernet Shield

How to Access your Arduino from the Internet

If you have built an Arduino web server (e.g. by following the Arduino web server tutorial), you will be able to access your web server on your local network, probably through your ADSL router. But what must be done if you want to access the Arduino server from outside of your home network?

The tutorial on connecting your Arduino web server to the Internet describes how to set up and access your Arduino web server from the Internet via any Internet connected device such as a PC, tablet or smart-phone. This allows you to remotely view and interact with your Arduino web server pages.

An external service such as no-ip can be used as a solution to the dynamic IP address that is usually assigned to the router. This is also explained in the tutorial.

Go to the tutorial now →