Simple CATS utilizando LUA como lenguaje script para el desarrollo de programas TPS

Nelson G. Lombardo

Resumen

Este texto presenta el procedimiento requerido para utilizar el lenguaje interprete LUA como parte de un simple CATS. Se definen las modificaciones necesarias a la arquitectura de LUA cómo así el protocolo final para el desarrollo de TPS. El gol del trabajo radica es proporcionar un interprete simple, poderoso, liviano y embebible multiplataforma que permita rápidamente generar los recursos computacionales para realizar los TE, TPS y DT con facilidad y flexibilidad. El trabajo apunta a dejar una base de desarrollo no así el de un sistema CATS propiamente dicho.

Neuquén, Argentina.

1 Introducción

Hace ya varios años que la implementación de sistemas CATS es necesaria. El proyecto que a continuación se propone es una simple implementación dónde se trabajo sólo en la interfaz de programación, realizando la tarea de acceso a los instrumentos directamente sin administración de grupos.
Para otorgar una solución elegante, sencilla y flexible se añadió al lenguaje script LUA soporte para el protocolo GPIB, en especial, para los equipos agilent. En este caso por una cuestión de disponibilidad se trabajo con el driver para la tarjeta PCI 82530b de agilent. El equipo de prueba es una osciloscopio agilent 54622A.
El trabajo procede en torno a la generación de una base lo suficientemente sencilla, modular y multiplataforma que permita con la generación de algunos scripts desarrollar las herramientas que se necesitan a medida. Varias puntos en contra no me permiten trabajar directamente en un sistema CATS:
  • Desconocimiento puntual de un mecanismo real o procedimiento normativo.
  • Hoy en día las soluciones modulares y flexibles son las que más se consumen a la hora de implementaciones industriales.
  • El interprete LUA tiene grandes implementaciones en sistemas embebidos, lo que me hace dejar asentado un sistema más compatible con el lenguaje para lograr una mayor interoperabilidad.
  • Pequeñas funciones comunes permiten una implementación totalmente a medida para cualquier cliente, mientras estás funciones otorguen el menor footprint la capacidad de comunicación más amplia y sencilla.

2 Arquitectura

2.1 Esquema

Figura 1: Esquema básico.

Para comenzar a comprender la solución que planteo, nos remitiremos en primer lugar a la figura 1↑. Podemos observar que en el medio de la gráfica existen tres pasos fundamentales y necesarios para la ejecución. Las partes que son anexas corresponden a la flexibilización que se le da a este proyecto. Puedo decir que la clave esta en la posibilidad de escribir código en LUA, lo que produce una menor cantidad de código a compilar dentro de LUA y así obtener una versión idéntica pero con algunas funciones nuevas que dan soporte al driver de la placa GPIB.

2.2 Ejecución

Figura 2: Proceso de ejecución

Para comprender un poco más el proyecto que propongo, vamos a interpretar cómo sería la ejecución del mismo. Una buena representación de este proceso se puede apreciar en la figura 2↑. Desde el momento que se comienza nos encontramos escribiendo código en LUA, sin alterar en absoluto la sintaxis del lenguaje. Dentro del TPS utilizaremos funciones de más alto nivel, estás ayudan al programador, otorgándole herramientas más completas. Estas están escritas en un parser también desarrollado en LUA, lo que permite además modificaciones sencillas y sin necesidad de recompilar código. Para que el trabajo de programación sea más sencillo aún no es necesario conocer exactamente los comandos del dispositivo que se va a utilizar, otro archivo en LUA contiene un juego de definiciones, pero en este caso utilizando las variables de LUA, intentando generar un modelo parecido al preprocesador del lenguaje C. Vamos a ejemplificar lo antes explicado, observando el código siguiente:

...
...
-- Function part of glua.lua
-- This function help to make sequencial process of questions.-
function tps.question()
	show(message.continue_question)			-- Continue?
	if io.stdin:read() ~= "y" then			-- Yes?
		show(message.sure_question)		-- Sure?
		if io.stdin:read() ~= "n" then		-- Yes?
			show(message.see_you)		-- Next time...
			os.exit()			-- Exit from TPS program.-
		end
	end
end
-- End of TPS_question().-
Algoritmo 1 Ejemplificando parser y redefiniciones.

2.3 Objetivos alcanzados

Puedo nombrar los siguientes como los puntos claves para destacar a esta solución:
  • El programa TPS se escribe íntegramente en LUA utilizando un parser que permite escribir código más sencillo y en cierta manera nmotécnico.
  • El LUA modificado al cual llamo GLUA, es idéntico al tradicional sólo que ahora posee soporte para GPIB.
  • El soporte del driver GPIB podrá ser para múltiples sistemas operativos como así para diferentes drivers gracias a la arquitectura adoptada.
  • Los datos se podrán almacenar en un archivo según el tipo de verbose seleccionado. Esto permite hacer reportes más poderosos y también lograr hacer depuraciones del programa TPS más sencillas.
  • Las comparaciones con las tolerancias son mucho más sencillas de realizar gracias al tipo de datos list que soporta LUA.

3 Funcionamiento

-- Lua script: utils.lua

-- Load the language.-
function TPS_language(language)
	-- Select the language for use for Spanish: esp.lang, English: eng.lang
	if string.match(language, "english") then
		file = "./utils/lang/english.lang"
	elseif string.match(language, "spanish") then
		file = "./utils/lang/spanish.lang"
	else
		print("The language selection is incorrect. Bye.")
		os.exit()
	end
	hlang = io.open(file,"r")
	-- Error.-
	if hlang == nil then
		print("Unable open language file! Exit.")
		os.exit()
	end
	message = {
		version = "v0.0.0\n",
		name_app = io.input(hlang):read(),
		info = io.input(hlang):read(),
		thanks = io.input(hlang):read(),
		some_steps = io.input(hlang):read(),
		continue_question = io.input(hlang):read(),
		sure_question = io.input(hlang):read(),
		see_you = io.input(hlang):read(),
		device_ok = io.input(hlang):read(),
		step_1 = io.input(hlang):read(),
		step_2 = io.input(hlang):read(),
		step_3 = io.input(hlang):read(),
		step_4 = io.input(hlang):read(),
		step_5 = io.input(hlang):read(),
		step_6 = io.input(hlang):read()
	}
end
-- End of load_lang().-

-- Close language file
function TPS_close()
	io.close(hlang)
end
-- End of close_utils().-

-- This function help to show message in diferents languages.-
function show(msg)
	local a,b=string.find(msg,’\\n’) — Find \n for io.write.
	io.write("> ")				   — Details.
	if ((a==nil)or(b==nil)) then
		io.write(msg)		        — No.
	else
		io.write(string.sub(msg,0,a-1),"\n")
	end
end
-- End of show().-

-- This function help to make sequencial process of questions.-
function TPS_question()
	show(message.continue_question)			-- Continue?
	if io.stdin:read() ~= "y" then			 — Yes?
		show(message.sure_question)			-- Sure?
		if io.stdin:read() ~= "n" then		 — Yes?
			show(message.see_you)			  — Next time...
			os.exit()						  — Exit from TPS program.-
		end
	end
end
-- End of TPS_question().-
Algoritmo 2 Archivo utils.lua con las funciones especiales que permiten escribir el TPS.

-- Parser with a devices definitions:
dofile("./utils/agilent54622.lua")
-- Thanks this parser is more easy write code:
dofile("./utils/utils.lua")
-- From here is the "header" of progam...
verbose = 1
warning = 0
programmer = "Tec. Electronico Nelson Lombardo"
job = "Medicion con osciloscopio Agilent 54622A (Proyecto Medidas II)"
-- The path to language file:
la("./utils/lang/log.esp")
-- From here is the "main" progam...
tpsinit()
-- The tolerance is a list with sub lists:
-- frequency, tension peak2peak, duty cycle, rise time
tol = {
	fq = {down = 9950, up = 10050},
	vpp = {down = 3.35, up = 3.55},
	dc = {down = 29.8, up = 30.2},
	rt = {down = 50E-9, up = 59.5E-9}
}
-- Define the address of device.
add54622="gpib0,7"
-- Reset the scope (know state):
bus(add54622, a54.reset..ENTER)
-- Time base to 20 us
bus(add54622, a54.timerange .. "20" .. us .. ENTER)
-- Time reference center:
bus(add54622, a54.timerefcenter .. ENTER)
-- TIME/DIV range of channel 1:
bus(add54622, a54.chan1range .. "4" .. ENTER)
-- Coupling DC:
bus(add54622, a54.chan1coupdc .. ENTER)
-- Limit band widht of channel 1:
bus(add54622, a54.chan1bwlimit .. ENTER)
-- Mode of acquire normal:
bus(add54622, a54.acqnormal .. ENTER)
-- Put a single banner on scope display (only for 54622A and similars):
bus(add54622, scope_message("Medidas Electronicas II - 2011 - Nelson Lombardo").. ENTER)
-- Query about frequency:
fq = bus(add54622, a54.frequency..QSE)
tolerance(tol.fq.down, tol.fq.up, fq, "Hz ")
-- Query about duty cycle:
dc = bus(add54622, a54.dutycycle..QSE)
tolerance(tol.dc.down, tol.dc.up, dc, "%")
-- Query about voltage peak2peak:
vpp = bus(add54622, a54.vpp..QSE)
tolerance(tol.vpp.down, tol.vpp.up, vpp, "V")
-- Time base to 20ns:
bus(add54622, a54.timerange.."20"..ns..ENTER)
-- Query about rise time:
rt = bus(add54622, a54.risetime..QSE)
tolerance(tol.rt.down, tol.rt.up, rt, "s")
-- Close TPS.
tpsclose()
-- End of program --
Algoritmo 3 Programa TPS de ejemplo con soporte gpib.

tinyTPS [tiny Test Program Simulator] using LUA language
++ Electroncis Measures II - 2011 - nelson.lombardo@gmail.com ++\n
Thanks for using this automatic plataform of measuring.\n
Is necesary release some steps before of automatic measure.\n
Continue? (Press ’y’ and ’Enter’ later for continue.):
Are you sure? (Press ’n’ and ’Enter’ later for continue.):
I see next time!\n
The device under test work fine.\n
1) Check the correct power alimentation of equipments of measure.\n
2) Turn ON the Agilent osciloscope.\n
3) Verify that Agilent osciloscope is really power up.\n
4) Verify the device under test.\n
5) Connect test point with ’A’ denomination to red connector.\n
6) Connect test point with ’B’ denomination to black connector.\n
Algoritmo 4 Archivo english.lang con frases en ingles.

Figura 3: Formato técnico del TPS.

Figura 4: Capas que alberga el sistema propuesto.

El TPS se escribe respetando la sintaxis de LUA pero utilizando un sistema de funciones especiales escritas también en LUA que están en un archivo llamado utils.lua, podemos apreciar parte del contenido en el código 2↑.
Podemos dar un ejemplo de como sería un TPS clásico escrito con esta propuesta si observamos el script escrito en 3↑. Para entender un poco más de como sería el funcionamiento interno del TPS, en la figura 3↑ se pone en evidencia el trabajo general que se presenta. Se puede apreciar la forma en que se llaman a la funciones, y como el dato tipo lista, provee una herramienta más que potente en relación con el manejos de datos y tolerancias, en casi todo lo que se necesite.
El proceso que se lleva a cabo se describe a continuación:
  1. El programador del TPS posee un juego de instrucciones prácticamente autodocumentadas, le permite escribir el TPS con todo lo necesario: evaluaciones lógicas, numéricas, manejo de equipos, etc.
  2. Utiliza cualquier tipo de entorno, puesto que el archivo es un archivo de texto, sino, se presenta un IDE idóneo para tal caso.
  3. Agregando un archivo tipo header , tiene acceso a un esquema unificado y simplificado de escritura para el TPS.
  4. El programa LUA lee el script y lo ejecuta como cualquier script, pero las funciones para el soporte GPIB, son agregadas, por lo cual se trabaja con este protocolo.
  5. El driver GPIB que se utilice, es el encargado de hacer las transacciones correspondientes de información entre el TPS(LUA), y la plataforma e interfase.
  6. Los datos que se envían y reciben son tratados o bien, como string o bien como numbers. Siempre existe la posibilidad de hacer agrupaciones en datos tipo list y hasta ¡objetos!
  7. El manejo de archivos es muy sencillo lo que puede ser transparente o no para el programador, ajustándose siempre a las necesidades del mismo.
Puesto que puede ser un poco complicado de comprender en un principio, la figura 4↑ nos muestras la principales capas que están presentes en este trabajo. Se pone de manifiesto que nos hemos alejado bastante de la capa workstation, cómo así de los equipos y ¡hasta del propio LUA! los que nos indica el nivel de versatilidad que se propone.

4 Estrategias

4.1 Realización

Para poder llevar a cabo el planteo presentado se respetan los siguientes puntos:
  • Utilizar los conceptos extrapolados de la filosofía de desarrollo UNIX.
  • Trabajar con herramientas GNU por su desarrollo abierto y métodos para asegurar el traspaso del conocimiento.
  • Optimizar la cantidad de código en la escritura tomando riesgos gracias a la excelente estructura de funcionamiento de LUA.
  • Optar por un script genérico y extensible siempre resguardando la complejidad del mismo.
  • La modularidad tiene prioridad frente a la prestabilidad.

4.2 Sistemas operativos y plataformas

Lograr adaptar este sistema para poder correr en diferentes sistemas operativos como así en diferentes plataformas puede resultar relativamente sencillo gracias a que LUA esta escrito íntegramente en ansi-C. Mientras exista un compilador derivado del conjunto GCC será aún más fácil de portar. Sin embargo aún es posible la compilación bajo cualquier compilador comercial y derivados por la gran versatilidad en la escritura de LUA.

4.3 Soporte driver a nivel de código

Para dar soporte a diferentes drivers, en especial se han revisado dos, el package Linux-GPIB y el soporte Agilent. En el caso del driver Agilent, conlleva dificultades para la compilación puesto que esta preparado para utilizar herramientas privativas y comerciales. Alternativas para lograr adaptar el driver a las fuentes de LUA:
  • Utilizar los .libs directamente dentro de la compilación con el compilador que se utilice tipo GCC.
  • Crear una dll con un compilador adoptado por Agilent y luego enlazar esta con la compilación de LUA.
  • Compilar enteramente el proyecto con un compilador adoptado por Agilent.

4.4 IDE

En este aspecto existe varias alternativas, pero apuesto firmemente a utilizar Geany como IDE. Un pequeño IDE, cross platform, con la suficiente capacidad de configuración y la posibilidad de ejecución on-fly de los TPS.

4.5 Documentación

Puesto que el problema central para este tipo de desarrollo es la creación y mantenimiento de la documentación, el modelo desarrollado permite crear el propio set de instrucciones lo que permite acercar una documentación dinámica, autodocumentada y que permita llevar un control preciso por parte de los usuarios sobre el alcance de las funciones así como de la implementación particular. De esta forma se reduce significativamente mi trabajo respecto al soporte a corto plazo.

4.6 Licencias

En casi todos los casos las licencias son GPLv2 y en particular LUA posee una licencia tipo MIT, la cuál me permite modificar las fuentes mientras respete algunos puntos. No representan impedimento para desarrollar de forma legal el proyecto.

5 Hacking LUA

5.1 Trabajo previo

La versión de LUA utilizada para este proyecto fue la 5.1.4. Las fuentes pueden ser descargas libremente y de forma gratuita del sitio oficial de lua, sección download, disponible en http://www.lua.org/donwload.html. Dentro de las fuentes, existe la carpeta src, la cual va a ser el target de nuestras modificaciones y agregados.

5.2 Agregando una nueva librería nativa

/* Some headers C used*/
#include <stdlib.h>
#include <string.h>
/* Define gpib library */
#define libgpib_c /* File name but with _ (not dot) */
/* Necesary to create a new library in LUA */
#define LUA_CORE
/* Include the Lua API header files */
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/* Next: All definitions and headers for the project */
/**********************************************************************/
/* This function is for example */
static int gpib_foo (lua_State *L)
{
	int n;
	const char *arg1;
	double arg2;
	double tmp;
	/* Read the numbers of parameters put into stack */
	/* If you need check this... */
	n = lua_gettop(L);
	/* Read the first argument from virtual stack */
	/* In this case you accept a string... *
	arg1 = luaL_checkstring(L, 1);
	/* Read the second argument from virtual stack */
	/* You accept a double... */
	arg2 = luaL_checknumber(L, 2);
	/* You can continue in this way. */
	/* Now you need put your "real function": */
	/* You accept example like you first parameter */
	if ((strcmp(arg1, "pow2")) == 0)
	{
		/* You can test: */
		tmp = arg2*arg2;
	}
	else
	{
		/* Error for example */
		tmp = -1;
	}
	/* Put the first output argument */
	lua_pushnumber(L, tmp);
	/* You need advise how many argument are output... */
	return (1);
}
/**********************************************************************/
/*  Now, this defines the functions you have created, into the net library group.
**  The right hand name (’net_uname’), is the name of the function in the C code.
**  The left hand name, is the name you want it to be called from Lua.
**  Take note of the names of variables, they correspond to your ’net’ library.
**  If you changed the name of the library, you would have to change these
**  variables and names.
*/
static const luaL_reg gpiblib[] = {
	{"foo", gpib_foo},
	{NULL, NULL}
};
/* This defines a function that opens up your library. */
LUALIB_API int luaopen_gpib (lua_State *L) {
	luaL_openlib(L, LUA_GPIBLIBNAME, gpiblib, 0);
	return (1);
}
Algoritmo 5 Protocolo en la escritura de una nueva librería nativa en LUA.

/*
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
** Initialization of libraries for lua.c
** See Copyright Notice in lua.h
*/

#define linit_c
#define LUA_LIB

#include "lua.h"

#include "lualib.h"
#include "lauxlib.h"

static const luaL_Reg lualibs[] = {
  {"", luaopen_base},
  {LUA_LOADLIBNAME, luaopen_package},
  {LUA_TABLIBNAME, luaopen_table},
  {LUA_IOLIBNAME, luaopen_io},
  {LUA_OSLIBNAME, luaopen_os},
  {LUA_STRLIBNAME, luaopen_string},
  {LUA_MATHLIBNAME, luaopen_math},
  {LUA_DBLIBNAME, luaopen_debug},
  {LUA_GPIBLIBNAME, luaopen_gpib}, /* GPIB support */
  {NULL, NULL}
};

LUALIB_API void luaL_openlibs (lua_State *L) {
  const luaL_Reg *lib = lualibs;
  for (; lib->func; lib++) {
    lua_pushcfunction(L, lib->func);
    lua_pushstring(L, lib->name);
    lua_call(L, 1, 0);
  }
}
Algoritmo 6 Modificación a la inicialización de las librerías de LUA (linit.c).

/*
@@ lua_stdin_is_tty detects whether the standard input is a ’tty’ (that
@* is, whether we’re running lua interactively).
** CHANGE it if you have a better definition for non-POSIX/non-Windows
** systems.
*/
#if defined(LUA_USE_ISATTY)
#include <unistd.h>
#define lua_stdin_is_tty()	isatty(0)
#elif defined(LUA_WIN) && !defined(__BORLANDC__)
#include <io.h>
#include <stdio.h>
#define lua_stdin_is_tty()	_isatty(_fileno(stdin))
#elif defined(LUA_WIN) && defined(__BORLANDC__)
#include <io.h>
#include <stdio.h>
#define lua_stdin_is_tty() __isatty(_fileno(stdin))
#else
#define lua_stdin_is_tty()	1  /* assume stdin is a tty */
#endif
Algoritmo 7 Indicando adecuadamente en que TTY se ejecutará LUA, esto es necesario en el caso de usar cómo OS windows y cómo compilador Borland Builder.
Para el proyecto creamos un nuevo archivo de texto que llamamos libgpib.c. Agregar librerías nativas requiere de un cierto protocolo. Dentro del código que observamos en 5↑. Es bastante sencillo y contiene lo necesario para comenzar a crear una nueva librería.
El segundo paso es modificar el archivo linit.c, esto permite que se inicialice nuestra librería para poder utilizar con LUA. El código se puede ver en 6↑. Simplemente se agrega un elemento a la estructura que contiene la definición de nuestra nueva librería cómo así el puntero a las nuevas funciones.
En algunos casos, cómo sucede para usuarios del OS windows y el compilador Builder de Borland es necesario enmascarar la TTY que por defecto se va a utilizar. Para esto en el archivo luaconf.h, debemos buscar donde comienza la Stand-alone configuration y cambiar el código de las directivas de identificación de LUA_USE_ISATTY por el código que se muestra en 7↑.

5.3 Instalación GLUA

Simplemente se puede copiar al PATH del sistema. Por ejemplo en Windows con copiar el ejecutable a la carpeta “Windows” ya se puede hacer el llamado del comando desde la consola cómo también quedar integrado para la ejecución desde el IDE que propongo Geany.

6 Escribiendo un TPS con utils.lua

6.1 Cuestiones generales

El script utils.lua contiene una serie de funciones complejas que permiten el desarrollo de TPS más sencillo. Este script funciona como un parser y tiene la finalidad de amalgamar funcionalidades comunes que buscan los desarrolladores de TPS para ahorrarles tiempo al momento de programar. Contiene una serie de ventajas para la depuración del programa cómo así de la ejecución del mismo.

6.2 Estructura de programa TPS

Cuando se desarrolle utilizando el parser utils.lua, existe un mínimo protocolo a seguir. Para poder comprender esto a continuación se muestra una estructura genérica:
dofile("./utils/utils.lua") — Thanks this parser is more easy write code.
dofile("./utils/agilent54622.lua") — Parser with a devices definitions.
verbose = 1 — Define the level of verbose. This is for log.
warning = 0 — Define the level of warning. Set to exit when a error is produce.
programmer = "Tec. Electronico Nelson Lombardo"
job = "Medicion con osciloscopio Agilent 54622A (Proyecto Medidas II)"
loglanguage("log.esp")
tpsinit() — Start all need for TPS.
-- From here is "main" progam...
add54622="gpib0,7" — Define the address of device.
scope = open(add54622) — Open a conection with the "set" device.
timeout(scope, 2000) — Define the timeout in miliseconds.
tr = command(scope, a54.risetime .. QUERY)
print("Fall time: " .. tr)
vm = gpib.command(scope, a54.vmax .. QUERY)
print("Voltage maximo: " .. vm)
close(scope)
tpsclose()
La primer función hace el llamado al script utils.lua. Es totalmente necesario este paso puesto que sino deberemos escribir todo el código en LUA sin las ventajas que otorga el parser. En la segunda linea podemos notar que se ejecuta un segundo script, en este caso este script contiene redefiniciones de los comandos GPIB (strings) que se pueden utilizar con el osciloscopio Agilent 54622A, así es mucho más sencillo programar el TPS.
De la línea 3 a la 6 inclusive, están declaradas una serie de variables que ayudan al registro adecuado de la ejecución del proceso. Para entender un poco más, se describirán:
  • verbose: Define el nivel de profundidad con que se desarrollara el log de la ejecución. Cuando vale 0 no produce más que información general, en general el nivel 1 producirá un log bastante detallado. Por el momento sólo se puede obtener un log con un verbose de 2.
  • warning: Cuando se setea la ejecución del TPS se termina ante el primer error que se detecte.
  • programmer: Nombre del programador del TPS actual.
  • job: Nombre del proceso que se llevara a cabo.
En la línea 7 la función loglanguage() nos sirve para definir el idioma en que el log se desarrollará en el proceso actual. Por el momento existen dos idiomas soportados: español e ingles. La finalidad de esto, es producir logs amigables con el depurador del TPS.
Para que el TPS funcione correctamente, se requiere que se respete la primer posición del parser utils.lua, y luego la cabecera de datos pueden estar posicionados con cualquier orden. El programa TPS se desarrollará dentro del bloque delimitado por las funciones tpsinit() y tpsclose(). Dentro del bloque que conforman, se escribe el TPS propiamente dicho.

6.3 Lenguaje

Más allá de las ventajas que ofrece el parser utils.lua, el lenguaje base es LUA, refiriéndose a su documentación se tendrá a disposición toda sintaxis, cómo así funciones que pueden ser necesarias para utilizar.

6.4 Estructura de los directorios y archivos

Se recomienda seguir la siguiente estructura, aunque se puede implementar la que sea de mayor comodidad. La siguiente imagen es sólo una guía para organizar los archivos.

7 Funciones especiales de utils.lua

La siguiente lista contiene las funciones que fueron escritas a alto nivel en el script utils.lua. Obviamente por estar escritas en LUA se podrán adaptar a las necesidades del usuario en cualquier momento. La elección de estas funciones fueron hechas basándome en una mínima cantidad de funcionalidades que se deberían otorgar al programador del TPS:

7.1 Funciones verbose

7.1.1 loglanguage(file)

Define el file (archivo) con los mensajes pre-establecidos. Por el momento se soportan dos archivos log.esp y log.eng, los cuales poseen los mensajes en español e inglés.

7.1.2 tpsinit()

Genera algunas configuraciones necesarias para poner en marcha el sistema de log.

7.1.3 tpsverbose(string)

Con esta función se puede escribir directamente en el archivo de log. La misma genera una línea formateada que comienza con la fecha y hora. Incrementa la escritura en una línea.

7.1.4 tpsclose()

Cierra el sistema de log.

7.2 Funciones “bonitas”

7.2.1 question()

Genera la consulta para seguir en la ejecución del proceso.

7.2.2 delay(seconds)

Genera un delay con las cantidad de segundos especificados con seconds.

7.2.3 printf(…)

Idéntica a la función printf de C.

7.2.4 sleep(n)

Es la típica función que se puede hallar en C. El parámetro “n” puede ser de punto decimal con lo que se pueden requerir tiempos muertos en milisegundos y microsegundos. Por ejemplo si n=0.2 el retardo es de 200ms.

7.3 Funciones con soporte GPIB

7.3.1 open(address)

Se le pasa una cadena con la dirección del equipo con el que deseamos conectarnos. Devuelve el ID de la coneccion, si este es cero es que no se produjo la coneccion.

7.3.2 timeout(id, time)

Setea el timeout de la coneccion GPIB del respectivo equipo (id) y según el tiempo que deseemos (time).

7.3.3 command(id, cmd, {mode}, {time})

Está función posee una estructura algo más compleja. Su utilización normal requiere de dos parámetros, uno es el identificador del dispositivo al cual quiero enviar comandos (id) y una cadena con el respectivo comando (cmd). El tercer parámetro es opcional e identifica un mode con el valor FORCE, dónde se hace una consulta al equipo y hasta que este no responda no se sigue con la ejecución del TPS. El cuarto parámetro, también opcional, entrega un tiempo (en segundos) para producir un delay entre cada consulta del modo FORCE.

7.3.4 close(id)

Cierra la coneccion con el equipo designado con id.

8 Caso de prueba ante fallo

8.1 Guía

La siguiente es la secuencia propuesta para la medición de las características relevantes de un tren de pulsos donde se produce una desconectan de la punta de prueba del osciloscopio y se registra el comportamiento de programa. Esta secuencia esta descripta dentro del TE, TPS y DT escrito para ejemplificar el uso de GLUA y el parser.
Primero corremos el TE, con este programa setearemos en primer lugar el nivel de verbose o reporte interno que provee el parser, una propuesta es directamente utilizando el ide Geany.
Una vez que ejecutamos el TE, nos aparece la consola que emula DOS y ya comenzamos a interactuar con el TE.
Luego tenemos la posibilidad de activar el warning, esta opción produce que se termine inmediatamente el TPS cuando algún problema se produzca, si queremos que el control lo tengamos de forma interactiva corremos el programa sin activar el warning.
Decidimos si vamos a correr la rutina TPS o bien DT.
En este punto deberíamos tener la lista de TPS’s que el programador nos provee. Se puede tener más de un TE como también DT, para esto no hay limitación. El programador puede ofrecernos múltiples opciones.
En nuestra prueba mediremos el tren de pulsos que otorga el osciloscopio para la calibración (Generador de onda cuadrada). El programador determina algunos pasos a seguir, en mi caso sólo aplique algunos mensajes para la correcta coneccion a modo de ejemplo.
Ahora podemos observar cómo al intetar medir el primer parámetro que es la frecuencia se produce un fallo. Cómo desactivamos el warning nos consulta sobre si deseamos continuar.
Le indicamos que no, y que estamos seguros.
Ahora nos pregunta si queremos correr el DT, al cúal le indicamos que sí.
Podemos notar que al correr el DT (que es un TPS que busca la causa de las fallas) logra comprobar que la punta de prueba puede que este desconectada.

8.2 Log

Un típico archivo de log se puede observar a continuación, en este caso correspondiente al de prueba.
Sistema operativo: Windows_NT
Programador TPS: "Tec. Electronico Nelson Lombardo"
Trabajo: "Medicion con osciloscopio Agilent 54622A (Proyecto Medidas II)"
[11/25/11 22:27:52] Comienzo del log.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:27:52] El nivel de verbose es 2.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:27:52] El nivel de warning es 0.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:27:56] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 36)(Funcion: bus)
[11/25/11 22:27:56] Se envio al equipo la cadena *RST\n al equipo gpib. (id = 1)(Linea de codigo 36)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 40)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :CHANnel1:RANGe 20\n al equipo gpib. (id = 1)(Linea de codigo 40)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 42)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :TIMEBASE:RANGE 1E-3\n al equipo gpib. (id = 1)(Linea de codigo 42)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 44)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :TIMEBASE:REFERENCE CENTER\n al equipo gpib. (id = 1)(Linea de codigo 44)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 46)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :CHANnel1:COUPLING DC\n al equipo gpib. (id = 1)(Linea de codigo 46)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 48)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :CHANnel1:BWLIMIT ON\n al equipo gpib. (id = 1)(Linea de codigo 48)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 50)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :ACQUIRE:TYPE NORMAL\n al equipo gpib. (id = 1)(Linea de codigo 50)(Funcion: bus)
[11/25/11 22:27:57] Conectado al equipo gpib con la direccion "gpib0,7" y id = 1.(Linea de codigo 52)(Funcion: bus)
[11/25/11 22:27:57] Se envio al equipo la cadena :MEASURE:FREQUENCY?\n al equipo gpib. (id = 1)(Linea de codigo 52)(Funcion: bus)
———————————--
Sistema operativo: Windows_NT
Programador TPS: "Tec. Electronico Nelson Lombardo"
Trabajo: "Revision de fallos en el osciloscopio Agilent 54622A (Proyecto Medidas II)"
[11/25/11 22:28:45] Comienzo del log.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:28:45] El nivel de verbose es 2.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:28:45] El nivel de warning es 0.(Linea de codigo 11)(Funcion: tpsinit)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 24)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena *RST\n al equipo gpib. (id = 2)(Linea de codigo 24)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 26)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :TIMEBASE:REFERENCE CENTER\n al equipo gpib. (id = 2)(Linea de codigo 26)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 28)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :CHANnel1:COUPLING DC\n al equipo gpib. (id = 2)(Linea de codigo 28)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 30)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :CHANnel1:BWLIMIT ON\n al equipo gpib. (id = 2)(Linea de codigo 30)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 31)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena *IDN?\n al equipo gpib. (id = 2)(Linea de codigo 31)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 39)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :CHANnel1:RANGe 0.4\n al equipo gpib. (id = 2)(Linea de codigo 39)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 40)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :MEASURE:VPP?\n al equipo gpib. (id = 2)(Linea de codigo 40)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 46)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena :SYSTEM:DSP "Medidas Electronicas II - 2011 - Nelson Lombardo"\n al equipo gpib. (id = 2)(Linea de codigo 46)(Funcion: bus)
[11/25/11 22:28:45] Conectado al equipo gpib con la direccion "gpib0,7" y id = 2.(Linea de codigo 47)(Funcion: bus)
[11/25/11 22:28:45] Se envio al equipo la cadena *IDN?\n al equipo gpib. (id = 2)(Linea de codigo 47)(Funcion: bus)
[11/25/11 22:28:45] Fin del log.(Linea de codigo 48)(Funcion: tpsclose)
[11/25/11 22:27:57] Tolerancia: 1190Hz  a 1210Hz ; Lectura: +99E+36Hz  - Fallo(Linea de codigo 53)(Funcion: tolerance)
[11/25/11 22:28:28] Saliendo del programa por warning!(Linea de codigo 125)(Funcion: wclose)
Se puede obsevar que todo el reporte interno se realiza en un mismo archivo para poder llevar un control mucho más preciso. Este tipo de reporte lo producen las funciones especiales del parser, el programador del TPS deberá programar el reporte que se requiera para la medición. El concepto detrás del log, es poder registrar las actividades que se llevaron a cabo e intentar dejar asentado todo lo acontecido respecto a las funciones que interactuan con el protocolo GPIB.
Gracias a que LUA posee un administrador para debug, tambien se pueden discriminar por capas las funciones padres o hijos que realizan las llamadas y así discriminar cúal nos importa. Otra de las ventajas es que todos estos mensajes están pre-empaquetados, por lo que son transparentes al programador del TPS cómo al del usuario, aunque ambos pueden modificar los mensajes o agregar los mensajes en otros idiomas fácilmente. En este caso sólo se realizaron en dos idiomas: castellano e inglés.

9 Ventajas

Se pueden enumerar, a mí entender, principalmente los siguientes pros:
  • Se utiliza ansi-C para trabajar, lo que permite asegurar un código limpio y estándar, con la posibilidades que esto da.
  • Se puede trabajar multi-plataforma.
  • Existe una fácil vinculación entre diferentes versiones de LUA, y gracias al unificador de sintaxis, es sencillo mantener uno o más estándares dentro del grupo de programadores del TPS.
  • Se puede realizar un debug con varios niveles de verbose.
  • Es un software muy liviano y rápido que entrega las posibilidades adecuadas para la cualquier tipo de expansión.
  • No se requieren conocimientos muy profundos en técnicas de programación y existe además una buena documentación.
  • ¡LUA es libre y gratuito! lo que permite realizar un proyecto de muy bajo costo y además totalmente legal, con la posibilidad de realizar licenciamientos específicos según el trabajo a implementar.
  • Desarrollo de instrucciones dinámicas gracias a la capacidad de desarrollo de macros sencillas.

10 Desventajas

Los siguientes puntos, se basan en los manejos de los tiempos que presenta el proyecto, como así se prevee una utilización fuera de lo académico:
  • Las licencias libres aún no son totalmente aceptadas por todos.
  • Algo de complejidad al momento de hacer modificaciones en las estructuras de control, lo que restringe la simplificación de las mismas.
  • El trabajo es desde consola, y aunque con el IDE apropiado es muy ameno, puede llegar a resultar un tanto tedioso al usuario final.

11 Proyectos dónde se usa LUA

Existen una infinidad de proyectos donde se utiliza LUA. Estos proyectos son de los más variados, desde juegos, servidores, generación de páginas web, generación de código en control electrónico, etc. Debido a una naturaleza sencilla, embebible y muchas otras ventajas técnicas al momento de programar, LUA es utilizado en simples proyectos hasta proyectos de una gran envergadura. A continuación sito algunos proyectos que a mi entender son afines al proyecto que he realizado y pueden ayudar a comprender porque de mi propuesta. La lista oficial de proyectos de LUA se puede ver en http://luaforge.net/projects/.

11.1 eLua

El proyecto ofrece la plena aplicación del lenguaje de programación Lua en el mundo de los sistemas embebidos, que se extiende con características específicas para el desarrollo de software eficiente, portátil e integrado. Disponible en http://www.eluaproject.net/.

11.2 pbLua

Este es una versión de Lua realizada para la programación de los Lego Mindstorms NXT, pequeños robots programables que se volvieron muy exitosos dentro del mundo de los niños, aficionados a la robótica y también dentro de las instituciones de altos estudios. Esta fork de Lua esta disponible en http://hempeldesigngroup.com/lego/pbLua/.

11.3 LXI y TPS

No es exactamente un proyecto, en realidad es un artículo de la compañia Keithley, una empresa que se dedica a la fabricación de instrumentos de medición y adquisición de datos, que relata las ventajas de las extensiones LAN en los instrumentos de medición y la ventaja del control escribiendo TPS’s. El artículo hace referencia a la ventajas de utilizar LUA cómo lenguaje script, por su pequeño tamaño, su velocidad de ejecución muy superior a sus competidores y también a su versatilidad para lograr embeberlo en nuestras aplicaciones. El artículo se puede ver en http://www.keithley.com/emarketing/resourceguides/lxitsp.

12 Software Utilizado

12.1 Lenguaje

  • LUA: Lenguaje script, liviano, poderoso, multi-plataforma y embebible. Página oficial: http://www.lua.org.

12.2 Editor

12.3 Compilador

12.4 Emulador

  • QEMU: Emulador de plataformas de computadoras, necesario para hacer las pruebas cross-over. Página oficial: http://wiki.qemu.org/Download.
  • VirtualBox: Emulador de plataformas de computadoras, necesario para hacer las pruebas cross-over. Página oficial: http://www.virtualbox.org.

12.5 Documentación

  • LyX: Sistema de preparación de documentos, permitiendo crear complejos artículos técnicos y científicos con soporte para fórmulas matemáticas, referencias cruzadas, bibliografía, índices, etc. Página oficial: http://www.lyx.org.

13 Conclusiones

Gracias a años de utilización de sistemas abiertos, se logra conocer soluciones elegantes y sencillas. Aportar un sistema de soporte de script con LUA, me ha resultado un trabajo muy enriquecedor. Esta propuesta posee varias ventajas no sólo desde el punto de vista operativo sino además desde el constructivo.
Dentro de las ventajas que defiendo podemos encontrar, la versatilidad, modularidad, eficiencia y bajo coste cómo así un ámbito de trabajo sencillo con posibilidades de expansión. Durante años LUA ha sido utilizado en muchas tipos de plataformas para varios tipos de tareas, desde un lenguaje para poder desarrollar niveles en un vídeo juego hasta el control de arreglos de monitores y vídeo para eventos a gran escala.
Desde el punto de vista del proyecto integrador cómo tal, pienso que almalgame los puntos solicitados. Con el proyecto demuestro un muy conociemiento en las herramientas informáticas, cómo así en diferentes sistemas operativos, arquitecturas y lenguajes de programación. También la solución que presento se alinea muy bien con los objetivos fijados, un sistema sencillo, flexible y de bajo costo económico.
La idea de utilizar LUA cómo base para este trabajo aparejo grandes ventajas. En primer lugar es un lenguaje interprete pequeño y embebible. Está muy bien construido, lo que lo hace rápido en su ejecución sobre diferentes plataformas. Posee un juego de instrucciones muy bien pensado, cómo así también las API’s de C que tiene. Todo el código está escrito en ANSI-C lo que lo hace mucho más simple de portar, cómo así de modificar. La posibilidad de ejecutar otros scripts a demanda potencian mucho su uso, permitiendo modularizar aún más el proyecto y entregando así un valor agregado a este trabajo.
Gracias a que LUA es soft-libre (aunque de licencia débil) nos permite integrar muy sencillamente este programa con otros y así darle características aún más interesantes y poderosas.
En resúmen, pude dar una solución a la propuesta cómo trabajo integrador en tiempo, forma y con algunas características adicionales más que interesantes, se presento una solución que es totalmente viable y que además es utilizada en la industria. También gracias al modelo de software libre pude tener acceso al código de LUA y adaptarlo a mis necesidades de forma legal y logrando compatibilidad para utilización comercial. El mayor trabajo fue enfocarme en otorgar una plataforma de programación sencilla que permita lograr desarrollar rutinas auto-documentadas, trabajando firmemente en la “forma” en que vamos a medir y no en la interface.

Referencias

[1] ”About LUA”. Disponible on-line en <http://www.lua.org/about.html>.

[2] ”LUA 5.1 Reference Manual”. Disponible on-line en <http://www.lua.org/manual/5.1/>.

[3] ”Parsing”. In Wikipedia, The Free Encyclopedia. Disponible on-line en <http://en.wikipedia.org/w/index.php?title=Parsing&oldid=434225898>.

[4] ”Extending LUA: Making your own libraries”. Disponible on-line en <http://heavycoder.com/tutorials/lua_extend.php>.

[5] ”Object Orientation Tutorial”. Disponible on-line en <http://lua-users.org/wiki/ObjectOrientationTutorial>.

[6] ”Lua (programming language)”. In Wikipedia, The Free Encyclopedia. Disponible en <http://en.wikipedia.org/w/index.php?title=Lua_(programming_language)&oldid=434687644>.

[7] ”GCC, the GNU Compiler Collection”. Disponible en <http://gcc.gnu.org/>.

[8] ”Linux GPIB Package Homepage”. Disponible en <http://linux-gpib.sourceforge.net/>.

[9] ”Linux-GPIB 3.2.11 Documentation”. Disponible en <http://linux-gpib.sourceforge.net/doc_html/index.html>.

[10] ”82350A PCI High-Performance GPIB Interface Card for Windows 95/98/Me/NT/2000”. Disponible en <http://www.home.agilent.com/agilent/techSupport.jspx?pid=1000001770%3Aepsg%3Apro&pageMode=DS&cc=AR&lc=eng>.

[11] ”About Minimalist GNU for Windows”. Disponible en <http://www.mingw.org/Welcome_to_MinGW_org>.

[12] ”About Geany: Small and lightweight IDE”. Disponible en <http://www.geany.org/Main/About>.

[13] ”GNU General Public License, version 2”. Disponible en <http://www.gnu.org/licenses/gpl-2.0.html>.

[14] ”LUA License”. Disponible en <http://www.lua.org/license.html>.

14 Anexo: Código fuente implementado en GLUA

14.1 utils.lua

El siguiente código es el del parser, también realizado en GLUA y con las herramientas propuestas para desenvolverse.
-- Lua script: utils.lua
-- This a complete parser to make easy the program interface to
-- programmer.

-- Some importants defines...
ENTER = "\n"
QUERY = "?"
SPACE = " "
QSE = "?\n"
FORCE = "force"
ns = "E-9"
us = "E-6"
ms = "E-3"

-- Some importants variables:
————————————————————————
-- Verbose ————————————————————-
————————————————————————
-- This function get the correcto language for log...
function la(language)
	-- Select the language for use for Spanish: log.esp, English: log.eng
	if language == nil then
		print("Error in the selection of language to log! Exit.")
		os.exit()
	end
	local file = language
	loglang = io.open(file,"r")
	-- Error.-
	if loglang == nil then
		print("Unable open language file! Exit.")
		os.exit()
	end
	logmsg =
	{
		a = io.input(loglang):read(),
		b = io.input(loglang):read(),
		c = io.input(loglang):read(),
		d = io.input(loglang):read(),
		e = io.input(loglang):read(),
		f = io.input(loglang):read(),
		g = io.input(loglang):read(),
		h = io.input(loglang):read(),
		i = io.input(loglang):read(),
		j = io.input(loglang):read(),
		k = io.input(loglang):read(),
		l = io.input(loglang):read(),
		m = io.input(loglang):read(),
		n = io.input(loglang):read(),
		o = io.input(loglang):read(),
		p = io.input(loglang):read(),
		q = io.input(loglang):read(),
		r = io.input(loglang):read(),
		s = io.input(loglang):read(),
		t = io.input(loglang):read(),
		u = io.input(loglang):read(),
		v = io.input(loglang):read(),
		w = io.input(loglang):read(),
		x = io.input(loglang):read(),
		y = io.input(loglang):read(),
		z = io.input(loglang):read(),
		aa = io.input(loglang):read(),
		bb = io.input(loglang):read(),
		cc = io.input(loglang):read(),
		dd = io.input(loglang):read(),
		ee = io.input(loglang):read(),
		ff = io.input(loglang):read()
	}
end
--

-- This function is for log the errors.
-- The level of log is the value of verbose.
function tpsinit()
	local logfile = "tps.log"
	local f=function (t,i) return os.getenv(i) end
	setmetatable(getfenv(),{__index=f})
	flog = io.open(logfile,"a+")
	io.input(flog):write("———————————--" .. ENTER)
	io.input(flog):write(string.format(logmsg.o, OS) .. ENTER)
	io.input(flog):write(string.format(logmsg.p, programmer) .. ENTER)
	io.input(flog):write(string.format(logmsg.q, job) .. ENTER)
	tpsverbose(logmsg.a) — Init
	if verbose == nil then
		tpsverbose(logmsg.m)
		wclose()
	else
		tpsverbose(string.format(logmsg.k, verbose))
	end
	if warning == nil then
		tpsverbose(logmsg.n)
		wclose()
	else
		tpsverbose(string.format(logmsg.l, warning))
	end
	print(logmsg.ee)
end
-- End of tpsinit()

-- This function
function tpsverbose(msg)
	io.input(flog):write("["..os.date().."] "..msg..string.format(logmsg.bb,debug.getinfo(3,"l").currentline)..string.format(logmsg.cc,debug.getinfo(2,"n").name)..ENTER)
end
-- End of tpsverbose(msg)

-- This function is for end the verbose mode.
function tpsclose()
	tpsverbose(string.format(logmsg.b))
	print(logmsg.dd)
	io.close(flog)
end
-- End of tpsend()
————————————————————————

————————————————————————
-- Pretty functions —————————————————-
————————————————————————

-- This function help to make sequencial process of questions.-
function question()
	print(logmsg.r)							-- Continue?
	if io.stdin:read() ~= logmsg.x then		-- Yes?
		print(logmsg.s)						-- Sure?
		if io.stdin:read() ~= logmsg.y then	-- Yes?
			print(logmsg.ff)
			wclose()
			if io.stdin:read() ~= logmsg.y then
				dofile("./DT3.lua")
			end
			print(logmsg.t)					-- Next time...
		end
	end
end
-- End of question().-

-- This function is a simple delay in seconds.
function delay(sec)
	-- Exist the parameter sec?
	if sec ~= nil then
		local oldtime = os.time() + sec
		while os.time() < oldtime do end
	else
		if verbose >=1 then
			tpsverbose(logmsg.z)
		end
		if warning >=1 then
			wclose()
		end
	end
end
-- End of tpsdelay().-

-- Typical sleep function, "n" can be double type (ms o us)
function sleep(n)
	os.execute("sleep " .. tonumber(n))
end
-- End of sleep()

-- This like classic printf C function
function printf(...)
	io.write(string.format(...))
end
-- End of printf(...)
————————————————————————

————————————————————————
-- GPIB support ——————————————————--
————————————————————————
-- All in One sending command
function bus (address, command, ...)
	local id, res, var
	var = ...
	id = gpib.open(address)
	if id == 0 then — Error to open connection
		if verbose >= 1 then
			tpsverbose(string.format(logmsg.c, address, id))
		end
		if warning >= 1 then wclose() end
	else — Connection success
		--gpib.timeout(id, 2000)
		if verbose >= 1 then
			tpsverbose(string.format(logmsg.d, address, id))
		end
		-- Is a query
		if string.find(command, "?") ~= nil then
			res = gpib.command(id, command)
			if verbose >= 1 then
				tpsverbose(string.format(logmsg.aa, string.gsub(command, "\n", "\\n"), id))
			end
		else — Is not a query
			gpib.iprintf(id, command)
			if verbose >= 1 then
				tpsverbose(string.format(logmsg.aa, string.gsub(command, "\n", "\\n"), id))
			end
		end
		gpib.close(id) — Close connection
		return res
	end
end
-- End of AllInOne command
————————————————————————

function wclose ()
	tpsverbose(logmsg.i)
end

————————————————————————
-- TPS support ———————————————————
————————————————————————
--
function tolerance (toldown, tolup, value, unit)
	local msg
	if ((toldown == "") or (tolup == "") or (value == "") or (unit == "")) then
		tpsverbose(logmsg.z)
		wclose()
	end
	msg = string.format(logmsg.u, toldown, unit, tolup, unit, value, unit)
	if not((toldown <= tonumber(value)) and (tonumber(value) <= tolup)) then
		msg = msg .. " - " .. logmsg.w
		msg = string.gsub(msg, "\n", "")
		print(msg) — FAIL
		if verbose >= 1 then
			tpsverbose(msg)
		end
		question()
	else
		msg = msg .. " - " .. logmsg.v
		msg = string.gsub(msg, "\n", "")
		print(msg) — OK
		if verbose >= 1 then
			tpsverbose(msg)
		end
	end
end
————————————————————————

14.2 TE.lua

El siguiente código es el que genera una serie de configuraciones iniciales y elecciones al momento de ejecutar el TPS correspondiente.
function menu ()
	print("Seleccione el DUT: ")
	print("1 - Generador de onda sinusoidal")
	print("2 - Generador de onda triangular")
	print("3 - Generador de onda cuadrada")
	print("4 - Salir")
end

function fail_menu ()
	print("Determinacion de fallas")
	print("1 - Generador de onda sinusoidal")
	print("2 - Generador de onda triangular")
	print("3 - Generador de onda cuadrada")
	print("4 - Salir")
end

function selection ()
	print("Menu")
	print("1 - TPS")
	print("2 - DT")
	print("4 - Salir")
end

function verbose_level ()
	print("Nivel de verbose: ")
	print("0 - Sin nivel de verbose")
	print("1 - Minimo nivel")
	print("2 - Medio nivel")
	print("4 - entrar")
end

function warning_level ()
	print("Nivel de warning: ")
	print("0 - Sin warning")
	print("1 - Activa el warning")
	print("4 - Salir")
end

while (1) do
	verbose_level()
	sel = io.stdin:read()
	if sel == "0" then
		verbose = 0
	elseif sel == "1" then
		verbose = 1
	elseif sel == "2" then
		verbose = 2
	elseif sel == "4" then
		os.exit()
	else
		print("Error! saliendo")
		os.exit()
	end
	warning_level()
	sel = io.stdin:read()
	if sel == "0" then
		warning = 0
	elseif sel == "1" then
		warning = 1
	elseif sel == "2" then
		warning = 2
	elseif sel == "4" then
		os.exit()
	else
		print("Error! saliendo")
		os.exit()
	end

	selection()
	sel = io.stdin:read()
	if sel == "1" then
		menu()
		sel = io.stdin:read()
		if sel == "1" then
			dofile("generador_sinusoidal.lua")
			os.exit()
		elseif sel == "2" then
			dofile("generador_triangular.lua")
			os.exit()
		elseif sel == "3" then
			dofile("generador_cuadrada.lua")
			os.exit()
		elseif sel == "4" then
			print("Saliendo.")
			os.exit()
		else
			print("Error! Saliendo.")
		end
	elseif sel == "2" then
		fail_menu()
		sel = io.stdin:read()
		if sel == "1" then
			dofile("DTl.lua")
			os.exit()
		elseif sel == "2" then
			dofile("DT2.lua")
			os.exit()
		elseif sel == "3" then
			dofile("DT3.lua")
			os.exit()
		elseif sel == "4" then
			print("Saliendo.")
			os.exit()
		else
			print("Error! Saliendo.")
		end
	elseif sel == "4" then
		os.exit()
	else
		print("Error! Saliendo.")
		os.exit()
	end
end

14.3 agilent54622.lua

Este script contiene las definiciones de necesarias de los comandos del osciloscopio Agilent 54622A.
a54 =
{
	cls = "*CLS",
	test = "*TST",
	reset = "*RST",
	autoscale = ":AUTOSCALE",
	idn = "*IDN?",
	clear = ":DISPLAY:CLEAR",
	probe1 = ":CHAN1:PROBE",
	persistence = ":DISPLAY:PERSISTENCE",
	dutycycle = ":MEASURE:DUTYCYCLE",
	falltime = ":MEASURE:FALLTIME",
	risetime = ":MEASURE:RISETIME",
	vmax = ":MEASURE:VMAX",
	vdelta = ":MEASURE:VDELTA",
	vpp = ":MEASURE:VPP",
	timerange = ":TIMEBASE:RANGE ",
	timerefcenter = ":TIMEBASE:REFERENCE CENTER",
	acqnormal = ":ACQUIRE:TYPE NORMAL",
	chan1range = ":CHANnel1:RANGe ",
	chan1coupdc = ":CHANnel1:COUPLING DC",
	chan1bwlimit = ":CHANnel1:BWLIMIT ON",
	chan2range = ":CHANnel2:RANGe ",
	chan2coupdc = ":CHANnel1:COUPLING DC",
	chan2bwlimit = ":CHANnel1:BWLIMIT ON",
	frequency = ":MEASURE:FREQUENCY",
	edge = ":TRIGGER:EDGE:SLOPE ",
	timeposition = ":TIMEBASE:POSITION ",
	timemodexy = ":TIMEBASE:MODE: XY",
	timemodenormal = ":TIMEBASE:MODE: MAIN"
}
function scope_message(string)
	return (string.format(":SYSTEM:DSP \"%s\"", string))
end

14.4 DT3.lua

Este script es el programa que revisa las fallas que se puedieran dar al realizar las mediciones.
-- Parser with a devices definitions:
dofile("./utils/agilent54622.lua")
-- Thanks this parser is more easy write code:
dofile("./utils/utils.lua")
-- From here is the "header" of progam...
programmer = "Tec. Electronico Nelson Lombardo"
job = "Revision de fallos en el osciloscopio Agilent 54622A (Proyecto Medidas II)"
-- The path to language file:
la("./utils/lang/log.esp")
-- From here is the "main" progam...
tpsinit()
print("Realize y revise los siquientes los siquientes pasos:")
print("Mantenga el coneccionado, en breve se realizaran algunas pruebas")
print("para determinar los problemas que puedieran estar ocurriendo.")
-- Define the address of device.
add54622="gpib0,7"
id = gpib.open(add54622)
if id == 0 then
	msg="El osciloscopio no esta conectado"
	print(msg)
	os.exit()
end
-- The id is?
bus(add54622, a54.reset..ENTER)
-- Time reference center:
bus(add54622, a54.timerefcenter..ENTER)
-- Coupling DC:
bus(add54622, a54.chan1coupdc..ENTER)
-- Limit band widht of channel 1:
bus(add54622, a54.chan1bwlimit..ENTER)
idn = bus(add54622, a54.idn..ENTER)
if idn ~= "AGILENT TECHNOLOGIES,54622A,MY40000630,A.01.20\n" then
	msg = "El osciloscopio conectado no es el 54622A"
	print(msg)
else
	msg = "El osciloscopio es correcto"
	print(msg)
end
bus(add54622, a54.chan1range .. "0.4" .. ENTER)
vpp = bus(add54622, a54.vpp..QSE)
vpp = tonumber(vpp)
if vpp >=10E-3 and vpp <= 70E-3 then
	msg = "La punta de prueba puede estar desconectada."
	print(msg)
end
bus(add54622, scope_message("Medidas Electronicas II - 2011 - Nelson Lombardo").. ENTER)
bus(add54622, a54.idn..ENTER)
tpsclose()
os.exit()
-- End of program --

14.5 log.esp

Este simple archivo de texto contiene los mensajes pre-empaquetados en español. Hay que respetar el orden si se quieren modificar los mensajes.
Comienzo del log.
Fin del log.
Fallo la coneccion al equipo gpib con la direccion "%s". (id = %d)
Conectado al equipo gpib con la direccion "%s" y id = %d.
La respuesta a %s fue %s en el modo forzado. (id = %d)
La respuesta a %s fue %s. (id = %d)
Error: No se paso un valor de tiempo a timeout. (id = %d)
El tiempo de timeout es %d[ms]. (id = %d)
Saliendo del programa por warning!
Error al cerrar la coneccion con el equipo gpib. (id = %d)
El nivel de verbose es %d.
El nivel de warning es %d.
Error: El nivel de verbose debe ser definido!
Error: El nivel de warning debe ser definido!
Sistema operativo: %s
Programador TPS: "%s"
Trabajo: "%s"
Desea continuar? (si-no unicamente)
Seguro? (si-no unicamente)
Chau!
Tolerancia: %s%s a %s%s; Lectura: %s%s
Ok
Fallo
si
no
Error en los parametros
Se envio al equipo la cadena %s al equipo gpib. (id = %d)
(Linea de codigo %s)
(Funcion: %s)
TPS finalizado!
TPS comenzando!
Correr DT?

14.6 log.eng

Este simple archivo de texto contiene los mensajes pre-empaquetados en inglés. Hay que respetar el orden si se quieren modificar los mensajes.
Start of log.
End of log.
Fail connection to gpib device with "%s" address. (id = %d)
Connect to gpib device with "%s" address and id = %d.
The response to %s was %s in the force mode. (id = %d)
The response to %s was %s. (id = %d)
Error: No time pass to timeout. (id = %d)
The time of timeout is %s[ms]. (id = %d)
Exit of program by warning!
Error to close the gpib device conection. (id = %d)
Level of verbose is %d.
Level of warning is %d.
Error: The level of verbose is not defined!
Error: The level of warning is not defined!
Operating system: %s
TPS programmer: "%s"
Job: "%s"
Continue? (yes-no only)
Sure? (yes-no only)
Bye!
Tolerance: %s%s to %s%s; Reading: %s%s
OK
FAIL
yes
no
Error into parameters
Send to gpib equipment the string %s. (id = %d)
(Line of code %s)
(Function: %s)
TPS ending!
TPS starting!
Run DT?

One thought on “Simple CATS utilizando LUA como lenguaje script para el desarrollo de programas TPS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s