INSTITUTO TECNOLÓGICO DEMORELIA INSTITUTO TECNOLOGICO DE MORELIA DEPARTAMENTO DE INGENIERÍA ELECTRÓNICA INGENIERIA ELECTRÓNICA Sistemas Operativos Embebidos Practica 4 Filas en FreeRTOS Claudia Lizeth Rodríguez González Edgar David Chávez Tapia MAESTRO: Miguel Angel Fraga MORELIA, MICHOACÁN 07 de Diciembre de 2020 Introducción Desarrollar un programa en FreeRTOS nos permite hacer varias tareas simultáneas con plazos de tiempo establecidos. Como ya se había visto anteriormente, cada tarea obtiene sus valores, y en este caso debemos hacer una tarea que nos envíe un dato obtenido en una tarea para poder utilizarlo en otra. Para esto, utilizamos QUEUE las cuales pueden ser utilizadas por cualquier otra tarea. Las queues, nos permiten enviar y recibir datos, cualquier tipo de dato puede ser usado en las queues, por lo que facilita la lectura y escritura para todas las tareas. En esta práctica desarrollamos el sistema para una máquina expendedora manejando las salidas con leds, lo cual en lo real, cada led sería un producto de la máquina. Desarrollando esta práctica, tuvimos que realizar dos tareas en FreeRTOS, las cuales fueron: a) Hacer la lectura del teclado b) Encender el mecanismo que da la salida De esta forma podemos una ejecución más rápida, y con el uso de queues en la primera tarea se crea el queue y se envía el dato y en el segundo, se hace una lectura del queue. Objetivo Aprender a usar correctamente FreeRTOS leyendo las filas y columnas de un teclado matricial y realizar dos tareas para poder comunicarse con queues. Desarrollo Para poder desarrollar la práctica se desarrollaron dos tareas: a) Hacer lectura del teclado matricial: obteniendo cada digito tecleado y estos datos meterlos a un vector para poder enviar el dato a la siguiente tarea. b) Realizar la lectura del dato obtenido y en base a este dato, es el led de salida que se deberá encender. Para saber que led encendería cada una de las salidas, se realizó bajo el siguiente esquema: Ilustración 1 Diagrama de salidas usadas Una vez obtenido el diagrama, iniciamos hacer las tareas: a) Para realizar la lectura del teclado, utilizamos el código ya proporcionado y explicado por el profesor, ya que aquí nos hace el barrido de las filas y columnas y pdemos encontrar el botón presionado. Al finalizar la lectura, guardamos el valor tecleado por el usuario en una variable y poderla enviar en el queue: Ilustración 2 Codigo para enviar los datos obtenidos en el queue b) Una vez obtenido el dato, tuvimos que hacer la lectura para poder prender el led correspondiente, según lo tecleado. Como solo nos quedaron 4 puertos digitales disponibles en nuestro arduino UNO, solo pudimos poner 4 salidas. Ilustración 3 Implementación de la segunda tarea. Obtencion de datos y los reimprime Código implementado #include <Arduino_FreeRTOS.h> #include <queue.h> QueueHandle_t datoQueue; #define COL0 2 #define REN0 6 #define MAXCOL 4 #define MAXREN 4 //leds const int A = 10; const int B = 11; const int C = 12; const int D = 13; void TaskTecla( void *pvParameters ){ unsigned int columna, renglon, codigo, teclaPresionada, anterior, contador; anterior=-1; contador=0; for(;;){ do{ teclaPresionada=0; //Explora la matriz de teclado for(columna=0;columna<MAXCOL;columna++){ digitalWrite(columna+COL0,LOW); for(renglon=0;renglon<MAXREN;renglon++){ if(LOW==digitalRead(renglon+REN0)) { teclaPresionada=1; codigo=(columna)|(renglon*MAXCOL); } } digitalWrite(columna+COL0,HIGH); } //Eliminación de rebotes if(1==teclaPresionada){ if(0==contador){ contador=1; anterior=codigo; }else{ if(anterior==codigo){ contador++; }else{ contador=1; anterior=codigo; } } }else contador=0; vTaskDelay(1); }while(contador<3); if(3==contador) Serial.println(codigo); //imprime el valor tecleado //Se declara que el queue enviará el dato guardado en "codigo" xQueueSend(datoQueue, &codigo, portMAX_DELAY); vTaskDelay(30); } } //Tarea para salidas - leds void TaskLed (void *pvParameters){ (void) pvParameters; vTaskDelay(1); int numQueue=0; for(;;){ //Recibe el dato enviado en la tarea pasada y lo guarda en una nueva variable if (xQueueReceive(datoQueue, &numQueue, portMAX_DELAY) == pdPASS){ Serial.print("dato recibido: "); Serial.println(numQueue); //imprime para verificar el dato obtenido if (numQueue==0){ digitalWrite(A , HIGH); // poner el Pin en HIGH vTaskDelay(133); // esperar un segundo digitalWrite(A , LOW); // poner el Pin en LOW } else if (numQueue==2){ digitalWrite(B , HIGH); // poner el Pin en HIGH vTaskDelay(133); // esperar un segundo digitalWrite(B , LOW); // poner el Pin en LOW } else if (numQueue==4){ digitalWrite(C , HIGH); // poner el Pin en HIGH vTaskDelay(133); // esperar un segundo digitalWrite(C , LOW); // poner el Pin en LOW } else{ digitalWrite(D , HIGH); // poner el Pin en HIGH vTaskDelay(133); // esperar un segundo digitalWrite(D , LOW); // poner el Pin en LOW } } } } void setup() { // Configura los GPIO pinMode(COL0,OUTPUT); pinMode(COL0+1,OUTPUT); pinMode(COL0+2,OUTPUT); pinMode(COL0+3,OUTPUT); pinMode(REN0,INPUT_PULLUP); pinMode(REN0+1,INPUT_PULLUP); pinMode(REN0+2,INPUT_PULLUP); pinMode(REN0+3,INPUT_PULLUP); digitalWrite(COL0,HIGH); digitalWrite(COL0+1,HIGH); digitalWrite(COL0+2,HIGH); digitalWrite(COL0+3,HIGH); // inicializa el puerto serie Serial.begin(9600); while (!Serial) { ; // Espera a que se conecte } //Declaramos los queues datoQueue = xQueueCreate (2, sizeof (int)); //Creamos las tareas que se utilizaran if( datoQueue != NULL){ //Tarea para la lectura del teclado, con prioridad 1 xTaskCreate(TaskTecla, "Teclado", 128,NULL,1, NULL ); //Tarea para encender los leds, con prioridad 2 xTaskCreate(TaskLed, "LED", 128, NULL, 2, NULL); } //Declaramos los pines de los leds como salidas pinMode(A,OUTPUT); pinMode(B,OUTPUT); pinMode(C,OUTPUT); pinMode(D,OUTPUT); } void loop(){} Evidencias Ilustración 4 Puerto Serial donde nos muestra primero el dato tecleado y en seguida el dato como se recibe en la segunda tarea Ilustración 5 Al presionar el 0 se prende el led 1 conectado al puerto 10 Ilustración 6 Al presionar el 2 se prende el led 2 conectado al puerto 11 Ilustración 7 Al presionar el 4 se prende el led 3 conectado al puerto 12 Ilustración 8 Al presionar el 6 se prende el led 4 conectado al puerto 13 Ilustración 9 Conexiones usadas Conclusiones El uso de las filas para la comunicación entre tareas en freeRTOS hace mucho más sencilla la implementación de nuestra máquina expendedora pues en una tarea realizamos lo que es el barrido del teclado, eliminación de rebotes y guardamos el valor presionado en nuestra fila. Mientras en la segunda tarea realizamos la lectura y verificación del valor de nuestra fila y la acción para la entrega del producto. Para realizar las tareas es muy sencillo, sin embargo para poder hacer el envío de datos por medio de los queues fue donde nos costó un poco más de trabajo, ya que no teníamos bien claro cómo es que funcionaba. Una vez que se entendió la sintaxis y los parámetros que utiliza, fue muy sencillo hacer la realización de la segunda tarea, ya que únicamente se debía encender cada led presionado por 2 segundos, lo cual en tiks son 133. En lo personal, creo que es un poco más complejo realizar un programa en FreeRTOS que en este caso hubiéramos podido hacerlo con una máquina de estados.