viernes, mayo 30, 2008

Paso 21: Ejemplos de aplicación - RTAI

Nos quedaba pendiente la publicación de algunos códigos como ejemplo de una aplicación RTAI. Si bien es una aproximación dado que aún estamos realizando diversas pruebas sobre el software y la electrónica, creemos que es una manera útil de ir mostrando los progresos del proyecto.

En éste caso, presentamos un ejemplo de una tarea de tiempo real, ejecutada como parte de un módulo del kernel, y un proceso usuario que muestra datos en pantalla. La tarea se encarga de muestrear cada 50 useg, las entradas discretas de la placa adquisidora. En el puerto, está conectado un encoder incremental de cuadratura y el algoritmo implementado determina si se debe incrementar o decrementar un pulso en el acumulador.

A continuación, se detallan los archivos empleados con algunos comentarios incluidos en el código.

Makefile

-------------------------------------------------------------------
obj-m := ktest_encoder.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
EXTRA_CFLAGS := -I/usr/realtime/include -I/usr/include/ -ffast-math -mhard-float

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
gcc -o utest_encoder utest_encoder.c
-------------------------------------------------------------------



.runinfo

-------------------------------------------------------------------
latency:ksched+fifos:push ktest_encoder;./utest_encoder;popall:control_c
-------------------------------------------------------------------


ktest_encoder.c

-------------------------------------------------------------------
/*
Archivo: ktest_encoder.c

COPYRIGHT (C) 2007-2008 Elias S. Fliger (elias.s.f@gmail.com)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
*/
/*----------------------------------------------------------
Descripción:
Se ejecuta 1 tarea denominada ENCODER.
Lee los canales A y B (chA y chB) y almacena los valores actuales
y anteriores del encoder en los vectores A y B para incrementar
o decrementar la variable x que especifica la posicion angular del motor.
----------------------------------------------------------*/
/* includes*/
#include <linux>
#include <linux>
#include <asm.h>
#include <math.h>
#include <rtai.h>
#include <rtai_sched.h>
#include <rtai_fifos.h>
/* defines*/
#define TICK_PERIOD 50000 //50 useg de periodo
#define TASK_PRIORITY 0
#define STACK_SIZE 10000
#define FIFO 0

#define BASEPORT 0x300 //Dirección Base de la placa adquisidora

/* globals */
static RT_TASK rt_task3;

/********************************************************
* FUNCION: encoder
*
* Descripcion: Tarea de lectura del encoder.
*
* Esta rutina lee los canales IN0 e IN1 (pin31 y 30) como canales A y B, respectivamente.
* Compara el estado de cada canal cada 50 useg ya que no posee interrupciones y
* luego incrementa o decrementa el acumulador de pulsos.
*********************************************************/
static void encoder(int t)
{
unsigned char chA=0, chB=0, entrada=0; //canales A y B , mas la mascara del puerto de entradas discretas
unsigned int A[2] = {0,0}; //Vector para comparar el valor actual y anterior del canal A
unsigned int B[2] = {0,0}; //Idem
int x=0; //Acumulador de pulsos

entrada=inb( BASEPORT);
chA = entrada & 0x01; //Lee IN 0 - Pin 31
chB = entrada & 0x02; //Lee IN 1 - Pin 30
A[0] = ( unsigned int )chA; //Inicializa canales de entrada
B[0] = ( unsigned int )chB;

rtf_reset(FIFO);


while(1)
{

entrada=inb( BASEPORT);

chA = entrada & 0x01;
chB = entrada & 0x02;
chB = chB/2;

A[1] = ( unsigned int )chA;
B[1] = ( unsigned int )chB;

if((A[1] & B[1])) //Ejecutar solo si A[1] = B[1] = 1
{
if( ((A[1]^A[0]) | (B[1]^B[0])) ) //si hubo cambio de estado para A o B, Incr o Decr
{
if((A[1]^B[0])) x++; // Si A[1] xor B[0] = 1 incrementa
else
{
if(x>0) x--; // De otra forma decrementa
else x=0;
}
}
}

A[0]=A[1]; //Actualiza valores
B[0]=B[1];

rtf_put(FIFO, &x, sizeof(x)); //Coloca en el FIFO para Proceso usuario

rt_task_wait_period();
}

}

/********************************************************
* FUNCION: init_module
*
* Descripcion: Inicializa el modulo.
*
* Inicializa tarea de tiempo real, establece modo periódico,
* crea FIFO e inicia temporizador.
*********************************************************/
int init_module(void)
{
RTIME tick_period;

rt_set_periodic_mode();

rt_task_init(&rt_task3, encoder, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
//tarea, funcion,valor inicial, tamaño stack, prioridad, usa FPU, usa Signal Handler.

rtf_create(FIFO, 10);

tick_period = start_rt_timer(nano2count(TICK_PERIOD));

rt_task_make_periodic(&rt_task3, rt_get_time() + tick_period, tick_period);

return 0;
}

/********************************************************
* FUNCION: cleanup_module
*
* Descripcion: Libera el modulo.
*
* Detiene temporizador, destruye FIFO y elimina tarea de tiempo real.
*********************************************************/
void cleanup_module(void)
{
stop_rt_timer();

rt_busy_sleep(10000000);
//recomendado

rtf_destroy(FIFO);
rt_task_delete(&rt_task3);
return;
}

MODULE_AUTHOR("Elias S. Fliger, ");
MODULE_DESCRIPTION("Proyecto BORA - RT test encoder - UNQ");
MODULE_LICENSE("GPL");
-------------------------------------------------------------------




utest_encoder.c

-------------------------------------------------------------------
/*
Archivo: utest_encoder.c

COPYRIGHT (C) 2007-2008 Elias S. Fliger (elias.s.f@gmail.com)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
*/

/*----------------------------------------------------------
Descripción:
El proceso solo recibe el valor del acumulador de pulsos
obtenido en el modulo ktest_encoder y lo muestra en pantalla.
Ejecutar ./utest_encoder
----------------------------------------------------------*/
/* includes*/
#include
#include
#include
#include
#include
#include
#include
#include

/* defines*/
#define BASEPORT 0x300
//direccion base de la placa de adquisicion

static int end;
static void endme(int dummy)
{
end=1;
}


int main(int argc, char * argv[])
{
int fifo;
int Contador;

if ((fifo = open("/dev/rtf0", O_RDONLY))
-------------------------------------------------------------------

miércoles, mayo 14, 2008

Paso 20: Estado del arte de la electrónica

El estado general del proyecto, desde el punto de vista electrónico, es avanzado con tendencia a definitivo.

Hemos planteado una serie de interfaces de adaptación y optoaislación, más un driver o controlador para el motor (IGNIS MR5-90).

- Optoacopladores: Tenemos 16 entradas/salidas discretas para varios destinos:

- 2 encoders de 3 salidas
- 4 finales de carrera
- 1 relé
- 1 electroimán
- 4 PWM
- 4 direcciones

- Adaptador: Dividimos la salida del DB-37, de la placa adquisidora ADQ12-B, en 3 salidas con las tierras separadas:

- Salidas discretas
- Entradas discretas
- Entradas analógicas

- Puente H: Implementamos esquema sencillo de un Puente H basado en el L298. Los resultados fueron aceptables bajo condiciones nominales de funcionamiento del motor. Sin embargo, para una mayor exigencia de consumo, el L298 pasó a convertirse en una especie de incienso electrónico.

La experiencia nos enseñó que los disipadores de temperatura, los fusibles y protecciones adicionales como el sensado de la corriente consumida por el motor, son una buena herramienta para evitar situaciones nefastas.

A continuación, mostramos algunos circuitos esquemáticos y diseño de los circuitos impresos.

Placa de optoaislación terminada.

Detalle de la cara superior de la placa optoaisladora.


Placa adaptadora de DB-37 a DB-9.

Circuito esquemático del puente H.


Detalle de la cara inferior y superior del circuito impreso para el puente H.