martes, noviembre 23, 2010

Paso 30: A lo guapo, o ¿a lo guaso? (Cómo soldar un acelerómetro con encapsulado QFN sin las herramientas apropiadas)

1. Todo fin tiene un principio
Hay muchas formas de hacer las cosas y entre todas esas formas elijo casi siempre entre dos opciones: hacerlas bien o simplemente hacerlas. La elección de una u otra manera de trabajo depende de varios factores y condiciones cuya breve lista expongo a continuación:
  • Tiempo disponible
  • Dinero necesario
  • Experiencia personal en el tema
  • Experiencia de terceros en el tema (a quienes pueda consultar)
  • Ayuda/Asistencia ofrecida
  • Información sobre el tema
  • Disponibilidad de herramientas/materiales
  • Momento del día
  • Estado de ánimo (esto puede ser: al borde del pánico, con culpa por haber dejado todo para el último momento o completamente enyoguizado)
De ésta manera, el árbol de decisiones dependerá de la combinación de los factores previamente mencionados. Para exponer algunos ejemplos:
  1. Si tengo suficiente tiempo disponible → alguna experiencia personal y de terceros → información accesible → pero sin herramientas adecuadas →al mediodía → y al borde del pánico: las cosas simplemente se hacen.
  2. Si tengo suficiente tiempo disponible → cuento con dinero necesario para tercerizar parte del trabajo → cuento con experiencia personal→ dispongo de información → mis herramientas están a la altura de la labor →aislado en mi lugar de trabajo desde las 6:00 de la mañana → y en armonía conmigo y con el mundo: las cosas se hacen perfectamente bien.
  3. Sin tiempo disponible →sin experiencia personal o de terceros → con escasa o nula información sobre el tema → con algunas buenas herramientas →siendo interrumpido cada 30 minutos → y tratando de terminar otros asuntos que dejé para último momento: las cosas se hacen y salen como quién tira maíz a las gallinas.
Debo confesar que la opción 2. es un excepcional acontecimiento en mi vida, aunque trabaje en ello para mejorarlo, cuya probabilidad de ocurrencia está en el mismo orden que el de ser teletransportado cuánticamente por coincidencia. Aún así, diversas variantes de 1. y 3. suelen dejarme resultados aceptables, que podrían llegar a satisfacer hasta al técnico más ortodoxo y detallista. Ésta introducción no pretende ser una excusa, sino un mero raconto de situaciones que concluyen en una determinada calidad de trabajo. En consecuencia, les presento a una descripción de los pasos realizados para soldar un acelerómeto de tres ejes MMA7260QT con encapsulado QFN de freescale.

2. ¿Para qué sirve?
La implementación del sensor de aceleración en el proyecto tiene por objetivo la medición de los ángulos de oscilación en el plano x-y de la carga útil del puente grúa.

3. Piedra, papel o tijera
La elección del sensor quedó determinada principalmente por problemas de disponibilidad en el mercado, económicas y por características técnicas. Existen diversas opciones con rangos de precios muy por encima del presupuesto del proyecto, aunque muchas de ellas presentan dificultad para adquirirlas. En cuanto a las características técnicas se pueden encontrar los siguientes modelos:

Memsic 2125 que comercializa Parallax. Es un sensor de 2 ejes, con salida PWM, montado sobre PCB para una fácil instalación, a u$s 30 en el exterior más impuestos.

MMA7455 de freescale. Sensor triaxial, con salida digital SPI/I2C y encapsulado LGA.

ADXL203 de Analog Devices. Sensor de 2 ejes, con salida modulada de frecuencia ajustable, encapsulado LCC, a u$s 10 en el exterior más impuestos.


AIS326DQ de STMicroelectronics. Sensor triaxial, con salida digital SPI/I2C y encapsulado QFPN-28.

MMA7260QT de freescale. Sensor triaxial, con salida analógica y encapsulado QFN-16, a u$s 3 en el exterior más impuestos o u$s 10 en distribuidores locales.

Además, la selección del sensor debe estar fundada de acuerdo con los siguientes criterios para acotar el rango de posibilidades:


  • Salida analógica como interfaz con la placa adquisidora ADQ12-B.

  • Dos ejes de sensado como mínimo o tres como máximo para una mejor resolución.

  • Encapsulado PDIP, DIP o similar para un montaje sencillo.


En consecuencia, de las opciones listadas, sólo 1. y 5. resultaron convenientes. En el caso del sensor comercializado por Parallax encontramos que la salida PWM (se podría considerar un filtro RC para una frecuencia de ~100 kHz) y su elevado precio, a pesar de su sencilla implementación, dieron lugar a la segunda opción. Con el sensor de freescale, cumplimos con las dos primeras condiciones sumado a su bajo precio (aproximadamente u$s 4,50 en la puerta de mi casa, gracias a un grupo de personas que realizan compras por internet).

De ésta manera, se consiguieron 3 integrados MMA7260QT, a riesgo de sufrir complicaciones con la soldadura del componente. Entonces, en un intento por combatir la ignorancia en asuntos de montaje superficial, hicimos una recorrida por distintos sitios donde los avezados exponen su experiencia con el encapsulado QFN.

Algunos interesantes ejemplos caseros se pueden encontrar aquí y aquí.


Enlace4. La base está

En el paso 27, se publicó el diseño electrónico y el PCB del circuito para la medición de los ángulos, al que se le hicieron algunos retoques, debido a errores en las librerías de componentes para Kicad.

Por un lado, el footprint para el acelerómetro no se encuentra adaptado para montaje superficial (me di cuenta de éste detalle justo en el momento de comenzar a soldar el componente). Por lo tanto, se tuvo que armar la versión 2.0 de la placa. La librería adicional para Kicad se puede conseguir en (http://library.oshec.org/).

Por el otro, el PCB para el regulador de tensión LM317 tiene sus patas OUT y ADJ invertidas (incluso las tiene numeradas tanto el esquema como en el pcb para el encapsulado TO-220). Esto significó que las patas tuvieron que ser dobladas y adaptadas al PCB ”on-the-fly” ya que no había tiempo para una nueva placa. Afortunadamente existen los protoboards en donde poder pulir estos asuntos, aunque una buena inspección hubiese sido lo recomendable.


5. Los utensilios

Para llevar la tarea a cabo, son necesarias las siguientes herramientas y materiales:


  • Horno para soldar o un buen soldador de punta fina

  • Flux

  • Estaño

  • Soporte

  • Microscopio

¿Qué nos faltó? Bueno, básicamente todo. Ni horno ni buen soldador. El microscopio ni en figuritas, apenas una lupa y gracias. Olvidaba mencionar que unas buenas copitas del alcohol que más les guste, ya que uno debe estar medio mamado para soldar ésta porquería (en alguna página que no logro recordar lo recomiendan). Para tener una dimensión de lo que estoy hablando, pasen y vean las figuras 1 y 2.



Figura 1


Figura 2


¿Qué nos sobró? Para ser moderados, coraje, paciencia, pulso y un buen manejo de insultos en habla hispana. Me remito a Fontanarrosa.


6. Las manos en la masa

En la introducción hablaba de los distintos factores que influyen en el resultado final de un trabajo. En nuestro caso, se combinaron la desesperación por terminar una tarea clavada desde hace más de un año, el horario de madrugada y la falta de herramientas adecuadas para terminar haciendo algo que, como premio consuelo, funciona y no preguntemos más.

Los pasos realizados fueron los siguientes:

  1. Una horita y media después de cenar, tipo 11:00 de la noche, poner la pava y preparamos la primera tanda de mates.

  2. Para empezar, pegamos el integrado con los pads mirando hacia arriba.

  3. Cortamos varios filamentos finos de un cable y cambiamos la yerba.

  4. Pasamos flux por los cables y preestañamos. Esto puede demandar unos minutos, así que preparamos la segunda pava.

  5. Pasamos flux por los pads del integrado y preestañamos.

  6. Soldamos uno a uno los pads de relevancia: Vdd, Vss, g1, g2, sleepmode, x, y, z. Los pads restantes los dejamos intactos, salvo uno para hacer una primera prueba. Al terminar será mejor que cambiemos la yerba y preparemos la tercera pava.

  7. El resultado puede verse en las figuras 3 y 4.


  8. En un protoboard verificamos el estado del sensor, si te da hambre luego de tanto mate, podemos picotear alguna galletita. Figuras 5 y 6.

  9. Preparamos el PCB del inclinómetro para montar el integrado, con una base de 4x4 mm sobrante de la misma placa. Figura 7.

  10. Le cortamos los flecos al integrado y luego doblamos las patas “artificiales” para luego soldar al impreso. Figura 8.

  11. Nuevamente pasamos flux a la placa y pines y soldamos con cuidado. CUIDADO, en éste paso se nos puede caer algo de pelo y alguna que otra puteada, nos podemos quemar con el soldador e incluso se puede desoldar alguna pata del integrado cuando las restantes se encuentran en su sitio. Figuras 9 y 10.

  12. Tipo 6:30 am tendremos los ojos como duraznos en compota y la placa debería estar terminada, hacemos las primeras pruebas. Ojo, la pata sleepmode debe estar conectada a Vdd para que el sensor se encuentre operacionalmente activo. Figura 11.

  13. Voilà!


7. Tomando serias medidas

Improvisando un banco de pruebas, sujetamos la placa y verificamos el comportamiento de cada salida frente a la variación de la posición angular, sobre todo prestando atención a los extremos del rango p a -pi.


Para un ángulo de inclinación cercano a cero, la salida debería estar en aproximadamente 1,60 V. Nuestros resultados arrojaron 1,496 V sin calibración. En resumidas cuentas, para cada eje se obtuvo lo siguiente:

Eje x, sentido positivo: 1,902 V.

Eje x, sentido negativo: 0,938 V.

Eje y, sentido positivo: 2,050 V.

Eje y, sentido negativo: 0,781 V.


Eje z, sentido positivo: 2,146 V.

Eje z, sentido negativo: 0,832 V.


8. Conclusiones

Evidentemente, pese a la falta de habilidades técnicas para soldar componentes QFN, sin herramientas apropiadas y con escaso tiempo, alcanzamos el objetivo y la cosa se hizo y funciona. Con eso me voy a dormir contento.

sábado, septiembre 05, 2009

Paso 29: Diseño e implementación de la aplicación de software

1.1.1. Características del sistema

Nuestro sistema de control consiste en una PC x86 estándar, con procesador Pentium III de 700 MHz y 128 MB de memoria RAM. El OS GNU/Linux, está basado en una distribución Debian con kernel 2.6.17 y parche de tiempo real RTAI 3.4.

La PC incluye, además, una placa adquisidora ISA, de 8 canales analógicos diferenciales de 12 bits de resolución con 10 μseg de conversión, 4 entradas y 7 salidas discretas y un temporizador de 16 bits. Tanto la PC como la placa adquisidora fueron provistos por la carrera de Ingeniería en Automatización y Control Industrial de la Universidad Nacional de Quilmes.

El controlador de los motores e interfaz de entradas/salidas (E/S) discretas están concentrados en un microcontrolador Atmega16 de 8 MHz, como se explica en la sección . Los ciclos de trabajo de las señales PWM de cada motor, se transmiten desde la PC al microcontrolador mediante una línea de comunicación RS-232, con un período de 20 mseg.

En la figura 1.1 se muestra un esquema de la disposición de los componentes de la planta.




Figura 1.1: Esquema de conexión entre la PC y los sensores y actuadores de la planta.




1.1.2. Diseño y arquitectura del software

La aplicación del software, desarrollada para cubrir los propósitos del proyecto, está dividida en un proceso para la interfaz de usuario y un módulo del núcleo destinado a las tareas de control, comunicación y adquisición de datos, como puede verse en la figura 1.2.

El proceso del espacio de usuario cuenta con las funcionalidades necesarias para ofrecer interacción entre el sistema y el usuario. Por medio de una simple interfaz de texto, en donde se presentan las variables más significativas de la planta, se reciben los comandos de actuación desde el teclado y se almacenan los datos en archivos. El corazón de la aplicación reside en el espacio del núcleo, desde donde se controlan las variables del sistema y se establece la comunicación, tanto con la placa adquisidora, como con la interfaz serie RS-232.




Figura 1.2: Diseño conceptual del software.



El código fuente de la aplicación se encuentra organizado según se trate del módulo o del proceso, con las características que se enumeran a continuación:

  • Módulo del núcleo

    • Código fuente

      • BORA_rt_task.c: Posee las funciones principales del módulo y se encarga de
        administrar las actividades de la aplicación.

      • BORAcom.c: Provee la interfaz de comunicación entre el uC y la PC por el puerto serie.

      • MR590.c: Contiene las funciones necesarias para manipular los motores de la planta.

      • kControl.c: Destinado para ejecutar las rutinas de control del sistema.

      • kEncoder.c: Posee la tarea de adquisición de pulsos provenientes de los encoders.




    • Archivos de cabecera

      • BORAglobal.h: Común al proceso y al módulo. Contiene las definiciones de tiempo, FIFOs, puerto serie, modos de operación, frecuencias de PWM y estructuras de datos y comandos.

      • serialP.h: Librería con las funciones y definiciones del driver de tiempo real del
        puerto serie.



  • Proceso usuario

    • Código fuente

      • gui.c: Contiene las funciones elementales para el manejo de la interfaz de texto y
        archivos.

      • uShow.c: Interfaz para presentar los datos en pantalla.

      • uOperacion.c: Provee las funciones de interfaz del teclado, menú y motores.


    • Archivos de cabecera

      • uConfig.h: Librería con las definiciones y estructuras de datos empleadas en el
        proceso usuario.


El entorno de desarrollo empleado es un editor de texto simple para KDE denominado Kate [3], que reconoce la sintaxis del lenguaje C/C++, entre otros. Mientras que el compilador es el GNU Compiler Collection (GCC) 4.2.1 [2].

1.1.2.1. Sistema de comunicación IPC
El mecanismo de comunicación entre el proceso y el módulo se establece por medio de dos buffers FIFO, uno de lectura y otro de escritura. El algoritmo ?? muestra la forma en que los buffers han sido implementados con las estructuras de datos asociadas. F_DATOS es, desde el punto de vista del módulo, un buffer de escritura encargado de suministrar todas las variables de importancia que representan al sistema. El lazo de comunicación se cierra con el buffer de lectura F_COMANDO, por el que se reciben los comandos ingresados desde el proceso usuario.

La creación de los FIFOs sucede durante la inicialización del módulo, con la llamada a init_module(). Además, en la misma función, se asocia la rutina de servicio de atención del FIFO de lectura con los datos provenientes desde el proceso, denominada rtf_create_handler().

Las funciones, despModoLibre() y despModoControl(), responden al proceso usuario con los datos actualizados de actuación, según se encuentre en el modo libre o control.


BORA_rt_task.c


1int init_module(void)
2{
3 ...
4 rtf_create(F_DATOS, 8000); /* FIFO de escritura */
5 rtf_create(F_COMANDO, 8000); /* FIFO de lectura */
6 ...
7 res = rtf_create_handler(F_COMANDO, (void*)fifo_handler_comando);
8 ...
9 return OK;
10}
11
12static int fifo_handler_comando(unsigned char fifo)
13{
14 int numbyte;
15 do
16 {
17 numbyte = rtf_get(F_COMANDO, &kMR590, sizeof(kMR590));
18 }
19 while (numbyte != 0);
20 return 0;
21}
22
23static int despModoLibre(void)
24{
25 ...
26 /* Cálculo de referencias en X e Y */
27 /* Cálculo del sentido de giro de los motores en X e Y */
28 /* Actualización de la actuación en modo libre */
29
30 /* Envío de los datos al proceso usuario por medio de F_DATOS */
31 retfifo = rtf_put(F_DATOS, &datos_user, sizeof(datos_user));
32 return OK;
33}
34
35static int despModoControl(void)
36{
37 ...
38 /* Cálculo de referencias en X e Y */
39 /* Cálculo del sentido de giro de los motores en X e Y */
40 /* Actualización de las variables de estado controladas */
41 /* Actualización de las variables de estado observadas */
42 /* Actualización de la acción de control */
43
44 /* Envío de los datos al proceso usuario por medio de F_DATOS */
45 retfifo = rtf_put(F_DATOS, &datos_user, sizeof(datos_user));
46 return OK;
47}


BORAglobal.h

1typedef struct
2{
3 unsigned int niter; /* Num de iteraciones para generar Ref */
4 float refx; /* vector Referencia X */
5 float refy[3]; /* vector Referencia Y */
6 float x1;
7 float x2;
8 float x3;
9 float x4;
10 float u;
11 int pulsoy;
12} STRUCT_DATOS;
13
14typedef struct
15{
16 int comandox;
17 int comandoy;
18 int frec;
19 int modo;
20} STRUCT_COMANDO;

En el algoritmo ?? figuran los datos enviados al proceso, que están asignados en la estructura STRUCT_DATOS, donde se encuentran las variables de estado del sistema, las referencias a seguir, el número de iteraciones o pasos, la acción de control, los pulsos de los encoders y ángulos de oscilación de la carga transportada. En cambio, la estructura STRUCT_COMANDO, contiene la información asociada con los comandos enviados para el desplazamiento en el eje x e y, la frecuencia de operación del PWM de ambos motores y el modo de funcionamiento del despachador.

La relación, vista desde el proceso, se establece por medio de las funciones que se detallan en el
algoritmo ??. En éste caso, el FIFO se puede leer y escribir como si se tratase de un dispositivo de caracteres, de la misma manera que un archivo o un puerto de comunicaciones. Esto significa que no se necesita una API adicional, por lo que se gana en portabilidad de la aplicación.

La función de lectura en el proceso está a cargo de getKernelDatos(), que espera la llegada de los datos desde el módulo del núcleo. Cuando los datos están disponibles, se imprime en la pantalla las variables de interés. Los comandos se comunican al módulo mediante la función setKernelCmd(). De ésta manera, el servicio de comunicación FIFO establece un mecanismo eficiente para el envío y recepción de datos entre el proceso usuario y el módulo del núcleo. La figura 1.3 da un ejemplo del caso.


1static STRUCT_DATOS getKernelDatos(fd_set read_fd)
2{
3 ...
4 /* Espera que el FIFO esté disponible */
5 FD_ZERO(&read_fd);
6 FD_SET(fiford, &read_fd);
7 stat = select (FD_SETSIZE, &read_fd, (fd_set*)NULL, (fd_set*)NULL, &timeout);
8 stat = read(fiford, &kernel_datos, sizeof(kernel_datos));
9 if (stat == ERROR)
10 {
11 /* Imprime datos recibidos en pantalla */
12 }
13 return (kernel_datos);
14}
15
16int setKernelCmd(STRUCT_COMANDO opMR590)
17{
18 if (sizeof(opMR590) != write(fifowr, &opMR590, sizeof(opMR590)))
19 {
20 return ERROR;
21 }
22 return OK;
23}





Figura 1.3: Comunicación entre el proceso y del módulo del núcleo.



1.1.2.2. Tarea Despachador
El módulo BORA_rt_task.c, descripto en el algoritmo ??, consiste en dos tareas, donde Despachador() es la rutina principal, que centraliza la actividad y modo de operación del sistema y es, por lo tanto, la de mayor prioridad. Luego, la tarea suplementaria Encoder() limita su función a la lectura de las entradas discretas de la placa ADQ12-B, para la adquisición de las pulsos de los encoders correspondientes al puente y montacargas. Ambas tareas se ejecutan en forma periódica y se crean y lanzan desde init_module(). También, durante el inicio del módulo, se crean los relojes de tiempo real, los FIFOs, se inicializan los datos del controlador y se abre el puerto serie para la comunicación con el microcontrolador. Cuando el módulo es descargado, se liberan todos los recursos ocupados por las tareas, FIFOs y otras funciones adicionales, en el punto de salida cleanup_module().


1int init_module(void)
2{
3 ...
4 /* Configuración del reloj de tiempo real en modo periódico */
5 rt_set_periodic_mode();
6
7 /* Inicio de las tareas */
8 rt_task_init(&rt_despacha, (void*)Despachador, 1, STACK_SIZE, TASK_PRIORITY, 1, 0);
9 rt_task_init(&rt_encoder, (void*)encoder, 1, STACK_SIZE, TASK_PRIORITY+10, 0, 0);
10
11 /* Creación e inicio de FIFOs F_DATOS y F_COMANDO */
12
13 /* Inicia los estados del controlador. */
14 iniciaEstados();
15
16 /* Inicia timers y tareas con base de tiempo de 2 mseg */
17 tick_period = start_rt_timer(nano2count(MS02));
18 rt_task_make_periodic(&rt_encoder, rt_get_time() + tick_period, tick_period);
19 rt_task_make_periodic(&rt_despacha, rt_get_time() + 10*tick_period, 10*tick_period);
20
21 /* Apertura del COM1 */
22 res = rt_spopen(COM1, BAUD, NUMBITS, STOPBITS,...
23 RT_SP_PARITY_NONE, RT_SP_NO_HAND_SHAKE, RT_SP_FIFO_DISABLE);
24 switch(res)
25 {
26 /* Verifica errores en el COM1 */
27 }
28 /* Limpia buffers Tx y Rx del COM1 */
29
30 return OK;
31}
32
33void cleanup_module(void)
34{
35 stop_rt_timer();
36 rtf_destroy(F_DATOS);
37 rtf_destroy(F_COMANDO);
38 rt_task_delete(&rt_despacha);
39 rt_task_delete(&rt_encoder);
40 rt_spclose(COM1);
41 return;
42}

La tarea Despachador puede entenderse como una máquina de estados, que cambiará de estado o modo de operación según lo determine el usuario. Se puede ver en el diagrama de la figura 1.4 que inicialmente la tarea envía un caracter de inicio de comunicación con el uC y queda en espera de la respuesta. Este mecanismo es de utilidad, ya que es en el uC donde se accionan los dos motores del puente grúa, y tanto el sentido de giro como el ciclo de trabajo de cada PWM son enviados por el puerto serie.



Figura 1.4: Diagrama de flujo del Despachador.


Una vez establecida la comunicación entre el driver de los motores y la PC, el modo de operación

determinará el funcionamiento de la aplicación. El Despachador cuenta con cuatro modos posibles, Libre, Control, Espera y Salida:

Libre:
Es el modo de funcionamiento del sistema a lazo abierto. Esto significa que no se controlarán las variables del sistema como posición y oscilación de la carga.

Control:
Se diferencia del anterior en que la planta se encuentra a lazo cerrado, controlando la
posición y oscilación de la carga de acuerdo con el algoritmo de control hallado en XXXXXXX.

Espera:
Aguarda el cambio del modo de operación sin realizar actividades de comunicación y control.

Salida:
Es un modo adicional que permite cerrar la aplicación y descargar el módulo, sin perder
la actividad del uC. El objetivo de éste modo de operación es lograr que al reiniciar la
aplicación, el uC se encuentre activo y reanude su funcionamiento en lugar de aplicar un ciclo de apagado-encendido para volverlo activo.

1.1.2.3. Comunicación serie de tiempo real
La comunicación con el uC se establece mediante un conjunto limitado de funciones, contenidas en BORAcom.c , para la transmisión y recepción de datos. La función receivedata() se encarga de recibir la respuesta desde el uC cuando se inicia el diálogo con la PC. Una vez que la comunicación ha sido establecida entre ambos dispositivos, la función senddata() transmite un byte por única vez, con la frecuencia del PWM que utilizará el uC para manipular a los motores. La tabla 1.1 muestra las frecuencias de PWM disponibles, según el divisor de reloj seleccionado en el microcontrolador.


Selección

Frecuencia










PWM_DIV_1

31,250 kHz

PWM_DIV_8

3,906 kHz

PWM_DIV_64

488,280 Hz

PWM_DIV_256

122,070 Hz

PWM_DIV_1024

30,520 Hz


Cuadro 1.1: Frecuencias del PWM posibles.



Finalmente, la función setComData(), asociada a los modos Libre y Control del Despachador, transmite tres bytes periódicamente con la información del ciclo de trabajo y el sentido de giro de los dos motores, tal como se describe en la figura 1.5.





Figura 1.5: Paquete de actuación.


Los parámetros de configuración del puerto serie son: 38400 bps, 8 bits de datos, sin paridad y 1 bit de stop (38400,8,N,1). Los dos primeros bytes del paquete de actuación contienen el ciclo de trabajo de los PWM, cuyo rango de uso se encuentra entre 0 y 255, correspondiente a una escala del 0 - 100 %. En el byte 3 se enmascaran el modo de operación del driver de los motores y los sentidos de giro para los ejes X e Y.
1.1.2.4. Generador de referencias
El esquema de control propuesto en XXXX cuenta con un generador de referencias para facilitar la operación de los motores durante el arranque y la parada. Su propósito consiste en producir las curvas óptimas de posición que debe seguir el puente grúa, en función de una secuencia de aceleraciones, cuya duración e intensidad dependen de las características inherentes al sistema. Este método, desarrollado por [1], está basado en la estrategia de los operadores humanos, que permite conseguir la máxima velocidad de traslado, con mínima oscilación de la carga. La figura 1.6 describe la secuencia del movimiento durante el arranque y la parada.



Figura 1.6: Secuencia de movimiento con el generador de trayectorias.



Desde el punto de vista funcional, getMR590ref() se encarga de generar la secuencia de pulsos de
aceleración que resulta en la curva de referencia de posición de la figura 1.7 a). De acuerdo con el parámetro recibido por la función, el generador producirá pulsos positivos, negativos o nulos, para los movimientos de avance, retroceso y parada, respectivamente.



Figura 1.7: a) Referencia de posición. b) Referencia de velocidad. c) Referencia de aceleración.


La función getMR590dir() sirve de complemento al generador de referencias ya que, debido a las

características del driver del motor, no es suficiente contar con el parámetro de referencias, sino que debemos calcular el sentido de giro con que deben actuar los motores. El algoritmo ?? da un ejemplo de la aplicación, tal como se encuentra en el archivo MR590.c.


MR590.c


1unsigned char getMR590ref(unsigned char cmd)
2{
3 unsigned char t_on;
4 int signo = 1;
5
6 if ((cmd == AVANZAR) || (cmd == RETROCEDER))
7 {
8 signo = POSITIVO;
9 }
10 else if (cmd == DETENER)
11 {
12 signo = NEGATIVO;
13 }
14 else if((cmd == RESET) || (cmd == SALIR))
15 {
16 signo = NULO;
17 niter = NULO;
18 }
19
20 if ((Posicion > LIMITE_MIN) && (Posicion < LIMITE_MAX))
21 {
22 refx[0] += signo * PENDIENTE;
23 if (refx[0] > 1) refx[0] = T_ON_MAX;
24 if (refx[0] < 0) refx[0] = T_ON_MIN;
25 }
26
27 /* Escalar refx[0] para DC de la salida PWM del uC */
28 t_on = (unsigned char)(refx[0] * 255);
29
30 return (t_on);
31}
32
33unsigned char getMR590dir(unsigned char cmd)
34{
35 if(cmd == AVANZAR)
36 girox = SENTIDO_AHORARIO;
37 else if(cmd == RETROCEDER)
38 girox = SENTIDO_HORARIO;
39 return (girox);
40}

1.1.2.5. Controlador
El controlador es el corazón y causa que justifica la aplicación. Su objetivo consiste en lograr que el puente grúa y montacargas sean ubicados de acuerdo con las referencias de posición deseadas, con el menor error posible. Además, la planta controlada debe ser capaz de alcanzar su posición con un ángulo de oscilación de la carga despreciable, facilitando la manipulación de los objetos

transportados.

En el esquema implementado, figura 1.4, el controlador es uno de los modos de operación del módulo del nucleo, definido por la función despModoControl(). Esta rutina, ejecuta en forma secuencial las cinco fases que comprenden al algoritmo de control, provistas por el módulo kControl.c, como se puede ver en la figura 1.8.



Figura 1.8: Secuencia del algoritmo de control.


En primer lugar, despModoControl() recibe el comando de operación con el que generará la referencia de posición. Luego, toma los valores de cada estado medible (ej.: posición lineal del puente y posición angular de la carga) y, con dicha información, estima los estados no medibles (ej.: velocidad lineal y angular). Con los estados estimados y medidos, se calculan las actuaciones para los dos motores y se actualizan los estados del sistema. Se prepara la trama, definida en 1.1.2.3, con el paquete de actuación, y se transmiten los datos de ambos motores al driver. Finalmente, se muestra la información en pantalla. El diagrama de la figura 1.9 resume su funcionamiento.




Figura 1.9: Diagrama de flujo del modo Control.


Las funciones principales se detallan en los fragmentos de algoritmo ??, ?? y ??.


1static void calculaEstados(void)
2{
3 sysve.x1[0] = sysve.x1[1]*A11 + sysve.x2[1]*A12 + sysve.x3[1]*A13 + sysve.u[1]*B1;
4 sysve.x2[0] = sysve.x2[1]*A22 + sysve.x3[1]*A23 + sysve.x4[1]*A24 - sysve.u[1]*B2;
5 sysve.x3[0] = sysve.x2[1]*A32 + sysve.x3[1]*A33 + sysve.x4[1]*A34 + sysve.u[1]*B3;
6 sysve.x4[0] = sysve.x2[1]*A42 + sysve.x3[1]*A43 + sysve.x4[1]*A44 - sysve.u[1]*B4;
7}


1static void observaEstados(void)
2{
3 obsve.x1_est[0] = obsve.L0[0][0]*sysve.x1[1] + obsve.L0[0][1]*sysve.x2[1] + (obsve.ALCBK[0][0]*obsve.x1_est[1] + obsve.ALCBK[0][1]*obsve.x2_est[1] + obsve.ALCBK[0][2]*obsve.x3_est[1] + obsve.ALCBK[0][3]*obsve.x4_est[1] ) + sysve.Bd[0]*sysve.u[1];
4
5 obsve.x2_est[0] = obsve.L0[1][0]*sysve.x1[1] + obsve.L0[1][1]*sysve.x2[1] + (obsve.ALCBK[1][0]*obsve.x1_est[1] + obsve.ALCBK[1][1]*obsve.x2_est[1] + obsve.ALCBK[1][2]*obsve.x3_est[1] + obsve.ALCBK[1][3]*obsve.x4_est[1] ) + sysve.Bd[1]*sysve.u[1];
6
7 obsve.x3_est[0] = obsve.L0[2][0]*sysve.x1[1] + obsve.L0[2][1]*sysve.x2[1] + (obsve.ALCBK[2][0]*obsve.x1_est[1] + obsve.ALCBK[2][1]*obsve.x2_est[1] + obsve.ALCBK[2][2]*obsve.x3_est[1] + obsve.ALCBK[2][3]*obsve.x4_est[1] ) + sysve.Bd[2]*sysve.u[1];
8
9 obsve.x4_est[0] = obsve.L0[3][0]*sysve.x1[1] + obsve.L0[3][1]*sysve.x2[1] + (obsve.ALCBK[3][0]*obsve.x1_est[1] + obsve.ALCBK[3][1]*obsve.x2_est[1] + obsve.ALCBK[3][2]*obsve.x3_est[1] + obsve.ALCBK[3][3]*obsve.x4_est[1] ) + sysve.Bd[3]*sysve.u[1];
10}


1static unsigned char Control(void)
2{
3 /* Normaliza el valor absoluto de actuación en 8 bits sysve.u[0] */
4 unsigned char res;
5
6 /* Actuación */
7 sysve.u[0] = sysve.ref[0]*k1 - obsve.acK[0]*sysve.x1[1] - obsve.acK[1]*obsve.x2_est[1] - obsve.acK[2]*obsve.x3_est[1] - obsve.acK[3]*obsve.x4_est[1];
8
9 /* Saturador */
10 if (sysve.u[0] > 1) sysve.u[0] = 1;
11 else if (sysve.u[0] < -1) sysve.u[0] = -1;
12
13 if ( sysve.u[0] >= 0) res = (unsigned char)(sysve.u[0]*255);
14 /* Si la actuación es negativa, toma el valor absoluto */
15 if ( sysve.u[0] < 0) res = ~(char)(sysve.u[0]*255)+1;
16
17 return (res);
18}
1.1.2.6. Interfaz con el usuario
El archivo gui.c contiene las funciones que permiten al proceso usuario establecer la interacción entre el operador y el sistema. Para ello se empleó la librería de programación ncurses1 , para el desarrollo de interfaces de texto que se ejecutan bajo un emulador de terminal de video [4].

De ésta manera, la interfaz con el usuario presenta un sencillo menú de configuracion, comandos y visualizacion de datos (posicion, ángulo, velocidad, estado de la comunicación, etc). Inicialmente el usuario elige elmodo de trabajo deseado (Libre, Control, Calibración o Salida), luego la frecuencia de los PWM de una lista de opciones que dispone el uC y, finalmente, el menú de comandos. Por medio de éste último es posible desplazar el puente grúa y montacargas. La figura 1.10 muestra un esquema de los diferentes menúes disponibles para la operación de la planta.




Figura 1.10: Esquema de los distintos menúes disponibles en la interfaz con el usuario.



Una vez que se ha establecido el modo de operación y la frecuencia de trabajo de los PWM, el menú de comandos provee las opciones posibles para desplazar el puente hacia adelante y atrás, y al montacarga hacia un lateral u otro. En la figura 1.11 se representan las teclas disponibles para efectuar los movimientos necesarios de la planta.





Figura 1.11: Teclas de operación del sistema.



En cuanto al funcionamiento del proceso, la interfaz presenta una secuencia que consta de tres estados posibles:

RUN:
Es el estado por defecto del proceso, una vez que se haya activado y exista comunicación

con el microcontrolador.


ERROR:
En caso de detectar un error durante la ejecución de la rutina, el estado de error se

encargará de eliminar el proceso y liberar los recursos asociados.


STOP:
Al finalizar la operación de la planta, el estado stop permite salir de la aplicación sin

problemas, eliminando el proceso y liberando los recursos asociados.


Inicialmente, el proceso crea todos lo recursos necesarios para correr la aplicación, desde el archivo de registro de variables, hasta los FIFOs de comunicación con la tarea del módulo del núcleo. Establece la configuración de la pantalla, donde se asignan regiones para mostrar los datos del sistema, la introducción de comandos y visualización de la posición del puente y montacargas. Luego, el sistema comienza a ejecutarse normalmente en el estado RUN. Bajo éste modo de funcionamiento, el proceso ejecuta dos rutinas básicas: una para la lectura de los comandos ingresados por el operario y posterior envío a la tarea del núcleo, y la otra para recibir los datos de la planta que serán mostrados en pantalla al operador y almacenados en un archivo de
registro de datos. Finalmente, en alguno de los dos modos restantes, ERROR o STOP, se eliminan
los recursos asociados y el proceso termina. La figura 1.12 expone un diagrama de flujo de su
comportamiento.




Figura 1.12: Diagrama de flujo de la interfaz con usuario.



La forma de interacción entre el usuario y la planta se describe en la figura 1.13, donde se puede ver la secuencia de ejecución de comandos descripta anteriormente.




Figura 1.13: Secuencia de la interacción entre el usuario y el sistema.



Bibliografía

[1] Fernando di Sciascio, Control borroso de sistemas dinámicos, Universidad Nacional de San Juan, INAUT, 1994.

[2] GCC, http://gcc.gnu.org/.

[3]
Kate, http://www.kate-editor.org/.

[4]
Wikipedia, Ncurses, http://en.wikipedia.org/wiki/Ncurses, Agosto 2009.

jueves, mayo 14, 2009

Paso 28: Esquemas eléctricos

Como parte de la organización del hardware del proyecto, se documentó el esquema en el que se conectarán las diversas placas electrónicas entre sí. Éste esquema será de gran utilidad en el momento del cableado del tablero general, que se encuentra instalado en la estructura de soporte del puente. A continuación, se detalla una lista de los elementos conectados:
  • Fuente de PC, con salida de +12V y +5V.
  • Fuente switching de +24V.
  • Placa de optoacopladores para todas las E/S discretas.
  • Placa con microcontrolador ATmega16L.
  • Dos puentes H.
  • Dos encoders.
  • Sensor de inclinación.
  • Placa adaptadora DB37 a DB9.
  • Puerto RS-232.
  • Cuatro finales de carrera inductivos.

Imagen 1: Cableado general.

Imagen 2: Cableado de las alimentaciones

Imagen 3, cableado del optoacoplador