Arduino, controlador máquina expendedora

 INTRODUCCIÓN: 

El objetivo de esta práctica es implementar un controlador para una máquina expendedora que esté basado en Arduino UNO y en los sensores/actuadores que se proporcionan en el kit Arduino. 

COMPONENTES USADOS: 

- Arduino UNO:

- LCD -> está conectado en los siguientes pines: 

    RS: pin 12

    ENABLE: pin 11

    DO: pin 6

    D1: pin 4

    D2: pin 3

    D3: pin 2

-  JOYSTICK- > está conectado a los siguientes pines: 

    VRx: pin  A1

    VRy: pin A2

    SW:  pin 9 

  Esquema que he seguido para asignar al eje x e y del joystick:

   

- DHT11 -> está conectado a : pin 13

- Ultrasónico -> está conectado a los siguientes pines:  

    TRIGGER : pin 8

    ECHO: pin 7 

- BOTÓN -> está conectado a: pin A2 

    El pin 1 me dio muchos problemas así que usé el pin analógico A2 que funcionó perfectamente.

- LED Rojo -> está conectado al pin 10

- LED Verde -> está conectado al pin 5

    

ESQUEMA: 

A continuación adjunto un esquema de toda la conexión en Fritzing.

FUNCIONAMIENTO:  

Para conseguir el funcionamiento descrito en el enunciado, he usado diferentes variable booleanas que describen los distintos estados del controlador. Para hacer una profunda descripción acerca de cada parte; voy a separarlo en 3 subapartados para no dejarme nada en el tintero.

 Antes de todo destacar que el modo de admin se puede ejecutar en cualquier momento del programa por lo que al principio del loop  tengo un thread que comprueba si el botón se ha pulsado durante más de 5 segundos y si es así entra en ese estado (lo describiré profundamente más adelante).

ESTADO ARRANQUE: 

En este estado se pide que el LED1(en mi caso el LED rojo) tiene que parpadear 3 veces a intervalos de 1 segundo. Por lo tanto yo he considerado que 500 milis está encendido y 500 milis apagado, así 6 veces. Por lo tanto, he usado timer1 inicializado cada 500 milis con una ISR que lo que hace es cambiar el estado del LED y aumentar el contador para que se cumpla lo de las 6 veces. 

Aquello de ver si se ha aumentado el contador y es menor de 6, lo trato fuera de la ISR ya que es peligroso que la ISR sea muy grande. 

Mientras ese contador es menor de 6, imprimo en el LCD  " CARGANDO...". Cuando ese contador llegar a 6, borro lo de la pantalla, hago un detach de esainterrupción para nohacer un mal uso de ella  y a lo largo de unas cuantas iteraciones y muestro por pantalla: " Servicio".

 El estado de arranque ha acabado, llegado a este punto.

ESTADO SERVICIO: 

Pasado la funcionalidad de contiene el estado de arranque, procedemos a sumergirnos al estado que ejecutaremos de manera infinita. 

En este estado hay que mirar si hay un cliente a menos de un metro  y mientras que esto no se cumpla hay que mostrar por pantalla "Esperando cliente". Para ello, he decidido implementar un thread que se irá llamando cada 300 milis para evitar obtener distancias que no son las correctas. Cuando se detecta que eso no se cumple, hago un remove del thread y así Arduino no se tiene que preocupar nunca más de que dicho sensor pueda estar activo sin deberlo. 

Para obtener la distancia he usado la fórmula de 29/2 ya que el valor que recibimos es solo de ida y 29 porque es una de las unidades de conversión de la velocidad del sonido. 

Para mostrar la temperatura durante cinco segundos seguiré el estilo como en el estado de arranque pero ahora haciendo un setperiod de 1 segundo y haciendo que se contador sea menor o igual a 5 segundos ya que es el tiempo que se tiene que mostrar por pantalla. Cuando llega a los 5 segundos, hago un detach de la interrupción. 

A continuación: hay que mostrar los productos por pantalla y yo lo hago hasta que no se pulse el botón. (if prepare_coffee != true).

Para mostrar esos valores y evitar los posibles bouncing times del pulsador y de mover el joystick en los ejes x e y uso la función millis(). He decidido darle un valor de 150 milis como margen

Cuando pulso el botón, pongo prepare_coffee = true y genero el número aleatorio que necesita para el brillo del led incremental en la siguiente fase. 

Dicho número aleatorio ha sido un poco un dolor de cabeza ya que no conseguía que fuese del todo aleatorio y siempreque lo ejecutaba me daba el valor de  6. Así que investigando, encontré la función randomSeed(analogRead(A0)) que fija una semilla aleatoria en cada ejecución del bucle. Dicha función solo la uso en el setup. 

También quiero destacar que para poder añadir el caracter de '€' en el lcd, tuve que usar un custom_char. Así que el '€' que podrás ver en el display, es obra mía. 

Tras haber pulsado el botón y realizado lo descrito anteriormente, entramos en la fase 1 a la hora de preparar el café. Imprimir por pantalla 'Preparando Café' a la vez que el led se ilumina incrementalmente'. He usado milis() ya que timer1 y salida PWM no termina de funcionar bien. 

Para que el LED se ilumine incrementalmente, he decidido insertarlo dentro de un thread llamado cada minuto para que el valor tenga que ser incrementado.  

El valor que he usado para incrementarlo es para cada segundo por lo tanto, cada segundo se incrementaba: led_value+= 255/random_num. Dicho valor lo he obtenido realizando una regla de 3.

Después de acabar esta parte en la fase 2 he usado también milis para mostrar por pantalla "RETIRE BEBIDA"  ya que a la hora de hacer detach de la interrupción no había ningún pin que deshabilitar ya que solo era mostrar ese mensaje por la pantalla del lcd. 

Hasta aquí es el funcionamiento de la fase de servicio que llegados a este punto volverá a ejecutarse indefinidamente. 

 

En cualquier momento del estado b), se puede reiniciar el estado, si se pulsa durante 2-3 segundos. Al igual que el thread usado para los 5 segundos del admin, he creado otro para que cuente si entre 2-3 segundos ha sido pulsado y reinicie el estado de servicio.

ESTADO ADMIN: 

Finalmente, llegamos al apartado de admin que podrás entrar dentro de él si pulsas el botón durante como mínimo 5 segundos.

Tras haber conseguido que ese tiempo sea 5 o más segundos, los 2 leds están encendidos. Uno de ellos usando digitalWrite(rojo) y el otro, (led verde) usando analog, ya que es el usado como pwm.

Dentro del estado de admin hago un remove del thread que ha conseguido contar 5  segundos  y meternos dentro de él  y hago un add del thread que voy a usar para salir de ese estado que comparten ambos la misma característica de que el botón esté pulsado 5 o máas segundos. 

 Mientras no se pulse el botón se muestra el siguiente menú: 

    i) Ver temperatura 

    ii) Ver distancia sensor

    iii) Ver contador

    iv) Modificar precios

    Una vez pulsado el botón dependiendo de la opción elegida tras el scroll (usando milis como anteriormente) podrás elegir entre las siguientes opciones:

i) Temp XX ºC Hum: YY%. Todo lo pongo en lcd.secursor(0, 0). Los valores de Temp y Hum están casteados para que sean ints. Para ir actualizando su valor, he usado un thread. 

ii) Distancia: XX cm.  Todo lo pongo en lcd.secursor(0, 0). Para ir actualizando su valor, he usado un thread.

iii) Ver contador: El contador usado para mostrar cuanto tiempo lleva lanzada la placa , lo he calculado así: contador=millis()/1000 para poder pasarlo a segundos.

iv) Modificar precios. Puedo hacer scroll arriba y abajo (eje y) , cuando me situo en una opción que quiero modificar su valor; desplazo el joystick hacia la derecha (ejex) y ya puedo hacer scroll arriba o abajo (eje y)  y dicho valor irá incrementando o decrementando. Si quiero fijar ese valor, pulso el botón. Sin embargo, si no quiero fijar ese valor, en vez de pulsar el botón, tienes que desplazar el joystick hacia la izquierda y verás como se reinicia el valor. Te dejará de nuevo moverlo a la derecha y dicho valor podrá ser modificado o sino puedes hacer scroll de todas la opciones. 

Igualmente para salir de uno de los submenus y poder ir a otro, es tan simple como si estás por ejemplo en el i), desplazar el joystick hacia la izquierda y podrás ver el menú.

CONCLUSION:

Me hubiese gustado hacer la memoria en inglés pero por falta de tiempo no me ha podido ser posible.

MULTIMEDIA:  

A continuación, podrás ver un video en el que se demuestra todo el proceso que requería la práctica.

VIDEO: 

 

Aunque no haya mostrado por falta de tiempo el estado de servicio con los valores modificados, puedo asegurar que el valor se mantiene al igual que has podido comprobar que se mantenía según hacía scroll para modificar otro valor.

 



Comentarios