Inicio

Inicio

Herramientas Programación de Sistemas

 

   ROBOZB

 

Inicio

 

Se explican aquí algunos conceptos y detalles acerca de las herramientas que fueron utilizadas para hacer los programas.

 

Puerto USB:

 

Como se menciona en la sección de hardware, se utilizó un XBee Explorer USB, que cuenta con un chip FTDI FT2232 encargado de convertir la comunicación UART a USB.

En Linux a partir del  kernel 2.6.9 trae soporte para este chip y no es necesario descaragar ningún driver.

 

Configuración de puerto USB:

 

Debido a que ya se encuentra soportado el chip, para trabajar con el puerto USB se configura como si fuera un puerto serial.

 

Pasos básicos:

 

Es necesario declarar la librería termios.h que controla el comportamiento del puerto:

 

#include <termios.h>

 

Se definen variables estáticas, una para la tasa a utilizar y otra abrir el puerto correcto.

 

#define BAUDRATE B9600

 

#define MODEMDEVICE "/dev/ttyUSB0"

 

Dentro del main se hace lo siguiente:

 

   Se crean dos estructuras una para almacenar la antigua configuración del puerto y otra para la nueva configuración que crearemos, esto es necesario para que al finalizar el programa el puerto se restaure a la antigua configuración.

  

struct termios oldtio,newtio;

 

Posteriormente se configura el puerto de la forma que mejor nos convenga, el siguiente material fue extraído de http://www.wikilearning.com/tutorial/como_programar_el_puerto_serie_en_linux-programas_ejemplo/20528-3.

Esta configuración es para un proceso de entrada Canónico, esto significa que toda la entrada es procesada en unidades de líneas, lo que significa que un read sólo devolverá una línea completa de entrada. Una línea está, por defecto, finalizada con un NL(ASCII LF), y fin de fichero, o un carácter fin de línea. Un CR (el fin de línea por defecto de DOS/Windows) no terminará una línea con la configuración por defecto.

 

/* 
      Abre el dispositivo modem para lectura y escritura y no como controlador
      tty porque no queremos que nos mate si el ruido de la linea envia 
      un CTRL-C.
*/
 
   fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
   if (fd <0) {  perror(MODEMDEVICE); exit(-1);  }
 
   tcgetattr(fd,&oldtio); /* almacenamos la configuracion actual del puerto */
 
   bzero(newtio, sizeof(newtio)); /* limpiamos struct para recibir los
                                        nuevos parametros del puerto */
 
/*
      BAUDRATE: Fija la tasa bps. Podria tambien usar cfsetispeed y cfsetospeed.
      CRTSCTS : control de flujo de salida por hardware (usado solo si el cable 
      tiene todas las lineas necesarias Vea sect. 7 de Serial-HOWTO)
      CS8     : 8n1 (8bit,no paridad,1 bit de parada)
      CLOCAL  : conexion local, sin control de modem
      CREAD   : activa recepcion de caracteres
*/
 
   newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 
/*
      IGNPAR  : ignora los bytes con error de paridad
      ICRNL   : mapea CR a NL (en otro caso una entrada CR del otro ordenador 
      no terminaria la entrada) en otro caso hace un dispositivo en bruto 
      (sin otro proceso de entrada)
*/
 
   newtio.c_iflag = IGNPAR | ICRNL;
 
/*
      Salida en bruto.
*/
   newtio.c_oflag = 0;
 
/*
      ICANON  : activa entrada canonica
      desactiva todas las funcionalidades del eco, y no envia segnales al
      programa
      llamador
*/
 
   newtio.c_lflag = ICANON;
 
/* 
      inicializa todos los caracteres de control
      los valores por defecto se pueden encontrar en /usr/include/termios.h, 
      y vienen dadas en los comentarios, pero no los necesitamos aqui
*/
 
   newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
   newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
   newtio.c_cc[VERASE]   = 0;     /* del */
   newtio.c_cc[VKILL]    = 0;     /* @ */
   newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
   newtio.c_cc[VTIME]    = 0;     /* temporizador entre caracter, no usado */
   newtio.c_cc[VMIN]     = 1;     /* bloqu.lectura hasta llegada de caracter. 1 */
   newtio.c_cc[VSWTC]    = 0;     /* '\0' */
   newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
   newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
   newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
   newtio.c_cc[VEOL]     = 0;     /* '\0' */
   newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
   newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
   newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
   newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
   newtio.c_cc[VEOL2]    = 0;     /* '\0' */
 
/* 
      ahora limpiamos la linea del modem y activamos la configuracion del
      puerto
*/
 
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd,TCSANOW,&newtio);

 

Para la comunicación se utilizan las funciones read y write, aquí un ejemplo:

 

read(fd,buf,255)

 

Hebras:

 

En la sección de software aparece un diagrama de alto de nivel de funcionamiento de todo el conjunto, y como se observa, dentro del programa principal, éste despliega un menú interactivo usando una hebra.

Las hebras, hilos o threads son necesarias para realizar múltiples tareas dentro de un mismo proceso. Es necesario además proveer mecanismos de sincronización como mutexs. Estos elemento son declarados de la siguiente manera.

 

pthread_t ntid;//id de la thread que contendra el menú

 

pthread_mutex_t mutexRxTx = PTHREAD_MUTEX_INITIALIZER;//ejemplo de un mutex.

 

Para crear la hebra:

 

pthread_create(&ntid, NULL, thr_fn, NULL);

 

La tarea que contendrá el menú estará dentro de “thr_fn”, que es declarada de la siguiente manera.

 

void * thr_fn(void *arg);

 

Para mayor información consultar el manpage de las threads de linux.

Procesos hijos:

 

Para desplegar los gráficos utilizando Octave se utilizan procesos hijos, estos procesos son creados con la función fork().

Un ejemplo sencillo de uso de la función fork():

 

pid_t pid;// identificador del proceso

 

if ((pid = fork()) < 0) {

        perror("fork");

        exit(1);

    }

 

    if (pid == 0) {// En el hijo la función fork() retorna un 0

//aquí el hijo

}

//Aquí el padre