0% encontró este documento útil (0 votos)
186 vistas26 páginas

Practicas 11

El documento describe el uso del sistema operativo FreeRTOS en Arduino. FreeRTOS permite la programación concurrente mediante tareas. Se presentan dos ejemplos: 1) parpadear un LED cada segundo y simular el envío periódico del estado del LED a la nube, y 2) mismo comportamiento pero implementado con tareas FreeRTOS.

Cargado por

kerly cervantes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
186 vistas26 páginas

Practicas 11

El documento describe el uso del sistema operativo FreeRTOS en Arduino. FreeRTOS permite la programación concurrente mediante tareas. Se presentan dos ejemplos: 1) parpadear un LED cada segundo y simular el envío periódico del estado del LED a la nube, y 2) mismo comportamiento pero implementado con tareas FreeRTOS.

Cargado por

kerly cervantes
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 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