- Eliminar una tarea en FreeRTOS Arduino
- ¿Qué es la cola en FreeRTOS?
- Crear una cola en FreeRTOS
- Diagrama de circuito
- Implementación de la cola FreeRTOS en Arduino IDE
En el tutorial anterior, presentamos FreeRTOS en Arduino Uno y creamos una tarea para el LED parpadeante. Ahora, en este tutorial, profundizaremos más en los conceptos avanzados de las API de RTOS y aprenderemos sobre la comunicación entre diferentes tareas. Aquí también aprendemos sobre la cola para transferir datos de una tarea a otra y demostramos el funcionamiento de las API de cola mediante la interfaz de 16x2 LCD y LDR con Arduino Uno.
Antes de discutir sobre las colas, veamos una API de FreeRTOS más que es útil para eliminar las tareas cuando se termina con el trabajo asignado. A veces, la tarea debe eliminarse para liberar la memoria asignada. Continuando con el tutorial anterior, usaremos la función API vTaskDelete () en el mismo código para eliminar una de las tareas. Una tarea puede utilizar la función API vTaskDelete () para borrarse a sí misma o cualquier otra tarea.
Para utilizar esta API, debe configurar el archivo FreeRTOSConfig.h . Este archivo se utiliza para adaptar FreeRTOS según la aplicación. Se utiliza para cambiar los algoritmos de programación y muchos otros parámetros. El archivo se puede encontrar en el directorio de Arduino, que generalmente está disponible en la carpeta Documentos de su PC. En mi caso, está disponible en \ Documents \ Arduino \ libraries \ FreeRTOS \ src como se muestra a continuación.
Ahora, abre este archivo con cualquier editor de texto y la búsqueda de la #define INCLUDE_vTaskDelete y asegúrese de que su valor es '1' (1 significa habilitar y 0 significa desactivar). Es 1 por defecto, pero lo comprueba.
Usaremos este archivo de configuración con frecuencia en nuestros próximos tutoriales para configurar los parámetros.
Ahora, veamos cómo eliminar una tarea.
Eliminar una tarea en FreeRTOS Arduino
Para eliminar una tarea, tenemos que usar la función API vTaskDelete (). Solo se necesita un argumento.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Es el identificador de la tarea que se va a eliminar. Es el mismo que el 6 º argumento de xTaskCreate () API. En el tutorial anterior, este argumento se establece como NULL pero puede pasar la dirección del contenido de la tarea usando cualquier nombre. Digamos si desea configurar el identificador de tareas para Task2 que se declara como
TaskHandle_t any_name; Ejemplo: TaskHandle_t xTask2Handle;
Ahora, en vTaskCreate () de la API establece 6 º argumento como
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Ahora se puede acceder al contenido de esta tarea utilizando el identificador proporcionado por usted.
Además, una tarea puede borrarse a sí misma pasando NULL en lugar de un identificador de tarea válido.
Si queremos eliminar la Tarea 3 de la misma tarea 3, debe escribir vTaskDelete (NULL); dentro de la función Task3 pero si desea eliminar la tarea 3 de la tarea 2, escriba vTaskDelete (xTask3Handle); dentro de la función task2.
En el código del tutorial anterior, para eliminar Task2 de task2, simplemente agregue vTaskDelete (NULL); en la función void TaskBlink2 (void * pvParameters) . Entonces la función anterior se verá así
void TaskBlink2 (void * pvParameters) { Serial.println (“Task2 se está ejecutando y está a punto de eliminarse”); vTaskDelete (NULL); pinMode (7, SALIDA); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Ahora, cargue el código y observe los LED y el monitor serial. Verá que el segundo LED no parpadea ahora y la tarea2 se elimina después de encontrar la API de eliminación.
Entonces, esta API se puede usar para detener la ejecución de la tarea en particular.
Ahora, comencemos con la cola.
¿Qué es la cola en FreeRTOS?
La cola es la estructura de datos que puede contener un número finito de elementos de tamaño fijo y se opera en el esquema FIFO (primero en entrar, primero en salir). Las colas proporcionan un mecanismo de comunicación de tarea a tarea, tarea a interrupción e interrupción a tarea.
El número máximo de elementos que puede contener la cola se denomina "longitud". Tanto la longitud como el tamaño de cada elemento se establecen cuando se crea la cola.
Un ejemplo de cómo se usa la cola para la transferencia de datos se ilustra bien en la documentación de FreeRTOS que se puede encontrar aquí. Puede comprender fácilmente el ejemplo dado.
Después de comprender las colas, intentemos comprender el proceso de creación de una cola e intentemos implementarlo en nuestro código FreeRTOS.
Crear una cola en FreeRTOS
Primero, describa el enunciado del problema que se implementará con la ayuda de la cola FreeRTOS y Arduino Uno.
Queremos imprimir el valor del sensor LDR en una pantalla LCD de 16 * 2. Así que ahora hay dos tareas
- Task1 está obteniendo valores analógicos de LDR.
- Task2 está imprimiendo el valor analógico en la pantalla LCD.
Entonces, aquí la cola juega su papel porque envía los datos generados por task1 a task2. En task1, enviaremos valor analógico a la cola y en task2, lo recibiremos de la cola.
Hay tres funciones para trabajar con colas
- Crear una cola
- Envío de datos a la cola
- Recibir datos de la cola
Para crear una cola, use la API de función xQueueCreate (). Se necesitan dos argumentos.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: el número máximo de elementos que la cola que se está creando puede contener en cualquier momento.
uxItemSize: el tamaño en bytes de cada elemento de datos que se puede almacenar en la cola.
Si esta función devuelve NULL, la cola no se crea debido a la memoria insuficiente y si devuelve un valor no NULL, la cola se crea correctamente. Almacene este valor de retorno en una variable para usarlo como identificador para acceder a la cola como se muestra a continuación.
QueueHandle_t queue1; cola1 = xQueueCreate (4, tamaño de (int));
Esto creará una cola de 4 elementos en la memoria del montón de tamaño int (2 bytes de cada bloque) y almacenará el valor de retorno en la variable de control queue1 .
2. Envío de datos a la cola en FreeRTOS
Para enviar los valores a la cola, FreeRTOS tiene 2 variantes de API para este propósito.
- xQueueSendToBack (): se utiliza para enviar datos a la parte posterior (cola) de una cola.
- xQueueSendToFront (): se utiliza para enviar datos al frente (cabeza) de una cola.
Ahora , xQueueSend () es equivalente y exactamente igual que xQueueSendToBack ().
Todas estas API toman 3 argumentos.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: el identificador de la cola a la que se envían (escriben) los datos. Esta variable es la misma que se utiliza para almacenar el valor de retorno de la API xQueueCreate.
pvItemToQueue: un puntero a los datos que se copiarán en la cola.
xTicksToWait: la cantidad máxima de tiempo que la tarea debe permanecer en el estado Bloqueado para esperar a que haya espacio disponible en la cola.
Establecer xTicksToWait en portMAX_DELAY hará que la tarea espere indefinidamente (sin tiempo de espera), siempre que INCLUDE_vTaskSuspend se establezca en 1 en FreeRTOSConfig.h, de lo contrario, puede usar la macro pdMS_TO_TICKS () para convertir un tiempo especificado en milisegundos en un tiempo especificado en ticks.
3. Recibir datos de la cola en FreeRTOS
Para recibir (leer) un elemento de una cola, se usa xQueueReceive (). El artículo que se recibe se elimina de la cola.
Esta API también toma tres argumentos.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
El primer y tercer argumento son los mismos que enviar API. Solo el segundo argumento es diferente.
const pvBuffer: un puntero a la memoria en la que se copiarán los datos recibidos.
Espero que haya entendido las tres API. Ahora, implementaremos estas API en el IDE de Arduino e intentaremos resolver el enunciado del problema que hemos descrito anteriormente.
Diagrama de circuito
Así es como se ve en el tablero:
Implementación de la cola FreeRTOS en Arduino IDE
Comencemos a escribir código para nuestra aplicación.
1. Primero, abra Arduino IDE e incluya el archivo de encabezado Arduino_FreeRTOS.h . Ahora, si se usa algún objeto del kernel como cola, incluya el archivo de encabezado. Como estamos usando 16 * 2 LCD, incluya también la biblioteca.
#incluir #incluir
2. Inicialice un identificador de cola para almacenar el contenido de la cola. Además, inicialice los números de pin de la pantalla LCD.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. En la configuración nula (), inicialice el monitor LCD y serie con una velocidad de 9600 baudios. Cree una cola y dos tareas utilizando las respectivas API. Aquí crearemos una cola de tamaño 4 con tipo entero. Crea una tarea con las mismas prioridades y luego intenta jugar con este número. Finalmente, inicie el programador como se muestra a continuación.
configuración vacía () { Serial.begin (9600); lcd. comienzo (16, 2); queue_1 = xQueueCreate (4, tamaño de (int)); if (queue_1 == NULL) { Serial.println ("No se puede crear la cola"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Ahora, cree dos funciones TaskDisplay y TaskLDR . En la función TaskLDR , lee el pin analógico A0 en una variable ya que tenemos LDR conectado al pin A0 de Arduino UNO. Ahora envíe el valor almacenado en la variable pasándolo a la API xQueueSend y envíe la tarea al estado de bloqueo después de 1 segundo usando la API vTaskDelay () como se muestra a continuación.
Void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Tarea1"); intensidad_corriente = analogRead (A0); Serial.println (intensidad_actual); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. De manera similar, cree una función para TaskDisplay y reciba los valores en una variable que se pasa a la función xQueueReceive . Además, xQueueReceive () devuelve pdPASS si los datos se pueden recibir correctamente de la cola y devuelve errQUEUE_EMPTY si una cola está vacía.
Ahora, muestre los valores en la pantalla LCD usando la función lcd.print () .
Void TaskDisplay (void * pvParameters) { int intensidad = 0; while (1) { Serial.println ("Tarea2"); if (xQueueReceive (cola_1, & intensidad, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensidad:"); lcd.setCursor (11, 0); lcd.print (intensidad); } } }
Eso es. Hemos terminado la parte de codificación de la implementación de la cola. El código completo con un video funcional se puede encontrar al final.
Ahora, conecte la pantalla LCD y LDR con Arduino UNO de acuerdo con el diagrama de circuito y cargue el código. Abra el monitor de serie y observe las tareas. Verá que las tareas están cambiando y los valores de LDR están cambiando según la intensidad de la luz.
NOTA: La mayoría de las bibliotecas creadas para diferentes sensores no son compatibles con el kernel FreeRTOS debido a la implementación de la función de retraso dentro de las bibliotecas. El retraso hace que la CPU se detenga por completo, por lo tanto, el kernel FreeRTOS también deja de funcionar y el código no se ejecutará más y comienza a comportarse mal. Por lo tanto, tenemos que hacer que las bibliotecas no tengan demoras para trabajar con FreeRTOS.