viernes, 7 de julio de 2017

Arduino y bluetooth ( I )


Arduino y bluetooth ( I )

Iniciaremos una serie de entradas relacionadas con Arduino y Bluetooth.
Sin profundizar demasiado, bluetooth es un tipo de comunicación inalámbrica entre dispositivos electrónicos. Su principal característica , es la facilidad con la que estos dispositivos se encuentran y se configuran de forma autónoma en función de los servicios que implementan.
Por contra, la distancia útil de esta comunicación, del orden de unos metros de alcance (unos 10 metros en los dispositivos habituales de bajo consumo sin antena), lo descarta para otro tipo de aplicaciones que necesiten  mayor alcance, robustez o velocidad de transmisión.
Necesitaremos por tanto añadir un dispositivo a nuestra placa de Arduino para dotarle de capacidad de conexión Bluetooth. Hay unos cuantos en el mercado , y de proveedores conocidos, pero me centraré en dos de los más conocidos y económicos ; -) , el HC-05 y el HC-06.

Módulo HC-06
Es el más sencillo de los dos. Dispone de tan solo 4 pins,  TX, RX, VCC, GND y sólo puede funcionar como esclavo, es decir no puede generar conexiones hacia otros dispositivos, y por lo tanto tan solo puede recibir órdenes de un dispositivo maestro. Es útil para todas aquellas aplicaciones en las que usemos un Smartphone, ordenador, etc , para enviar órdenes a nuestro Arduino, pero no necesitemos obtener un feedback.
Tiene la particularidad, de que se alimenta a 3.3V, por lo que para usarlo con nuestro Arduino lo correcto sería montar un divisor de tensión con dos resistencias para obtener esos 3.3V. En la práctica, todos los que he usado los he alimentado directamente con los 5Vcc de la placa de Arduino, y están vivos…
Módulo HC-05
Es un módulo con idéntico chip que el HC-06, pero con diferente firmware y dos pins adicionales State y Key (o WakeUP según versión). Este es un módulo Maestro-Esclavo, lo que le permite generar conexiones con otros dispositivos para establecer comunicación punto a punto. La diferencia es que un BlueTooth Slave solo puede conectarse a un master y a nadie más, en cambio un master BlueTooth, puede conectarse a varios Slaves o permitir que ellos se conecten y recibir y solicitar información de todos ellos. 
De momento, nos centraremos en el uso y  configuración del HC-06, que es el que usaremos para los próximos tutoriales.
Se puede apreciar como dispone de las dos entradas adicionales, pero no tienen soldado ningún pin. Hay algún tutorial de cómo convertirlo en un HC-05, pero te recomiendo que lo compres directamente, porque es bastante complejo.

Imagenes

Repaso de la librería SofwareSerial
Antes de empezar a explicar para que sirve, comentaré por qué la usaremos. Podríamos hacer un ejemplo tan sencillo como conectar los pins de Rx y TX, a los del Arduino, pines (Rx y Tx, 0 y 1 respectivamente) y funcionar. Pero tendremos el problema que son los mismos que usa para comunicar el CHIP UART del Arduino para la comunicación serie con nuestro ordenador, por lo que cada vez que quisiéramos cargar un código de prueba, necesitaríamos desconectar el módulo bluetooth, cargar el programa, desconectar la placa, conectar el módulo, y volver a emparejar con el móvil.
Un poco lío, ¿no?
Por eso esta librería, que implementa vía software un chip TTL-UART virtual. Tiene algunas limitaciones, como que pins se pueden usar según el tipo de placa de Arduino, y que en caso de implmentar varios puertos, solo uno puede puede recibir datos a la vez.
Para usarla, primero deberemos incluir esta librería en nuestro skecth, con la línea:
#include <SoftwareSerial.h>
Después se debe declarar una variable del tipo SoftwareSerial ,con los dos pins que usaremos como RX y TX. Sería algo como:
SoftwareSerial newSerial(txpin,rxpin);
Donde newSerial, es el nombre que queremos usar, y txpin y rxpin, el ´numero del pin donde van conectados
Si queremos llama a este puerto btserie, y usar el pin 2  como transmisor, y el pin 3 como receptor, quedaría:
SoftwareSerial btserie (2,3);

Para el resto de código, se usan las sentencias habituales con puerto serie.

A la hora de hacer el montaje, hay que tener en cuenta que las conexiones en serie van "cruzadas", y que por tanto el pin TX del HC-06 va al pin definido como RX en la placa Arduino y viceversa. Os debe quedar así:



Vamos con un ejemplo básico, que lee el puerto serie y encendería un LED al recibir un “1” y lo apagaría al recibir un “0”.


#include <SoftwareSerial.h>
//Variable para almcenar la lectura del puerto serie
char caracter;
/* En la siguiente sentencia declaramos los pines que vamos
 *  a usar para realizar la comunicación serie con el modulo
 *  bluetooth. Recuerda que se cablean cruzados. Rx Arduino
 *  con Tx módulo y viceversa
 */
SoftwareSerial btserie(2, 3);
void setup() {
  btserie.begin(9600);
  pinMode(13,OUTPUT);
}
void loop() {

// Este bucle qeda a la espera de una lectura por el puerto serie
// del módulo bluetooth

    while (btserie.available() == 0) {
    ;
  }
  caracter = btserie.read();

  if ( caracter == '0' ) digitalWrite(13, LOW);
  if ( caracter == '1' ) digitalWrite(13, HIGH);
  delay(100);
}



Los parámetros que he usado de velocidad son lo habituales para módulos comprados en tiendas web lowcost habituales, eso es velocidad de transmisión 9600 bauds y pin de conexión 1234. Si no obtuviese comunicación prueba con distintos valores de velocidad, 4800, 9600, 19200, 38400,57600, etc.
Para comunicarnos con nuestro módulo, yo he usado la aplicación Arduino Bluetooh Terminal. Es de una sencillez extrema y muy ligera. Los pasos a seguir son:

-          Cargar el programa en nuestro Arduino,
-          Descargar la plicación de la Play Store, e instalarla
-          En ajustes Bluetooh de nuestro teléfono, localizar el módulo HC-06 y vinvularnos. El pin habitual es 1234,
-          Vamos a la aplicación y escribimos un 1, y pulsamos send, el led 13 se encenderá
-          Escribimos un 0 y send y se apagará.

Os dejo con un sencillo vídeo de cómo va el proceso.
Este programa es muy sencillo de hacer con app inventor, así que en la próxima veremos cómo crear nuestra propia aplicación de Android, para gestionar tantos dispositivos como queramos.

Nos vemos.

lunes, 12 de octubre de 2015

Cálculo de distancias por ultrasonidos

Cálculo de distancias por ultrasonidos


Hola de nuevo. Vamos a ver en esta entrada cómo calcular distancias con un Arduino y un sensor de ultrasonidos tipo el HC-SR04, o similar. Este tipo de montajes tiene diferentes utilidades, pero el denominador común al calculo de distancias.

Yo lo utilizo para evitar las colisiones en los robots domésticos, o bajar velocidades en otras aplicaciones cuando me aproximo al sujeto.  En cualquier caso la precisión decae cuando el obstáculo no está perfectamente perpendicular al sensor, por lo que se debe mejorar el sistema, en caso de aplicaciones críticas.

Pero veamos primero en que basa su funcionamiento este sistema.

Este sensor, usa dos transductores, un emisor y un receptor que trabajan en la frecuencia de los ultrasonidos, inaudible para el ser humano. El emisor emite un pulso que rebota en el obstáculo, permitiendo que el receptor capte el eco de ese pulso. Gráficamente sería algo como esto:



Necesitaremos un poquito de mates y física básica, para poder modelar este comportamiento con nuestro Arduino. Nos interesa conocer la distancia del objeto, por lo que emplearemos la fórmula que relaciona las variables, velocidad, espacio (distancia) y tiempo.

            v=d/t

Despejando la distancia que, que es lo que nos interesa, obtenemos que :

            d=v·t


La velocidad del sonido la conocemos, en el aire a 20ºC es de 343 m/s.

El tiempo, es lo que calcularemos con nuestro Arduino. ¿Cómo? Calculando el tiempo que pasa entre que el traductor emite el sonido, y el receptor lo capta. Para eso necesitaremos presentar una función nueva, pulseIn

Esta funcion sirve para medir pulsos, es decir, el intervalo que pasa entre que una señal pasa de un nivel bajo a un nivel alto o viceversa. La medición la realiza en microsegundos.

La sintaxis de esta función es:


pulseIn(pin, value, timeout)


Donde:
  • pin, es el conector donde conectaremos el receptor de la señal, v
  • value, que debe ser HIGH o LOW, según si queremos detectar un flanco de subida o de bajada, para el caso que nos ocupa, HIGH.
  • timeput, es opcional, y sirve para delimitar el tiempo que queremos que nuestro Arduino esté "escuchando" en espera de un cambio. Si el tiempo de espera supera los 3 minutos dará un error de timeout ( devuelve un 0).
Este valor, es más importante de lo que parece, pues es el que nos dará fluidez en el programa. Por un lado limitará el tiempo de escucha agilizándolo. También es razonable que si el sensor no puede medir más de 6 metros , la escucha sea de 3 minutos, es decir detectar un objeto a más de                ¡¡¡30 kilómetros !!!


Por último, es importante tener en cuenta que las ondas realizan un trayecto de ida y vuelta. Es decir, se emiten, van al objeto, rebotan y vuelven. ¿ Lo has adivinado? Pues sí, la distancia que calculamos, la tenemos que vivir entre dos para obtener lo que andábamos buscando.

Bueno, después de la introducción teórica, vamos a ver el montaje, que en esta ocasión , es bien sencillo:



Y el sketch, que quedaría de la siguiente manera. 

long distancia; 
long tiempo;
int trigger=9;// pin trigger del SR04
int echo=8;// pin echo del SR04

void setup (){
  Serial.begin(9600);// preparamos el port serial para ver lecturas
  pinMode(trigger,OUTPUT); // definimos trigger  como salida
  pinMode(echo,INPUT); // y echo como entrada
}

void loop (){
  digitalWrite(trigger,LOW);  // Aseguramos que esta 0
  delayMicroseconds(5);       //Retraso para asegurar respuesta
  digitalWrite(trigger,HIGH); // Lanzamos el pulso
  delayMicroseconds(10);//
  tiempo=pulseIn(echo,HIGH,2945);  // MEdimos el tiempo del rebote
  // timeout calculado para 50cm
  distancia = (0.0343*(tiempo/2));//Usamos las unidades apropiadas, en 
  // este casola velocidad del sonido en cm/microsegundos
  // Y lo dividimos entre 2 para mostrar distancia "solo ida"
  Serial.println("Distancia");//mostramos resultados 
  Serial.println(distancia);  //en el monitor serial
  Serial.print("cm"); // en cm
  
}


Quedaría explicar  el valor del timeout.

Imaginad que quereis ignorar, distancias superiores a 50cm. Por tanto deberemos calcular que tardaría la onda de sonido en recorrer 50cm, ida y vuelta. Despejando el tiempo de la fórmula anterior:


                                                                        t=e/v

Usando las unidades apropiadas, cm y cm/us, (recordar multiplicar la distancia x 2 )nos daría un tiempo de,

                t=e/v= 100/0,0343 = 2915 microsegundos

Haced vosotros la cuentas de la cantidad de cosas que puede hacer nuestro Arduino con el tiempo que    se ahorra limitando el tiempo de escucha. Borrando el valor, el limitante será la capacidad del sensor que usemos.


Y como función?

Como ya explicamos en una entrada anterior, ésta, sería interesante generar una función para que fuese más sencillo introducirlo en un programa más complejo, como por ejemplo un robot de suelo, o similar, de manera que se pudiese llamar en cualquier momento. Esta parte os la dejo a vosotros, pero no dudes en plantear cualquier duda.

Nos vemos!

Os dejo con un video del experimento. Como vereis la precisión es mejorable, pero es un buen mecanismo de aproximación y anticolisiones.








lunes, 29 de junio de 2015

Arduino , Ethernet Shield y algo de HTML

Repasando la entrada anterior, me gustaría comentar algunos puntos que no se tocaron y que pueden resultar de interés.
El primero tiene que ver con el hardware del ejemplo. Hay mucha variedad de Ethernet Shields en el mercado. Os recomendé un par que son compatibles con el Arduino, hay muchas más, pero debéis fijaros que el CHIP que use sea el W5100 Ethernet controller IC , para evitar problemas de compatibilidad.

 El siguiente punto, también de hardware tiene que ver con el consumo de ese chip. Puede llegar a ser muy alto, y además de calentarse, y de qué manera, es necesario alimentar el ejemplo con una fuente de alimentación externa, pues vuestra conexión USB no dispone de la potencia necesaria. Si aún no lo habíais hecho, es un buen momento para hacerse con una fuente externa de 9 V para alimentar vuestro Arduino.
El último punto relacionado con el hardware,  tiene que ver con los pins 10,11,12 y 13 del Arduino. Estos pins se usan para la comunicación con la Ethenet shield, por lo que no podrán ser usados para otro fin cuando se use con esta ampliación.
El resto de puntos que me gustaría tratar, están relacionados con el código del sketch de ejemplo. Al final lo que conseguimos es convertir nuestro Arduino en un servidor web.  La página mostrada es de una sencillez máxima,(es un ejemplo “demo”)  y tampoco veréis grandes florituras en los ejemplos míos  que vendrán, pues mis conocimientos de HTML son básicos.
Pero me gustaría desarrollar un poco las líneas más básicas de código HTML para mostrar la información de una manera mínimamente inteligible.
Hasta ahora, en algún ejemplo como este, habíamos usado la instrucción serial.print(); para mostrar la información que queríamos en el Monitor Serial.
Sin embargo en este ejemplo usamos la instrucción :

client.println();

Entre los parantésis podemos escribir desde un texto entre comillas:

            client.print("analog input ");


O el valor de una variable cualquiera:

            client.print(sensorReading);


Salto de línea, mostrará el siguiente valor o texto en otra línea:

            client.println("<br />");      


Y dos líneas imprescindibles que marcan el inicio y el final de un código en HTML:

            client.println("<html>");


Y
          client.println("</html>");


Otra instrucción también interesante, es la que controla el tiempo de refresco de la página. En el ejemplo del día anterior era cada 5 segundos:

client.println("Refresh: 5"); // refresh the page automatically every 5 sec

Eso es todo de momento. Espero hayáis podido configurar vuestra Ethernet Shield y el router sin problemas, pues seguiremos avanzando en las próximas entradas en estos temas.

viernes, 12 de junio de 2015

Conectando nuestro Arduino a Internet

Es momento de abrir al mundo nuestro Arduino. Vamos a configurar todo lo necesario para conectar a internet nuestro Arduino através de una shield Ethernet.

Este post veremos cómo configurar nuestro entorno de trabajo para poder sacar partido de esta shield, que creo que es de las más productivas que podemos encontrar. Veremos cómo configurar el router, como parametrizar la shield Ethernet y un sencillo ejemplo que puede servir de base para desarrollar otros proyectos.

Los requisitos necesarios para poder sacar partido de este ejemplo son:

-       - Placa Arduino UNO, o compatible, por poco más de 6€
-       - Placa shield Ethernet  compatible, un coste similar de unos 6 €
-       - La librería Ethernet, http://arduino.cc/en/Reference/Ethernet
-       - Sería recomendable, tener nociones de HTML,
-       - Un router conectado a internet, y sus instrucciones si es posible
-       - Cable RJ-45
-       - Paciencia y algo para hidratarnos que ya empieza a hacer demasiada calor
-       - Opcionalmente, ya  lo explicaremos, un IP fija o servicio DDNS equivalente

Vamos a ello,

El router


Antes de seguir, debo advertir que este ejemplo está realizado con mi router. Se trata del que facilita  mi proveedor de internet (no lo nombraré hasta que no me paguen por ello ),  y hay que advertir que cada modelo gestiona las opciones de configuración de manera distinta. La parte positiva, es que de todas maneras las opciones suelen ser bastante similares y no difieren mucho de un modelo a otro.
En cualquier caso, podéis localizar mucha información sobre configuración de routers en páginas como esta www.adslayuda.com

¿Preparados? Bien, pues lo primero es conocer en que dirección IP podemos configurar nuestro router. Podemos mirar si físicamente tiene alguna pegatina, (versión cutre pero efectiva), o lanzar unos comandos desde nuestro ordenador.

Si utilizas Windows, los pasos son estos:
 -  Botón de inicio y busca ejecutar
-      -  Teclea en la pantalla cmd y enter ( Estos dos pasos son equivalentes a pulsar Tecla windows + R)
-      -  Tendrás ahora una ventana con fondo negro del tipo MS-DOS, teclea ipconfig y enter

-        En la pantalla que te habrá salido, busca la línea Puerta de enlace predeterminada, esa es tu dirección IP.




 Ahora con tu dirección IP, abre una pestaña de tu navegador favorito y pega el número tal cual en la barra de direcciones. 

Según el ejemplo : http://192.168.1.1

Te saldrá la pantalla de bienvenida de tu router, y los más probable, dos espacios solicitando usuario y contraseña.



Si no los sabes, puedes buscar con google, por tu modelo y/o operador de internet. Este sitio te puede servir de referencia. Los más habituales:

-        Usario:  admin, user,(en blanco)
-        Contraseña: admin, user, 1234,(en blanco)

Llegados a este punto, deberíamos haber sido capaces de acceder al entorno de configuración del router.  El siguiente paso es :

Asignar una IP al Arduino


Ahora, necesitamos que cada vez que nuestro Arduino se conecte a nuestra red local, lo haga siempre a la misma dirección. Si no lo configuramos, el router va gestionando las direcciónes IP de manera automática y toalmente aleatoria, y nosotros necesitamos que sea siempre la misma.

¿Cómo? Primero asignaremos a nuestra shield un identificador único. Esto lo hacemos desde el void setup, configurando el MAC de la placa. Podéis profundizar más sobre el tema aquí, pero básicamente se trata de un identificador con la dirección física del dispositivo, lo tiene cualquier aparato que se conecte a la red, y la única premisa que debe cumplir es que no sea igual al de alguno de los dispositivos conectado en nuestra red. Por defecto, puedes usar :

0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED

Y la instrucción completa:

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

Si nuestro proyecto tuviese dos shields Ethernet este número debería ser diferente para cada una de ellas.

Podéis comprobar las direcciones MAC de los equipo conectados buscando entre las opciones del router algo del tipo Device Info - > DCHP, donde os saldrá una tabla con las direcciones MAC de los dispositivos conectados la última semana.

Ahora es momento de localizar en el menú del router dentro de las opciones de DCHP, algo  parecido a DCHP estáticas, o asignaciones de MAC . Es el punto donde debemos escoger la dirección IP que asignaremos al Arduino y decirle al router la MAC que corresponde al Arduino. Una imagen de como queda en mi router.



Accediendo desde el “exterior”



Una vez completados los pasos anteriores ya puedes acceder vía IP desde tu red local al Arduino, y probar el ejemplo que hay más adelante. Tan solo tendrías que teclear la dirección IP que le hemos asignado dentro de la barra del navegador. Algo como esto http://192.168.1.177

Para poder acceder desde fuera de la red local, tenemos que decirle al router que permita las conexiones entrantes. Para ello habilitaremos un puerto, el nº 80 por ejemplo para permitirlo. A muchos les sonará esto del emule... para los que no deberemos buscar en el router un menú relacionado con puertos, NAT, virtual servers o similar. En caso contrario, una búsqueda en google con el nombre de vuestro equipo del estilo : abrir puertos router XXXXX, os solventará el problema.
 Recordad , puerto 80, y la IP que le hemos asignado al Arduino la 192.168.1.177 .






¿Esto es todo? No, I'm sorry. Falta saber la dirección IP que el proveedor nos asigna a nuestra conexión. Para eso teclear en vuestro navegador:

www.cualesmiip.com  o  www.sabermiip.es


Anotad la dirección que os aparece, cerrad el navegador y reiniciar el router. Ahora volved a teclearlo y comprobad si los números son iguales. No coincide ¿verdad? , es normal que no coincidan, eso significa que tu IP es dinámica, como la del 99% de los usuarios.
¿Que implica que tu IP sea dinámica? El número que te ha mostrado es tu dirección IP, tecleando desde cualquier parte del mundo accederías a tu red, o al menos al puerto 80 ( es el que hemos abierto).  Si es dinámica, cambiará ante cualquier incidencia ( corte de tensión o reasignación por parte del proveedor), y te impedirá acceder a tu sistema.

Tranquilo, esto tiene solución, no hemos llegado hasta aquí para abandonar ahora. Tienes al menos dos maneras para resolverlo:

1 .- Contratar con tu suministrador un servicio de IP estática o fija. El coste ronda los 30€ anuales. El inconveniente, al margen del precio, es que una dirección tan solo numérica es difícil de recordar.

2.- Contratar un servicio de DDNS. Los hay de pago o gratuitos, y lo que hacen es seguir tu IP dinámica y asignarla a un nombre de servidor ( de tu elección) que lo hace más fácil de recordar. El inconveniente es que tu router debe soportar este servicio. Algunos ejemplos de proveedores de este servicio pueden ser, DynDNS, TZO, NoIP (gratuito con reactivación mensual), DNSdynamic (gratuito). Configurarlo en tu router será tan sencillo como buscar la opción e introducir el usuario y contraseña asignados. Recuerda que el registro previo se ha decir vía web.



Recuerda que no es necesario, ni abrir puertos, ni configurar el DDNS para poder realizar el ejercicio propuesto. Esto sólo será necesario en caso de querer hacerlo funcionar desde fuera de nuestra red local.

Una forma rápida de comprobar si todo gira, uno de los ejemplos de los que vienen por defecto en el IDE de Arduino. Os recomiendo:

Archivo -> Ejemplos -> Ethernet -> WebClient

Abrir el navegador y poner la dirección 192.168.1.177 si estás conectado en tu red local (lo recomiendo para empezar), o tu dirección IP. Obtendrás una pantalla con 6 lecturas analógicas totalmente arbitrarias, pues no hay nada conectado.



Hay trabajo para rato con lo aquí propuesto para configurar vuestra red local, así que os dejo en este punto. El montaje consistiría únicamente en montar la shield encima del Arduino, alimentar el conjunto y conectar a la red local mediante un cable RJ-45. Poned los valores propuestos, pues son los que usa el ejemplo del IDE.

En la siguiente entrada habilitaremos el código para leer un TMP-36 y hacer una lectura real de temperatura. Nos vemos!

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