martes, 25 de octubre de 2016

Semáforos vs Mutex - FreeRTOS

El semáforo sirve para sincronizar tareas. Es una simple Queue, de extensión 1. Puede estar vacía o llena. La tarea va a tratar de leer el semáforo y lo verá vacio, entonces se bloquea. Cuando llega la interrupción, esta da ('give') el token al semáforo, es decir llena la queue. Entonces ahora la tarea que estaba bloqueada ya puede venir a tomar ('take')​ el token del semáforo. Realiza su tareas. Al finalizar, vuelve a leer el semáforo, al no tener nada se bloquea.

En el semáforo, la tarea no devuelve el token, es decir que no vuelve a rellenar la queue (el semáforo)
Para aquellos que recién comienzan con el desarrollo en freeRTOS, y en particular a aquellos que nos gusta leer la teoría, antes de ir a la programación, se puede dar una pequeña confusión entre Mutex y Semáforos, ya que aparentemente utilizan el mismo medio: Una cola de lenght 1.

La Mutual Exclusion, es una Técnica, que permite que no exista una inconsistencia en la utilización de recursos compartidos. Y se pueden utilizar varias estrategias para asegurar la Mutual Exclusion.
  1. Entrando en secciones críticas. 
  2. Suspendiendo el scheduler. A mi parecer es lo mismo que el anterior. 
  3. Utilizando Mutex.
Mutex es implementado a través de una especie de semáforo (Queue de extensión 1 que puede estar vacia o llena). La diferencia radica en que las tareas que utilizan un recursos compartido, primero van a mirar el mutex, si está "lleno" toman el token (y dejan el semáforo vacio). Si otra tarea quiere tocar el recurso, verá que el mutex está vacio, por lo tanto se bloquea.

Aqui va la diferencia primordial: para el caso del MUTEX, se tiene que devolver el token. Es decir, esta especie de "semáforo", se vuelve a llenar.

lunes, 24 de octubre de 2016

ARGENTOS, Nuevo lenguaje esotérico bien argento

Introducción

Argentos nació como producto del concurso CALESYTA 2016 (Concurso Argentino de Lenguajes Esotéricos y Tarpits). En un principio iba a ser un lenguaje más “clásico”, pero me aburrí de lo mismo.

Así fue que en una tarde, mientras desarrollaba unas de mis partidas de ajedrez más importante… bueno no, iba en el bondi, y en una de esas epifanías que tienen los que hacen programación, me surgió la idea de hacer una tablero de ajedrez, y tratar de programar con el movimiento de una de las piezas. Me pareció interesante hacerlo con el caballo… hacer… el lenguaje.

Características principales

  • El control de todo el programa se realiza moviendo una pieza del ajedrez: el caballo.
  • Existen tres campos de movimiento, basados en el tablero de ajedrez: el principal, el de variables y el de caracteres.
  • Las coordenadas de los campos (8x8) son 'A’, ‘R’, ‘G’, ‘E’, ‘N’, ‘T’, ‘O’, ‘S’.
  • Las variables se almacenan en el campo de variables (matriz 8x8), solo se pueden almacenar 64 variables.
  • Las variables son de 1 Bytes.
  • Para asignar valores a las variables, se debe utilizar el campo de caracteres. 
  • Los únicos flujos de control son: condicional y repetitivo.

 Fundamentos

Para lograr cumplir con lo esperado de un lenguaje, como control de flujo, almacenar variables, realizar operaciones; fue necesario crear varios campos o tableros de ajedrez.

Para ello  ARGENTOS proporciona un campo de movimiento, que llevaría el flujo principal del programa, y donde se encuentran los códigos principales de control (salto de linear, retorno de carro, espacio, +, -, <, >, =, etc).

Para hacerlo más interesante, la libertard del programador tendría ciertas limitaciones, lo que representa un divertido desafío.

En primer lugar todos los datos que se ingresan en un programa (caracteres, numeros) ya son previstos por ARGENTOS. Para almacenar datos en memoria, también tiene sus limitaciones. Los datos se almacenan en un tablero 8x8 y es necesario recordar la posición en la que esa variable fue almacenada.

 El campo donde se encuentran los caracteres se llama campo de caracteres y el campo donde se almacenan las variables se llama campo de variables.

Campo de movimiento

Argentos es un lenguaje basado en el movimiento del caballo del ajedrez. Se debe imaginar un tablero 8x8, cuyas coordenadas son las letras ‘A’, ‘R’, ‘G’, ‘E’, ‘N’, ‘T’, ‘O’, ‘S’. A continuación se muestra la representación:




Las coordenadas de cada casillero se nombra FILA x COLUMNA. Es decir, el primer casillero (el (0,0)) tiene la coordenada [A,A].

El caballo inicia desde la posición normal del caballo izquierdo, en la posición SR.




El caballo se debe mover respetando el movimiento del ajedrez (en L) .

Rellenando el campo de movimiento


Todos los casilleros se rellenan siguiendo el código ASCII.

Desde el casillero [A,A] hasta el casillo [N,T] está formado por los símbolos de control, incluyendo los operadores matemáticos y lógicos. El mapeo se muestra en la siguiente figura.


 

Campo de caracteres


El campo de caracteres es utilizado para cuando se necesita imprimir por pantalla una cadena de caracteres, o bien almacenar en memoria una cadena. También en esta tabla se encuentran los números.

La idea es la misma, un tablero 8x8, el caballo comienza en la coordenada [S,R].



Para ingresar al campo de caracteres se debe llevar al caballo a la posición [T,A].

Primer Programa

ARCHIVO

El archivo fuente escrito en argentos, debe tener la extensión .argentos.


Ejemplo:
holamundo.argentos

 

ARGENTOS

Todo programa debe empezar y terminar con el comando ARGENTOS.

ARGENTOS

% Tu código aquí

ARGENTOS

Una vez colocado el comando inicial, y antes de cualquier sentencia, se debe mover el caballo hacia cualquier posición, es decir abrir el juego. Para finalizar el script, antes del comando final ARGENTOS, se debe volver al caballo a la posición inicial.

Comandos reservados

Todos los comandos se forman con la combinación de los siguientes caracteres: ‘A’, ‘R’, ‘G’, ‘E’, ‘N’, ‘T’, ‘O’, ‘S’. A continuación se listan los comandos reservados:


argentos Comando para iniciar y finalizar el script
argento Comando para mover el caballo. Comando (espacio) coordenada. Ej: argento tg
ss Comando para ingresar a los campos (de variables, caracteres, etc.).
oo Comando para salir de los campos (de variable, caracteres, etc.).
aaa Con este comando se aceptan las sentencias, coordenadas
ge Print. Se empieza y terminar con el comando ge. Ej “ge ‘algo para print’ ge” → algo para print
rr Se indica que se va a almacenar una variable, en la posición actual del puntero.
nn Se indica que se va a leer una variable de posición actual del puntero.
tt Aumenta el puntero del campo de variables
gg Diminuye el punter del campo de variables
arg Asigna valor a variable (=)
ent Extrae variable

Comentarios

Los comentarios empiezan con %.


% Esto es un comentarios

%Estas son dos líneas

% de comentario

Hola Mundo

A continuación se muestra el clásico “Hola Mundo”

ARGENTOS

argento tg

ge

argento ER argento TA aaa %ingreso al campo de variables

argento OG argento NR aaa % 'h'

argento OG argento TA aaa % 'o'

argento NG argento TN argento OO argento NT aaa  % 'l'

argento TE argento EG aaa %'a'

oo% 'salgo del campo de caracteres'

argento NA aaa % 'espacio'

argento TG argento ER argento TA aaa % Ingreso al campo de caracteres

argento OG argento TN argento NO aaa % 'm'

argento TN argento ET argento TO aaa  % 'u'

argento ET argento NS aaa % 'n'

argento ET aaa % 'd'

argento NE argento OG argento TA aaa %'o'

ge %imprimo


ARGENTOS


Salida:

hola mundo


Campo variables


ARGENTOS brinda una pila 64 Bytes para el almacén de variables. Todas las variables se almacenan dentro de esta pila. No se puede definir variables. Para acceder a esas variables es neceario la utilización de un puntero:

rr Se indica que se va a almacenar una variable, en la posición actual del puntero.
nn Se indica que se va a leer una variable de posición actual del puntero.
tt Aumenta el puntero del campo de variables
gg Diminuye el punter del campo de variables


Es importante recordar a qué posición apunta el puntero de variables. AL comenzar el puntero apunta a la posición 0. Se utiliza el comando rr para indicar que se va a almacenar una variable

En el ejemplo siguiente se muestra como almacenar dos variables en el campo de variables:

%…
nn argento OE argento NN argento argento OT aaa %Se almancena el 1 en la posición 0
tt %Se aumenta el puntero del campo de variables
nn argento SE aaa % Se almacena el 7 en la posición 1 del campo de variables
tt

%…

Flujo selectivo


El lenguaje ARGENTOS permite llevar a cabo un control selectivo. Esto es similar al IF en los demás lenguajes clásicos (como C/C++, Python, etc).

Para empezar un flujo selectivo se debe mover la pieza dos veces, seguidos de tres caracteres, operador de la izquierda, operando y el operador de la derecha. Para salir del flujo selectivo se debe volver a la posición de inicio del flujo.

En pseudo-lenguaje sería de la siguiente manera:

Mover una posición de la pieza

Mover una posición de la pieza

Aceptar la secuencia con ‘aaa’

Ingresar al campo de variables o campo de caracteres

Ingresar el primer operador y aceptar con ‘aaa’

Salir del campo y buscar dentro del campo principal el operando que corresponda. Aceptar con ‘aaa’

Ingresar al campo de variables o campo de caracteres

Ingrear el segundo operador y aceptar con ‘aaa’

Aceptar todo el flujo con ‘aaa’

Escribir el código que corresponda

Mover la pieza del caballo al punto inicial del flujo.

Aceptar la secuencia con ‘aaa’

 

 Flujo repetitivo

El flujo repetitivo es similar al flujo selectivo. Para ingresar a este se debe mover tres posiciones de la pieza. Luego ingresar la cantidad de veces a repetir. Para finalizar el flujo se debe volver al punto de inicio del mismo.

En pseudo-lenguaje sería de la siguiente manera:

Mover una posición de la pieza

Mover una posición de la pieza

Mover una posición de la pieza

Aceptar la secuencia con ‘aaa’

Ingresar al campo de variables o campo de caracteres

Llegar hasta el valor deseado (tiene que ser un número necesariamente) aceptar el valor con ‘aaa’

Aceptar todo el flujo con ‘aaa’

Escribir el código que corresponda

Mover la pieza del caballo al punto inicial del flujo y finalizar el flujo con ‘aaa’.


Conclusión 

Hasta ahora está un poco (¿?) inmaduro pero va tomando forma, en estos días estaré actualizando el post, de manera  de ir completandolo. El compilador, ese es el problema.

miércoles, 12 de octubre de 2016

Resolución de sistemas de ecuaciones lineales con Scilab

Supongamos que tenemos un sistema de ecuaciones lineal del tipo:

 

Lo que se hará básicamente resolver la ecucación de la forma 

A * x = b

Dónde A es la matriz, usualmente cuadrada, conformada por los

Primero, definimos una matriz A que contenga los coeficientes. b es una matriz columna conformada por los resultados del sistema. 

Hacemos:

A = [1 1 2; 2 4 -3; 3 3 -1];
b = [1; 2; 0];

Para resolver esto hacemos:

X = linsolve(A, -b)

o

X = A\b

Y obtenemos como resultado:

x = - 1.3571429 
y =   1.5       
z =   0.4285714  

jueves, 6 de octubre de 2016

nRF24L01 para Arduino (AVR), ejemplo con structs

En el último post de esta serie de publicaciones con respecto al módulo de RF nRF24L01, hemos transmitido un simple entero desde un Arduino Nano a un Arduino Mega2560. 

En este caso veremos un pequeño ejemplo, que permitirá transmitir un struct, que estará conformado por 
  • ID del paquete
  • Cantidad de milisegundos en el que fue enviado el paquete.
El paquete saldrá del Arduino Nano, llegará al Mega el cual simplemente lo recibe, lo imprime en consola por medio del protocolo UART y luego lo reenvía. por su lado el Arduino Nano, se queda esperando un determinado lapso de tiempo. Cuando recibe el paquete que envió calcula la diferencia de milisegundos y la imprime en consola (UART).

La estructura del ejemplo es muy parecida a la del post anterior (sería conveniente volverlo a mirar). Desde el lado del transmisor usamos el struct siguiente:

1:  struct Data_struct {  
2:       uint8_t id;  
3:       uint64_t timing;  
4:  } data_to_send, data_responce;  


Se usará data_to_send para el struct que se envía; y se usa data_responce para el mensaje que se recibe. Se podría usar el mismo y optimizar el código pero opté por mantenerlo simple (y no tan eficiente).
Por el lado del receptor el struct es el siguiente:

1:  struct Data_struct {  
2:       uint8_t id;  
3:       uint64_t timing;  
4:  } data_to_read;  

Envío de datos

Para envíar el dato, primero conformamos el struct. asignamos un ID y llamamos  a la función millis():

1:  data_to_send.id = i;  
2:  data_to_send.timing = millis();  
3:  i++;  
4:  /*Go to TX_MODE*/  
5:  TX_MODE(&data_to_send);  
6:  /*Sending data*/  

Espero mientras se termina el proceso de envío y luego paso al modo de recepción:

1:  /*Wait for transmission end*/  
2:  while(nrf24_isSending());  
3:  RX_MODE(); /*Go to RX MODE*/

La variable lastTiming la utilizo para almacenar el instante en el que envío el paquete (Nota: no es lo más eficiente. Solo es una prueba.)

Si recibo el dato, calculo el tiempo que demora y lo imprimo en pantalla.

Si pasa más de 10000 ms imprimo un mensaje de error, de no llegada de paquetes.


1:     lastTiming = millis();  
2:            do{  
3:                 if(rf_data_ready())  
4:                      {  
5:                           rf_get_data(&data_responce);  
6:                           put_string("\nData recieve correctly\n");  
7:                           put_int(data_responce.id);  
8:                           put_string("\n");  
9:                           put_string("El mensaje tardo: ");  
10:                           put_long(millis() - data_responce.timing);  
11:                           break;  
12:                      }  
13:            }while((lastTiming - temp) < 10000);  
14:            if((lastTiming - temp) > 1000){  
15:                 put_string("\nSending Fails\n");  
16:            }  

Recepción de datos

Para la recepión de datos (en el Arduino Mega2560) simplemente se reciben los paquetes, los imprimo en pantalla y luego se los reenvía, sin realizar ninguna modificación.

1:  if(rf_data_ready())  
2:            {  
3:                 rf_get_data(&data_to_read);  
4:                 put_int(data_to_read.id);  
5:                 put_string("\n");  
6:                 put_long(data_to_read.timing);  
7:                 put_string("\n");  
8:                 TX_MODE(&data_to_read);  
9:                 /*Wait for transmission end*/  
10:                 while(nrf24_isSending());  
11:                 RX_MODE();  
12:            }  


Resultados

El resultado de la ejecución se la ve en la siguiente imágen:


El código del receptor se lo puede encontrar aquí.
El código del transmisor se lo puede encontrar aquí.