INTRODUCCIÓN
Ahora que hemos visto la utilización de los switches y leds en las prácticas anteriores, los utilizaremos en un ejemplo de aplicación. Así que realizaremos una aplicación de un semáforo el cual no solo cambiará el color del led de entre vede amarillo y rojo, sino que tendrá otras opciones propias de los semáforos.
La práctica se pensó con una máquina de estados. A continuación presentamos el diagrama.
En el diagrama anterior presentamos los estados que tendrá el semáforo. Los estados principales son los 4 círculos grandes, estos son: estado rojo, estado verde, verde parpadeo y amarillo. Estas son los estados normales de un semáforo. Cada uno tiene un tiempo asignado, tiempo que da la duración activa de cada estado. Así mismo las flechas gruesas de color azul son las que indican el funcionamiento en operación normal.
Adicionalmente tendremos opción de emular el funcionamiento del semáforo en operación inusual, por ejemplo un estado de falla, o las veces en que un policía opera manualmente los semáforos para intentar liberar un atascamiento de carros en tráfico intenso. Estos casos se muestran en la máquina de estados con flechas delgadas y rojas, para el caso de falla tendremos un nuevo estado al que le llamaremos: parpadeo amarillo. Este estado emula las veces cuando un semáforo se descompone y solo parpadea en color amarillo. Este estado también puede ser usado para el funcionamiento nocturno de algunos semáforos, en el que el semáforo solo parpadea en amarillo como signo de precaución. Para poder utilizar estos estados necesitaremos presionar los botones que se encuentran integrados en la tarjeta. Se presentan las siguientes condiciones:
- Sin importar en qué estado se encuentre el semáforo (rojo, verde, etc), siempre podremos pasar al estado de falla (parpadeo amarillo). En el cual permanecerá indefinidamente hasta una nueva interacción por parte del usuario. Para poner el semáforo en este estado deberemos presionar el sw2.
- Podremos salir del estado de falla si, y solo si, presionamos el sw3, el cual nos enviará directamente al estado rojo.
- Podremos pasar rápidamente del estado rojo o verde solo presionando el sw3. Si el semáforo se encuentra en estado rojo y presionamos el sw3, pasará inmediatamente al siguiente estado (estado verde). Se igual manera si es semáforo se encuentra en estado verde y presionamos el sw3 cambiará inmediatamente al siguiente estado (verde parpadeo). Sin embargo el usuario no tendrá ningún dominio de cambio rápido de estado en los estados amarillo y verde parpadeo. Por lo que deberá pasar el tiempo programado para que pase al siguiente estado.
DESARROLLO DE LA PRÁCTICA
Lo primero que analizaremos serán los componentes que agregamos y la configuración de cada uno de estos componentes. Ya no se abordará tan afondo como en la práctica 1 la manera de agregar los componentes puesto que ya se mostró en esa práctica. Así que los componentes que se utilizan son:
Figura 1. “COMPONENTES UTILIZADOS EN LA PRÁCTICA”
Primero veremos la configuración del CPU y el reloj del CPU. Es importante mencionar que la configuración del CPU (y el reloj) es exactamente la misma que la de la práctica 1. Así que para mayor información es aconsejable revisar dicha práctica.
Figura 2. “CONFIGURACIÓN DEL MODULO Cpu:MK64FN1M0VLL12”
Figura 3. “CONFIGURACIÓN DE RELOJ DEL CPU clockMan1:fsl_clock_manager”
Ahora continuaremos con la configuración del siguiente componente el cual es para la configuración de los pines. Este es el apartado donde se asigna un nombre personalizado a determinado pin de la tarjeta para poder llamarlo con mayor facilidad en el código. El componente que analizaremos es el pin_mux:PinSettings. Cabe mencionar que esta configuración es exactamente igual que la de la práctica 1. Así que para más información es recomendable analizar esa práctica
Primero veremos la configuración del GPIO
Figura 4.“CONFIGURACIÓN DE PINES PARA EL GPIO”
El último componente a analizar es el pitTimer1:fls_pit. La configuración es parecida a la de la práctica 1, pero en este caso el periodo está ajustado a 1 ms en lugar de 1000 ms.
Figura 5. “CONFIGURACIÓN DEL pitTimer”
Ya hemos terminado de ver la configuración de los componentes que se utilizarán en la práctica. Como pudimos ver la configuración es exactamente la misma que la de la práctica pasada. A continuación vamos a ver el diagrama de flujo que representa lo que vamos a realizar en esta práctica.
Figura 6. “DIAGRAMA DE FLUJO PARA EL SEMÁFORO”
Lo primero son las definiciones. Declaramos 3 constantes llamadas FLASH_SLOW, FLASH_MEDIUM y FLASH_FAST. Cada uno será un contador de 0x200, 0x100 y 0x80 ms respectivamente.
Luego declaramos 4 variables. Dos de estas son variables enteras de 16 bits, la primera se llama ‘TiempoLed’ y la segunda ‘TiempoCambio’. Las dos variables restantes son 2 variables de un tipo creado por nosotros, lo veremos más adelante. El tipo de variable es status_semaforo y las variables que son de este tipo son una llamada ‘estado’ y la otra llamada ‘next_state’
Ahora declaramos dos estados llamados ‘DOWN’ y ‘UP’ junto con 4 variables que pueden tomar este estado, una llamada state_sw3, la segunda se llama last_state_sw3. La tercera y cuarta reciben el nombre de las 2 primeras pero en lugar del sw3 será para el sw2.
En el siguiente renglón declaramos tres estados llamados ‘NONE’, ‘PULSE’ y ‘HOLD’ junto con 2 variables que pueden tomar estos estados. La primera se llama boton_sw2 y la segunda boton_sw3
En la siguiente línea definimos un tipo de variable llamado ‘colors’ y 3 estados de este tipo, llamados BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN y WHITE.
Por ultimo tendremos otra enumeración llamada rgb_color que tendrá 3 estados R=1, G=2 y B=4
Antes de continuar debemos agregar un nuevo archivo llamado Semaforo_APP.h el cual contendrá el siguiente código.
Dentro de este nuevo archivo tendremos, primero, una enumeración que define un tipo de variable, el tipo se llama ‘status_semaforo’. Habrá 5 estados que serán de este tipo: ESTADO_ROJO, ESTADO_VERDE, ESTADO_PARPADEO, ESTADO_AMARILLO y ESTADO_FLASH_AMARILLO.
Además declaranos 6 constantes: TIEMPO_ROJO=5000, TIEMPO_VERDE=5000, TIEMPO_AMARILLO=2000, TIEMPO_PARPADEO=2000, TIEMPO_ANTIREBOTE=100 Y TIEMPO_CAMBIO=250. También agregaremos 3 de las variables que tenemos en el archivo main.c. Estas variables son TiempoLed, TiempoCambio y estado.
Al agregar este nuevo archivo Semaforo_APP.h necesitamos incluir el archivo para que pueda ser leído desde el archivo main.c así que agregaremos la siguiente instrucción.
Ahora analicemos el otro archivo que nos compete que es el Events.c. En este archivo utilizaremos las interrupciones generadas por el pitTimer. Y agregaremos 3 variables que nos serán de utilidad.
Las variables agregadas son las siguientes
Y dentro de las interrupciones del pitTimer pondremos lo siguiente:
La variable time_delay será la que nos ayude a hacer en tiempo las transiciones entre un estado y otro del semáforo. Las variables time_deb_sw2 y time_deb_sw3 serán para evitar el tiempo de rebote del switch, esto debido a que el microcontrolador lee con demasiada velocidad los puertos y al momento de apretar el switch manualmente, el microcontrolador puede leer es estado presionado durante mucho más de un ciclo y hacer cosas que no deseamos.
El conter_ms será la variable que nos ayudará a controlar el tiempo del flasheo del led.
Ahora, regresando al archivo main.c debemos agregar las variables del archivo de eventos que también utilizaremos en él. Así que dentro de main.c agregaremos lo siguiente:
Ahora declaramos las subrutinas que utilizaremos antes del inicio de la función main. Las subrutinas son las siguientes
Vamos a ver, en primer lugar la función led
Esta función tiene como argumento una variable de tipo ‘colors’ llamada x, este tipo de variable que se declaró previamente. Según la variable que se ingrese habilitará la salida de los los leds necesarios para dar el color deseado, ya sea verde, rojo, amarillo etc. Esto gracias al peso de los bits. Ahora continuaremos con la función main, la iremos analizando poco a poco con la secuencia en la que van ocurriendo las instrucciones.
La primera instrucción que podemos ver es la inicialización del Processor Expert PE_low_level_init( );
A continuación asignará ESTADO_ROJO a la variable next_state y asignará el valor de cero a la variable time_delay. Esto con el fin de que el semáforo inicie en el color rojo, la razón la veremos un poco más adelante.
Ahora entramos en el for infinito que se encargará de que nuestro programa entre en un loop que nos permitirá pasar indefinidamente por el mismo conjunto de instrucciones.
Lo primero es la función botones
Esta función se encargara de hacer que los botones tengan un tiempo anti-rebote. Esto es que el microcontrolador no detecte un botón pulsado como si se presionara dos veces. Esto se debe a que el microcontrolador trabaja a una alta frecuencia, y lo que para el usuario pude ser un pulso inmediato, el micro puede leer que la entrada permanece apretada durante 10, 100 o 1000 ciclos (por poner un ejemplo). Así que esta función fue creada para evitar que esto pase realizando una serie de condicionantes junto con un TIEMPO_ANTIRREBOTE que nos ayudará a evitar esto. Esto es útil cuando un solo botón hace funciones sucesivas en una secuencia de trabajo. En esta práctica el sw3 nos sirve para “apurar” el color rojo y verde, si no se tuviera una función como esta, haría que termine el tiempo del color rojo, y de inmediato haría lo mismo con el tiempo del color verde, y esta no es la función deseada.
La siguiente función es la función ‘falla’. En esta función preguntaremos si el estado del botón_sw2 es igual que PULSE (o sea que se encuentre pulsado). Si la condición se cumple haremos que el time_delay sea igual a cero, a la variable next_state le asignaremos el valor de ESTADO_FLASH_AMARILLO y diremos que es estado del botón_sw2 es none.
En caso de que el botón sw2 se presionara el estado de la variable next_state ahora sería ESTADO_FLASH_AMARILLO. Como podemos apreciar dentro de la función main asignamos el valor de la función next_state a la variable estado. Además decimos que si el time_delay es cero entrará a la función SWITCH que está más abajo. La función switch tendrá como elemento de selección el valor de la variable estado. Así que en este caso el valor de la variable estado sería ESTADO_FLASH_AMARILLO, por lo que el switch entrará al case:ESTADO_FLASH_AMARILLO. El cual tiene como única instrucción el llamado de función de fflashamarillo (), vamos a analizar la función:
Esta función manda el color YELLOW a la función de parpadeo ‘flash_led’ y después tendrá una condición por medio de un if. Esta condición preguntará si el botón_sw3 está presionado, de ser así hará que el time_delay tenga un valor de cero. Además le asignará a la variable ‘next_state’ el ESTADO_ROJO y pondrá el boton_sw3 en estado NONE.
Al pasar de esta función el next_state tiene como valor ESTADO_ROJO y el time delay tiene cero como valor, por lo que estaremos en el estado inicial del programa, recordemos que así se inicializan estas variables. Así que si no se entrara dentro de la función de falla iniciaríamos el switch en el case ESTADO_ROJO. La cual tiene como instrucción el llamado de función a la variable frojo. Vamos a analizar las instrucciones de esta función.
La función ‘frojo’ es la que contiene las instrucciones necesarias para que funcione el estado rojo del semáforo. La primera instrucción es un if que pregunta si el tiempo de retardo ‘time_delay’ es igual a cero. Además pregunta si al mismo tiempo el valor de la variable ‘next_state’ es ESTADO_ROJO. La primera instrucción se asegura de que el tiempo del estado anterior haya concluido, la segunda se asegura de que el estado que está próximo a entrar sea ESTADO_ROJO. Si ambas condiciones se cumplen hará lo siguiente:
- Asignará el tiempo para el estado rojo ‘TIEMPO_ROJO’ al tiempo del contador ‘time_delay’.
- Mandan el color rojo (RED) a la función led.
- Hace que la variable ‘next_state’ tome el valor ‘ESTADO_VERDE’.
Además habrá otra condición en la que se pregunta si el estado del ‘botón_sw3’ es ‘PULSE’, si se cumple cambiará el tiempo del time_delay a cero. Esto es para emular la función cuando el policía aprieta el botón para apresurar los tiempos del semáforo, así que al mandar el tiempo a cero cambiará inmediatamente de estado.
Como pudimos apreciar el next_state tendrá como valor ESTADO_VERDE por lo que el switch entrará dentro del case ESTADO_VERDE. Pero esto lo hará solo hasta que el time_delay haya terminado su conteo, recordemos que aprovechamos la interrupción del pitTimer para decrementar el conteo del time_delay cada milisegundo.
La función fverde tendrá un funcionamiento análogo a la función frojo, pero activará el tiempo y led de color verde, además hará que el siguiente estado guardado en la variable ‘next_state’ sea el estado de parpadeo.
Ahora de la misma manera que en el caso anterior cambiaremos al estado ESTADO_PARPADEO, dentro del switch nos mandará a la función fparpadeo.
La función fparpadeo comenzará con una comparación similar a la de las funciones frojo y fverde, preguntando si el tiempo de retraso ‘time_delay’ es cero, además si el siguiente estado next_state es igual a ESTADO_PARPADEO. Si esta condición se cumple asignara el tiempo de TIEMPO_PARPADEO a la variable ‘time_delay’, además hará que el siguiente estado sea el ESTADO_AMARILLO, guardado en la variable ‘next_state’ fuera de las instrucciones del if mandará el color GREEN a la función flash_led.
El siguiente estado por analizar es el ESTADO AMARILLO el cual manda a llamar a la función famarillo
La siguiente función es famarillo. Esta función podemos analizarla de manera análoga a las funciones fverde y frojo, aplicado al color amarillo, sin embargo no tiene las instrucciones necesarias para cambiar de estado inmediatamente a través de un botonazo, esto debido a que no es posible omitir el color amarillo (preventivo) de un semáforo en la realidad.
Al terminar esta función el time_delay quedara con valor cero y el siguiente estado será ESTADO_ROJO, por lo que volveremos al estado inicial y comenzaremos nuevamente con el flujo normal de los colores del semáforo.
Proyecto de la práctica:
https://www.dropbox.com/sh/rtiuvtkls4dii03/AABRajbFkd_tTiKQr9M8Zxeja?dl=0Proyecto de la práctica:
No hay comentarios:
Publicar un comentario