Category Archive Mini tutoriales

Rafael Sobrevilla PorRafael Sobrevilla

Sistemas Operativo en Tiempo Real, para un Sistema Embebido (ARDUINO)

Introducción

Tradicionalmente los microcontroladores, se programan usando un algoritmo secuencial, en la cual los recursos de hardware, no se comparten entre funciones, es decir el uso de un periférico, como son: la Unidad Aritmetica Lógica, contadores, Convertidores Analogico Digital, etc; no son liberados hasta que termina la función actual de ejecutarse. Esto implica tener varias funciones anidadas, que esperan a que la función en ejecución termina de usar los recursos del microcontrolador.

El nivel de integración actual, ha permitido que los microcontroladores posean, mayor capacidad de memoria, mayor velocidad de transferencia de datos para su procesamiento y un acceso mas rápido a la lectura y escritura de memoria.

Todas las características anteriormente citadas, permiten el poder implementar un RTOS (Sistema Operativo en Tiempo Real) en un microcontrolador de 8 bits. Un RTOS, es un gestor de tiempo de ejecución, que administra diferentes tareas que son parecidas a una función secuencial, pero permiten ser, puestas en espera, imitarles el acceso a la memoria y/o al hardware, guardar el entorno actual de contadores, periféricos, contador del programa, etc. Saltar a otra tarea, compartir los recursos y regresar a la tarea que se quedo en espera. Todo esto gracias a la creación de varios Stacks (pilas de registros guardados) en este caso generalmente en memoría RAM. Finalmente la tarea que estaba esperando o que se quedo a mitad de ejecución, puede continuar su ejecución justo en el punto donde fue interrumpida.

Después de comprender este sencillo ejemplo, imaginémonos que esta “puesta en espera” se realiza con diferentes tareas, compartiendo recursos y saltando simultáneamente entre ellas. La combinación de un gestor de tiempos entre tareas secuenciales que comparten recursos, es el objetivo de los RTOS.

Arduino UNO con un RTOS

Una arquitectura Arduino UNO (Atmega328, 8 Bits uC a 16 mega hertz) gracias a freeRTOS, nos permite implementar un pequeño Sistema en Tiempo Real.

Quiero compartirles, este código que utiliza un RTOS en un arduino UNO, es para un cubo de leds de 3×3. En futuras aportaciones explicare a detalle como funciona este RTOS y como configurar las diferentes tareas creadas. Por el momento a grandes razgos:

  • Una tarea ejecuta las secuencias de patrones de encendido de los leds

  • Una tarea revisa el potenciómetro (genera un voltaje variable) que aumenta la velocidad de las secuencias

  • Una tarea revisa el estado de un botón que cambia la secuencia de encendido de los leds, por si ya te aburriste y quieres que los leds prendan con un patrón diferente.

Este programa también se puede escribir de manera tradicional, con lógica secuencial, pero al usar un RTOS, para actualizar las variables globales, que controlan el sentido y velocidad de los patrones de encendido de los leds, se hace evidente, que al usar un RTOS, el programa final es más sencillo y utiliza más eficientemente los recursos del microcontrolador.

Adjunto también, un enlace a un video, para que vean el funcionamiento de este cubito de 3×3.

Rafael Sobrevilla

Referencias

Programación de Sistemas Embebidos en C, Gustavo Galeano, Primera Edición, 2009, Alfaomega

https://aprendiendoarduino.wordpress.com/tag/rtos/

 

Video

Código

/**************************************************************************************************
* File name: cube3x3.ino
* Date Start: 17-may-17
* Author: Rafael Sobrevilla
* email: rasobrevilla@yahoo.com
* Descrip:
* – Control a 27 leds cube
* – Use digital outputs of arduino UNO
* + D2 – D10 Control of base leds
* + D11 – D13 The three floors
* + A0 – A1 Two Buttons
* + D0 and D1 To keep the serial port available
*
* led1 led2 led3
*
* led4 led5 led6
*
* led7 led8 led9
*
* floor0
* floor1
* floor2
*
**************************************************************************************************/

/**************************************************************************/
/* Include headers */
/**************************************************************************/
#include <Arduino_FreeRTOS.h>

/*************************************************************************/
/* Define two task for Sensors and Clock */
/*************************************************************************/
void TaskPatron( void *pvParameters );
//void TaskPotenciometer ( void *pvParameter );
void TaskButton ( void *pvParameter );

/********************************************************************/
/* Global variables */
/********************************************************************/
int led1 = 2;
int led2 = 3;
int led3 = 4;
int led4 = 5;
int led5 = 6;
int led6 = 7;
int led7 = 8;
int led8 = 9;
int led9 = 10;
int floor0 = 11;
int floor1 = 12;
int floor2 = 13;

int sen_pin0 = A0;
int sen_pin1 = A2;
const int ON = 1;
const int OFF = 0;
int delay_ms_value_1 = 250;
int delay_ms_value_2 = 500;
int button_status = 0;
int potenciometer_status = 0;

/***************************************************************************/
/* Setup function is executed when you press reset or power the board */
/***************************************************************************/
void setup() {

Serial.begin(9600);

while (!Serial) {
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
}

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(led6, OUTPUT);
pinMode(led7, OUTPUT);
pinMode(led8, OUTPUT);
pinMode(led9, OUTPUT);
pinMode(floor0, OUTPUT);
pinMode(floor1, OUTPUT);
pinMode(floor2, OUTPUT);

// Now set up two tasks to run independently.
xTaskCreate (
TaskPatron
, (const portCHAR *) “Sensor”
, 128 // Stack size
, NULL
, 3 // Priority
, NULL );

xTaskCreate (
TaskButton
, (const portCHAR *)”Motors” // A name just for humans
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 3 // Priority, with 3 (configMAX_PRIORITIES – 1) being the highest, and 0 being the lowest.
, NULL );

xTaskCreate (
TaskPotenciometer
, (const portCHAR *) “Sensor”
, 128 // Stack size
, NULL
, 3 // Priority
, NULL );

// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

/***********************************************************************/
/* Function for turn on a Position led */
/***********************************************************************/
int enable(int position_led, int floor_on)
{
digitalWrite(position_led, ON);
digitalWrite(floor_on, ON );

}

/***********************************************************************/
/* Fnction for turn off a Position Led */
/***********************************************************************/
int disable(int position_led, int floor_on)
{
digitalWrite(position_led, OFF);
digitalWrite(floor_on, OFF );
}

/*****************************************************************************/
/* LOOP FUNCTION */
/*****************************************************************************/
void loop()
{
// Empty. Things are done in Tasks.
}

/******************************************************************************/
/* Tasks */
/******************************************************************************/

void TaskPatron(void *pvParameters) // This is a task.
{
(void) pvParameters;
for (;;)
{
Serial.println(“PATRONES”);
do{
patron1();
}while(button_status > 200);

do{
patron2();
}while(button_status > 200);

do{
patron3();
}while(button_status > 200);

do{
patron4();
}while(button_status > 200);
}
}

void TaskPotenciometer (void *pvParameters) // This is a task.
{
(void) pvParameters;
for(;;)
{
potenciometer_status = analogRead (sen_pin0);
Serial.println(potenciometer_status);
//delay(delay_ms_value_2);
}
}

void TaskButton (void *pvParameters) // This is a task.
{
(void) pvParameters;
for(;;)
{
button_status = analogRead (sen_pin1);
Serial.println(button_status);
//delay(delay_ms_value_2);
}
}

/************************************************************************/
/* Patron 1 */
/************************************************************************/
void patron1 (void)
{
//floor 2
enable(led1, floor2);
enable(led2, floor2);
enable(led3, floor2);
enable(led4, floor2);
enable(led5, floor2);
enable(led6, floor2);
enable(led7, floor2);
enable(led8, floor2);
enable(led9, floor2);
delay(potenciometer_status );

disable(led1, floor2);
disable(led2, floor2);
disable(led3, floor2);
disable(led4, floor2);
disable(led5, floor2);
disable(led6, floor2);
disable(led7, floor2);
disable(led8, floor2);
disable(led9, floor2);

//floor 1
enable(led1, floor1);
enable(led2, floor1);
enable(led3, floor1);
enable(led4, floor1);
enable(led5, floor1);
enable(led6, floor1);
enable(led7, floor1);
enable(led8, floor1);
enable(led9, floor1);
delay(potenciometer_status );

disable(led1, floor1);
disable(led2, floor1);
disable(led3, floor1);
disable(led4, floor1);
disable(led5, floor1);
disable(led6, floor1);
disable(led7, floor1);
disable(led8, floor1);
disable(led9, floor1);

//floor 0
enable(led1, floor0);
enable(led2, floor0);
enable(led3, floor0);
enable(led4, floor0);
enable(led5, floor0);
enable(led6, floor0);
enable(led7, floor0);
enable(led8, floor0);
enable(led9, floor0);
delay(potenciometer_status );

disable(led1, floor0);
disable(led2, floor0);
disable(led3, floor0);
disable(led4, floor0);
disable(led5, floor0);
disable(led6, floor0);
disable(led7, floor0);
disable(led8, floor0);
disable(led9, floor0);

//floor 1
enable(led1, floor1);
enable(led2, floor1);
enable(led3, floor1);
enable(led4, floor1);
enable(led5, floor1);
enable(led6, floor1);
enable(led7, floor1);
enable(led8, floor1);
enable(led9, floor1);
delay(potenciometer_status );

disable(led1, floor1);
disable(led2, floor1);
disable(led3, floor1);
disable(led4, floor1);
disable(led5, floor1);
disable(led6, floor1);
disable(led7, floor1);
disable(led8, floor1);
disable(led9, floor1);
}

/*********************************************************************************/
/* Patron 2 */
/*********************************************************************************/
void patron2(void)
{
//wall 2
enable(led1, floor2);
enable(led2, floor2);
enable(led3, floor2);
enable(led1, floor1);
enable(led2, floor1);
enable(led3, floor1);
enable(led1, floor0);
enable(led2, floor0);
enable(led3, floor0);
delay(potenciometer_status );

disable(led1, floor2);
disable(led2, floor2);
disable(led3, floor2);
disable(led1, floor1);
disable(led2, floor1);
disable(led3, floor1);
disable(led1, floor0);
disable(led2, floor0);
disable(led3, floor0);

//floor 1
enable(led4, floor2);
enable(led5, floor2);
enable(led6, floor2);
enable(led4, floor1);
enable(led5, floor1);
enable(led6, floor1);
enable(led4, floor0);
enable(led5, floor0);
enable(led6, floor0);
delay(potenciometer_status );

disable(led4, floor2);
disable(led5, floor2);
disable(led6, floor2);
disable(led4, floor1);
disable(led5, floor1);
disable(led6, floor1);
disable(led4, floor0);
disable(led5, floor0);
disable(led6, floor0);

//floor 0
enable(led7, floor2);
enable(led8, floor2);
enable(led9, floor2);
enable(led7, floor1);
enable(led8, floor1);
enable(led9, floor1);
enable(led7, floor0);
enable(led8, floor0);
enable(led9, floor0);
delay(potenciometer_status );

disable(led7, floor2);
disable(led8, floor2);
disable(led9, floor2);
disable(led7, floor1);
disable(led8, floor1);
disable(led9, floor1);
disable(led7, floor0);
disable(led8, floor0);
disable(led9, floor0);

//floor 1
enable(led4, floor2);
enable(led5, floor2);
enable(led6, floor2);
enable(led4, floor1);
enable(led5, floor1);
enable(led6, floor1);
enable(led4, floor0);
enable(led5, floor0);
enable(led6, floor0);
delay(potenciometer_status );

disable(led4, floor2);
disable(led5, floor2);
disable(led6, floor2);
disable(led4, floor1);
disable(led5, floor1);
disable(led6, floor1);
disable(led4, floor0);
disable(led5, floor0);
disable(led6, floor0);
}

/*********************************************************************************/
/* Patron 3 */
/*********************************************************************************/
void patron3 (void)
{
//wall 2
enable(led1, floor2);
enable(led4, floor2);
enable(led7, floor2);
enable(led1, floor1);
enable(led4, floor1);
enable(led7, floor1);
enable(led1, floor0);
enable(led4, floor0);
enable(led7, floor0);
delay(potenciometer_status );

disable(led1, floor2);
disable(led4, floor2);
disable(led7, floor2);
disable(led1, floor1);
disable(led4, floor1);
disable(led7, floor1);
disable(led1, floor0);
disable(led4, floor0);
disable(led7, floor0);

//wall 1
enable(led2, floor2);
enable(led5, floor2);
enable(led8, floor2);
enable(led2, floor1);
enable(led5, floor1);
enable(led8, floor1);
enable(led2, floor0);
enable(led5, floor0);
enable(led8, floor0);
delay(potenciometer_status );

disable(led2, floor2);
disable(led5, floor2);
disable(led8, floor2);
disable(led2, floor1);
disable(led5, floor1);
disable(led8, floor1);
disable(led2, floor0);
disable(led5, floor0);
disable(led8, floor0);

//wall 0
enable(led3, floor2);
enable(led6, floor2);
enable(led9, floor2);
enable(led3, floor1);
enable(led6, floor1);
enable(led9, floor1);
enable(led3, floor0);
enable(led6, floor0);
enable(led9, floor0);
delay(potenciometer_status );

disable(led3, floor2);
disable(led6, floor2);
disable(led9, floor2);
disable(led3, floor1);
disable(led6, floor1);
disable(led9, floor1);
disable(led3, floor0);
disable(led6, floor0);
disable(led9, floor0);

//floor 1
enable(led2, floor2);
enable(led5, floor2);
enable(led8, floor2);
enable(led2, floor1);
enable(led5, floor1);
enable(led8, floor1);
enable(led2, floor0);
enable(led5, floor0);
enable(led8, floor0);
delay(potenciometer_status );

disable(led2, floor2);
disable(led5, floor2);
disable(led8, floor2);
disable(led2, floor1);
disable(led5, floor1);
disable(led8, floor1);
disable(led2, floor0);
disable(led5, floor0);
disable(led8, floor0);
}

/*********************************************************************************/
/* Patron 4 */
/*********************************************************************************/
void patron4 (void)
{
//wall 2
enable(led1, floor2);
enable(led5, floor1);
enable(led9, floor0);
delay(potenciometer_status );

disable(led1, floor2);
disable(led5, floor1);
disable(led9, floor0);

//wall 1
enable(led2, floor2);
enable(led5, floor1);
enable(led8, floor0);
delay(potenciometer_status );

disable(led2, floor2);
disable(led5, floor1);
disable(led8, floor0);

//wall 0
enable(led3, floor2);
enable(led5, floor1);
enable(led7, floor0);
delay(potenciometer_status );

disable(led3, floor2);
disable(led5, floor1);
disable(led7, floor0);

//floor 1
enable(led4, floor2);
enable(led5, floor1);
enable(led6, floor0);
delay(potenciometer_status );

disable(led4, floor2);
disable(led5, floor1);
disable(led6, floor0);
}

 

León Ramos PorLeón Ramos

¿Cómo cambiar un texto en varios archivos en Linux?

Mini tutorial: ¿Como cambiar texto o cadena en varios archivos en Linux?

¡Hola Creadores!

En éste mini tutorial vamos a ver cómo cambiar un texto o una cadena en varios archivos en un sistema Linux.

En la primera parte nos concentramos en encontrar los archivos que tienen la cadena de texto con la herramienta egrep.

$ egrep 'texto' * -ri

Luego vemos cómo contar los archivos encontrados utilizando la herramienta wc.

$ egrep 'cadena' -ri | wc -l

Finalmente nos concentramos en realizar el cambio que queremos

$ egrep 'cadena' -ril | xargs sed -i 's/cadena/nueva/g'

Espero que les sirva!

León Ramos PorLeón Ramos

¿Cómo puedo salir de vi?

Mini tutoriales: ¿Cómo salir de vi?

Hola creadores:

Si, seguramente les ha pasado, no son muy diestros en vi/vim y ya entraron a cambiar un archivo, pero ¿cómo salimos?

Bueno en este mini tutorial les explicamos cómo salir:

  1. Salir sin guardar
  2. :q

  3. Salir sin guardar forzando
  4. :q!

  5. Guardar el contenido del archivo
  6. :w

  7. Guardar y salir
  8. :wq

  9. Guardar y salir abreviado
  10. :x

  11. Guardar y salir más abreviado
  12. SHIFT+z+z

León Ramos PorLeón Ramos

Mini tutorial de comandos Linux: SSH

Mini Tutoriales: SSH

¡Hola Creadores!

Con este post comenzamos la sección de minitutoriales de comandos GNU/Linux. El objetivo de dicha sección es tener un compendio de videos en español que expliquen tips y trucos que frecuentemente se necesitan al operar éstos sistemas.

Se cubren los siguientes puntos de forma breve:

  1. Formas de usar el comando
  2. Switches simples
  3. Usar otro puerto para SSH
  4. Formas de salir de una conexión SSH
  5. SSH sin password
  6. Crear un proxy SOCKS para navegar
  7. Reenviar un puerto remoto a la máquina local (ideal para realizar comunicaciones encriptadas rápidas)

Si tienes dudas, no vaciles en escribirnos, o bien, sugiere qué otros comandos quieres que expliquemos.

¡Hasta luego Creadores!