Instalación y programación.
Con esta aplicación podemos conocer el valor de 4 entradas analógicas, 3 digitales y activar 4 salidas digitales; con Arduino UNO y la placa de conexión a Ethernet W5100, desde cualquier equipo conectado a Internet.
La parte primera del programa hay que cargarla en el Arduino UNO y la segunda parte en la tarjeta microSD que lleva el módulo W5100.
La página Web será la siguiente:
#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, 1, 15); // 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 boolean LED_state[4] = {0}; // stores the states of the LEDs void setup() { // disable Ethernet chip pinMode(10, OUTPUT); digitalWrite(10, HIGH); Serial.begin(9600); // 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."); // switches on pins 2, 3 and 5 pinMode(2, INPUT); pinMode(3, INPUT); pinMode(5, INPUT); // LEDs pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); Ethernet.begin(mac, ip); // initialize Ethernet device server.begin(); // start to listen for clients } 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 // 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(); SetLEDs(); // send XML file containing input states XML_response(client); } 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(); } } // display received HTTP request on serial port Serial.print(HTTP_req); // 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) } // checks if received HTTP request is switching on/off LEDs // also saves the state of the LEDs void SetLEDs(void) { // LED 1 (pin 6) if (StrContains(HTTP_req, "LED1=1")) { LED_state[0] = 1; // save LED state digitalWrite(6, HIGH); } else if (StrContains(HTTP_req, "LED1=0")) { LED_state[0] = 0; // save LED state digitalWrite(6, LOW); } // LED 2 (pin 7) if (StrContains(HTTP_req, "LED2=1")) { LED_state[1] = 1; // save LED state digitalWrite(7, HIGH); } else if (StrContains(HTTP_req, "LED2=0")) { LED_state[1] = 0; // save LED state digitalWrite(7, LOW); } // LED 3 (pin 8) if (StrContains(HTTP_req, "LED3=1")) { LED_state[2] = 1; // save LED state digitalWrite(8, HIGH); } else if (StrContains(HTTP_req, "LED3=0")) { LED_state[2] = 0; // save LED state digitalWrite(8, LOW); } // LED 4 (pin 9) if (StrContains(HTTP_req, "LED4=1")) { LED_state[3] = 1; // save LED state digitalWrite(9, HIGH); } else if (StrContains(HTTP_req, "LED4=0")) { LED_state[3] = 0; // save LED state digitalWrite(9, LOW); } } // send the XML file with analog values, switch status // and LED status void XML_response(EthernetClient cl) { int analog_val; // stores value read from analog inputs int count; // used by 'for' loops int sw_arr[] = {2, 3, 5}; // pins interfaced to switches cl.print("<?xml version = \"1.0\" ?>"); cl.print("<inputs>"); // read analog inputs for (count = 2; count <= 5; count++) { // A2 to A5 if (count == 2) //Añadimos este código para escalar las señales analógicas {analog_val = analogRead(count);} if (count == 3) {analog_val = analogRead(count);} if (count == 4) {analog_val = analogRead(count)*5*100/1024;} //Escalamos la entrada para un sensor de temperatura LM35 if (count == 5) {analog_val = analogRead(count)*5*100/1024;} //Escalamos la entrada para un sensor de temperatura LM35 cl.print("<analog>"); cl.print(analog_val); cl.println("</analog>"); } // read switches for (count = 0; count < 3; count++) { cl.print("<switch>"); if (digitalRead(sw_arr[count])) { cl.print("ON"); } else { cl.print("OFF"); } cl.println("</switch>"); } // checkbox LED states // LED1 cl.print("<LED>"); if (LED_state[0]) { cl.print("checked"); } else { cl.print("unchecked"); } cl.println("</LED>"); // LED2 cl.print("<LED>"); if (LED_state[1]) { cl.print("checked"); } else { cl.print("unchecked"); } cl.println("</LED>"); // button LED states // LED3 cl.print("<LED>"); if (LED_state[2]) { cl.print("on"); } else { cl.print("off"); } cl.println("</LED>"); // LED4 cl.print("<LED>"); if (LED_state[3]) { cl.print("on"); } else { cl.print("off"); } cl.println("</LED>"); cl.print("</inputs>"); } // 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; }
El programa que hay que introducir en la microSD de la placa W5100 que nos comunica por Ethernet, debe tener el nombre «index.htm». Podremos activar las salidas y recibir la información de las entradas digitales y analógicas desde cualquier lugar del mundo.
<!DOCTYPE html> <html> <head> <title>Arduino</title> <script> strLED1 = ""; strLED2 = ""; strLED3 = ""; strLED4 = ""; var LED3_state = 0; var LED4_state = 0; function GetArduinoIO() { nocache = "&nocache=" + Math.random() * 1000000; var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200) { if (this.responseXML != null) { // XML file received - contains analog values, switch values and LED states var count; // get analog inputs var num_an = this.responseXML.getElementsByTagName('analog').length; for (count = 0; count < num_an; count++) { document.getElementsByClassName("analog")[count].innerHTML = this.responseXML.getElementsByTagName('analog')[count].childNodes[0].nodeValue; } // get switch inputs var num_an = this.responseXML.getElementsByTagName('switch').length; for (count = 0; count < num_an; count++) { document.getElementsByClassName("switches")[count].innerHTML = this.responseXML.getElementsByTagName('switch')[count].childNodes[0].nodeValue; } // LED 1 if (this.responseXML.getElementsByTagName('LED')[0].childNodes[0].nodeValue === "checked") { document.LED_form.LED1.checked = true; } else { document.LED_form.LED1.checked = false; } // LED 2 if (this.responseXML.getElementsByTagName('LED')[1].childNodes[0].nodeValue === "checked") { document.LED_form.LED2.checked = true; } else { document.LED_form.LED2.checked = false; } // LED 3 if (this.responseXML.getElementsByTagName('LED')[2].childNodes[0].nodeValue === "on") { document.getElementById("LED3").innerHTML = "SALIDA 8 ON "; LED3_state = 1; } else { document.getElementById("LED3").innerHTML = "SALIDA 8 OFF "; LED3_state = 0; } // LED 4 if (this.responseXML.getElementsByTagName('LED')[3].childNodes[0].nodeValue === "on") { document.getElementById("LED4").innerHTML = "SALIDA 9 ON "; LED4_state = 1; } else { document.getElementById("LED4").innerHTML = "SALIDA 9 OFF "; LED4_state = 0; } } } } } // send HTTP GET request with LEDs to switch on/off if any request.open("GET", "ajax_inputs" + strLED1 + strLED2 + strLED3 + strLED4 + nocache, true); request.send(null); setTimeout('GetArduinoIO()', 1000); strLED1 = ""; strLED2 = ""; strLED3 = ""; strLED4 = ""; } // service LEDs when checkbox checked/unchecked function GetCheck() { if (LED_form.LED1.checked) { strLED1 = "&LED1=1"; } else { strLED1 = "&LED1=0"; } if (LED_form.LED2.checked) { strLED2 = "&LED2=1"; } else { strLED2 = "&LED2=0"; } } function GetButton1() { if (LED3_state === 1) { LED3_state = 0; strLED3 = "&LED3=0"; } else { LED3_state = 1; strLED3 = "&LED3=1"; } } function GetButton2() { if (LED4_state === 1) { LED4_state = 0; strLED4 = "&LED4=0"; } else { LED4_state = 1; strLED4 = "&LED4=1"; } } </script> <style> .IO_box { float: left; margin: 0 20px 20px 0; border: 1px solid blue; padding: 0 5px 0 5px; width: 120px; } h1 { font-size: 120%; color: blue; margin: 0 0 10px 0; } h2 { font-size: 85%; color: #5734E6; margin: 5px 0 5px 0; } p, form, button { font-size: 80%; color: #252525; } .small_text { font-size: 70%; color: #737373; } </style> </head> <body onload="GetArduinoIO()"> <h1>Arduino</h1> <div class="IO_box"> <h2>Entradas analógicas</h2> <p>A2: <span class="analog">...</span></p> <p>A3: <span class="analog">...</span></p> <p>Tª interior: <span class="analog">...</span>ºC</p> <p>Tª exterior: <span class="analog">...</span>ºC</p> </div> <div class="IO_box"> <h2>Entradas</h2> <p>Entrada 2: <span class="switches">...</span></p> <p>Entrada 3: <span class="switches">...</span></p> <p>Entrada 5: <span class="switches">...</span></p> </div> <div class="IO_box"> <h2>Salidas</h2> <form id="check_LEDs" name="LED_form"> <input name="LED1" value="0" onclick="GetCheck()" type="checkbox">Salida 6<br> <br> <input name="LED2" value="0" onclick="GetCheck()" type="checkbox">Salida 7<br> <br> </form> </div> <div class="IO_box"> <h2>Salidas</h2> <button type="button" id="LED3" onclick="GetButton1()">SALIDA 8 OFF </button><br> <br> <button type="button" id="LED4" onclick="GetButton2()">SALIDA 9 OFF </button><br> <br> </div> </body> </html>