Mostrando entradas con la etiqueta termometro. Mostrar todas las entradas
Mostrando entradas con la etiqueta termometro. Mostrar todas las entradas

viernes, 22 de mayo de 2015

Termómetro diario ( II )

Sigamos con el ejemplo del día anterior. Después de completar en casa el ejemplo, el código tenía una complejidad considerable. Bueno, para ser más exactos, más que complejo empezaba a tener unas dimensiones considerables, y la programación tal y como la hemos visto hasta ahora, hacía muy complicado e ininteligible el código del programa.

Por lo que he decido hacer un bloque principal para el cuerpo del programa, y diferentes "subprogramas" que realizarán los cálculos necesarios , o las acciones complementarias que iremos describiendo.

Estos "subprogramas" reciben el nombre de funciones.

Uso de funciones con Arduino

Aunque pueda parecer algo nuevo, ya hemos usado funciones en nuestros sketches de Arduino, son las funciones void setup y void loop, que además son de uso obligatorio.

Las funciones personalizadas se han de declarar siempre después del void loop. A partir de aquí existen diferentes formas de trabajar según si la función debe devolver valores ( el resultado de una operación), o simplemente ejecutar una parte del código.

Mejor un ejemplo:


void setup() {
  Serial.begin(9600);
}

void loop()
{
  int a = 2;
  int b = 3;
  int c;

  c = FuncionMultiplicarNumeros(a, b); // C vale 6
  Serial.println(c);
  delay(500);
}

int FuncionMultiplicarNumeros(int x, int y) 
{
  int resultado;
  resultado = x * y;
  return resultado;
}







En este ejemplo, declaramos una función del tipo integer. Le pasamos dos valores a y b  , que queremos que multiplique. Para ello, dentro de la función definimos dos variables más, las variables x  e Y, que usaremos para realizar los cálculos, y que solo serán validos dentro de la función de multiplicar.
Una vez realizada la operación devolvemos el resultado con la función return

¿ Se entiende? No verdad, yo tampoco lo entendí a la primera, por lo que a veces es mejor coger lápiz y papel y dibujar el baile de variables. 

Algunas de las FAQ's que comúnmente surgen tras el ejemplo es, ¿para qué tantas variables para multiplicar dos números? Bien, si solo tengo que multiplicar dos números, hasta el uso de funciones es un poco exagerado, pero definir las variables dentro de la función me permite "mandarle" cualquier pareja de valores en cualquier punto del programa.
En codigos más complejos también sirve para tener un programa más estructurado y nos permite ir programando bloques. Incluso, si trabajaremos en equipo para miembro podría hacerse cargo de programar una función concreta.

Un uso más sencillo, usar las variables definidas en el cuerpo del programa

Algo así:







void setup() {
  Serial.begin(9600);
}

void loop()
{
  int a = 2;
  int b = 3;
  int c;

  c = FuncionMultiplicarNumeros(); // C vale 6
  Serial.println(c);
  delay(500);
}

int FuncionMultiplicarNumeros() 
{
 c = a * b;;
}


Obtendría el mismo resultado, pues usaría las variables que se han declarado de manera global, pero solo me permitiría multiplicar los valores a y b. De la primera manera, insisto me permitirá obtener el resultado de diferentes valores.

Aprovechad, para tomar un respiro, ir al baño o beber algo de líquido antes de seguir.

De vuelta ya, os voy a colocar el código completo del ejercicio. Tomaros un tiempo en ver que hace cada función y entender porque se llaman en cada momento.

También se podría hacer una función para leer las pulsaciones de los botones, pero eso lo dejo en vuestras manos.

Para que en cualquier momento me pueda ofrecer una temperatura media, mínima o máxima coherente, antes de nada, en el void setup, inicializo TODOS los valores de la matriz con la primera muestra de temperatura. Es sólo un criterio, y cualquier otro podría ser válido. No olvides cambiar en el bucle milllis el 1000 por 360000 para obtener las muestras cada hora.




#include <LiquidCrystal.h>

LiquidCrystal lcd(4, 5, 6, 7, 8, 9);

float tempactual = 0; //mostrara la temperatura actual
float tempmin = 0; // VAlor minimo obtenido
float tempmax = 0; // el maximo
float tempmedia = 0; // y el minimo
float sensor = 0; 
float voltaje = 0;

int boton1 = 2; // Pulsador de Reset en el pin 2
int boton2 = 3; // El de set o show en el pin 3
int pulsacion = 0; // Necesaria para ller estado del pulsador
int accion = 0; // Truco para mantenerme en el bucle de la pulsacion
int posicion = 0; // Indicador o puntero de la matriz de Temperatura
float temperatura; // Para almacenar temperatura
float tempdata [24]; //Array para almacenar las muestras
unsigned long tiempoentremuestras = 0; // necesarias para los intervalos de
unsigned long tiempomuestraanterior = 0;// tiempo

void setup() {

  Serial.begin(9600);
  lcd.begin(16, 2); // Dimensiones de la pantalla
  lcd.setCursor(0, 0);
  lcd.print("    Arduino    ");//Para mi autoestima
  lcd.setCursor(0, 1);
  lcd.print("*   Practico   *"); // Pero lo puedes cambiar ;)
  delay(3000);
  lcd.clear();
  pinMode (boton1, INPUT);
  pinMode (boton2, INPUT);
  Calculo_temperatura(); // Medimos la temperatura
  Reset_Temp(); // E iniciamos las variables con la primera muestra
  
}

void loop()

{

  tiempomuestraanterior = millis();
// PAra muestras horarias sustituir el 1000 por 360000

// Cogemos muestras y vamos rellenado el array con los valores

  if ( tiempomuestraanterior - tiempoentremuestras > 1000)
  {

    Calculo_temperatura ();
    tempdata[posicion] = temperatura;
    posicion = posicion + 1;
    tiempoentremuestras = tiempomuestraanterior;

  }

  if (posicion > 23)
  {
    posicion = 0;
  }
  
  // Mostramos en pantalla la temperatura actual
  
  show_temperatura();

  // Empezamos el bloque para leer los pulsadores
  
  pulsacion = digitalRead(boton2);

// SI pulsamos mostramos las ultimas 24 muestras
// y los valores calculados

  if ( pulsacion == HIGH)

  {
    pulsacion = 0;
    Calculo_Tmax_Tmin_Tmedia();// llamada a la funcion de calculos
    lcd.clear(); // clear LCD screen
    lcd.setCursor(0, 0);
    lcd.print("Las ultimas 24");
    lcd.setCursor(0, 1);
    lcd.print("muestras son:");
    delay(1000);
    for (int j = 0; j <= 23; j++)
    {
      lcd.clear(); //
      lcd.setCursor(0, 0);
      lcd.print("Muestra: ");
      lcd.print(j + 1);
      lcd.print("/24  ");
      lcd.setCursor(0, 1);
      lcd.print(tempdata[j], 2);
      lcd.print(" grados C");
      delay(500);
    }
    lcd.clear(); // clear LCD screen
    lcd.setCursor(0, 0);
    lcd.print("Tmin  Tmed  TMax");
    lcd.setCursor(0,1);
    lcd.print(tempmin,1);
    lcd.setCursor(6, 1);
    lcd.print(tempmedia,1);
    lcd.setCursor(12, 1);
    lcd.print(tempmax,1);
    delay (3000);
    lcd.clear();
  }

// Lectura del pulsador de Reset

  pulsacion = digitalRead(boton1);
  if (pulsacion == HIGH)
  {
    pulsacion = 0;
    accion = 0;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Reset min/max?");
    lcd.setCursor(0,1);
    lcd.print("1 = Yes, 2 = No");
    delay(500); // Tiempo para evitar rebotes
    while (accion == 0) // Aun no ha pasado nada
    {
      if (digitalRead(boton1)==HIGH)  // Ha pulsado si?
      {
        Reset_Temp();
        accion = 1;// Ha pasado algo y por tanto puedo salir del loop
        delay(500); // Tiempo para evitar rebotes
      }
      if (digitalRead(boton2)==HIGH) // Ha pulsado no?
      {
        accion = 1; // Ha pasado algo y por tanto puedo salir del loop
        delay(500); // Tiempo para evitar rebotes
      }

    } 
    lcd.clear();
  }




}

void Calculo_temperatura()

{

  sensor = analogRead(2);       // TMP36 sensor  pin 0
  voltaje = (sensor * 5000) / 1024;
  voltaje = voltaje - 500;
  temperatura = voltaje / 10;

}

void Calculo_Tmax_Tmin_Tmedia()
{
  for (int j = 0; j <= 23; j++)
  {
    if (tempdata[j] < tempmin)
    {
      tempmin = tempdata[j];
    }
    else if (tempdata[j] > tempmax)
    {
      tempmax = tempdata[j];
    }
  }
  tempmedia=0;
  for (int j = 0; j <= 23; j++)
  {
    tempmedia=tempmedia+tempdata[j];
  }
  tempmedia=tempmedia/24;
    
}


void show_temperatura()
{

  lcd.setCursor(0, 0);
  lcd.print("Temp actual");
  lcd.setCursor(0, 1);
  lcd.print(temperatura);
  lcd.print(" grados C");
  delay(1000);
}

void Reset_Temp() // Restablecemos todos los valores con el ultimo valor
{  
  tempmin = temperatura;
  tempmax = temperatura;
  for (int j = 0; j <= 23; j++)
  {
    tempdata[j] = temperatura;
  }
}


Si os resulta más cómodo lo podéis descargar desde aquí.

Os dejo un video con el funcionamiento del proyecto. Nos vemos!!







viernes, 27 de marzo de 2015

Termómetro LCD

Termometro LCD


En esta entrada vamos aprovechar nuestro montaje "estrella" del termómetro con un TMP36, para explicar el uso de una pantalla LCD.

Como podeis apreciar en la fotografia la pantalla consta de 16 pins que explicaremos brevemente a continuación.



El esquema de conexiones:


Siendo los pines en orden del 1 al 16, los siguientes:

  1. VSS, o GND
  2. VCC, 5 Volts, (comprobarlo en el datasheet, pues hay fabricantes que usan 3,3V)
  3. Contraste, (llevarlo al puntero de un potenciómetro de 10K para ajustar) 
  4. RS
  5. RW
  6. Enable,
  7. DB0, (de DB0...DB7), se usan para transmisión de datos
  8. DB1
  9. DB2
  10. DB3
  11. DB4
  12. DB5
  13. DB6
  14. DB7
  15. LED+, alimentación positiva para la retroiluminación.( no para todas las pantallas)
  16. LED-, GND para la retroiluminación. 
La pantalla del ejemplo tiene retroiluminación y funciona a 5V. Por tanto el esquema de conexión será el siguiente:



Estas pantallas pueden funcionar con 4 u 8 líneas de datos. Para la aplicación que nos ocupa, y para la mayoría, con cuatro tendremos suficientes.


Para este ejemplo, y otros que seguirán con este tipo de display, usaremos una pantalla compatible con el chipset de HITACHI HD44780. En este ejemplo, usaremos una pantalla de 16x2, es decir, 2 líneas de 16 caracteres cada una.

El motivo de usar este tipo de  pantalla compatible, es el de usar una librería ya creada para el entorno Arduino, que tendremos que llamar con una línea como ésta al principio de nuestro sketch.


#include <LiquidCrystal.h> //libreria necesaria para el uso del LCD


Esta librería facilita enormemente la gestión de la pantalla, y realizar las operaciones más habituales, con unos sencillos comandos. Una vez incluida la librería, deberemos crear una variable para el LCD, definiendo los pines a los cuales la hemos conectado.
Por orden serán, RS, Enable, D4, D5, D6 y D7.

LiquidCrystal lcd(4,5,6,7,8,9);


Por último, y para terminar de configurar la pantalla deberemos incluir en el void setup{} la siguiente instrucción:

lcd.begin(16,2);

Esta instrucción configura nuestra pantalla LCD de 16 columnas y 2 filas, definida previamente como variable lcd.

Veamos ahora algunas de las instrucciones que usaremos en nuestro ejemplo. 

   lcd.clear();


Con esta instrucción , borramos el contenido de la pantalla.

 
  lcd.setCursor(0,0);


Sirve para posicionar el cursor donde queremos emplazar el texto. Para colocarlo en la primera línea entre paréntesis usaremos los valores (0,0). Para colocarlo en el inicio de la segunda fila, la instrucción debe ser (0,1).


  lcd.print("Temperatura:");


Escribe el texto entre parentesis. Funciona igual que la instrucción print, escribiendo tal cual el texto que se encuentra entre las comillas .


  lcd.print(Temperatura);


Presenta el valor de la variable Temperatura.

Pues estas son las nociones básicas que deberían ser suficientes para completar esta primera parte del ejercicio propuesto. Si recuperamos de esta entrada, y sustituimos las líneas que muestran el resultado  en el serialmonitor, por las LCD , y configuramos la pantalla, deberíamos conseguir finalizar el ejercicio....

Que no lo conseguimos, de acuerdo  pues os muestro mi propuesta, que podéis descargar desde aquí.


/* Ejemplo practico para mostrar la temperatura de un TMP-36
en una pantalla LCD. La explicacion necesaria la encontramos
aqui http://arduinopractico.blogspot.com.es
 */
 
#include <LiquidCrystal.h> //libreria necesaria para el uso del LCD

LiquidCrystal lcd(4,5,6,7,8,9);// definicion de los pins conectados al 
// Arduino, por este orden RS, Enable, D4, D5, D6 y D7.

void setup() 
{
  Serial.begin(9600); // Iniciamos puerto serie, solo necesario si usamos PC 
  lcd.begin(16, 2); // Definimos el tamaño de pantalla que usaremos
  lcd.setCursor(0,0);// Posicionamos el cursor enel punto 0
  lcd.print("Arduino practico"); // Imprimimos nuestro logo...usad el vuestro
  lcd.setCursor(0,1);// vamos a la segunda linea
  lcd.print("*Termometro LCD*"); // Y explicamos que haremos
  delay(3000); //Esperamos 3 segundos para dar tiempo a leerlo
  lcd.clear(); // Y borramos la pantalla
}

float temperatura = 0; // Variable para leer la temperatura

void loop()
{
  
  delay(200);
    temperatura = analogRead(0);           // Lectura del TMP36 en pin0
    temperatura = (temperatura*5000)/1024; // Convertimos el valor en milivolts
    temperatura = temperatura-500;         // Restamos el offset de 0.5V
    temperatura = temperatura/10;          // Convertimos los milivolts en º Celsius
    lcd.clear();              // Borramos pantalla
    lcd.setCursor(0,0);       // vamos al inicio de la primera linea
    lcd.print("Temperatura"); // Mostramos el texto temperatura
    lcd.setCursor(0,1);       // Saltamos a la segunda linea
    lcd.print(temperatura,2); // mostramos la  temperatura con 2 digitos decimales
    lcd.print("C");           // la unidad de medida, grados Celsius
    delay(1000);              //
}


Os dejo con unas imágenes del montaje, y del resultado en pantalla que obtendréis.


Y funcionando:



Nos vemos.



domingo, 15 de marzo de 2015

Trabajando con servos (II). Termómetro analógico

Hola de nuevo.

Ya vimos el día anterior como mover un servo en función del valor leído en una resistencia. En otra entrada anterior, también vimos como usar un sensor de temperatura.

Bien, pues hoy vamos a montar un termómetro analógico juntando estos dos proyectos.

Antes de nada , para nuestro sketch necesitaremos definir las dos temperaturas extremas que querremos mostrar, nuestro máximo y mínimo. Aquí no os puedo ayudar, no es lo mismo Burgos que Sevilla. Yo he usado un rango que va de -15ºC a +45ºC, aunque reconozco que nunca he visto nada parecido por estos lares.

El circuito a implementar es muy sencillo. Vamos a utilizar un sensor de temperatura TMP-36, y un servomotor, además de nuestra placa de Arduino compatible.

Los conectaremos siguiendo el siguiente esquema:


Un ejemplo de como quedaría en placa:


El sistema que he utilizado para mostrar la temperatura, es un tanto, sencillo, pero nos servirá para la ocasión. Aún es más sencillo como he fijado el servo a la escala de temperaturas, pero este ejemplo tiene solo fines demostrativos.


Y la fijación:



De acuerdo, después de haber demostrado que las artes plásticas no son lo mío, vamos a explicar el sketch que hará que por lo menos el funcionamiento sea correcto.

Antes de nada, deberíamos conocer cuales son los parámetros de tiempo que llevan nuestro servo a su posición de 0º y de 180º. Una ojeada a esta entrada debería ser suficiente para aclarar las ideas.

De todas maneras podeis cargar este programa e ir sustituyendo los valores, valormin y valormax, hasta encontrar los que se ajusten. Recordad cargar el programa, y anotar los valores correctos.


// Programa para encontrar los valores en ms limites de un servo

#include <Servo.h> // instruccion para incluir la libreria en el sketch
 
Servo myservo;  // creamos el objeto servo, para luego controlarlo
 
int valormin=450;  //valor minimo en ms para conseguir los 0º
int valormax=2100; // valor maximo en ms para llegar a los 180º
int grados;
void setup() 
{ 
  myservo.attach(9,valormin,valormax);  // Pin conectado al servo 
} 
 
void loop() 
{ 
  grados=0; //lo llevamos a minimo y observamos si ratea
  myservo.write(grados);       // esta instrucción envía al servo a la 
                               //posición indicada en grados. 
  delay (200);
  grados=180; // lo llevamos al otro extremo y observamos si ratea  
  delay (200);                             
  
  // variar los valores minimos y maximos hasta encontrar los que 
  // se ajusten. Recordad cargar el programa despues de cada cambio
}


Una vez encontremos estos dos valores, podemos proceder a programar nuestro sketch , que quedaría de la siguiente manera:



/* Lectura de temperatura
Con un TMP-36, y repreentacion analogica a traves de un
servo y arduino
 */

#include <Servo.h> 

// Declaración de constantes
Servo myservo; 
const int sensorPin = A0; // Pin conectado al TMP36
float voltaje; //variable para calcular la tensión 
float temperatura; //variable para almacenar la temperatura;
int temperaturamin=-15; // Temperatura mínima de nuestro termometro
int temperaturamax=45; // Temperatura máxima de nuestro termometro

void setup()
{
  // Empezamos la comunicación con el puerto serie
  // para mostrar los valores en el serial monitor
  Serial.begin(9600); 
  myservo.attach(9,465,2200);//,540,2100);  //pin conectado a nuestro servo 

}


void loop(){
  // Leemos el valor de tensión en el pin
  // donde está conectado el sensor TMP36
  int sensorVal = analogRead(sensorPin);

  // Convertimos el valor de la lectura digital
  // en voltaje
  float voltaje = (sensorVal/1024.0) * 5.0;

  // Mostramos el valor del voltaje en pantalla
  Serial.print(", Volts: ");
  Serial.print(voltaje);
  
  // Convertimos el valor de tensión en temperatura
  // en grados Celsius. Para ello usamos la formula
  // explicada en http://arduinopractico.blospot.com.es
  // restando al voltaje el offset de 0.5V que tiene el sensor
  // e incrementando la temperatura en 1ºC por cada 10 mV
  // T = (V-0.5)*100 , siendo V el voltaje leido
  
  Serial.print(", Temperatura en C: "); 
  float temperatura = (voltaje - .5) * 100;
  Serial.println(temperatura);
  
  // Ahora preparamos el dato para mostrar con nuestro
  //servo de forma analogica primero restringiendo el valor
  // de temperatura a los definidos 
  constrain(temperatura,temperaturamin,temperaturamax);
  //Luego mapeamos los valores para mostralos proporcionalmente
  //en el arco recorrido de 180ºC
  
  temperatura=map(temperatura,temperaturamin,temperaturamax,0,180);
  
  //Ttrasladamos el valor al servo en forma de grados
  
  myservo.write(temperatura);
  
  
   delay(1000);
}


El ejemplo es muy parecido a las entradas anteriores, con las siguientes particularidades.

 myservo.attach(9,465,2200);

En esta línea, le decimos al Arduino cuales son los calores correctos que definen los limites de funcionamiento de nuestro servo.

 constrain(temperatura,temperaturamin,temperaturamax);

La temperatura ya aprendimos como calcularla. Pero en esta línea lo que hacemos con las instrucción constriain, es despreciar cualquier valor por encima o por debajo de los definidos en el inicio.

 temperatura=map(temperatura,temperaturamin,temperaturamax,0,180);

Y con esta instrucción hacemos la salida proporcional para que la representación en nuestro termómetro "ardulógico" tenga cierta precisión.



De acuerdo, que el ejemplo es muy sencillo pero muestra la manera de hacer proporcional el movimiento de un servo entre dos valores conocidos y definidos. En la próxima entrada, veremos como "hackear" un servo para que gire 360º.

Nos vemos