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!!







No hay comentarios:

Publicar un comentario