Display Analógico con JavaScript

Objetivos

 

  • Presentar un ejemplo de HTML y JavaScript.
  • Mostrar el valor e A2 en un reloj como display .
  • Presentar un componente reusable de representación de valores.
  •  

    Material requerido.

     

    Imagen de Arduino UNO  Arduino Uno o similar.
    Vista principal Un Ethernet shield R3
    Vista principal Un potenciómetro de 10K

     

    La ventaja de disponer de una SD Card

     

    Disponer de un lector de tarjetas SD nos abre una cantidad de posibilidades inmensas, en cuanto a las cosas que podemos hacer con nuestros Arduinos, porque nos abre la puerta a utilizar código externo, tanto HTML como ya vimos en alguna sesión anterior, como a utilizar javascript. Y esto merece una pequeña explicación.

    Hasta ahora, todo el código HTML que hemos ido viendo lo generaba nuestro Arduino y a través del web server interno se lo mostraba al cliente web que se conectase a él.

    Al tener que generar el código con print (), suponía que todo el código que escribiéramos tenía que ir dentro del sketch de Arduino, lo que en la práctica eliminaba la posibilidad de usar un UNO y teníamos que usar automáticamente un MEGA porque los modelos sencillos de Arduino carecen de la capacidad de memoria necesaria para esto.

    Pero al disponer de la tarjeta SD, en principio, podemos pasar buena parte del código HTML a ficheros en la SD, lo que nos permite descargar parte del programa, y además por otra parte nos podemos plantear usar código JavaScript para hacer cosas adicionales.

    Yo no soy la persona adecuada para hablar de JavaScript porque no lo he usado nunca, pero por lo que he visto la sintaxis es muy  próxima a la de C++, que ya conocemos, lo que parece indicar que la curva de aprendizaje no sería muy empinada si decidimos meternos con él.

    Para los que podáis seguir unos tutoriales en ingles sobre Arduino, HTML y java, un buen sitio para empezar es la página de starting electronics, que tiene unos excelentes tutoriales (de donde he sacado el ejemplo que vamos a ver hoy), sobre estos temas y basados en el shield Ethernet que os recomiendo. La dirección es:

    http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/

    La ventaja del JavaScript es que se ejecuta en el navegador que nos consulta, con lo que nuestro Arduino queda libre para corretear por ahí haciendo sus cosas, sin preocuparse del mundo exterior y nos esto nos permite hacer algunas cosas sorprendentes.

    En esta sesión, vamos a generar con JavaScript un reloj analógico (Gauge) que muestre el valor de una lectura analógica que leemos del pin A2. El resultado es una página web que muestra las variaciones en tiempo real del valor que leamos en A2, con el reloj que veis a continuación.

    Miniatura blog

     

    Esquema para protoboard

     

    El circuito va a ser muy sencillo. Simplemente montar un potenciómetro conectado al pin A2 para leer su valor.

    Arduino, Ethernet y potenciomentro

     

    El programa de control

     

    Vamos a utilizar un reloj analógico o galga (gauge) para representar el valor que leemos en cada instante en la puerta analógica A2.

    El reloj está escrito en JavaScript  con HTML5, y lo utilizamos simplemente como un componente estándar que puedes usar en tus propios proyectos. El valor del reloj se actualiza cada 200 ms.

    Destacar aquí que no pretendemos tener el menor mérito en este programa y componente. EL desarrollo original es de Mykhailo Stadnyk y aquí vamos a utilizar la versión sin modificar, de starting electronics, que os mencionamos en el apartado anterior

    Cualquier defecto es nuestro, pero los méritos son sin duda de ellos.

    El programa tiene dos partes diferenciadas. Un sketch para Arduino y un par de ficheros para que copies en la tarjeta SD, con el programa JavaScript. Descomprime este fichero y copia sus dos archivos (gauge_license.txt e index.htm)  al directorio raíz de una tarjeta SD limpia sin nada más:

    Arduino_web_gauge.zip (6.3 kB)

    Después, necesitas cargar este programa en tu Arduino Prog_66_1. Cambia simplemente la dirección IP si no se acomoda a tu rango.

    Aquí os pongo un listado pulido del programa. Veréis que utiliza el mismo esquema básico de control de peticiones HTTP que utilizamos en los programas anteriores.

    #include <SPI.h>
    #include <Ethernet.h>
    #include <SD.h>
    #define REQ_BUF_SZ   50    // Buffer para las peticiones HTTP
    
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1,177); // Pon aqui una IP de tu rango
    EthernetServer server(80);
    File webFile;               // El fichero de la pagina web en la SD card
    
    char HTTP_req[REQ_BUF_SZ] = {0};
    char req_index = 0;
    
    void setup()
       {  pinMode(10, OUTPUT);
          digitalWrite(10, HIGH);
          Serial.begin(9600);       // for debugging
          Serial.println("Initializing SD card...");
          if (!SD.begin(4))
             {   Serial.println("ERROR - Fallo al inicar SD card!");     
                 return;    // init failed
             }
          Serial.println("SUCCESS - SD card initialized.");
          if (!SD.exists("index.htm")) 
             { Serial.println("ERROR - No encuentro 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()
       {  EthernetClient client = server.available();
          if (client)
             {  // Si tenemos cliente
                boolean currentLineIsBlank = true;
                while (client.connected()) 
                 { if (client.available())    // Hay algo pendiente de leer
                    {  char c = client.read();
                       if (req_index < (REQ_BUF_SZ - 1))
                         {   HTTP_req[req_index] = c;   // Montar la peticion HTTP
                             req_index++;
                         }
                       if (c == '\n' && currentLineIsBlank)
                         {   client.println("HTTP/1.1 200 OK");
                             if (StrContains(HTTP_req, "ajax_inputs"))
                                { client.println("Content-Type: text/xml");
                                  client.println("Connection: keep-alive");
                                  client.println();
                                  // send XML file containing input states 
                                  XML_response(client);
                                }
                       else
                           {  client.println("Content-Type: text/html");
                              client.println("Connection: keep-alive");
                              client.println();
                              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();
                                 }
                           }
                       Serial.print(HTTP_req);
                       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')
                        currentLineIsBlank = true;
                    else if (c != '\r')
                        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 XML file containing analog value
    void XML_response(EthernetClient cl)
       { int analog_val;
         cl.print("<?xml version = \"1.0\" ?>");
         cl.print("<inputs>");
         // read analog pin A2
         analog_val = analogRead(2);
         cl.print("<analog>");
         cl.print(analog_val);
         cl.print("</analog>");
         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 resultado es espectacular. Aquí os dejo un minivideo conel montaje y a ver que os parece:

     

    Y por si hablaís JavaScript, aquí teneis el programa que hay en index.htm

    <!DOCTYPE html>
    <html>
       <head>
           <title>Arduino Ajax Dial</title>
           <script>
            var data_val = 0;
            eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseIn…..
            function GetArduinoInputs()
              {
                 nocache = "&nocache=" + Math.random() * 1000000;
                 var request = new XMLHttpRequest();
                 request.onreadystatechange = function()
                  {
                      if (this.readyState == 4) {
                          if (this.status == 200) {
                              if (this.responseXML != null) {
                                  document.getElementById("input3").innerHTML = this.responseXML.getElementsByTagName('analog')[0].childNodes[0].nodeValue;
                                  data_val = this.responseXML.getElementsByTagName('analog')[0].childNodes[0].nodeValue;
                              }
                           }
                       }
                  }
                  request.open("GET", "ajax_inputs" + nocache, true);
                  request.send(null);
                  setTimeout('GetArduinoInputs()', 200);
              }
           </script>
       </head>
       <body onload="GetArduinoInputs()">
        <h1>Arduino Ajax Dial</h1>
        <p>Analog (A2): <span id="input3">...</span></p>                 
        <canvas id="an_gauge_1" data-major-ticks="0 100 200 300 400 500 600 700 800 900 1000 1023" data-type="canv-gauge" data-min-value="0" data-max-value="1023" data-onready="setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(data_val);}, 200);">
        </canvas>
    </body>
    </html>

     

    Resumen de la sesión

     

  • Hemos presentado u ejemplo de cómo cargar código HTML o Java desde la tarjeta SD de nuestro Shield Ethernet.
  • Hemos presentado un componente excepcional para mostrar valores de vuestros sensores en una página web, mediante un pequeño código JavaScript.
  •  

    Deja una respuesta