Created on: 20 February 2013
Part 9 of the Arduino Ethernet Shield Web Server Tutorial
Updating the status of more than one switch that is interfaced to the Arduino web server, as well as showing the value of one of the analog inputs.
JavaScript is used to make AJAX calls to request the switch status and analog value from the web server.
This video shows the switches and analog input updated on the web page without flicker. Only parts of the web page are updated using AJAX.
The circuit diagram below shows how the switches are interfaced to the Arduino (with Ethernet shield plugged into it). A potentiometer is interfaced to analog input A2 so that the value on A2 can be changed and updated on the web page.
The Arduino sketch is a modified version of the sketch from the previous tutorial.
/*-------------------------------------------------------------- Program: eth_websrv_AJAX_IN Description: Uses Ajax to update the state of two switches and an analog input on a web page. The Arduino web server hosts the web page. Does not use the SD card. Hardware: Arduino Uno and official Arduino Ethernet shield. Should work with other Arduinos and compatible Ethernet shields. Software: Developed using Arduino 1.0.3 software Should be compatible with Arduino 1.0 + References: - WebServer example by David A. Mellis and modified by Tom Igoe - Ethernet library documentation: http://arduino.cc/en/Reference/Ethernet - Learning PHP, MySQL & JavaScript by Robin Nixon, O'Reilly publishers Date: 20 February 2013 Author: W.A. Smith, http://startingelectronics.org --------------------------------------------------------------*/ #include <SPI.h> #include <Ethernet.h> // MAC address from Ethernet shield sticker under board byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(10, 0, 0, 20); // IP address, may need to change depending on network EthernetServer server(80); // create a server at port 80 String HTTP_req; // stores the HTTP request void setup() { Ethernet.begin(mac, ip); // initialize Ethernet device server.begin(); // start to listen for clients Serial.begin(9600); // for diagnostics pinMode(7, INPUT); // switch is attached to Arduino pin 7 pinMode(8, INPUT); // switch is attached to Arduino pin 8 } void loop() { 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 HTTP_req += c; // save the HTTP request 1 char at a time // 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"); client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); // AJAX request for switch state if (HTTP_req.indexOf("ajax_switch") > -1) { // read switch state and analog input GetAjaxData(client); } else { // HTTP request for web page // send web page - contains JavaScript with AJAX calls client.println("<!DOCTYPE html>"); client.println("<html>"); client.println("<head>"); client.println("<title>Arduino Web Page</title>"); client.println("<script>"); client.println("function GetSwitchAnalogData() {"); client.println( "nocache = \"&nocache=\" + Math.random() * 1000000;"); client.println("var request = new XMLHttpRequest();"); client.println("request.onreadystatechange = function() {"); client.println("if (this.readyState == 4) {"); client.println("if (this.status == 200) {"); client.println("if (this.responseText != null) {"); client.println("document.getElementById(\"sw_an_data\")\ .innerHTML = this.responseText;"); client.println("}}}}"); client.println( "request.open(\"GET\", \"ajax_switch\" + nocache, true);"); client.println("request.send(null);"); client.println("setTimeout('GetSwitchAnalogData()', 1000);"); client.println("}"); client.println("</script>"); client.println("</head>"); client.println("<body onload=\"GetSwitchAnalogData()\">"); client.println("<h1>Arduino AJAX Input</h1>"); client.println("<div id=\"sw_an_data\">"); client.println("</div>"); client.println("</body>"); client.println("</html>"); } // display received HTTP request on serial port Serial.print(HTTP_req); HTTP_req = ""; // finished with request, empty string 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) } // send the state of the switch to the web browser void GetAjaxData(EthernetClient cl) { int analog_val; if (digitalRead(7)) { cl.println("<p>Switch 7 state: ON</p>"); } else { cl.println("<p>Switch 7 state: OFF</p>"); } if (digitalRead(8)) { cl.println("<p>Switch 8 state: ON</p>"); } else { cl.println("<p>Switch 8 state: OFF</p>"); } // read analog pin A2 analog_val = analogRead(2); cl.print("<p>Analog A2: "); cl.print(analog_val); cl.println("</p>"); }
The above sketch produces the following HTML code:
Arduino pins 7 and 8 are both configured as inputs in the setup() part of the sketch.
The JavaScript function that handles the AJAX call has been renamed. The Arduino function that responds to the AJAX call has also been renamed.
A HTML <div> has been created below the H1 header in the HTML code and given the id "sw_an_data". The div is invisible on the page, but it serves as a place for the JavaScript to put the information (switch and analog values) sent back from the Arduino.
The JavaScript function GetSwitchAnalogData() is called every second. Every second, it sends a GET request to the Arduino web server.
When the Arduino receives the AJAX request, it runs the GetAjaxData() function. This function reads the state of the two switches and sends the switches' statuses (ON or OFF) back to the web browser. The function also reads the value on the A2 analog pin and sends the value back to the browser.
When the web browser receives the data requested from the Arduino, it simply inserts it into the div that has the ID sw_an_data.