Está en la página 1de 26

011000010111001101100001011011100111101001100001

01101010011001010110000101101110
PRACTICA 11
FreeRTOS

1
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Lista de Software:
Objetivos

01101010011001010110000101101110
• Familiarización con Sistema operativo FreeRTOS.

• Realizar programación concurrente usando FreeRTOS.

Arduino

• Proteus – From Development Board


• IDE Arduino - FreeRTOS

2
Sistemas Embebidos
011000010111001101100001011011100111101001100001
FreeRTOS

01101010011001010110000101101110
https://www.freertos.org/RTOS.html 3
Sistemas Embebidos
011000010111001101100001011011100111101001100001

Structure of FreeRTOS

01101010011001010110000101101110
4
Sistemas Embebidos
011000010111001101100001011011100111101001100001
FreeRTOS
Tipos de multitareas

01101010011001010110000101101110
Cooperativa: da el control a un proceso y este es el que cede de nuevo el
control cuando decide voluntariamente que no puede seguir su ejecución,
pasando a esta en espera. Al depender del propio proceso en ejecución puede
ser problemático, ya que, si el proceso de usuario se interrumpe y no cede la
CPU al sistema operativo, todo el sistema quedará bloqueado, es decir, sin
poder hacer nada.
Apropiativa o preventiva: el sistema operativo es el encargado de administrar
el o los procesadores repartiendo el tiempo de uso entre los procesos que
estén esperando para utilizarlo. Cada proceso utiliza el procesador durante
lapsos cortos, pero el resultado final es virtualmente igual a ejecutarse todo al
mismo tiempo.
Real: solo se da en sistemas con multiprocesador; varios procesos se ejecutan
realmente al mismo tiempo en distintos microprocesadores, suele ser también
preferente.

https://www.freertos.org/RTOS.html 5
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Free RTOS en Arduino

01101010011001010110000101101110
6
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Free RTOS en Arduino

01101010011001010110000101101110
7
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Free RTOS en Arduino

01101010011001010110000101101110
8
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Proteus

01101010011001010110000101101110
9
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Ejemplo 1
void setup() {

01101010011001010110000101101110
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
led();
enviar();
}
* Expectativa del código:
* Parpadear un led cada segundo void led(){
* Simular el envío del estado del led a una plataforma digitalWrite(LED_BUILTIN, HIGH);
IOT en la nube cada 500 ms, delay(1000);
* se esparía recibir al menos 1 estado en alto y 1 en digitalWrite(LED_BUILTIN, LOW);
bajo delay(1000);
}

void enviar(){
String estado = (digitalRead(LED_BUILTIN))?"Encendido":"Apagado ";
int delay_ms = random(1000,5000);
Serial.print("Enviando");
for(int i = 0; i<3; i++){
delay(delay_ms/3);
Serial.print('.');
}
Serial.println();
Serial.print("Estado del led: " + estado);
Serial.println("\tRetardo: " + String((float)delay_ms/1000,3) + " seg\r\n");
delay(500);
}

10
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Ejemplo 2
#include <Arduino_FreeRTOS.h>

01101010011001010110000101101110
void led( void *pvParameters );
void enviar( void *pvParameters );

void setup() {
//int min_delay_ms = 2000;
Serial.begin(9600);
pinMode(13, OUTPUT);
xTaskCreate(
led
, "BlinkLed" // Nombre descriptivo de la función (MAX 8 caracteres)
, 128 // Tamaño necesario en memoria STACK
, NULL // Parámetro INICIAL a recibir
, 3 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
* Expectativa del código: , NULL ); // Variable que apunta al task (opcional)

* Parpadear un led cada segundo xTaskCreate(


enviar
* Simular el envío del estado del led a una plataforma , "envioIOT" // Nombre descriptivo de la función (MAX 8 caracteres)
, 128 // Tamaño necesario en memoria STACK
IOT en la nube cada 500 ms, , NULL
, 3
// Parámetro INICIAL a recibir
// Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
* se esparía recibir al menos 1 estado en alto y 1 en }
, NULL ); // Variable que apunta al task (opcional)

bajo void loop() {


//Serial.println("Este es el main");
//delay(2000);
//vTaskDelay( 1000 / portTICK_PERIOD_MS );
}

//void led(){
void led(void *pvParameters){
while(1){
digitalWrite(LED_BUILTIN, HIGH);
//delay(1000);
vTaskDelay( 1000 / portTICK_PERIOD_MS );
digitalWrite(LED_BUILTIN, LOW);
//delay(1000);
vTaskDelay( 1000 / portTICK_PERIOD_MS );
}
}

//void enviar(){
void enviar(void *pvParameters){
for(;;){
String estado = (digitalRead(LED_BUILTIN))?"Encendido":"Apagado ";
int delay_ms = random(1000,5000);
Serial.println("Enviando");
for(int i = 0; i<3; i++){
vTaskDelay( (delay_ms/3) / portTICK_PERIOD_MS );
Serial.print('.');
}
Serial.println();
Serial.print("Estado del led: " + estado);
Serial.println("\tRetardo: " + String((float)delay_ms/1000,3) + " seg\r\n");
//delay(500);

}
vTaskDelay( 1000 / portTICK_PERIOD_MS ); 11
Sistemas Embebidos }
011000010111001101100001011011100111101001100001
Proteus

01101010011001010110000101101110
12
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Ejemplo 3
#include <Arduino_FreeRTOS.h>

01101010011001010110000101101110
int min_max_delay_ms[] = {2000,5000};
int delay_envio = 500;
int delay_led = 250;

void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
xTaskCreate(
led
, "BlinkLed" // Nombre descriptivo de la función (MAX 8 caracteres)
, 128 // Tamaño necesario en memoria STACK
, NULL // Parámetro INICIAL a recibir (void *)
* Expectativa del código: , 0 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
, NULL ); // Variable que apunta al task (opcional)
* Parpadear un led cada segundo
xTaskCreate(
* Simular el envío del estado del led a una plataforma enviar
IOT en la nube cada 500 ms, , "envioIOT"
, 128
// Nombre descriptivo de la función (MAX 8 caracteres)
// Tamaño necesario en memoria STACK
* se esparía recibir al menos 1 estado en alto y 1 en , NULL // Parámetro INICIAL a recibir (void *)
, 0 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
bajo , NULL ); // Variable que apunta al task (opcional)
}

void loop() {
}

void led(){
while(1){
digitalWrite(LED_BUILTIN, HIGH);
vTaskDelay(delay_led / portTICK_PERIOD_MS); //250 ms
digitalWrite(LED_BUILTIN, LOW);
vTaskDelay(delay_led / portTICK_PERIOD_MS); //250 ms
}
}

void enviar(){
for(;;){
String estado = (digitalRead(LED_BUILTIN))?"Encendido":"Apagado ";
int delay_ms = random(min_max_delay_ms[0],min_max_delay_ms[1]); //[2000 - 3000)
Serial.print("Enviando");
for(int i = 0; i<3; i++){
vTaskDelay((delay_ms/3) / portTICK_PERIOD_MS);
Serial.print('.');
}
Serial.println();
Serial.print("Estado del led: " + estado);
Serial.println("\tRetardo: " + String((float)delay_ms/1000,3) + " seg\r\n");
vTaskDelay(delay_envio / portTICK_PERIOD_MS); //500
} 13
Sistemas Embebidos }
011000010111001101100001011011100111101001100001
#include <Arduino_FreeRTOS.h>

Ejemplo 4 TaskHandle_t TaskEnviar_Handler;

int min_max_delay_ms[] = {2000,3000};


int delay_sensado = 5000;
int delay_led = 250;
float voltaje = 0;

01101010011001010110000101101110
void led( void *pvParameters );
void enviar( void *pvParameters );
void analogico( void *pvParameters );

void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
xTaskCreate(
led
, "BlinkLed" // Nombre descriptivo de la función (MAX 8 caracteres)
, 128 // Tamaño necesario en memoria STACK
, NULL // Parámetro INICIAL a recibir (void *)
, 0 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
, NULL ); // Variable que apunta al task (opcional)

xTaskCreate(
enviar
, "envioIOT" // Nombre descriptivo de la función (MAX 8 caracteres)
* Expectativa del código: , 128
, NULL
// Tamaño necesario en memoria STACK
// Parámetro INICIAL a recibir (void *)
, 0 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
* Tomar 100 muestras de un voltaje analógico, sacar su , &TaskEnviar_Handler); // Variable que apunta al task (opcional)

promedio cada 5 segundos y xTaskCreate(


analogico

* Simular el envío del promedio a una plataforma IOT , "Voltaje"


, 128
// Nombre descriptivo de la función (MAX 8 caracteres)
// Tamaño necesario en memoria STACK
, NULL // Parámetro INICIAL a recibir (void *)
en la nube. , 0 // Prioridad, priridad = 3 (configMAX_PRIORITIES - 1) es la mayor, prioridad = 0 es la menor.
, NULL); // Variable que apunta al task (opcional)

vTaskSuspend(TaskEnviar_Handler);
}

void loop() {
}

void led( void *pvParameters ){


while(1){
digitalWrite(LED_BUILTIN, HIGH);
vTaskDelay(delay_led / portTICK_PERIOD_MS); //250 ms
digitalWrite(LED_BUILTIN, LOW);
vTaskDelay(delay_led / portTICK_PERIOD_MS); //250 ms
}
}

void enviar( void *pvParameters ){


for(;;){
int delay_ms = random(min_max_delay_ms[0],min_max_delay_ms[1]); //[2000 - 3000)
Serial.print("Enviando");
for(int i = 0; i<3; i++){
vTaskDelay((delay_ms/3) / portTICK_PERIOD_MS);
Serial.print('.');
}
Serial.println();
Serial.print("Voltaje Analógico: " + String(voltaje));
Serial.println("\t\tRetardo: " + String((float)delay_ms/1000,3) + " seg\r\n");

vTaskSuspend(TaskEnviar_Handler);
}
}

void analogico( void *pvParameters ){


while(1){
for(int j=0;j<6;j++){//60
voltaje += analogRead(A0)*100/1023;//0%-100%
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
voltaje /= 6;//60
vTaskResume(TaskEnviar_Handler);
vTaskDelay(delay_sensado / portTICK_PERIOD_MS);//tiempo mayor al que se demora Enviar 14
Sistemas Embebidos }
}
011000010111001101100001011011100111101001100001
Proteus

01101010011001010110000101101110
15
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Desafío:

01101010011001010110000101101110
• Agregar una tarea que utilice TaskEnviar_Handler para ser activada al
momento que debe enviar el dato promediado almacenado en la variable
Datos1. El dato a enviar deberá ser enviado utilizando la trama de
comunicación con el ID del coordinador.
• Agregar una tarea que utilice TaskPWM_Handler para setear un valor PWM en
una de sus salidas.

16
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Trama Comunicación Serial:

01101010011001010110000101101110
17
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Serial Communication:

01101010011001010110000101101110
Start byte ID byte Byte Task Byte Data Byte Checksum
0x00
. XOR (Start byte,
0x31 (1) – ED 0x41 (A) – Read
0x24 ($) 0x30 (0) ID byte, byte
0x36 (6) – C 0x42 (B) - PWM
. Task, byte Data)
0xFF ()

*(ASCII) End Device


*End Device (ED)
*Coodinator (C)

• El equipo Coordinador (C) deberá enviar


la siguiente trama de solicitud de datos al
End Device (ED) con Byte ID de 0x31:
0𝑥24 0𝑥31 0𝑥41 0𝑥00 0𝑥54

Sensor1
18
Sistemas Embebidos http://www.ginsei-jp.com/ZigBee.html
011000010111001101100001011011100111101001100001
Codigo a editar
#include <Arduino_FreeRTOS.h>

01101010011001010110000101101110
TaskHandle_t TaskLed_Handler;

//variables globales
int led = 13;
int led_pwm=11;
float ADCsensor,Dato = 0;
int estado =0;
int RXTrama[5];
int TramaS[5] ={0x24,0x31,0x41,0x00,0x54};//sensor
int TramaA[5] ={0x24,0x31,0x42,0x00,0x57};//actuador
int IdCoordinador =0x36;//'6'
// Sensor AD-0
//24 31 41 00 54
// Actuador PWM-11
//24 31 42 FF A8
//24 31 42 7F 28
//24 31 42 00 57

// End Device
void TaskBlink( void *pvParameters );
void TaskRxTrama( void *pvParameters );
void TaskAnalogRead( void *pvParameters );// Sensor

void setup() {
pinMode(led, OUTPUT);
pinMode(led_pwm, OUTPUT);
Serial.begin(9600);
xTaskCreate(
TaskBlink
, "Blink" // A name just for humans
, 128 // Stack size

Trama: , NULL
, 0 // priority
, &TaskLed_Handler); // Variable que apunta al task (opcional)

xTaskCreate(
TaskRxTrama

// Sensor AD-0 , "Blink" // A name just for humans


, 128 // Stack size
, NULL
,1 // priority
, NULL );

//24 31 41 00 54 xTaskCreate(
TaskAnalogRead
, "AnalogRead"
, 128 // This stack size can be checked & adjusted by reading Highwater
, NULL
, 3 // priority

// Actuador PWM-11 }
, NULL );

vTaskSuspend(TaskLed_Handler);

void loop()

//24 31 42 FF A8 {
}
/*---------------------- Tasks ---------------------*/
void TaskBlink(void *pvParameters) // This is a task.
{
for (;;){

//24 31 42 7F 28 digitalWrite(led, HIGH);


vTaskDelay( 1000 / portTICK_PERIOD_MS );
digitalWrite(led, LOW);
vTaskDelay( 1000 / portTICK_PERIOD_MS );
vTaskSuspend(TaskLed_Handler);
}

//24 31 42 00 57 }

void TaskRxTrama(void *pvParameters) // This is a Main task.


{
for (;;){
if(Serial.available()){
if(estado==0 and Serial.read () == 0x24){
RXTrama[estado]=0x24;estado=1;
}else if(estado>0){
RXTrama[estado]=Serial.read ();
estado+=1;
if(estado>4){
estado=0;
if(RXTrama[0]==TramaS[0] and RXTrama[1]==TramaS[1] and RXTrama[2]==TramaS[2] and RXTrama[3]==TramaS[3]and RXTrama[4]==TramaS[4]){
//Enviar todos los datos almacenados usando la trama de envio al coordinador*******
Serial.print("Valor ADC: ");
Serial.println(Dato);
//vTaskResume(TaskLed_Handler);//proteus se pone lento
//vTaskDelay( 2000 / portTICK_PERIOD_MS );//proteus se pone lento
}
if(RXTrama[0]==TramaA[0] and RXTrama[1]==TramaA[1] and RXTrama[2]==TramaA[2]){
if(RXTrama[4] == (((RXTrama[0] ^ RXTrama[1]) ^ RXTrama[2]) ^ RXTrama[3])){
Serial.println("Valor PWM en salida");
analogWrite(led_pwm,RXTrama[3]);//PWM output
//vTaskResume(TaskLed_Handler);//proteus se pone lento
//vTaskDelay( 1000 / portTICK_PERIOD_MS );//proteus se pone lento
}
}
}
}
}
}
}

void TaskAnalogRead(void *pvParameters) // This is a Main task.


{
for (;;){
ADCsensor=0;
for(int j=0;j<6;j++){//durante 60 datos en 1min
ADCsensor += analogRead(A0)*10/1023;// [0% - 100%]
vTaskDelay( 1000 / portTICK_PERIOD_MS );//cada 1 segundo
}
ADCsensor /= 6;//60
Dato=ADCsensor;
}
}

19
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Proteus

01101010011001010110000101101110
20
Sistemas Embebidos
011000010111001101100001011011100111101001100001
(Adicional) Semáforos binarios usados
para sincronización

01101010011001010110000101101110
• FreeRTOS posee los siguientes elementos para la sincronización de eventos :
colas, semáforos binarios, semáforos contadores, semáforos recursivos y mutex.
• Aunque la finalidad de los semáforos es permitir el acceso de forma segura a un
recurso compartido entre varias tareas, también puede usarse para sincronizar
dos tareas entre si, o una tarea con una rutina de atención a interrupción.
• La rutina de atención a interrupción realiza la interacción con el hardware y
libera el semáforo para permitir desbloquear la tarea que queremos sincronizar
con la interrupción.
• El código implementado dentro de una rutina de atención a interrupción debe
ocupar pocos ciclos de procesador.

21
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Semáforos binarios usados para
sincronización

01101010011001010110000101101110
22
Sistemas Embebidos
011000010111001101100001011011100111101001100001

Using FreeRTOS Semaphores in Arduino IDE

01101010011001010110000101101110
#include <Arduino_FreeRTOS.h>
#include <semphr.h> // add the FreeRTOS functions for Semaphores (or Flags).

// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
// It will be used to ensure only only one Task is accessing this resource at any time.
SemaphoreHandle_t xSerialSemaphore;

// define two tasks for Blink & AnalogRead


void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );

// the setup function runs once when you press reset or power the board
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// Semaphores are useful to stop a Task proceeding, where it should be paused to wait,
// because it is sharing a resource, such as the Serial port.
// Semaphores should only be used whilst the scheduler is running, but we can set it up here.
if ( xSerialSemaphore == NULL ) // Check to confirm that the Serial Semaphore has not already been created.
{
xSerialSemaphore = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use to manage the Serial Port
if ( ( xSerialSemaphore ) != NULL )
xSemaphoreGive( ( xSerialSemaphore ) ); // Make the Serial Port available for use, by "Giving" the Semaphore.
}

// Now set up two Tasks to run independently.


xTaskCreate(
TaskBlink,
"Blink", // A name just for humans
128, // Stack size
NULL,
2, // priority
NULL );

xTaskCreate(
TaskAnalogRead
, "AnalogRead"
, 128 // This stack size can be checked & adjusted by reading Highwater
, NULL
, 1 // priority
, NULL );
}

void loop()
{
Serial.println("this is main Task");
delay(1000);
}

/*---------------------- Tasks ---------------------*/


void TaskBlink(void *pvParameters __attribute__((unused)) ) // This is a task.
{
(void) pvParameters;
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
for (;;) // A Task shall never return or exit.
{
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
{
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW

xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
}
}
}

void TaskAnalogRead(void *pvParameters __attribute__((unused)) ) // This is a task.


{
(void) pvParameters;
// initialize serial communication at 9600 bits per second:
//Serial.begin(9600);
for (;;)
{
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
{
// print out the value you read:
Serial.println(sensorValue);
//vTaskDelay(1); // one tick delay (15ms) in between reads for stability

xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second

}
}
23
Sistemas Embebidos }
https://www.hackster.io/feilipu/using-freertos-semaphores-in-arduino-ide-b3cd6c
011000010111001101100001011011100111101001100001
Proteus

01101010011001010110000101101110
24
Sistemas Embebidos
011000010111001101100001011011100111101001100001
Free RTOS en Arduino

01101010011001010110000101101110
25
Sistemas Embebidos https://www.hackster.io/feilipu/using-freertos-semaphores-in-arduino-ide-b3cd6c
011000010111001101100001011011100111101001100001

Recursos:
• Algunos contenidos vistos en clase como presentaciones,

01101010011001010110000101101110
ejercicios resueltos, entre otros. Serán almacenados y
compartidos en el siguiente Drive:

26
Sistemas Embebidos

También podría gustarte