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