Tutoriales de FreeRTOS en Arduino
Tutoriales de FreeRTOS en Arduino
Fre
Tarea eRTOS para parpadear un LED en Arduino UNO
El sistema operativo presente en los dispositivos embebidos se llama RTOS (Sistema Operativo en Tiempo Real)
Sistema). En dispositivos embebidos, las tareas en tiempo real son críticas donde el tiempo juega un papel muy
papel importante. Las tareas en tiempo real son deterministas en el tiempo, lo que significa que el tiempo de respuesta a cualquier
el evento es siempre constante por lo que se puede garantizar que cualquier evento en particular ocurrirá
a una hora fija. El RTOS está diseñado para ejecutar aplicaciones con un temporizador muy preciso y un alto
grado de confiabilidad. RTOS también ayuda en la multitarea con un solo núcleo.
En este tutorial, comenzaremos con FreeRTOS. FreeRTOS es una clase de RTOS para
dispositivos embebidos que son lo suficientemente pequeños como para funcionar en microcontroladores de 8/16 bits,
aunque su uso no está limitado a estos microcontroladores. Es completamente de código abierto
y su código está disponible engithubSi conocemos algunos conceptos básicos de RTOS, entonces es
muy fácil de usar FreeRTOS porque tiene APIs bien documentadas que se pueden utilizar directamente
utilizado en el código sin conocer la parte del backend de la codificación. CompletoFreeRTOS
documentaciónse puede encontrar aquí.
Dado que FreeRTOS puede ejecutarse en un MCU de 8 bits, también se puede ejecutar en la placa Arduino Uno. Nosotros
solo tienes que descargar la biblioteca FreeRTOS y luego comenzar a implementar el código usando
APIs. Este tutorial está destinado a un principiante completo, a continuación se presentan los temas que cubriremos.
en este tutorial de Arduino FreeRTOS:
Antes de comenzar a trabajar con RTOS, veamos qué es una Tarea. Una Tarea es un fragmento de código que
está programado en la CPU para ejecutarse. Así que, si quieres realizar alguna tarea, entonces
debe ser programado utilizando un retraso del núcleo o utilizandointerrupcionesEste trabajo es realizado por
Planificador presente en el núcleo. En un procesador de un solo núcleo, el planificador ayuda a las tareas a
ejecutar en un intervalo de tiempo particular, pero parece que diferentes tareas se están ejecutando
simultáneamente. Cada tarea se ejecuta de acuerdo con la prioridad asignada a ella.
Ahora, veamos qué sucede en el núcleo RTOS si queremos crear una tarea para el LED
parpadeando con un intervalo de un segundo y asigna esta tarea a la máxima prioridad.
Además de la tarea LED, habrá una tarea más que es creada por el núcleo, que es
conocido como una tarea ociosa. La tarea ociosa se crea cuando no hay ninguna tarea disponible para su ejecución.
Esta tarea siempre se ejecuta con la prioridad más baja, es decir, prioridad 0. Si analizamos el gráfico de tiempo
dado lo anterior, se puede ver que la ejecución comienza con una tarea LED y se ejecuta durante un
el tiempo especificado, entonces para el tiempo restante, la tarea ociosa se ejecuta hasta que ocurre una interrupción de tick.
Luego el kernel decide qué tarea debe ejecutarse de acuerdo con la prioridad de la tarea
y el tiempo total transcurrido de la tarea LED. Cuando se completa 1 segundo, el kernel elige
la tarea led se ejecuta de nuevo porque tiene una mayor prioridad que la tarea de inactividad, podemos
también di que la tarea del LED interrumpe la tarea inactiva. Si hay más de dos tareas con
la misma prioridad, luego se ejecutarán en forma de ronda durante un tiempo determinado.
Si la Tarea1 está suspendida en estado en ejecución usando las APIs de Suspender, entonces la Tarea1 pasará a
Estado suspendido y no está disponible para el programador nuevamente. Si reanudas Task1 en
el estado suspendido luego volverá al estado de listo como puedes ver en el bloque
diagrama.
Esta es la idea básica de cómo se ejecutan las tareas y cambian sus estados. En este tutorial, nosotros
se implementarán dos tareas en Arduino Uno utilizando la API de FreeRTOS.
2. Planificador: Es responsable de seleccionar una tarea de la lista de estado listo para la ejecución.
estado. Los planificadores a menudo se implementan para mantener todos los recursos informáticos ocupados (como
en balanceo de carga).
3. Preemption: Es el acto de interrumpir temporalmente una tarea que ya se está ejecutando con el
intención de eliminarlo del estado de ejecución sin su cooperación.
Programación Preventiva: En este tipo de programación, las tareas se ejecutan con igual tiempo
rebanar sin tener en cuenta las prioridades.
2. Basado en prioridades preemptivo: La tarea de alta prioridad se ejecutará primero.
3. Programación cooperativa: el cambio de contexto ocurrirá solo con la co-
operación de ejecución de tareas. La tarea se ejecutará continuamente hasta que se llame a la cesión de la tarea.
6. Objetos del Kernel: Para señalar a la tarea que realice algún trabajo, la sincronización
se utiliza un proceso. Para llevar a cabo este proceso se utilizan objetos del núcleo. Algunos objetos del núcleo
son Eventos, Semáforos, Colas, Mutex, Buzones, etc. Veremos cómo usar estos
objetos en los próximos tutoriales.
A partir de la discusión anterior, hemos obtenido algunas ideas básicas sobre el concepto de RTOS y
ahora podemos implementar el proyecto FreeRTOS en Arduino. Así que, empecemos por
instalando bibliotecas FreeRTOS en Arduino IDE.
1. Abre el IDE de Arduino y ve a Esbozo -> Incluir biblioteca -> Administrar bibliotecas.
Busca FreeRTOS e instala la biblioteca como se muestra a continuación.
Puedes descargar la biblioteca de github y agregar el archivo .zip en Sketch -> Incluir
Biblioteca
Ahora, reinicia el IDE de Arduino. Esta biblioteca proporciona algunos ejemplos de código, también que se pueden
encontrado en el archivo -> Ejemplos -> FreeRTOS como se muestra a continuación.
Aquí escribiremos el código desde cero para entender cómo funciona, más adelante podrás verificar
los códigos de ejemplo y úsalos.
Diagrama de circuito
A continuación se muestra el diagrama de circuito para crear la tarea de LED parpadeante utilizando FreeRTOS en Arduino:
Ejemplo de Arduino FreeRTOS - Creando tareas FreeRTOS en
Arduino IDE
Veamos una estructura básica para escribir un proyecto de FreeRTOS.
#include <Arduino_FreeRTOS.h>
2. Da el prototipo de función de todas las funciones que estás escribiendo para la ejecución que es
escrito como
..
….
Para crear una tarea, se llama a la API xTaskCreate() en la función de configuración con ciertos
parámetros/argumentos.
xTaskCreate(task1,"task1",128,NULL,1,NULL);
5. La función loop() vacía permanecerá vacía ya que no queremos ejecutar ninguna tarea manualmente y
infinitamente. Porque la ejecución de tareas ahora está manejada por el Programador.
6. Ahora, tenemos que implementar funciones de tarea y escribir la lógica que deseas ejecutar.
dentro de estas funciones. El nombre de la función debe ser el mismo que el primer argumento
API ofxTaskCreate()
while(1) {
..
..//tu lógica
}
7. La mayoría del código necesita una función de retraso para detener la tarea en ejecución, pero en RTOS no es así.
se sugiere usar la función Delay() ya que detiene la CPU y, por lo tanto, el RTOS también se detiene
trabajando. Así que FreeRTOS tiene una API del núcleo para bloquear la tarea por un tiempo específico.
Esta API se puede usar para propósitos de retraso. Esta API retrasa una tarea por un número dado de
Tics. El tiempo real durante el cual la tarea permanece bloqueada depende de la tasa de tics. El
constantportTICK_PERIOD_MS se puede utilizar para calcular el tiempo real a partir de la tasa de ticks.
Esto significa que si quieres un retraso de 200 ms, solo escribe esta línea
Así que para este tutorial, utilizaremos estas API de FreeRTOS para implementar tres tareas.
APIs a utilizar:
1. xTaskCreate();
2. vTaskStartScheduler();
3. vTaskDelay();
Tarea a crear para este tutorial:
#include <Arduino_FreeRTOS.h>
void configuración() {
Serial.begin(9600);
xTaskCreate(TaskBlink1,"Task1",128,NULL,1,NULL);
xTaskCreate(TaskBlink2,"Task2 ",128,NULL,1,NULL);
vTaskStartScheduler();
3. Ahora, implementa las tres funciones como se muestra a continuación para la tarea 1 de parpadeo de LED.
pinMode(8, SALIDA);
mientras(1)
digitalWrite(8, ALTO);
digitalWrite(8, BAJO);
int contador = 0;
mientras(1)
contador++;
Serial.println(contador);
vTaskDelay( 500 / portTICK_PERIOD_MS );
Eso es todo. Hemos completado con éxito un proyecto de FreeRTOS para Arduino.
Uno. Puedes encontrar el código completo junto con un video al final de este tutorial.
Además, observa los LEDs, están parpadeando en diferentes intervalos de tiempo. Intenta jugar con el
argumento de prioridad en la función xTaskCreate. Cambia el número y observa el
comportamiento en el monitor serial y LEDs.
Ahora, puedes entender los dos primeros códigos de ejemplo en los que se lee analógicamente y digitalmente.
se crean tareas de lectura. De esta manera, puedes hacer proyectos más avanzados utilizando solo
Arduino Uno y APIs de FreeRTOS.
Código
#include <Arduino_FreeRTOS.h>
void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );
void TareaImprimir( void *pvParametros );
void setup() {
// inicializar la comunicación serie a 9600 bit por segundo:
Serial.begin(9600);
xTaskCreate(
TaskBlink1
task1
, 128
NULL
, 1
, NULL );
xTaskCreate(
TaskBlink2
task2
128
, NULO
, 1
, NULO );
xTaskCreate(
Impresión de tarea
task3
, 128
, NULO
, 1
, NULO );
vTaskStartScheduler();
}
void loop()
{
}
void TaskBlink1(void *pvParameters) {
pinMode(8, SALIDA);
while(1)
{
Serial.println("Tarea1");
digitalWrite(8, ALTO);
vTaskDelay( 200 / portTICK_PERIOD_MS );
digitalWrite(8, BAJO);
vTaskDelay( 200 / portTICK_PERIOD_MS );
}
}
void TaskBlink2(void *pvParameters)
{
pinMode(7, SALIDA);
mientras(1)
{
Serial.println("Tarea2");
digitalWrite(7, ALTO);
vTaskDelay( 300 / portTICK_PERIOD_MS );
digitalWrite(7, BAJO);
vTaskDelay( 300 / portTICK_PERIOD_MS );
}
}
void Taskprint(void *pvParameters) {
int contador = 0;
mientras(1)
{
contador++;
Serial.println(contador);
vTaskDelay(500 / portTICK_PERIOD_MS); }
}
Vídeo
#include <Arduino_FreeRTOS.h>
void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );
void Taskprint( void *pvParameters );
void setup() {
// inicializar la comunicación serie a 9600 bits por segundo:
Serial.begin(9600);
xTaskCreate(
TareaParpadear1
tarea1
, 128
, NULL
, 1
, NULO );
xTaskCreate(
TaskBlink2
task2
128
, NULO
, 1
, NULO );
xTaskCreate(
Impresión de tareas
task3
128
, NULO
, 1
, NULO );
vTaskStartScheduler();
}
vacío bucle()
{
}
void TaskBlink1(void *pvParameters) {
pinMode(8, SALIDA);
mientras(1)
{
Serial.println("Tarea1");
digitalWrite(8, ALTO);
vTaskDelay( 200 / portTICK_PERIOD_MS );
digitalWrite(8, BAJO);
vTaskDelay( 200 / portTICK_PERIOD_MS );
}
}
void TaskBlink2(void *pvParameters)
{
pinMode(7, SALIDA);
mientras(1)
{
Serial.println("Tarea2");
digitalWrite(7, ALTO);
vTaskDelay( 300 / portTICK_PERIOD_MS );
digitalWrite(7, BAJO);
vTaskDelay( 300 / portTICK_PERIOD_MS );
}
}
void TareaImprimir(void *pvParametros) {
int contador = 0;
mientras(1)
{
contador++;
Serial.println(contador);
vTaskDelay(500 / portTICK_PERIOD_MS); }
}
PARTE 2
Tutorial de Arduino FreeRTOS 2 - Usando
Colas en Arduino FreeRTOS
INCRUSTADO
PorRishabh Jain06 de abril de 20200
Arduino FreeRTOS utilizando Colas
En el tutorial anterior, presentamosFreeRTOS en Arduino Uno y se creó una tarea para
el LED parpadeanteAhora, en este tutorial, profundizaremos más en los conceptos avanzados de RTOS
APIs y aprender sobre la comunicación entre diferentes tareas. Aquí también aprendemos sobre
Cola para transferir datos de una tarea a otra y demostrar el funcionamiento de
Colas de APIs mediante la interfaz de un LCD 16x2 y un LDR con el Arduino Uno.
Antes de discutir sobre las Colas, veamos una API más de FreeRTOS que es útil en
eliminando las tareas cuando se ha terminado con el trabajo asignado. A veces la tarea necesita
ser eliminado para liberar la memoria asignada. En continuación de latutorial anterior, nosotros vamos a
usevTaskDelete() función API en el mismo código para eliminar una de las tareas. Una tarea puede
utilice la función API vTaskDelete() para eliminarse a sí mismo, o cualquier otra tarea.
Para usar esta API, tienes que configurar el archivo FreeRTOSConfig.h. Este archivo se utiliza para
ajustar FreeRTOS según la aplicación. Se utiliza para cambiar la programación
algoritmos y muchos otros parámetros. El archivo se puede encontrar en el directorio de Arduino
que generalmente está disponible en la carpeta Documentos de tu PC. En mi caso, es
disponible en\Documentos\Arduino\libraries\FreeRTOS\srccomo se muestra a continuación.
Ahora, abre este archivo con cualquier editor de texto y busca #define
INCLUDE_vTaskDelete y asegúrate de que su valor sea '1' (1 significa habilitar y 0 significa
desactivado). Por defecto es 1, pero lo comprueba.
Estaremos utilizando este archivo de configuración frecuentemente en nuestros próximos tutoriales para establecer los parámetros.
TaskHandle_t cualquier_nombre;
El contenido de esta tarea ahora se puede acceder utilizando el identificador que usted proporcionó.
Además, una tarea puede eliminarse a sí misma al pasar NULL en lugar de un identificador de tarea válido.
En el código del tutorial anterior, para eliminar Task2 desde la propia task2, simplemente
agregar vTaskDelete(NULL); en la función void TaskBlink2(void *pvParameters). Luego el
la función anterior se verá así
vTaskDelete(NULL);
pinMode(7, SALIDA);
mientras(1)
digitalWrite(7, ALTO);
vTaskDelay( 300 / portTICK_PERIOD_MS );
digitalWrite(7, BAJO);
Ahora, suba el código y observe los LEDs y el monitor serie. Verá que el
el segundo LED no parpadea ahora y la tarea2 se ha eliminado después de encontrar la API de eliminación.
Por lo tanto, esta API se puede usar para detener la ejecución de la tarea en particular.
El número máximo de elementos que una cola puede contener se llama su "longitud". Tanto la longitud
y el tamaño de cada elemento se establece cuando se crea la cola.
Un ejemplo de cómo se utiliza la cola para la transferencia de datos se ilustra bien en FreeRTOS.
documentación que puede serencontrado aquí. Puedes entender fácilmente el ejemplo dado.
Después de entender las colas, intentemos comprender el proceso de crear una cola
y tratar de implementarlo en nuestro código de FreeRTOS.
Queremos imprimir el valor del sensor LDR en una pantalla LCD de 16*2. Así que hay dos tareas.
ahora
La cantidad máxima de elementos que la cola que se está creando puede contener
en cualquier momento.
Si esta función devuelve NULL, entonces la cola no se crea debido a memoria insuficiente
y si devuelve un valor no nulo, la cola se crea exitosamente. Almacena este retorno
valor a una variable para usarlo como un manejador para acceder a la cola como se muestra a continuación.
QueueHandle_t cola1;
Esto creará una cola de 4 elementos en la memoria heap de tamaño int (2 bytes de cada bloque)
y almacena el valor de retorno en la variable queue1handle.
Para enviar los valores a la cola, FreeRTOS tiene 2 variantes de API para este propósito.
xQueue: El manejador de la cola a la que se están enviando (escribiendo) los datos. Esta variable
es el mismo que se utiliza para almacenar el valor de retorno de la API xQueueCreate.
Para recibir (leer) un elemento de una cola, se utiliza xQueueReceive(). El elemento que es
recibido se elimina de la cola.
El primer y tercer argumento son los mismos que enviar API. Solo el segundo argumento es
diferente.
Espero que hayas entendido las tres API. Ahora, implementaremos estas API en el Arduino.
IDE y trata de resolver el problema que hemos descrito anteriormente.
Diagrama de circuito
1. Primero, abre el IDE de Arduino e incluye el archivo de encabezado Arduino_FreeRTOS.h. Ahora, si hay algún
Si se utiliza un objeto de núcleo como una cola, entonces incluye el archivo de encabezado de él. Como estamos utilizando 16*2
LCD, así que incluye también la biblioteca para ello.
#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <LiquidCrystal.h>
2. Inicializa un manejador de cola para almacenar el contenido de la cola. También, inicializa el pin de LCD
números.
QueueHandle_t cola_1;
3. En la función setup(), inicializa el LCD y el monitor serie con una velocidad de 9600 baudios. Crea una cola.
y dos tareas utilizando las respectivas API. Aquí crearemos una cola de tamaño 4 con
tipo entero. Crea una tarea con prioridades iguales y luego intenta jugar con este número.
Por fin, inicia el programador como se muestra a continuación.
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
si (queue_1 == NULL) {
vTaskStartScheduler();
int intensidad_actual;
mientras(1) {
Serial.println("Tarea1");
corriente_intensidad = analogRead(A0);
Serial.println(intensidad_actual);
5. De manera similar, crea una función para TaskDisplay y recibe los valores en una variable que es
se pasó a la función xQueueReceive. Además, xQueueReceive() devuelve pdPASS si el
los datos se pueden recibir con éxito de la cola y devolverá ERR_QUEUE_EMPTY si un
la cola está vacía.
int intensidad = 0;
mientras(1) {
Serial.println("Tarea2");
lcd.limpiar();
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 Cola. Código completo
con un video que se puede encontrar al final.
Ahora, conecta el LCD y el LDR con Arduino UNO según el diagrama de circuito
sube el código. Abre el monitor serial y observa las tareas. Verás que las tareas son
los valores de conmutación y 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
El kernel de FreeRTOS debido a la implementación de la función de retardo dentro de las bibliotecas. El retardo hace
la CPU se detiene por completo, por lo tanto, el núcleo de FreeRTOS también deja de funcionar y el código
no ejecutará más y comenzará a comportarse mal. Así que, tenemos que hacer las bibliotecas
sin retrasos para trabajar con FreeRTOS.
Código
#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <LiquidCrystal.h>
QueueHandle_t cola_1;
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // RST E D4 D5 D6 D7
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
xQueueCreate(5, sizeof(int));
si (queue_1 == NULL) {
Serial.println("La cola no se puede crear");
}
xTaskCreate(TaskDisplay, "Tarea_Display", 128, NULL, 1, NULL);
xTaskCreate(TaskLDR, "LDR_tarea", 128, NULL, 1, NULL);
vTaskStartScheduler();
}
void loop() {
}
void TaskDisplay(void * pvParameters) {
int intensidad = 0;
mientras(1) {
Serial.println("TaskDisplay");
si (xQueueReceive(cola_1, &intensidad, portMAX_DELAY) == pdPASS) {
lcd.borrar();
lcd.setCursor(0, 0);
lcd.print("Intensidad:");
lcd.setCursor(11, 0);
lcd.print(intensidad);
}
}
}
void TaskLDR(void * pvParameters) {
int intensidad_actual;
mientras(1) {
Serial.println("TareaLDR");
intensidad_actual = analogRead(A0);
Serial.println(intensidad_actual);
xQueueSend(queue_1, ¤t_intensity, portMAX_DELAY);
vTaskDelay( 1000 / portTICK_PERIOD_MS );
}
}
Vídeo
PARTE 3
Tutorial de Arduino FreeRTOS 3 - Uso de
Semáforo y Mutex en FreeRTOS
con Arduino
INTEGRADO
PorRishabh Jain09 de abril de 20200
Semáforo y Mutex en FreeRTOS con Arduino
En tutoriales anteriores, hemos cubierto elfundamentos de FreeRTOS con Arduino y
elObjeto de kernel de cola en FreeRTOS ArduinoAhora, en este tercer tutorial de FreeRTOS, nosotros
aprenderá más sobre FreeRTOS y sus API avanzadas, que pueden hacer que entiendas
la plataforma de múltiples tareas más profundamente.
El semáforo y el mutex (exclusión mutua) son los objetos del núcleo que se utilizan para
sincronización, gestión de recursos y protección de recursos contra la corrupción. En el
en la primera mitad de este tutorial, veremos la idea detrás de Semaphore, cómo y dónde usarlo
En la segunda mitad, continuaremos con Mutex.
¿Qué es un Semáforo?
En tutoriales anteriores, hemos discutido sobre las prioridades de las tareas y también hemos llegado a conocer que un
una tarea de mayor prioridad interrumpe una tarea de menor prioridad, por lo que durante la ejecución de la tarea de alta prioridad
puede haber una posibilidad de que ocurra corrupción de datos en tareas de menor prioridad porque
no se ha ejecutado todavía y los datos están llegando continuamente a esta tarea desde un sensor que
causa pérdida de datos y mal funcionamiento de toda la aplicación.
Entonces, hay una necesidad de proteger los recursos de la pérdida de datos y aquí Semaphore juega un papel
papel importante.
El semáforo es un mecanismo de señalización en el que una tarea en estado de espera es señalizada por
otra tarea para ejecutar. En otras palabras, cuando una tarea 1 termine su trabajo, entonces
muestra una bandera o incrementa una bandera en 1 y luego esta bandera es recibida por otra tarea (tarea2)
mostrando que puede realizar su trabajo ahora. Cuando la tarea2 termine su trabajo, entonces la bandera estará
ser disminuido en 1.
Entonces, básicamente, es un mecanismo de 'Dar' y 'Tomar' y el semáforo es una variable entera.
que se utiliza para sincronizar el acceso a los recursos.
1 Semáforo Binario
2. Semáforo contador
1. Semáforo binario: Tiene dos valores enteros 0 y 1. Es algo similar a la
Cola de longitud 1. Por ejemplo, tenemos dos tareas, tarea1 y tarea2. Tarea1 envía datos
a task2, por lo que task2 verifica continuamente el elemento de la cola; si hay uno, entonces puede leer el
los datos, de lo contrario tiene que esperar hasta que se convierta en 1. Después de tomar los datos, la tarea 2 decrementa el
agregar a la cola y hacerlo 0 Eso significa que task1 nuevamente puede enviar los datos a task2.
Del ejemplo anterior, se puede decir que el semáforo binario se utiliza para
sincronización entre tareas o entre tareas e interrupciones.
2. Semáforo de conteo: Tiene valores mayores que 0 y se puede pensar como una cola de
longitud superior a 1. Este semáforo se utiliza para contar eventos. En este escenario de uso,
un manejador de eventos 'dará' un semáforo cada vez que ocurra un evento (incrementando el
valor de conteo del semáforo), y una tarea de controlador 'tomará' un semáforo cada vez que lo haga
procesa un evento (decrementando el valor del conteo del semáforo).
El valor del conteo es, por lo tanto, la diferencia entre el número de eventos que han
ocurrido y el número que ha sido procesado.
Ahora, puede haber dos tipos de APIs para el mismo objeto de núcleo. Si tenemos que dar
semaforo desde un ISR, entonces la API de semaforo normal no puede ser utilizada. Debería usar
API protegidas contra interrupciones.
Creando un Semáforo:
Para utilizar cualquier objeto de núcleo, primero tenemos que crearlo. Para crear un semáforo binario,
usevSemaphoreCreateBinary().
sema_v = xSemaphoreCreateBinary();
Dando un semáforo:
Para dar un semáforo, hay dos versiones: una para interrumpir y otra para el
tarea normal.
Para tomar un semáforo, utiliza la función API xSemaphoreTake(). Esta API toma dos
parámetros.
Ahora, utilicemos estas API y escribamos un código para realizar algunas tareas.
Para hacer que el sistema parezca multitarea, conecta otros LED con el pin 7 que estarán en
estado de parpadeo constante.
#include <Arduino_FreeRTOS.h>
#include <semphr.h>
2. Declare una variable de tipo SemaphoreHandle_t para almacenar los valores del semáforo.
SemaphoreHandle_t semáforoDeInterrupción;
3. En void setup(), crea dos tareas (TaskLED y TaskBlink) usando la API xTaskCreate()
y luego crea un semáforo usando xSemaphoreCreateBinary(). Crea una tarea con igual
prioridades y más tarde intenta jugar con este número. También, configura el pin 2 como una entrada y
habilita la resistencia de pull-up interna y conecta el pin de interrupción. Finalmente, inicia el
programador como se muestra a continuación.
void setup() {
pinMode(2, INPUT_PULLUP);
interruptSemaphore = xSemaphoreCreateBinary();
si (interruptSemaphore != NULL) {
4. Ahora, implementa la función ISR. Crea una función y nómbrala igual que la
segundo argumento de la función attachInterrupt(). Para que la interrupción funcione correctamente, tú
necesito eliminar el problema de rebote del botón pulsador utilizando la función millis o micros
y por ajustando el desacoplamientotiempo. De esto función
función callinterruptHandler() como se muestra a continuación.
void debounceInterrupt() {
interrumpirManejador();
micros();
}
void manejadorDeInterrupciones() {
xSemaphoreGiveFromISR(interruptSemaphore, NULL);
5. Crea una función TaskLed y dentro del bucle while, llama a la API xSemaphoreTake()
y verificar si el semáforo ha sido tomado exitosamente o no. Si es igual a pdPASS (es decir, 1)
entonces haz que el LED parpadee como se muestra a continuación.
(void) pvParameters;
pinMode(8, SALIDA);
mientras(1) {
digitalWrite(8, !digitalRead(8));
6. Además, crea una función para parpadear otro LED conectado al pin 7.
(vacío) pvParameters;
pinMode(7, SALIDA);
mientras(1) {
digitalWrite(7, ALTO);
vTaskDelay(200 / portTICK_PERIOD_MS);
digitalWrite(7, BAJO);
vTaskDelay(200 / portTICK_PERIOD_MS);
void loop() {}
Eso es todo, el código completo se puede encontrar al final de este tutorial. Ahora, sube este código.
y conecta los LED y el botón pulsador con el Arduino UNO según el circuito
diagrama.
Diagrama de Circuito
Después de cargar el código, verás que un LED parpadea después de 200 ms y cuando el
Al presionar el botón, inmediatamente el segundo LED brillará como se muestra en el video dado en
el fin.
De esta manera, los semáforos se pueden utilizar en FreeRTOS con Arduino donde sea necesario.
pasa los datos de una tarea a otra sin ninguna pérdida.
¿Qué es un Mutex?
Como se explicó arriba, el semáforo es un mecanismo de señalización, de manera similar, Mutex es un bloqueo.
mecanismo que a diferencia del semáforo tiene funciones separadas para incrementar y
decremento pero en Mutex, la función toma y da en sí misma. Es una técnica para evitar
la corrupción de los recursos compartidos.
Para proteger el recurso compartido, se le asigna una tarjeta de token (mutex) al recurso.
Quien tenga esta tarjeta puede acceder al otro recurso. Los demás deben esperar hasta que la tarjeta
devuelto. De esta manera, solo un recurso puede acceder a la tarea y los demás esperan su
oportunidad.
Aquí tenemos tres tareas, una para imprimir datos en el LCD, la segunda para enviar datos del LDR
tarea de LCD y última tarea para enviar datos de temperatura en LCD. Así que aquí hay dos tareas
compartiendo el mismo recurso, es decir, LCD. Si la tarea LDR y la tarea de temperatura envían datos
simultáneamente, entonces uno de los datos puede estar dañado o perdido.
Por lo tanto, para proteger la pérdida de datos, necesitamos bloquear el recurso LCD para la tarea1 hasta que termine.
la tarea de visualización. Luego, la tarea de LCD se desbloqueará y la tarea2 podrá realizar su trabajo.
Creando un Mutex:
Para crear un Mutex, utiliza la API xSemaphoreCreateMutex(). Como su nombre sugiere que
Un mutex es un tipo de semáforo binario. Se utilizan en diferentes contextos y propósitos.
Un semáforo binario se utiliza para sincronizar tareas, mientras que un Mutex se utiliza para proteger un
recurso compartido.
SemaphoreHandle_t mutex_v;
mutex_v = xSemaphoreCreateMutex();
Tomando un Mutex:
Dando un Mutex:
Después de acceder al recurso compartido, la tarea debe devolver el Mutex para que otros
Las tareas pueden acceder a it.xSemaphoreGive() API se utiliza para devolver el Mutex.
Usando las APIs anteriores, implementemos Mutex en el código de FreeRTOS utilizando Arduino
IDE.
Aquí el objetivo de esta parte es usar un monitor serie como un recurso compartido y dos
diferentes tareas para acceder al monitor serie para imprimir un mensaje.
#include <Arduino_FreeRTOS.h>
#include <semphr.h>
2. Declara una variable del tipo SemaphoreHandle_t para almacenar los valores de Mutex.
SemaphoreHandle_t mutex_v;
3. En void setup(), inicializa el monitor serie con una tasa de baudios de 9600 y crea dos
tareas (Tarea1 y Tarea2) utilizando la API xTaskCreate(). Luego crea un Mutex
usando xSemaphoreCreateMutex(). Crea una tarea con prioridades iguales y luego intenta
juega con este número.
void setup() {
Serial.begin(9600);
mutex_v = xSemaphoreCreateMutex();
si (mutex_v == NULL) {
4. Ahora, crea funciones de tarea para la Tarea1 y la Tarea2. En el bucle mientras de la función de tarea, antes de
imprimir un mensaje en el monitor serial tenemos que tomar un Mutex
usando xSemaphoreTake() luego imprime el mensaje y luego devuelve el Mutex
usandoxSemaphoreGive(). Luego da un retraso.
mientras(1) {
xSemaphoreTake(mutex_v, portMAX_DELAY);
xSemaphoreGive(mutex_v);
vTaskDelay(pdMS_TO_TICKS(1000));
Para probar el funcionamiento del Mutex, simplemente comenta xSemaphoreGive(mutex_v); de cualquier tarea.
Puedes ver que el programa se congela en el último mensaje de impresión.
Así es como se pueden implementar Semaphore y Mutex en FreeRTOS con Arduino. Para
más información sobre Semáforo y Mutex, puedes visitar el oficialdocumentaciónde
FreeRTOS.
Los códigos completos y el video para Semáforos y Silenciadores se dan a continuación.
Código
1 CÓDIGO para Semáforo:
2
#include <Arduino_FreeRTOS.h>
3
#include <semphr.h>
4
long debouncing_time = 150;
5
volatile unsigned long last_micros;
6
7
SemaphoreHandle_t interruptSemaphore;
8
9
void setup() {
10
pinMode(2, INPUT_PULLUP);
11
xTaskCreate(TaskLed, "Led", 128, NULL, 0, NULL);
12 xTaskCreate(TaskBlink, "LedBlink", 128, NULL, 0, NULL );
13 interruptSemaphore = xSemaphoreCreateBinary();
si (interruptSemaphore != NULL) {
14
adjuntarInterrupción(digitalPinToInterrupción(2), debounceInterrupción, BAJO);
15
}
16
}
17
18
void loop() {}
19
20
void manejadorDeInterrupciones() {
21
xSemaphoreGiveFromISR(interruptSemaphore, NULL);
22 }
23
25 {
26 (void) pvParameters;
pinMode(8, SALIDA);
27
para (;;) {
28
si (xSemaphoreTake(interruptSemaphore, portMAX_DELAY) == pdPASS) {
29
digitalWrite(8, !digitalRead(8));
30
}
31
}
32
}
34 {
35 (void) pvParameters;
36 pinMode(7, SALIDA);
37 por (;;) {
digitalWrite(7, ALTO);
38
vTaskDelay(200 / portTICK_PERIOD_MS);
39
digitalWrite(7, BAJO);
40
vTaskDelay(200 / portTICK_PERIOD_MS);
41
}
42
}
43
void debounceInterrupt() {
45 manejadorDeInterrupciones();
46 micros();
47 }
}
48
49
CÓDIGO para Mutex:
50
#include <Arduino_FreeRTOS.h>
51
#include <semphr.h>
52
53
SemaphoreHandle_t mutex_v;
54
void setup() {
55
Serial.begin(9600);
56
mutex_v = xSemaphoreCreateMutex();
57 si (mutex_v == NULL) {
59 }
60 xTaskCreate(Tarea1, "Tarea1", 128, NULL, 1, NULL);
}
62
63
void Task1(void *pvParameters) {
64
mientras(1) {
65
xSemaphoreTake(mutex_v, portMAX_DELAY);
66
Serial.println("Hola desde Task1");
67
xSemaphoreGive(mutex_v);
68
vTaskDelay(pdMS_TO_TICKS(1000));
69 }
70 }
71
73 mientras(1) {
xSemaphoreTake(mutex_v, portMAX_DELAY);
74
Hola desde Task2
75
xSemaphoreGive(mutex_v);
76
vTaskDelay(pdMS_TO_TICKS(500));
77
}
78
}
79
80
void loop() {
81 }
82
83
84
85
86
87
88
Video
CÓDIGO para Semáforo
#incluír <Arduino_FreeRTOS.h>
#include <semphr.h>
largo debouncing_time = 150;
volátil sin signo largo últimos_micros
SemaphoreHandle_t interruptSemaphore;
vacío configurar() {
pinMode(2, INPUT_PULLUP);
xTaskCreate(TaskLed, "Led", 128, NULL, 0, NULL);
xTaskCreate(TareaParpadeo, "LedParpadeo", 128, NULL, 0, NULL );
interruptSemaphore = xSemaphoreCreateBinary();
si (interruptSemaphore != NULL) {
adjuntarInterrupción(digitalPinToInterrupción(2), interrupciónDeBoteo, BAJO);
}
}
vacío loop() {}
vacío manejarInterrupcion() {
xSemaphoreGiveFromISR(interruptSemaphore, NULL);
}
SemaphoreHandle_t mutex_v;
vacío configuración() {
Serial.begin(9600);
mutex_v = xSemaphoreCreateMutex();
si (mutex_v == NULL) {
No se puede crear el mutex
}
xTaskCreate(Task1, "Task1", 128, NULL, 1, NULL);
xTaskCreate(Tarea2, "Tarea2", 128, NULL, 1, NULL);
}
vacío bucle() {
}
Tutorial
Entendiendo los Sistemas Operativos en Tiempo Real
Entendiendo lo Real
Sistema Operativo en Tiempo Real (RTOS)
Los sistemas embebidos tienen una amplia gama de aplicaciones en todos los dispositivos electrónicos alrededor.
nosotros, un ejemplo evidente es el mini portátil que llevamos con nosotros todo el tiempo, sí yo
me refiero a nuestros teléfonos móviles.
¿Qué es RTOS?
El sistema operativo en tiempo real, popularmente conocido como RTOS, proporciona al controlador la capacidad
responder a las entradas y completar tareas dentro de un período de tiempo específico basado en prioridades.
A primera vista, un RTOS podría sonar como cualquier otro programa embebido o
firmware, pero está construido sobre la arquitectura de un sistema operativo. Por lo tanto, como cualquier
el sistema operativo RTOS puede permitir que múltiples programas se ejecuten al mismo tiempo
Soporte de multiplexión. Como sabemos, el núcleo de un procesador o controlador solo puede
ejecuta una sola instrucción a la vez, pero el RTOS tiene algo llamado
el programador que decide qué instrucción ejecutar primero y así ejecuta el
instrucciones de múltiples programas una tras otra. Técnicamente, un RTOS solo crea
una ilusión de multitarea al ejecutar instrucciones paralelas una a la vez.
Esto hace que RTOS sea adecuado para diversas aplicaciones en el mundo real. En RTOS, para cualquier entrada
siempre que una lógica ha sido evaluada que da la salida correspondiente. Esta lógica es
medido no solo en función de la creatividad lógica sino también de la duración del tiempo
en el que se ha realizado la tarea específica. Si un sistema falla en realizar la tarea en ese
La duración específica del tiempo se conoce como falla del sistema.
La compartición del tiempo es la base de la ejecución Los procesos se ejecutan sobre la base de
1
de procesos en el sistema operativo el orden de su prioridad
Tipos de RTOS
Podemos categorizar los sistemas operativos en tiempo real principalmente en tres partes, a saber
El ejemplo más fácil de usar un RTOS suave es una base de datos en línea, ya que dentro del RTOS suave el
el parámetro que más nos preocupa es la velocidad. Por lo tanto, las características de un RTOS blando son:
Un brazo robótico que se utiliza para recoger objetos puede considerarse como uno de los
ejemplo de RTOS firme. Aquí, dentro de este RTOS firme, incluso si el proceso se retrasa, es
tolerado.
Ahora, a pesar de tener muchas ventajas para RTOS en aplicaciones del mundo real, tiene
también hay varias desventajas. Algunos de los problemas relacionados con ello se discuten aquí.
. Las interrupciones se utilizan normalmente en los programas para detener el programa en ejecución y desviar
el flujo a otra parte importante del código. Aquí, dentro del RTOS, ya que es rápido
se requiere tiempo de respuesta; se recomienda que las interrupciones deban estar desactivadas para
un tiempo mínimo posible.
. Dado que el núcleo también debe responder a varios eventos, es necesario que
tenga un tamaño de núcleo menor para que quepa adecuadamente dentro de la ROM
. Las características sofisticadas del RTOS deberían ser eliminadas ya que no hay un concepto de como
tale memoria virtual dentro de ella.
Tornado – VxWorks
Tornado es un entorno integrado para desarrollar sistemas embebidos relacionados con tiempo real.
Las aplicaciones RTOS en el sistema objetivo. Tornado consta de tres elementos básicos
que se enumeran a continuación.
VxWorks
2) Herramientas de construcción de aplicaciones (compilador y programas asociados)
VxWorksis a networked real time operating system. To begin with VxWorks we should
tengo un kit de desarrollo (objetivo) junto con una estación de trabajo. Aquí, el kit de desarrollo es
nada más que el host o componente de destino que se comunica con el servidor de destino en
la estación de trabajo. El objetivo aquí conecta herramientas de tornado como el shell y
el depurador. Por lo tanto, utilizando VxWorks, configuraremos y construiremos los sistemas mientras
Tornado nos proporciona una interfaz gráfica de usuario y herramientas de línea de comandos para
configuración y construcción.
Un punto muy importante que entra en juego aquí es que al instalar tornado dentro
su sistema el directorio de instalación debe usar las rutas como:
installDir/target. Por ejemplo, si deseas almacenar tu tornado en C:\tornado en un
el sistema operativo Windows, la ruta completa debería identificarse en ese caso como
installDir/target/h/vxworks.h.
Por lo tanto, este Windriver es capaz de invocar tanto VxWorks como el módulo de aplicación
subrutinas. Puedes iniciar la aplicación Windriver ya sea desde el lanzamiento de tornado
barra de herramientas (-> botón i) luego haz clic en el menú y luego haz clic en shell. Por último, desde el
escriba en el símbolo del sistema “>windsh servidor de destino”.
Compila el programa fuente de la aplicación C++ y obtén, por ejemplo, el archivo hello.cpp. Luego ejecútalo.
masticar el .o y compilar el archivo ctdt.c generado. Además, enlazar la aplicación con
ctdt.o para generar un módulo descargable, hello.out dentro de VxWorks. La salida después de
Ejecutar este VxWorks será un archivo make que se utilizará en algún objetivo.
Free RTOS
Generalmente, cada vez que comenzamos con RTOS, preferimos Vx Works RTOS. Pero,
aquí tengamos una discusión breve sobre el Free RTOS, que también se puede utilizar
para que los principiantes comprendan el concepto de sistema operativo en tiempo real. Free RTOS es
desarrollado por Richard Barry y el equipo de FreeRTOS, también es propiedad de Real Time
ingenieros ltd pero es gratuito para usar y se puede descargar fácilmente haciendo clic en el enlace
debajo
La mayor ventaja de FreeRTOS que lo hace superior en comparación con los demás
RTOS es su comportamiento independiente de la plataforma en términos de hardware, es decir, el código C que
estaremos utilizando para ejecutar un sistema operativo que puede funcionar en varias plataformas que tienen
diferente arquitectura. Por lo tanto, independientemente de si estás utilizando8051
microcontroladoro algunos últimosmicrocontrolador ARMel código que escribiste junto con
el proceso de ejecución será similar para ambos.
Hay muchos otros beneficios de usar Free RTOS sobre VxWorks y otros RTOS.
herramientas operativas. Algunas de ellas se pueden expresar como:
4. Mantenimiento fácil
5. Abstracto fuera de la información temporal
Además, el basicKernel, donde Kernel se refiere al componente central de un sistema operativo
el sistema que está presente dentro del free RTOS lo hace accesible para usar en varios
aplicaciones. Dado que es fácil adjuntar módulos ampliados en los sistemas operativos para obtener su
más aplicaciones free RTOS se vuelve más poderoso.
Uno de los ejemplos de usar Free RTOS se puede explicar utilizando el concepto de
combinando Free RTOS con Nabto. Nabto es un dispositivo web gratuito utilizado para transferir el
información del dispositivo al navegador.
Por lo tanto, al combinar Free RTOS con Nabto, se convierte en un pequeño fragmento de código en C como
explicado en la figura a. Hoy en díaInternet de Cosas (IOT)está de moda y todo IOT
el dispositivo al que accedemos tiene una URL única a través de Internet y la tecnología
permite conexiones punto a punto seguras y de ancho de banda extremadamente bajo. En ausencia de
la conectividad a internet esta combinación puede ser útil. Por lo tanto, free RTOS es popular
elección cuando se trata de implementar IoT.