bclose

Display Analógico con JavaScript

Mostrando un reloj 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 equivalente.
Shield Ethernet
Un Shield Ethernet

 

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.

 

 

 

 

 

 

(7) Comments

    • Milka

    Excelente el trabajo que realizas. Con respecto a esto tengo una pequeña duda, se puede escribir en el propio sketch del arduino con JavaScript???
    Mil gracias de antemano por tus respuestas, he estado leyendo varios de tus tutoriales para aprender de Arduino.

    • Milka

    Hola, excelentes tutos, solo una sugerencia, seria bueno si colocaran mas imágenes de los resultados, por lo menos de como se vería la pagina html, los montajes, etc.

    • Abraham

    hola! Me asalta una duda… En el caso de que la memoria no fuese suficiente, no se podría ejecutar el arranque del UNO y hacerle leer/escribir posiciones de memoria de la SD con las instrucciones de nuestro codigo? Así por ejemplo se podría usar el UNO para el control de domotica del ejemplo anterior.
    Salu2

    • Seguro que podriamos Abraham, pero me da la sensacion que daria mucho mas trabajo del que merece la pena y por eso prefiero usar un MEGA

    • David Rivera

    hola!
    primero felicitarte por tu exelente pagina, la cual me a ayudado mucho con el tema de familiarizarme con arduino.
    ahora queria consultarte si tu crees q seria posible montar una pagina weab desde arduino q me muestre graficos del comportamiento de un sensor a travez del tiempo, y que ademas se pueda ejecutar un control on off desde esta misma.

    gracias por tus aportes, saludos!

    • Ricardo

    Un excelente tip!

    Saludos

Give a Reply

WordPress Anti-Spam by WP-SpamShield