viernes, 8 de mayo de 2015

Termometro diario ( I )

Recuperamos el hilo donde lo dejamos hace ya unos días. Espero que las circunstancias personales me permitan continuar con el ritmo anterior.
Recordemos el último post, donde realizábamos un termómetro con una pantalla LCD de 16x2, que nos mostraba la temperatura.
Vamos a ir un poco más allá, y empezaremos a realizar proyectos que nos permitan interactuar con la información que nos presentan, y a procesar la información según nos convenga.
La propuesta, que atenderemos en varias entradas, es confeccionar un termómetro que guarde un registro de 24 muestras diarias a intervalos de una hora, y que las muestre a voluntad del usuario. Informando también de la temperatura media, mínima y máxima. También debe permitir resetear los valores tomados.

Casi nada.

El interfaz de usuario lo haremos con una pantalla LCD de 16X2 y dos pulsadores. Uno servirá para mostrar la información y además confirmar el borrado de datos. El otro pulsador lanzará el menú de reseteo de muestras, y desestimará la opción de borrar los datos.
La temperatura la calcularemos con nuestro ya conocido TMP-36.

El hardware es bien sencillo, pero para resolver posibles dudas y aclarar el tema de las entradas usadas , mi propuesta es esta.


Una de las primeras dificultades que nos encontramos es donde almacenar las 24 muestras que iremos tomando a lo largo del tiempo. Mi propuesta para resolverlo es a través de una matriz o ARRAY, vamos a ello.

Arrays[]

Un array, o matriz, es un conjunto de valores a los cuales se puede acceder a través de un índice. El primer valor de una matriz está indicado con el numero 0.

Hay varias formas de declarar una matriz. Veamos unos ejemplos:


int array1[5];

int array2[] = {1,3,5,7,9}

int array3[5] = {1,3,5,7,9}




En el caso del array1, declaramos un array de 5 elementos tipo integer (se puede escoger cualquier tipo de variable flor, double,string) , pero no asignamos valores, ya lo haremos más adelante, en cualquier punto del sketch.



El array2, declaramos un array, sin especificar la dimensión, pero sí que les asignamos unos valores. Por tanto a la hora de compilar, leerá el número  de valores y creará un array de dimensión igual al número de valores.



En el ejemplo del array3, declaramos la dimensión del array, y los valores que le asignaremos.

Como ya he comentado el primer índice de una matriz es el 0, por tanto :




int array3[5] = {1,3,5,7,9}

// array3[0] Contiene el valor 1
// array3[4] Conetiene el valor 9
// array3[5] No existe y producir´a un error


Una de las dificultades de los array, es que indexar en lenguaje C un valor "imposible" como el del ejemplo no genera un error, y puede ser un fallo complicado de detectar.

Para asignar un valor a un array, se debe indicar la posición y el valor que queremos guardar. Hay que tener cuidado con asignar valores del mismo tipo del que se ha creado el array, y tener en cuenta que machacaremos el valor que hubiese.




Así cambiar el valor 5 por un 4 tendría la siguiente sintaxis:



    
array3[2] = 4;



Es decir, el numero cinco , que ocupa la posición 2 ( recordad que se empieza contando desde 0), le asignamos el número 4.


Otra utilidad es asignar a una variable el valor de una posición en concreto. ¿Cómo? Pues si queremos asignar a la variable dato el valor de la posición 3:

        dato = array3[3]; // array3[3] Contiene el valor 7



Para el ejemplo que nos ocupa, usaremos el array como si se tratara de una variable circular. Este es uno de los usos más comunes que se le da a este tipo de variable. 

Definiremos un bucle que va rellenando la matriz con los valores captados, y cuando llega al último empieza desde el principio. Si queremos tomar muestras de temperaturas máxima , mínima y media de un día, lo haremos con un array de 24 posiciones.


Esta parte del cuerpo del programa podría quedar algo parecido a esto:



...
...
...


float tempdata [24];//array de tipo float para 24 muestras hora
...
...
...
for (int i=0; i<=23; i++)//Bucle que nos permite tomar 24 muestras
  {
  sensor = analogRead(0); //Sensor TMP36 en pin analogico 0 
  voltaje = (sensor*5000)/1024; //operaciones necesarias
  voltaje = voltaje-500;        // para calculo de temperatura
  tempactual = voltaje/10;  
  tempdata[i]=tempactual;// Grabamos en la posición iesima  del array
                          // la temperatura calculada
  delay (360000); retardo de 1 hora entre muestras
}
...
...
...







Obviando la parte del programa que realiza el cálculo, que ya está explicada aquí, vemos como declaramos una variable array para 24 valores float.

Luego definimos un bucle de 0 a 23, para grabar en cada posición el valor de temperatura obtenido. 

Establecemos un delay de una hora con el fin de conseguir una muestra horaria que es lo que estamos buscando. 

Pero....


¿Que sucederá si aplicamos un delay de una hora? Pues eso, que durante una hora nuestro arduino no atenderá ninguna de sus entradas-salidas, porque estará esperando. Vamos que así no nos sirve.

Sí que hay una manera de interrumpirlo, y es usar uno de los pies de entrada (depende del modelo de Arduino usado), como una interrupción, que saque del delay al equipo. De todas maneras es un método que no me gusta para este ejemplo por lo que lo resolveremos de otra manera.

¿Cómo?

Pues con el uso de la función milis(). Ya la explicamos brevemente en su día en esta entrada

Un breve repaso, esta función cuenta el tiempo que ha pasado desde que se puso en marcha nuestro Arduino. Podemos contar en cada bucle el tiempo pasado y tomar muestras si es mayor de una hora respecto la muestra anterior. Esto nos permitirá con el código necesario, atender también los pulsadores del interfaz de usuario. 

Esta modificación también repercute en el bucle que recorre el array para grabar las muestras. Ahora será necesario crear un "puntero" que indique la posición del array que queremos grabar. Es importante que se mueve solo ente las posiciones 0-23, de lo contrario el comportamiento sería inesperado. 

¿Cómo quedaría el bloque anterior con la modificación?

...
...
...
unsigned long tiempoentremuestras=0; // reseteamos contadores de tiempo
unsigned long tiempomuestraanterior=0;// Este tambien
int posicion=0;//indice o puntero que recorrera el array
...
...


void loop() 

{
  ...
  ...

 tiempomuestraanterior=millis();// leemos el tiempo trasncurrido
 if( tiempomuestraanterior-tiempoentremuestras>360000)//Una hora

 {
  sensor = analogRead(2);       // TMP36 sensor  pin 0
  voltaje = (sensor*5000)/1024; // Calculos necesarios para tempertura
  voltaje = voltaje-500;   // Calculos necesarios para tempertura    
  tempactual = voltaje/10;    // Calculos necesarios para tempertura
  ...
  tempdata[posicion]=tempactual;// Grabamos en el array el dato
  posicion=posicion+1;// Incremetamos el puntero para la siguiente posici´n
  tiempoentremuestras=tiempomuestraanterior;// Resetamos el "cronometro"
  }
  
  if (posicion > 23)
   {posicion=0;} // Volvemos el puntero a 0 cuando pase de la posicion 23
   
...
...
}


¿Alguna duda este bloque? Los nombres de las variables son un tanto extensos, pero nos ayudará a entender mejor el funcionamiento del programa.

Hasta aquí la entrada de hoy. Con esto tenemos resuelto el grabar muestras de temperatura a intervalos de una hora durante un día. Pasadas 24 horas el programa irá machacando la primera muestra, y así sucesivamente, con lo que tendré siempre los datos de las últimas 24 horas.

En la proxima entrada trabajaremos el interfaz de usuario y como conseguir mostrar la información. Gracias por vuestra atención.

Nos vemos!




No hay comentarios:

Publicar un comentario