Antonio Vargas Gómez Automatización, mediante Raspberry pi...

89
Antonio Vargas Gómez Automatización, mediante Raspberry pi, de la gestión de los equipos de medidas eléctricas durante la caracterización de sensores de gases. TRABAJO FIN DE GRADO Dirigido por José Luis Ramírez Falo Grado de Ingeniería en Electrónica Industrial y Automática Tarragona 2018

Transcript of Antonio Vargas Gómez Automatización, mediante Raspberry pi...

Page 1: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

Antonio Vargas Gómez

Automatización, mediante Raspberry pi, de la gestión de los equipos de medidas eléctricas durante la caracterización de sensores de gases.

TRABAJO FIN DE GRADO

Dirigido por José Luis Ramírez Falo

Grado de Ingeniería en Electrónica Industrial y Automática

Tarragona

2018

Page 2: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

2

1. Índice

1. Índice ................................................................................................................................. 2

2. Memoria Descriptiva ........................................................................................................ 4

2.1 Introducción ............................................................................................................. 4

2.2 Antecedentes ........................................................................................................... 4

2.3 Estado del arte ......................................................................................................... 5

2.3.1 Microcontrolador ..................................................................................... 5

2.3.2 Lenguaje de programación ....................................................................... 8

2.4 Objetivos ................................................................................................................. 9

3. Memoria de creación de software .................................................................................... 11

3.1 Instrumentación ..................................................................................................... 11

3.2 Programa principal ................................................................................................ 13

3.3 Comunicación LAN ................................................................................................ 15

3.3.1 Módulos para la comunicación LAN ..................................................... 16

3.4 Autodetección de equipos ...................................................................................... 19

3.5 Instrucciones SCPI ................................................................................................ 21

3.6 Petición de canales ................................................................................................. 25

3.7 Creación y guardado de fichero .csv ....................................................................... 27

3.8 Adquisición de datos ............................................................................................. 28

3.8.1 Toma de datos ........................................................................................ 28

3.8.2 Almacenamiento de datos ...................................................................... 31

3.8.3 Cierre de comunicación ......................................................................... 31

3.9 Terminal de usuario ................................................................................................. 32

3.10 Representación gráfica de datos ............................................................................ 33

3.11 Librerías utilizadas ............................................................................................... 36

4. Manual de usuario ........................................................................................................... 38

4.1 Creación del archivo ejecutable .............................................................................. 38

4.2 Uso del software ...................................................................................................... 39

4.3 Interpretación del archivo .csv ................................................................................. 44

5. Resultados ........................................................................................................................ 48

6. Mejoras ............................................................................................................................ 49

7. Conclusiones .................................................................................................................... 50

8. Presupuesto ...................................................................................................................... 51

Page 3: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

3

9. Pliego de condiciones ...................................................................................................... 52

10. Referencias Bibliográficas ............................................................................................. 53

11. Anexos .......................................................................................................................... 55

11.1. Tablas de datos ..................................................................................................... 55

11.2. Código fuente ....................................................................................................... 61

11.2.1. __init__.py ............................................................................................ 61

11.2.2. Main.py ................................................................................................ 61

11.2.3. Comunicacion.py .................................................................................. 63

11.2.4. LAN.py ................................................................................................. 64

11.2.5. adquisicion_datos.py ............................................................................ 64

11.2.6. SAVE.py............................................................................................... 69

11.2.7. CSV_Data.py ........................................................................................ 70

11.2.8. PLOT.py ............................................................................................... 71

11.2.9. Lista_Instrucciones.py .......................................................................... 75

11.2.10. Select_Chan.py ................................................................................... 83

11.2.11. PIN_Instrumento.py............................................................................ 84

11.2.12. Terminal.py ........................................................................................ 88

Page 4: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

4

2. Memoria descriptiva

2.1. Introducción

En este proyecto se llevará a cabo la gestión de varios equipos de medidas

eléctricas durante la caracterización de sensores de gases de forma automática.

El grupo de investigación al que va dirigido este proyecto es el grupo MINOS

(Microsistemas y Nanotecnologías para el Análisis Químico), situado en el edificio de

plantas piloto del Campus Sescelades de Tarragona (Cataluña, España) de la Universidad

Rovira i Virgili.

El cometido de dicho grupo está orientado a la investigación, fabricación y

caracterización de microsistemas químicos, especialmente orientados a sensores de gases.

Esta automatización se llevará cabo sobre hardware de Raspberry Pi, en concreto

sobre la placa de desarrollo Raspberry PI 3-B, utilizando el lenguaje de programación

Python 2.7.

El motivo de la realización de este proyecto es el de complementar proyectos

anteriores orientados a la actualización y mejora del sistema actual de medición de gases.

La actualización de este sistema viene dada debido a factores tales como la

obsolescencia de algunos componentes como los equipos PC, la reducción del espacio

utilizado en pos de la instalación de nuevos sistemas y la mejora de rendimiento global

del sistema actual.

2.2. Antecedentes

Para poder contextualizar el proyecto, es necesario conocer cuáles son las

referencias y los aspectos técnicos de los que parte y sobre los que se encuentra

fundamentado.

Este proyecto se complementa junto con otros proyectos realizados con

anterioridad para la mejora del sistema actual de caracterización de sensores de gases.

El sistema actual de control de gases está basado en un sistema de control de

MassFlow (Controladores de Flujo Másico) para la regulación de estos gases. Dicho

sistema trabaja con un software creado bajo el lenguaje de programación Visual Basic, lo

que implica que el único sistema operativo sobre el que puede funcionar el sistema de

control sea Windows, reduciendo así la versatilidad. A demás, dicho software fue

optimizado para el sistema operativo Windows XP, el mantenimiento del cual ha sido

abandonado por la empresa distribuidora Microsoft, de ahí la necesidad de actualización

del software, entre otros motivos.

Puesto que este proyecto es continuidad de otros proyectos de mejora del sistema

de caracterización, debemos conocer dichas mejoras introducidas. Entre estas, podemos

encontrar un sistema de introducción de datos mediante ventanas para el control y

funcionamiento de los MassFlow, un sistema de log-in para diferenciar entre distintos

usuarios y un sistema de almacenaje de los datos obtenidos por los MassFlow, entre otras.

Page 5: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

5

2.3. Estado del arte

Para la realización del proyecto, se ha tenido que tener en cuenta diferentes

aspectos como la plataforma donde desarrollarlo, el lenguaje de programación a utilizar,

costes de hardware etc.

A continuación se detallan los motivos por los que se han elegido las distintas

características sobre las que se fundamenta el proyecto tales como el microcontrolador y

el lenguaje de programación. En este apartado no tendremos en cuenta elementos como

los MassFlow, relés etc debido a que, a pesar de formar parte del proyecto global, no

tienen relación directa con este proyecto

2.3.1 Microcontrolador

Un microcontrolador es un circuito digital integrado capaz de realizar diferentes

tareas debido a que puede ser programado. Está compuesto por la unidad central de

procesado (CPU), distintos tipos de memoria (RAM, ROM) y diferentes líneas de entrada

y salida para la conexión de periféricos.

Para la realización del proyecto, es necesario buscar un hardware que no se exceda

demasiado en su coste y que a la vez nos proporcione ciertas características necesarias

para el desarrollo. El mercado actual ofrece centenares de opciones, por lo que es difícil

hacer un estudio comparativo de todas, por este motivo, reduciremos las opciones a las

más utilizadas comúnmente, siendo estas opciones las plataformas ofrecidas por las

marcas Arduino y Raspberry Pi.

Arduino

Arduino es una plataforma de hardware libre, basada en una placa con un

microcontrolador incorporado que trabaja junto con diferentes periféricos de entrada

y salida, diseñada para el uso de la electrónica en proyectos multidisciplinares.

Además, proporciona un software de compilación propio, también libre, bajo un

entorno de desarrollo (IDE) para poder ser programada y cumplir así con

prácticamente cualquier cometido.

Arduino puede ser utilizado para desarrollar elementos autónomos, conectarse con

diferentes dispositivos e interactuar tanto con software como con hardware.

Entre los periféricos que puede utilizar, se encuentran conversores AD/DA,

PWM, USB, Ethernet, Wifi etc. A parte, cabe la posibilidad de añadirle placas de

expansión (shields) para incrementar las posibilidades de uso.

En cuanto al software, entre los lenguajes más comunes para su programación se

encuentran C/C++/C#, Matlab, Python o Scratch (S4A) entre otros. Puesto que se

trata de una plataforma abierta, al igual que muchos de los lenguajes de programación

mencionados, cuenta con una gran variedad de librerías de dominio público para su

uso.

En el mercado actual podemos encontrarnos con diferentes propuestas como

Arduino Mega, Arduino Ethernet o Arduino Due.

Page 6: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

6

Arduino Mega es la versión más completa de la plataforma, con un

microcontrolador ATmega2560 con una frecuencia de 16 MHz, 54 pines I/O digitales,

16 entradas analógicas, una memoria flash de 256 KB, un puerto USB y

comunicaciones tipo UART y SPI a un precio de 42 €. Es una opción poco interesante

puesto que carece de conexión tipo Ethernet par la comunicación LAN que vamos a

necesitar en el proyecto.

Arduino Ethernet está basado en la placa Arduino Uno y permite comunicación

mediante un puerto de red. Consta de un procesador ATmega328 con una frecuencia

de reloj de 16 MHz, 14 pines I/O digitales y una memoria flash de 32 KB a un precio

de 48 €.

Arduino Due está formado por un procesador AT91SAM3X8E, con una

frecuencia de 84 MHz, el más potente de la plataforma, 54 pines I/O digitales y una

memoria flash de 512 KB, a un precio de 43 €. Al igual que el primer caso, no dispone

de conexión Ethernet, por lo que no sería apta para el proyecto.

Podemos encontrar una comparativa1 entre las diferentes opciones proporcionadas

por esta plataforma en su página web oficial.

Raspberry Pi

Raspberry Pi es una placa computadora de bajo coste, es decir un ordenador de

tamaño reducido al que se le puede instalar un sistema operativo. El concepto es el de

un ordenador eliminando todos los accesorios posibles sin que esto afecte al

funcionamiento básico.

Consta de diferentes periféricos de entrada y salida, según modelo, y su software

es open source.

A diferencia de Arduino, el catálogo de Raspberry es algo más reducido. En todas

sus versiones, Raspberry ofrece un procesador Broadcom, una memoria RAM, una

GPU, 40 pines GPIO, puertos USB, HDMI y Ethernet, exceptuando el primer modelo,

motivo por el cual lo excluiremos de la lista de posibles opciones. Cabe mencionar

que todos los modelos necesitan una tarjeta microSD para la instalación del S.O.

Entre los distintos modelos a elegir, obviando el primer modelo ya mencionado,

podemos encontrar los modelos 2B, 3B/3B+, entre algunos otros de menor interés.

El modelo 2B posee un procesador de 4 núcleos de 900 MHz, 1 GB de memoria

RAM, 40 pines GPIO, conexión HDMI, 4 puertos USB, un puerto Ethernet, un puerto

para jack de audio de 3.5 mm y conexión para cámara de Raspberry a un precio de

29.50 €.

El modelo 3B consta, al igual que su antecesor, de un procesador de cuatro

núcleos, pero con una mayor frecuencia de reloj, pasando a tener de 1 a 1,4 GHz.

Mantiene la misma memoria RAM, puertos GPIO y puertos de conexión. La

diferencia entre el modelo B y B+ reside en la mejora del Wifi, Bluetooth y el

Ethernet, pasando a una conexión wifi de doble banda, Bluetooth 4.2 y mejora de la

1 https://www.arduino.cc/en/Products/Compare - Comparativa de productos marca Arduino

Page 7: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

7

velocidad de transmisión del puerto Ethernet de 100 a 300 Mbps. Al ser el modelo B+

una renovación del modelo predecesor, la compañía ha decidido mantener el precio

de venta, siendo este de 30 €.

A modo de comparativa entre las dos plataformas de desarrollo planteadas,

podemos ver que por el mismo precio, o incluso un poco menos, Raspberry Pi ofrece

mejores prestaciones que la plataforma Arduino. La única desventaja que ofrece frente a

la plataforma rival es la carencia de conversor AD/DA y de PWM. Puesto que estos

elementos no van a ser necesarios en el proyecto, no suponen ningún tipo de pérdida o

desventaja.

Puesto que este proyecto es complementario junto con otros realizados con

anterioridad y que forman parte de un proyecto mayor, el microcontrolador utilizado ha

sido el mismo que en dichos proyectos.

El microcontrolador elegido es el proporcionado por la plataforma Raspberry PI,

en concreto el modelo 3-B.

Las razones por las que eligieron esta plataforma y modelo fueron el bajo coste

del producto y la versatilidad de este.

El precio es realmente asequible para el propósito del proyecto, ya que el hardware

no supera los 40 € y el software es de libre distribución. Al tratarse de un mini ordenador,

cabe la posibilidad de instalarle un sistema operativo como Linux, Ubuntu o Raspbian,

que es SO distribuido de forma gratuita por la misma empresa que subministra el

hardware. Como ventajas principales de poder instalar un SO, tenemos que podemos

programar el software en cualquier lenguaje de programación utilizando cualquier

herramienta de desarrollo (IDE) que esté a nuestra disposición, podemos controlar

distintos dispositivos periféricos y tenemos un soporte gráfico que facilita su uso y

entendimiento.

A parte, en relación con el hardware, este modelo dispone de conexión Wi-Fi y

Ethernet, lo cual es vital para la conexión LAN con los distintos instrumentos de medida

que se requieren para la realización del proyecto. A demás, ofrece una mayor potencia de

cómputo con respecto a sus versiones anteriores y a las placas Arduino a prácticamente

el mismo precio.

Las características del microcontrolador son las siguientes:

Procesador Quad Core Broadcom 2837 ARMv8 64bits 1,2 GHz

1 Gb de memoria RAM

Wifi integrado (BCM43143)

Bluetooth integrado

40 pines GPIO

4 puertos USB

Salida de video y audio HDMI

Puerto CSI para cámara Raspberry PI

Puerto DSI para pantalla táctil

Lector de tarjeta MicroSD

Micro USB para alimentación, máximo 2.5 A

Page 8: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

8

2.3.2 Lenguaje de programación

Al igual que se ha hecho con el hardware, es necesario hacer un pequeño estudio

comparativo con las diferentes opciones de software disponibles para evaluar qué

lenguaje de programación es el más adecuado para la realización del proyecto.

De entre la gran cantidad de lenguajes posibles, se valorarán los tres que se

podrían considerar los más adecuados para el proyecto por sus características. Estos tres

lenguajes candidatos son Visual Basic, C/C++ y Python.

Visual Basic

Se trata de un lenguaje creado por la empresa Microsoft. Está orientado a la

programación por eventos, es decir, la estructura y la ejecución del programa se

determinan según los sucesos que ocurran, ya sean estos definidos por el usuario o por

otros eventos.

Dado que el programa original que se utiliza actualmente está programado en este

lenguaje, no se podía obviar de lista de posibles opciones. Uno de los problemas que

introduce este lenguaje es que sólo es funcional sobre sistemas operativos Windows, lo

que conlleva la reducción de la versatilidad del código utilizado ya que, en caso de

renovación de equipos, como ocurre actualmente, se requeriría de forma obligatoria

trabajar sobre equipos con sistema operativo Windows. Otra problemática sería que, en

caso de renovación del código del programa actual, nos veríamos forzado a trabajar con

procesadores con arquitectura x86 puesto que la comunicación de los MassFlow se realiza

con el software distribuido por la marca Bronkhorst, el cual sólo funciona sobre este tipo

de arquitectura.

A pesar de que este proyecto no trata directamente con los MassFlow, es importante

tener en cuenta que tanto este proyecto como el que le precede, deberán trabajar

conjuntamente para la correcta caracterización de los sensores de gases, por lo que para

evitar problemas de compatibilidad, lo más adecuado es que ambos proyectos se realicen

bajo las mismas especificaciones técnicas.

C/C++

Se trata de un lenguaje de programación estructurada de bajo nivel, en el caso de C,

con el añadido de la orientación a objetos en C++. Además, este último permite la

programación multitarea en tiempo real y de entorno gráfico.

Como característica general, podríamos decir que se trata de un lenguaje ampliamente

extendido de carácter general. Esto hace que existan un gran número de librerías

disponibles para su uso. A la vez, esto crea un problema, el cual reside en que cada sistema

operativo tiene sus propias librerías, reduciendo así la versatilidad del proyecto puesto

que si se utilizan las librerías de Windows, el código deja de ser compatible con otros

sistemas operativos.

Python

Se trata de un lenguaje de programación de código abierto, interpretado y de alto nivel

que permite la programación orientada a objetos entre otros paradigmas de programación.

Además, permite la programación multitarea y de entorno gráfico.

Page 9: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

9

El ser un lenguaje interpretado, en vez de compilado, lo convierte en un lenguaje

multiplataforma, pues sólo es necesario la instalación del intérprete para su correcto

funcionamiento sobre cualquier sistema operativo. A su vez, esto hace que no sea

compatible con la programación en tiempo real, ya que el tiempo de interpretación es

bastante superior al tiempo de compilación.

Es el lenguaje más utilizado para la programación sobre Raspberry Pi. Dispone de

una gran cantidad de librerías open source que facilitan en gran medida el trabajo con este

lenguaje.

De la misma manera que ocurre con el hardware, el lenguaje de programación

utilizado nos viene impuesto por los proyectos anteriormente realizados.

El lenguaje elegido es Python 2.7.

Los motivos por los que se eligió este lenguaje fueron que Python es un lenguaje

de código abierto que permite la programación multitarea y de entorno gráfico. A su vez,

es de simple aprendizaje en comparación con otros lenguajes, es intuitivo y compatible

con todos los sistemas operativos tras instalar su intérprete. Se trata del lenguaje de

programación más utilizado en la plataforma de Raspberry Pi entre otros entornos. Esto,

junto con el hecho de que se trate de un lenguaje de código abierto, hace que dispongamos

de una gran cantidad de librerías que pueden facilitar mucho la programación. Este en

concreto es el motivo por que se utiliza la versión 2.7 del lenguaje, ya que es la versión

con más módulos accesibles gratuitos creados por la comunidad.

Como única desventaja, hay que tener en cuenta que Python es un lenguaje

interpretado y no compilado, lo que no permite una programación en tiempo real.

2.4. Objetivos

El objetivo principal del proyecto es el de crear un software para llevar a cabo la

gestión de distintos equipos de medida durante la caracterización de sensores de gases.

Para alcanzar dicho objetivo, se ha precisado cubrir ciertos requisitos bajo una

serie de criterios técnicos que se listan a continuación:

Comunicación remota vía LAN de la placa Raspberri con distintos equipos de

medida.

Autodetección de los equipos de medida en uso.

Creación de fichero para almacenaje de datos tipo ‘.csv’.

Opción para poder elegir nombre y ruta de guardado del fichero.

Sincronismo de datos entre MassFlow y equipos de medida.

Representación gráfica constante de los datos obtenidos, con dos ejes de medida

con escalas independientes compartiendo el mismo eje temporal.

Como las medidas se tomarán con distintos instrumentos a lo largo del proyecto,

el software de comunicación debe ser lo más modular posible, es decir, que sea funcional

Page 10: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

10

independientemente de los instrumentos con los que se pretenda realizar las medidas

pertinentes.

A demás de la autodetección de los instrumentos, se debe poder elegir para cada

uno de ellos qué tipo de medidas realizarán y en qué canales se llevarán a cabo, en caso

de que exista este parámetro en el instrumento de medida, puesto que cada instrumento

es capaz de realizar distintos tipos de medida según interés.

A parte, existe la posibilidad de conectarnos con instrumentos vía LAN que no

sean de medida, sino generadores de señales tales como fuentes de tensión, corriente, o

generadores de funciones. Estos instrumentos también deben ser detectados

automáticamente y se deben almacenar los datos de las consignas que introducen en el

sistema.

Page 11: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

11

3. Memoria de creación del software

3.1. Instrumentación

En este apartado se muestra un listado de los distintos instrumentos con los que

se puede trabajar de forma remota y sus características principales. Dichos equipos son

los siguientes:

Dataloguer. Keysight/Agilent 34972A LXI

Dataloguer de las marcas Keysight y Agilent. Modelos 34972A LXI. Utilizado

para la toma de medidas de tensión y corriente AC/DC y medida de resistencia a

2 y 4 hilos entre otras.

Figure 1. Dataloguer Agilent. Modelo 34972A LXI. Panel frontal y trasero con distintos módulos de conexión.

Power Supply. Agilent N5752A LXI

Fuente de tensión regulada por corriente de la marca Agilent. Modelo N5752A.

Tensión máxima: 600 V DC. Corriente máxima capaz de subministrar: 1,3 A DC.

Figure 2. Power Supply Keysight. Modelo N5752A. Panel frontal y trasero.

Page 12: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

12

Arbitrary Waveform Generator. Agilent 33521A LXI

Generador de funciones aleatorias de la marca Agilent. Modelo 33521A LXI.

Sin uso para el proyecto. Se ha contemplado su futura implementación y se han

añadido pautas al código para la facilitación de esta.

Figure 3. Arbitrary Waveform Generator Agilent. Modelo 33521A LXI. Panel frontal

Bench LCR meter. BK Precision 891

Medidor de impedancias de la marca BK Precision. Modelo 891. Utilizado para

la toma de medidas de inductancia y capacitancia con resistencias en serie y

paralelo, valores de impedancias, conductancias, admitancias, resistencias

equivalentes y factores de calidad.

Figure 4. Bench LCR meter de BK Precision. Modelo 891. Panel frontal.

Page 13: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

13

3.2. Programa principal

El programa principal es el encargado de gestionar las llamadas a los distintos

módulos y de la creación y activación de los distintos hilos de ejecución para poder

trabajar en un sistema multitarea.

Puesto que se trata de una ejecución concurrente de código, el esquema de

funcionamiento es el siguiente:

Inventario_Instrumentos.txt¿Conexión

Instrumentos?

Seleccion instrucciones de

medida

¿Canales?

Selección de canales

NO

Creación archivo .csv

Etiquetas Plot

Datos Medidas

Thread Medidas

Toma de medidas

Thread Plot

Plot tiempo real

Thread Terminal

N5752A?

Cambio consigna

NO

Fin Programa

NO

Fin Programa

Figure 5. Esquema de funcionamiento del programa principal

Page 14: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

14

El orden de ejecución establecido se debe en gran parte a la lógica de uso y

funcionamiento de los instrumentos.

En primer lugar se comprueba que se pueda establecer conexión con al menos un

instrumento. Para ello debe existir en la carpeta contenedora del programa un archivo tipo

.txt denominado ‘Inventario_Instrumentos.txt’. Este archivo debe contener tres datos por

cada instrumento separados por coma simple, diferenciando cada instrumento con un

retorno de carro. Estos datos son la IP del instrumento, el nombre y modelo y el tiempo

de espera en segundos o timeout para establecer la conexión. Mediante la IP el programa

podrá establecer una conexión vía internet con el instrumento para su uso remoto. La IP

se obtiene directamente desde el panel frontal de cada instrumento estando estos

conectados a la red mediante un cable Ethernet. Con el nombre y modelo se podrá

diferenciar entre los distintos instrumentos tanto en la ventana de ejecución del programa,

como en el archivo .csv que se creará a posteriori para almacenar los datos, como en el

plot o gráfico de datos que se mostrará durante la ejecución. Finalmente, el timeout es

necesario para establecer el tiempo máximo de espera para la conexión con cada

instrumento. Si los tiempos de espera son demasiado largos, dado que el programa

comprueba la conexión con todos los instrumentos del inventario, la espera de la primera

conexión puede llegar a ser de minutos. Sin embargo, si el tiempo de espera es demasiado

corto, este puede ser insuficiente para establecer la conexión y no se detectará ningún

instrumento conectado. Como apunte, un tiempo de 0,5 segundos sería suficiente para la

conexión con cualquier instrumento, a excepción del Keysight/Agilent 34972A que

requiere de un timeout mínimo de 6 segundos.

Una muestra del contenido del archivo .txt sería la siguiente:

10.30.239.203,Keysight 34972A,6

169.254.9.72,Agilent 34972A,0.5

10.30.240.134,Agilent N5752A,0.5

10.30.231.254,Agilent 33521A,0.5

10.30.235.170,BK Precision 891,0.5

Si no se detecta ningún instrumento conectado o no se desea utilizar ninguno de

los instrumentos detectados, el programa finalizará de forma automática emitiendo un

mensaje de aviso en el primer caso, o se podrá forzar su cierre en caso de no desear utilizar

ningún instrumento. Este último punto es de vital importancia ya que el programa

detectará cualquiera de los instrumentos del inventario que se encuentren conectados a la

red. Esto implica que se detectará cualquier instrumento en uso por cualquier otra persona

que esté realizando medidas de forma remota. Si seleccionamos un instrumento que no

sea el que nosotros deseamos utilizar, modificaremos el tipo medidas que otra persona

esté tomando en ese momento interfiriendo en su trabajo. La opción de salir del programa

sin seleccionar ningún instrumento se ha implementado para evitar interferir en medidas

ajenas en caso de no estar seguros de cuál es nuestro instrumento o de que este no haya

sido detectado. Si se detectan dos instrumentos de la misma marca y modelo, la manera

de diferenciarlos es a través de su IP, la cual se muestra en la pantalla de selección de

instrumentos para cada uno de ellos. Como ya se ha dicho, la IP de un instrumento se

puede obtener conectando este a la red mediante un cable Ethernet y visualizándola en el

panel frontal. A demás, la IP de cada instrumento debe estar incluida obligatoriamente en

el fichero ‘Inventario_Instrumentos.txt’ anteriormente mencionado.

Page 15: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

15

Figure 6. Pantalla de selección de instrumentos con diferentes opciones de selección

Una vez establecida la conexión, si nuestros instrumentos se encuentran en la lista

de opciones a seleccionar, podemos elegir hasta dos instrumentos distintos para que

trabajen a la vez. Tras seleccionarlos, se pedirá el tipo de medidas a realizar con cada

instrumento pudiendo elegir entre 1 o 2 tipos distintos de medidas, según el caso. Una

vez seleccionadas las medidas de cada instrumento, el programa comprueba si alguno de

esos instrumentos trabaja mediante la selección de canales para la toma de medidas. En

caso afirmativo, se pedirá introducir por pantalla el canal en el que medir para cada tipo

de medida. Cabe mencionar, que los únicos instrumentos que trabajan mediante la

selección de canales de medida son los dataloguer modelo 34972A (Keysight/Agilent).

Tras haber seleccionado los tipos de medidas a realizar con cada instrumento, se

pedirá al usuario que elija una ruta para crear un archivo tipo .csv para almacenar los

datos. Tras ello, el programa enviará automáticamente los datos de cada instrumento y

medida a los módulos de creación del plot y toma de datos y seguidamente procederá a

crear los threads respectivos de dichos módulos.

Tras el inicio de la toma de datos y mientras estos se muestran por pantalla

mediante el plot en tiempo real, se mostrará en la terminal de ejecución del programa la

opción de cerrar la comunicación y finalizar el programa. El cierre de la comunicación

implica la detención de todas las medidas y la puesta a 0 y desactivación de todas las

consignas entregadas a parte de la propia desconexión con el instrumento. A su vez, si el

instrumento conectado es la fuente de tensión N5752A, se dará la opción de modificar su

consigna, tanto en tensión como en corriente, en tiempo real. Durante la modificación de

la consigna no será posible cerrar la comunicación. Es importante destacar que el cierre

de comunicación se trata a modo de paro de emergencia, pudiendo activarse mediante el

uso de cualquier tecla. Esto se debe a que en ciertos casos puede ser de vital importancia

la desconexión de ciertos instrumentos como la fuente de tensión.

3.3. Comunicación LAN

En este apartado se explica el funcionamiento de las distintas partes que

componen la comunicación LAN con los distintos equipos de medida. Se trata de un

conjunto de funciones, distribuidas en distintos módulos, que interactúan entre ellas

enviando y recibiendo información de los distintos instrumentos conectados.

Page 16: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

16

La comunicación se divide en tres partes, el módulo que ejecuta la comunicación

LAN con los equipos a través de un socket, el módulo de detección de equipos y las

instrucciones SCPI de cada instrumento.

3.3.1. Módulos para la comunicación LAN

La comunicación LAN, propiamente dicha, está formada por dos módulos

distintos, el módulo Comunicación.py y el módulo LAN.py, la combinación de los cuales

permite la conexión remota con los instrumentos.

El primer módulo, el cual puede considerarse el módulo principal de

comunicación, contiene únicamente una clase llamada ‘comunicación_instrumento’. Esta

clase hereda sus variables principales de la librería socket, la cual es de código abierto y

es la que permite la comunicación remota vía internet. Estas variables heredadas, tales

como la IP, el puerto de conexión del instrumento, el tamaño del buffer de datos y el

timeout de conexión, se inicializan mediante el constructor de la clase.

Este constructor de clase puede ser considerado el núcleo de la comunicación.

Antes de inicializar las distintas variables con los valores recibidos, los cuales se

explicaran a continuación, se invoca al constructor de la clase socket, inicializándola con

los valores predeterminados para el tipo de comunicación que queremos realizar. Tras

ello, se establecen los valores de las variables principales que permitirán la comunicación.

Estos valores son la IP del instrumento, el puerto de comunicación LAN del instrumento

y el tamaño de datos del buffer. Tanto el puerto como el tamaño del buffer suelen ser

valores fijos, siendo el puerto de comunicación el 5025 y el tamaño del buffer de 1024.

Es importante comprobar el puerto de comunicación si se pretende instalar un nuevo

instrumento ya que, a pesar de que se utiliza el mismo puerto de manera estándar para la

comunicación LAN, podría no ser el mismo para todos los instrumentos. Lo mismo ocurre

con el tamaño del buffer, debemos asegurarnos que los datos que vamos a recibir son

inferiores al tamaño establecido. Finalmente se establece el valor de timeout, el cual no

es un valor propio del constructor de la clase socket, si no que forma parte de una de las

funciones propias de dicha librería, y que ha sido añadido al constructor para poder

establecer distintos tiempos de comunicación con los diferentes instrumentos. Podemos

observar esta adición al constructor viendo que el valor de timeout se envía como

parámetro a la función ‘settimeout()’, la cual pertenece a la clase socket.

Tras establecer los diferentes parámetros, se comprueba que se pueda establecer

una conexión con la IP mediante el método connect, propio de la clase socket. Si se

confirma la conexión, finaliza la ejecución del constructor de la clase al crear el objeto,

si no, se crea una excepción y se evita realizar ninguna acción tal como detener el

programa o mostrar ningún aviso. Esto se debe a que, como se mostrará más adelante, se

crea y destruye un objeto de esta clase para cada IP de cada instrumento para comprobar

únicamente qué instrumentos se encuentran conectados a la red. Si un instrumento se

detecta, se volverá a crear otro objeto para volver a establecer la conexión.

A parte del constructor de nuestra clase, también se han creado tres funciones

diferentes. Una para el envío de datos, otra para la recepción de datos y una última para

el cierre de la comunicación con el socket. Como nuestra clase funciona con la herencia

Page 17: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

17

de la clase socket, tanto el envío y recepción de datos, como el cierre de la comunicación,

funcionan utilizando métodos propios de la clase padre.

El segundo módulo utilizado para el funcionamiento de la comunicación es el

módulo LAN. Al igual que en el anterior, este módulo contiene una clase que hereda sus

atributos principales de la clase creada en el módulo anterior. La estructura de

funcionamiento es la misma. Tras crear el objeto enviándole los valores pertinentes (IP,

puerto de conexión, tamaño del buffer de datos y timeout) como parámetros, se inicializa

la clase padre (comunicacion_instrmento) del módulo ‘Comunicación’. Esto hará, como

ya se ha explicado, que se inicialice la clase socket mediante su constructor, lo que nos

permitirá comunicarnos de forma remota vía internet.

Al igual que en el caso anterior, la clase se compone de diferentes funciones que

nos proporcionaran el apoyo adecuado para las distintas peticiones y envíos de datos. Se

podría pensar que esta segunda clase es innecesaria debido a la existencia de la clase

básica de la comunicación. El motivo por el que se ha creado esta segunda clase que se

apoya sobre la clase padre del anterior módulo, es para permitir que se puedan

personalizar las distintas demandas y envíos de información durante el funcionamiento

del programa. Como se verá más adelante, en ciertas ocasiones es necesario hacer envíos

de información, pero no recibir ningún tipo de respuesta o enviar información con más o

menos datos, dependiendo del instrumento conectado. Estos casos se pueden ver

reflejados en las cuatro funciones implementadas en la clase.

La primera función, llamada ‘Dato_Auxiliar’, se encarga de enviar un dato al

instrumento, como por ejemplo la petición de su IDN para identificarse la cual veremos

más adelante, y devolver esa información al módulo que ha hecho la petición. La segunda

función, ‘Dato_auxiliar_2’, cumple un cometido similar. Hace un envío de información

al instrumento, pero no pide ni devuelve al módulo que la ejecuta ningún tipo de

información. Esta función se utiliza para establecer el tipo de medidas a realizar o enviar

instrucciones que no requieren una respuesta para que sea tratada, como la desactivación

de consignas o medidas en curso. La tercera función recibe el nombre de ‘hacer_medida’.

Su objetivo consiste en enviar al instrumento la petición de realizar una medida y obtener

de él un dato. Según si el instrumento funciona mediante el uso de canales o no, la función

realiza un tipo de pedio u otro. La información sobre si se debe utilizar peticiones de datos

con canales o no, debe ser indicada a la función mediante parámetro, además del tipo de

medida a realizar y el canal en el que realizar la medida si es necesario. Finalmente, la

última función denominada ‘cierre_Com’ se encarga de cerrar la comunicación.

Para la conexión con un instrumento es necesario la creación del objeto de la clase

LAN y la correcta definición de sus parámetros. La forma correcta para crear el objeto

sería utilizando el siguiente método:

Nombre_Objeto=LAN.LAN (IP, PUERTO, BUFFER_SIZE, TIMEOUT)

Todos estos parámetros pueden ser definidos previa creación del objeto o

introducidos de forma directa al crear el objeto como parámetros. En ciertos casos, como

por ejemplo al comprobar qué instrumentos hay conectados a la red de forma automática,

algunos de estos parámetros como la IP o el timeout se obtendrán mediante distintos

algoritmos, como se verá más adelante.

Page 18: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

18

Para el uso de las distintas funciones de la clase, el método a utilizar es el uso del

nombre del objeto seguido de un punto y el nombre de la función con los parámetros

pertinentes, como se muestra en el siguiente ejemplo:

Nombre_Objeto.Dato_auxiliar_2 (‘instrucción’)

Si lo que se desea es obtener un valor o dato tras la llamada a alguna de las

funciones que componen la clase, el funcionamiento es el mismo. Se utiliza el nombre

del objeto seguido por un punto y los parámetros pertinentes igualándolo a una variable.

A continuación se muestra un ejemplo:

Varaible_Aux = Nombre_Objeto.Dato_auxiliar (‘instrucción’)

Es importante tener en cuenta que esto sólo debe hacerse con las funciones que

retornen un valor, de no ser así esta acción carecería de sentido puesto que la variable

auxiliar que utilizamos no contendrá ningún valor útil.

Parametros constructor (IP, PORT, BUFF_SIZE,

TIMEOUT)

Objeto LAN.LAN

Constructor Clase 'comunicacion_instrumento'

Constructor clase 'Socket'

Dato_Auxiliar

enviar_dato

send

recibir dato

recv

Dato_Auxiliar_2

enviar_dato

send

hacer_medida

¿Canales?

enviar_dato

send

recibir_dato

recv

cierre_Com

cerrar_puerto

close

Figure 7. Esquema de funcionamiento de la comunicación LAN

Page 19: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

19

3.4. Autodetección de equipos

La detección de los distintos equipos conectados a la red debe gestionarse de

forma automática y totalmente ajena al usuario. La única labor que este deberá llevar a

cabo será la de seleccionar con qué instrumento trabajar una vez hayan sido detectados.

Todo el sistema de autodetección de los distintos instrumentos se gestiona en un

mismo módulo llamado PIN_Instrumento.py. En primer lugar, desde el programa

principal, se invoca a la función ‘Leer_Inventario’ de este módulo. Como su nombre

indica, esta función se encarga de leer el archivo .txt, mencionado en los apartados

anteriores, que contiene el inventario de instrumentos. Como ya se ha explicado, el

inventario debe estar formado por el nombre, la IP y el tiempo máximo de espera para

establecer la conexión con cada uno de los instrumentos. Es importante que, tanto el

nombre como la composición del archivo, no se vean modificados en ningún momento,

pues eso impediría la ejecución del programa.

Tras leer y separar los distintos datos dependiendo del tipo, estos se envían a la

siguiente función del módulo, llamada PIN. Esta función se encarga de intentar crear una

conexión con todas las IP listadas teniendo en cuenta el tiempo máximo de conexión

establecido para cada una de ellas. Esta acción se lleva a cabo creando un objeto para la

comunicación, del tipo LAN.LAN, explicado con anterioridad. Esto se hace para cada

instrumento de forma progresiva siguiendo el orden establecido en el inventario. Tras

crear el objeto e inicializar el constructor con los datos del instrumento a probar, se le

envía la instrucción ‘*IDN?’. Esta es una instrucción en lenguaje SCPI (Standard

Commands for Programmable Instruments) con el que se puede programar la gran

mayoría de instrumentos programables, como indica su nombre. Cualquier instrumento

que reciba este comando devolverá su IDN. El IDN de un instrumento consiste en una

cadena de caracteres de identificación con el nombre del fabricante, modelo y versión de

software, entre otros datos. Si el instrumento con el que estamos intentado realizar la

conexión nos retorna un IDN, significa que se encuentra conectado a la red y que hemos

podido establecer una conexión con él. En caso de no obtener ninguna respuesta, puede

significar que el instrumento no esté conectado o que el tiempo de conexión establecido

es demasiado pequeño. Si estamos seguros de que cierto instrumento se encuentra

conectado a la red y no es detectado, es necesario modificar el timeout de la conexión.

Tras realizar la comprobación, se haya establecido o no una conexión con el instrumento,

esta se cierra y se pasa a crear otro objeto para probar a conexionar con el siguiente

instrumento listado.

Es importante comprender el funcionamiento del código por si es necesario

realizar modificaciones futuras. Tras crear el objeto para la conexión, se envía la

instrucción ‘*IDN?’ al instrumento utilizando el método try-except de Python. Este

método consiste en ejecutar inicialmente el código contenido dentro de ‘try’. Si durante

la ejecución de ese código aparece una excepción que impide la ejecución de dicho

código, se pasa a ejecuta el código contenido dentro del ‘except’. De esta manera, si el

envío de la instrucción genera una excepción indicando que no se ha podido conectar con

el instrumento, el programa cierra directamente la comunicación con este para evitar

posibles errores mediante el método ‘except’, en lugar de detener la ejecución. Si el

instrumento contesta enviando su IDN, no se generaría ninguna excepción y se procedería

Page 20: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

20

a ejecutar el código contenido en el método ‘try’, en el cual se obtienen el nombre y

modelo del instrumento para su futuro uso. A demás, tras la conexión con un objeto, se

incrementa un contador cuya función es almacenar la cantidad de instrumentos

conexionados. Si esta cantidad es mayor que 0, se establece como cierta la variable

booleana ‘conexión’, la cual es devuelta a la función anterior que invocaba a la actual. Si

la cantidad es 0, la variable se establece como falsa.

Tras finalizar la ejecución de la función PIN, la función Leer_Inventario, la cual

había llamado a la anterior, recibe el valor de la variable ‘conexión’ y a su vez lo retorna

al programa principal. Una vez en este, se comprueba el valor recibido. Si este es

verdadero, se proseguiría con la ejecución del código. En caso de ser falso, finalizaría la

ejecución del programa, puesto que no se habría encontrado ningún instrumento

conectado o no se habría realizado la conexión con ningún instrumento.

Programa principal

Módulo PIN_Instrumento.py

Leer_Inventario

PIN

CONEXIONES

Retorno de datos a función Leer_Inventario

Retorno de datos a Programa principal

¿Conexión?

Prosigue la ejecución

NO

Fin programa

Figure 8. Esquema de ejecución para autodetección de instrumentos

Page 21: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

21

Finalmente, si se ha detectado algún instrumento y se prosigue con la ejecución

normal del programa, pasaríamos a seleccionar los instrumentos a utilizar. Esto se lleva

a cabo en otra función del mismo módulo, la cual recibe el nombre de INSTRUMENTS.

Esta función es llamada desde el programa principal para poder obtener los datos de los

instrumentos y poder enviarlos a otros módulos con mayor facilidad.

Tras indicar por pantalla la cantidad de instrumentos conectados, se muestra un

listado de estos con sus correspondientes nombres, modelos e IP. A demás, se muestra un

breve comentario explicando que tan sólo pueden elegirse dos instrumentos como

máximo, que en caso de tan sólo desear utilizar uno de los que componen la lista puede

hacerse, o que se puede salir del programa sin seleccionar ninguno (Ver figura 6). El

hecho de permitir seleccionar únicamente un instrumento o ninguno se debe a evitar

interferir en las medidas de otros compañeros al poder seleccionar cualquier instrumento

que se encuentre conectado a la red, como se ha explicado con anterioridad en el

documento. La limitación a dos en el número máximo de instrumentos a utilizar se debe

a los planteamientos iniciales del proyecto. Como posible futura revisión de este, podrían

añadirse a la ejecución la toma de medidas simultáneas de más instrumentos. Esto

implicaría la modificación de los distintos módulos que intervienen en el proceso.

Tras seleccionar los instrumentos, el programa obtiene la IP, el nombre y el

modelo de cada uno y lo retorna al programa principal para ser utilizado en otros módulos

y funciones. Si tan sólo se ha seleccionado un instrumento, ya sea porque tan sólo se ha

encontrado uno conectado o porque sólo se desee utilizar uno de toda la lista, los datos

del segundo instrumento se rellenarán de espacios en blanco para representar la ausencia

de estos y facilitar así la programación. Es importante mencionar que, tanto en esta como

en todas las selecciones de instrumentos o instrucciones del programa, se ha tenido en

cuenta que no puedan elegirse valores que no sean los predefinidos para evitar errores

durante las selecciones. Si se introduce un comando no definido en el panel de ejecución,

se mostrará un mensaje de error y se volverá a ofrecer la opción de hacer la selección

pertinente.

Como en el caso de la detección de los instrumentos, si no deseamos utilizar

ninguno de los listados, finalizará la ejecución del programa sin interferir en ninguno de

los otros posibles instrumentos conectados para no perjudicar la toma de medidas ajenas.

3.5. Instrucciones SCPI

Cada instrumento es capaz de realizar distintos tipos de medida o entregar

distintas consignas. Para ello, es necesario enviarles las instrucciones pertinentes según

nos convenga en cada caso. Puesto que lo que estamos haciendo es programar en tiempo

real los instrumentos, las instrucciones deben ser enviadas en lenguaje SCPI. En el caso

anterior, para la identificación de cada instrumento mediante su IDN, enviábamos la

misma instrucción SCPI a todos. Esto se debe a que todos los instrumentos tienen ciertas

instrucciones básicas para proporcionar información sobre su sistema que son comunes

para todos ellos, pero puesto que cada instrumento realiza medidas diferentes o entregan

distintas consignas, las instrucciones SCPI para programarlos no son las mismas para

todos. Esto implica que cada instrumento debe ser tratado de forma independiente para

su programación y uso.

Page 22: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

22

Para cada instrumento, es necesario hacer un estudio de sus funcionalidades y de

qué instrucciones se deben utilizar para poderlas poner en uso. Además, es necesario

conocer las limitaciones de tensión y corriente, entre otras de ciertos instrumentos para

evitar que las instrucciones que entreguemos no entren en conflicto con la programación

interna del instrumento y su funcionamiento. Todos estos datos pueden encontrarse en los

distintos manuales de uso de cada instrumento.

La selección de las diferentes instrucciones de cada instrumento se realiza en el

módulo Lista_Instrucciones.py. Este módulo está compuesto por diferentes funciones, las

cuales están enfocadas a la selección de las instrucciones propias de cada instrumento.

Desde el programa principal se llama a la función Instrucción_medir enviándole por

parámetros el modelo y el nombre del instrumento. Mediante el modelo, la función

comprueba de qué instrumento se trata e invoca a la función pertinente según el

instrumento. Llegados a este punto es importante destacar uno de los instrumentos, en

concreto el dataloguer de la familia Agilent 34972A. Se hace una especial mención

debido a que es el único que funciona mediante la selección manual de canales y permite

realizar uno o dos tipos de medida simultáneamente. Debido a este último punto, antes de

hacer la llamada a la función que le corresponde para seleccionar sus instrucciones,

primero se hace la llamada a la función Num_meas. El cometido de esta función es el de

dar a elegir al usuario si desea realizar una única medida con el instrumento o si desea

realizar dos de manera simultánea. Como patrón general, todas las funciones ejecutan el

mismo procedimiento. Inicialmente se mostrará el nombre del instrumento y la lista de

instrucciones o medidas que este puede realizar. A continuación se le pedirá al usuario

que seleccione el número de la medida a realizar. Puesto que cada instrumento realiza las

medidas de una manera diferente, a continuación se detalla brevemente las características

propias a la hora de seleccionar las medidas para cada uno de ellos.

Agilent/Keysight 34972A Como característica principal, la función se ajusta a la elección del usuario de

realizar una o dos medidas. En caso de querer realizar tan sólo una, tras seleccionarla

se pasará al siguiente paso del programa. Si se desean realizar dos medidas, tras la

primera selección se pedirá elegir una segunda.

Figure 9. Menú de selección de medidas Agilent/Keysight 34972A

Page 23: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

23

BK Precision 981

Se trata de un instrumento que realiza dos medidas simultáneamente. Estas

medidas se encuentran parametrizadas. Para seleccionar un tipo de medida, es

necesario seleccionar el parámetro principal y secundario para conformar una única

medida de dos magnitudes diferentes. Por ejemplo, si se desea medir el valor de una

capacitancia en serie con un resistor y a la vez se desea medir la resistencia

equivalente, debe seleccionarse como parámetro principal el parámetro ‘CS’ para la

capacitancia serie y a continuación el parámetro secundario ‘R’ para la medida de la

resistencia equivalente. Es de gran importancia mencionar que a cada parámetro

principal le corresponden tan sólo ciertos parámetros secundarios. Es decir no se

podrá medir un parámetro secundario que no corresponda con el principal. Para

facilitar el uso, inicialmente se muestran los distintos parámetros principales que se

pueden seleccionar, y tras hacerlo, tan sólo se mostrarán los parámetros secundarios

que permita el principal.

Figure 10. Menú de selección de medidas BK Precision 891

Tras la selección de los parámetros, se crea un objeto de comunicación que los envía

al instrumento para establecer el tipo de medida que se van a realizar. Puesto que este

instrumento es el único que nos devuelve el valor medido junto con sus unidades,

aprovechamos esta situación para obtener cuales son. Para ello, mediante la

comunicación previa establecida, se le envía al instrumento una primera orden de

lectura. Tras obtener el valor leído, se envía a la función BK_Unidades para separar

el dato de las unidades de la medida, las cuales se utilizarán para ser mostradas tanto

en el futuro archivo .csv como en los ejes de medida del plot.

Keysight N5752A Al tratarse de una fuente de tensión, no se eligen tipos de medida, si no que se

entregan unas consignas, tanto de corriente como de tensión, según necesite el

usuario. En primer lugar se establece una conexión con el instrumento y a

continuación se le pide al usuario que establezca un límite de corriente y una tensión

Page 24: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

24

de inicio, mostrando los valores máximos y mínimos para cada una de las consignas.

En ningún caso se permite que se superen los valores máximos o mínimos, mostrando

un mensaje de error si esto ocurre y volviendo a preguntar la consigna deseada.

Figure 11. Menú de selección de consignas para la fuente de tensión Agilent N5752A

Tras ello, y mediante la comunicación ya establecida, se entregan las consignas al

instrumento de modo que estas no se disparen hasta que se reciba la instrucción

adecuada que indique dicho disparo. Por razones de seguridad, dicha instrucción se

recibirá una vez se inicie la toma de medidas. Esto se debe a que entre el proceso de

establecimiento de las consignas y la toma de medidas, existen diferentes pasos a

llevar a cabo. Uno de ellos es la selección de la ruta de guardado del archivo .csv. El

inconveniente de este paso, es que no hay un tiempo límite para establecer la ruta de

guardado. Este tiempo dependerá directamente del usuario. Puesto que se trata de una

fuente de tensión, la consigna entregada podría causar daños a los equipos o elementos

conectados a ella, pudiendo causar accidentes, lesiones o iniciar fuegos. Si no

podemos desconectar la fuente remotamente de forma rápida tras disparar las

consignas, esto podría derivar en los problemas mencionados. Por ello, el disparo se

establece una vez se empiecen a tomar medidas y el usuario no tenga que interactuar

con el programa más que para detenerlo si así lo desea. Si entre el disparo y la opción

de detener el programa se intercalase este tiempo variable, el cual depende del usuario,

estaríamos reduciendo drásticamente la seguridad de todo el sistema.

Cabe mencionar que tras seleccionar las instrucciones de medida o las consignas

a entregar, estos datos son devueltos al programa principal para poder ser utilizados por

otros módulos. Puesto que podemos trabajar con hasta dos instrumentos, todo este

procedimiento se repetirá para un segundo instrumento si es necesario. En caso de que no

hubiese un segundo instrumento, desde el programa principal se llamaría a la función

‘No_instrument’, contenida en el mismo módulo, cuya función es la de retornar todos los

valores necesarios para definir el tipo de medida en blanco. Al igual que en el caso de la

selección e instrumentos, estos valores deben ser conjuntos en blanco para simular la

ausencia de estos. Más adelante, estos datos serán utilizados para reconocer si es necesario

realizar ciertas acciones o no, como un plot doble o la inclusión de medidas o no en el

archivo .csv donde se almacenarán.

Page 25: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

25

3.6. Petición de canales

Tras la selección de los instrumentos y de los tipos de medida a realizar con cada

uno, el programa comprueba si alguno de estos instrumentos necesita información previa

a realizar las medidas de los canales en los que realizarlas. Los únicos instrumentos que

necesitan estos datos son los dataloguers modelo 34972A LXI, ya sean de la marca

Keysight o Agilent.

Tanto la comprobación como la selección de los canales, si son necesarios, se

llevan a cabo en el módulo Select_Chan.py. Mediante la función ‘Diferenciar_Modelo’

se comprueba cuál es el modelo del instrumento y de coincidir con los anteriormente

mencionados, se hace una llamada a la función ‘CHANELS’ para obtener la lista de

canales a utilizar, dependiendo de si se necesitan hacer una o dos medidas.

Figure 12. Menú de selección de canales para medidas de tensión AC y DC con Keysight 34972A

Dentro de la función ‘CHANELS’ se comprueba que los canales seleccionados se

encuentren dentro de los rangos especificados por la documentación del instrumento para

evitar conflictos con la programación interna de es este. A su vez, en caso de haber

seleccionada una medida resistiva a 4 hilos, se muestra un mensaje de aviso indicando

qué canales deben ser cableados para la toma de esta medida y la comprobación de que

estos no estén ya en uso.

Figure 13. Selección de instrucciones y canales con medida resistiva a 4 hilos con Keysight 3492A

Como dato importante para comprender el funcionamiento del programa para

futuras revisiones de este, tras la selección de los canales, las variables booleanas de

nombre ‘BI_CHAN_1’ y ‘BI_CHAN_2’ pasarán a ser ciertas, dependiendo de si se trata

del primer o segundo instrumento. Estas variables se encuentran en el programa principal

junto con los datos de los instrumentos y sus canales, en caso de necesitarlos. Estas dos

variables mencionadas, serán las que determinen qué tipo de mensaje se enviará al

Page 26: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

26

instrumento desde la clase de comunicación. Si la variable es cierta, la instrucción de

medida se enviará junto con el canal en el que realizarla. Si es falsa no se indicará ningún

canal de medida.

Como en los casos anteriores, este procedimiento se realizará para cada

instrumento conectado a la red que requiera de una selección de canales. En caso de no

ser necesario, se llamará a la función ‘No_Instrument’ del mismo módulo para devolver

al programa principal los datos de los canales como espacios en blanco, del mismo modo

que se hacía en los puntos anteriores.

Programa Principal

Módulo Select_chan

Diferenciar_Modelo

¿34972A?

CHANELS

1 Medida

CH_1=''CH_2=xxx

BI_CHAN_1=FalseBI_CHAN_2=True

CH_1=xxxCH_2=''

BI_CHAN_1=TrueBI_CHAN_2=False

2 Medidas

CH_1=xxxCH_2='yyy'

BI_CHAN_1=TrueBI_CHAN_2=True

NO

No_Instrument

CH1=''CH2=''

BI_CHAN_1=FalseBI_CHAN_2=False

Figure 14. Esquema de funcionamiento del selector de canales

Page 27: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

27

3.7. Creación y guardado de fichero .csv

Para el almacenamiento y posterior tratado de los datos obtenidos, durante la

ejecución del programa, se creará un archivo de extensión ‘.csv’ (comma separated

values). Este tipo de archivos se caracterizan por almacenar datos separándolos mediante

una coma simple en una misma celda dentro de un fichero tipo Excel o similar.

Para obtener el fichero de almacenamiento, primero se debe elegir la ruta de

guardado. Para ello, mediante el uso de la librería de código libre ‘wx’ de Python, se crea

una ventana auxiliar en la que el usuario puede seleccionar una ruta específica de

guardado. El funcionamiento de esta ventana es idéntico al que ya conocemos en nuestro

sistema operativo habitual. Mediante la interfaz gráfica de carpetas, podemos seleccionar

la ubicación dónde guardar el archivo o escribir directamente la ruta de guardado. A

demás, podremos elegir el nombre del archivo y obtener un mensaje de aviso si alguno

de los ya existentes va a ser sobrescrito en este proceso. Es importante destacar que

únicamente podrán crearse archivos tipo .csv y de ningún otro tipo.

Puesto que este archivo de guardado es de suma importancia para la realización

de cualquier experimento, puesto que es donde se almacenarán los datos, se han tomado

ciertas medidas de seguridad. La primera de ellas consiste en la creación de un archivo

de seguridad en caso de cerrar la ventana de guardado anteriormente mencionada sin

haber elegido una ruta específica. Este archivo de seguridad se almacenará en la misma

ruta en la que se esté ejecutando el programa y tomará el nombre de ‘Security_file_’

seguido de la fecha y hora en la que se cree el archivo. Además se mostrará un mensaje

por pantalla indicando este suceso y mostrando el nombre y la ubicación exacta del

fichero. La otra medida de seguridad tomada es la aparición de un mensaje de error en

pantalla en caso de no haber podido crear el archivo. Si esto ocurre, el programa dejaría

de ejecutarse al intentar almacenar datos en un archivo inexistente.

Para llevar esto a cabo, se ejecuta el código contenido en el módulo SAVE.py. Este

módulo consta de cuatro funciones. La primera es la función ‘save’, en la cual se

encuentra el código que realiza todas las acciones necesarias para llevar a cabo lo

anteriormente descrito. La segunda es la función de nombre ‘exe’. Esta función es la que

permite ejecutar la interfaz gráfica de la función anterior. Esto se debe a que estamos

trabajando con clases y funciones de la librería ‘wx’, mencionada al principio, la cual

requiere de ciertas instrucciones específicas para ejecutarse y que se encuentran

contenidas en esta función. Finalmente nos encontramos con las dos últimas funciones,

las cuales son ‘Nombre_instrumento’ y ‘Leer_Pathname’. La primera, previo a la

creación del fichero, recibe desde el programa principal el nombre, modelo y medidas a

realizar de cada instrumento y ejecuta la función ‘exe’ para que aparezca la interfaz

gráfica. Esto es debido a que el fichero no sólo almacenará datos, si no que contendrá

información sobre qué instrumento ha tomado el dato y a qué tipo de medida se refiere

cada uno de ellos, como se ve en la Figura 15. La segunda función se encarga de enviar

al módulo que la invoque la dirección exacta de guardado del fichero. Esta dirección o

‘pathname’ es de suma importancia puesto que más adelante será necesario saber la

ubicación del fichero en el que se guardarán los datos y que, a su vez, será leído para

mostrarlos en el plot.

Page 28: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

28

Figure 15. Diferenciación de las distintas medidas en el archivo .csv

3.8. Adquisición de datos

La adquisición de datos por parte del programa consiste en enviar de forma

periódica una misma instrucción de lectura al instrumento pertinente para que este tome

una muestra de las magnitudes físicas previamente indicadas y seguidamente las

almacene en el archivo .csv creado. Este procedimiento se llevará a cabo en un hilo de

ejecución distinto al del programa principal y será uno de los cuatro hilos que habrá

ejecutándose simultáneamente a partir de este punto.

Podemos separar la adquisición de datos o medidas en dos partes, la toma de los

datos por parte de los instrumentos y el almacenamiento de estos para su posterior estudio.

3.8.1 Toma de datos

La toma de datos se realiza en su totalidad en el módulo adquisicion_datos.py

mediante el uso de diferentes funciones. Inicialmente, desde el programa principal se

invocan las funciones ‘Datos_para_lectura’ y ‘Control_Com’. La primera se encarga de

recibir todos los datos de los distintos instrumentos conectados, siendo estos la IP, los

canales de lectura, la información de si estos son o no necesarios, los tipos de medida a

realizar, y el modelo del instrumento. La segunda recibe la información necesaria para

determinar si se autoriza o no el inicio de la toma de medidas y si se debe o no cerrar la

comunicación con los instrumentos. Esta última función será la misma a la que se llame

más adelante desde otro módulo para dar fin a la toma de medidas desconectando los

instrumentos.

Tras obtener los datos de los equipos y autorizar las medidas, se crea e inicia el

hilo de ejecución para la toma de estas ejecutando la función ‘Adquirir_Datos’. Tras ello

se crearán entre uno y dos objetos distintos de comunicación, según la cantidad de

instrumentos en uso. Tras ello, y antes de la primera toma de datos, se comprobará si

alguno de los instrumentos utilizados es la fuente de tensión N5752A mediante la

comprobación del modelo. Si se da el caso, se procederá a iniciar el sistema de disparo

de las consignas previamente entregadas, se activarán las salidas del instrumento y se

realizarán los disparos de dichas consignas. Esto se llevará a cabo mediante las

instrucciones SCPI correspondientes y el uso del objeto de comunicación pertinente a

cada equipo. Como ya se explicó anteriormente, que los disparos de las consignas de

tensión y corriente de la fuente se realicen justo antes de iniciar la toma de medidas se

Page 29: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

29

debe a una razón de seguridad. Si tras realizar el disparo los valores fuesen demasiado

elevados y pudieran provocar daños en los equipos conectados a la fuente, esta podría

detenerse inmediatamente justo tras realizar la primera medida, el tiempo de realización

de la cual es prácticamente inmediato a efectos de uso del usuario.

Tras esta comprobación, se dará inicio a la toma de medidas. Estas tomas se

realizarán dentro de un bucle infinito de ejecución del cual sólo se saldrá si así lo indica

el usuario, como veremos más adelante. Puesto que cada instrumento puede realizar hasta

dos tipos distintos de medida, tendremos un total posible de hasta cuatro llamadas a la

función ‘hacer_medida’ del módulo LAN de comunicación ya explicado. La cantidad de

tipos de medidas a realizar vendrá dada por el nombre de la instrucción SCPI de cada una

a realizar por cada instrumento. En cada ciclo de ejecución del bucle se comprobará si

existe o no un nombre de instrucción o medida a realizar para cada instrumento. En caso

de no ser un conjunto vacío (‘’) se utilizará el objeto de comunicación asignado al

instrumento pertinente para indicarle que realice el tipo de medida previamente

seleccionada. Puesto que se crean dos objetos para comunicarse, cada uno será asignado

al primer y segundo instrumento seleccionado respectivamente. Si un mismo instrumento

realiza dos tipos distintos de medida, mediante el mismo objeto, se enviará primero una

instrucción y a continuación, tras recibir el dato de esta, se enviará la otra. Si un

instrumento tan solo realiza un tipo de medida o no existe un segundo instrumento, estos

datos se considerarán, como en anteriores casos en los que no había ningún dato, como

conjuntos vacíos (‘’).

Objeto Comunicación Instrumento 1

¿IP_2?

Objeto Comunicación Instrumento 2

NO

Medida 1 Instrumento 1

¿Instrucción medida 2 Instrumento 1?

Medida 2 Instrumento 1

NO

¿Objeto de comunicación 2?

Medida 1 Instrumento 2

¿Intrucción medida 2 Instrumento 2?

Medida 2 Intrumento 2

NO

NO

Figure 16. Esquema de ejecución de las distintas medidas según instrumentos conectados

Page 30: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

30

Tras cada ciclo de toma de medidas, todos los datos son almacenados en un array

de cuatro posiciones que se envía al módulo CSV_Data junto con la hora de las lecturas

para ser almacenadas en el archivo .csv. Es importante mencionar que la hora se toma

justo tras realizar la última medida de cada ciclo del bucle de lecturas, por lo que habrá

una pequeña variación de tiempo respecto a la toma real de las primeras medidas con

respecto a las últimas de cada ciclo. Puesto que esta variación de tiempo oscila entre los

0.001 y los 0.006 segundos en prácticamente el cien por cien de los casos, podemos

considerar que no interfiere en la veracidad de los tiempos de medida, pudiendo

considerar la totalidad de las medidas de un ciclo como simultáneas puesto que el tiempo

mínimo establecido entre lecturas es de un segundo. Estas diferencias de tiempo han sido

medidas almacenando los datos en la memoria interna de la Raspberry que se utilizará

para llevar a cabo el proyecto, en una memoria externa tipo flash y en la memoria interna

de un pc portátil. En los tres casos se confirman las diferencias de tiempo entre medidas

anteriormente mencionadas, incluyendo estas el tiempo de almacenamiento en el archivo

.csv. Excepcionalmente, y tras realizar distintas pruebas, se han dado casos de tiempos

de mayor duración de forma totalmente aislada de 0.063 segundos, los cuales siguen

siendo lo suficientemente pequeños como para comprometer las medidas que se realicen.

Antes de ser enviados al módulo CSV_Data para ser almacenados, los datos pasan

por un último filtro. Si el modelo de alguno de los instrumentos con los que se están

tomando las medidas coincide con el del BK 891, los datos recibidos por este instrumento

serán tratados antes de ser almacenados en el archivo .csv. Esto es debido a que este

instrumento entrega los datos obtenidos de las lecturas junto con caracteres alfanuméricos

indicando las unidades de estas medidas. Por el modo en cómo se tratan los datos para ser

mostradas en el plot, que veremos más adelante, los datos almacenados en el archivo .csv

deben ser únicamente caracteres numéricos que no contengan ninguna letra u otro

símbolo distinto a un número. Para eliminar estos caracteres sobrantes de las medidas

realizadas con el BK 891, tras comprobar qué datos provienen de él, estos son enviados

a la función ‘BK_DATA’. Es importante saber que este instrumento siempre realiza dos

tipos de medida y que ambas son devueltas como si se tratase de un único dato,

separándolas por una coma simple. Estos datos, tras ser recibidos en la función

anteriormente nombrada, son separados mediante la coma simple y enviados por separado

a la función ‘BK_Num_Transform’. En esta función se eliminan los espacios en blanco

y los caracteres que indican las unidades de la medida. Recordemos que estas unidades

ya han sido obtenidas tras realizar la conexión con el instrumento la primera vez. Puesto

que todas las medidas se deben encontrar dentro de ciertos márgenes debido a las

características del instrumento, si estos márgenes se rebasan el instrumento responderá

con un mensaje de error. Este mensaje será una serie de caracteres alfanuméricos, los

cuales debemos conservar para guardar en el archivo .csv ya que es de sumo interés saber

cuándo ha habido un error en la lectura. Puesto que en la última función mencionada se

eliminan todo tipo de caracteres no numéricos, se permite que ciertas cadenas no sean

eliminadas y se consideren válidas para ser almacenadas. Esas cadenas de caracteres son

los posibles mensajes de error que el instrumento ofrece al superar los rangos de medida

de cualquier magnitud. Se ha mencionado que todos los datos almacenados deben ser

numéricos para que puedan ser tratados por el módulo que mostrará el plot. Como se

explicará más adelante, si al leer el archivo .csv se encuentran valores no transformables

Page 31: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

31

en tipo float, se considerarán mensajes de error y se les dará un valor predeterminado

para hacer visible ese error en la medida a simple vista.

3.8.2 Almacenamiento de datos

Como se ha mencionado en el punto anterior, una vez por cada ciclo de lectura de

las distintas magnitudes seleccionadas, estos datos se almacenan en un archivo de

extensión .csv. Esto se lleva a cabo en el módulo CSV_Data. Para ello, tras haber creado

el fichero y desde el mismo módulo SAVE, se le envía al módulo actual la ruta de guardado

del archivo mediante la llamada a la función ‘Rec_Path’. Una vez obtenido el ‘pathname’

del archivo y obtenida la primera tanda de datos del primer ciclo de ejecución del bucle

de lecturas mencionado anteriormente, la función ‘escribir’ recibe el array con los datos

y la hora de la lectura de estos. Tras ello, los separa, abre el archivo .csv, y los escribe en

él siguiendo un orden preestablecido.

Sería de esperar un algoritmo de exclusión mutua (MUTEX) a la hora de abrir el

archivo .csv para escribir y leer, pero no es necesario. La ausencia del MUTEX recae en

que sólo hay una única función en todo el código que escribe en el fichero, lo que provoca

que no exista la posibilidad de ser modificado por un tercero y corromper los datos

sobrescribiéndolos y perdiendo lecturas. A parte, la lectura del archivo tampoco modifica

los datos, por lo que esta se puede dar en cualquier momento sin ningún tipo de peligro,

teniendo en cuenta únicamente que tras cada lectura, al igual que con la escritura, debe

cerrarse el fichero.

Finalmente, si durante la escritura sucede algún error, se mostrará por pantalla un

aviso de este indicando que no se están almacenando los datos en el archivo. El error

típico, el cual es de suma importancia evitar, es el de abrir el archivo .csv mientras se

están almacenando los datos es él. La apertura del archivo impediría que el programa

pudiera abrirlo él mismo para almacenar datos, los cuales se perderían irremediablemente.

Al igual que en el caso anterior, la inclusión de un algoritmo de exclusión mutua no

solventaría este error, puesto que la apertura del archivo que provocaría la pérdida de

información se daría fuera de la ejecución del código del programa.

3.8.3 Cierre de comunicación

Una vez esté en proceso la toma de datos, el usuario podrá detener este

procedimiento en cualquier instante. Esta opción se dará en el tercer y último hilo de

ejecución, que se explicará más adelante, en el módulo Terminal.py. Tras modificar los

valores de las variables de la función ‘Control_Com’, que autorizan el inicio de medidas

y controlan el cierre de las comunicaciones, se saldrá del bucle de ejecución de las lecturas

y se ejecutará la última parte de la función ‘Adquirir_Datos’. Esta última parte consiste

en una serie de comprobaciones de los distintos modelos de instrumentos para asegurar

una total desconexión de estos.

Puesto que todos los instrumentos a excepción del BK Precision 891 son de la

marca Agilent o Keysight, comparten ciertas instrucciones SCPI que afectan al sistema

principal de estos y que son comunes para todos ellos. Una de estas instrucciones consiste

en finalizar cualquier subsistema de toma de datos, de tal manera que todos los

instrumentos dejarían de tomar medidas. Esto sería suficiente para dejar de utilizar de

forma segura los dataloguers 34972A. Aparte, se hace otra comprobación para detectar si

Page 32: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

32

está en uso la fuente de tensión N5752A. Si se detecta que este instrumento está siendo

utilizado, no sólo se detiene la medida de las consignas que están siendo entregadas, si no

que se desactiva por completo el sistema de entrega y a su vez estas retoman el valor 0.

Esto es de vital importancia puesto que indicar tan sólo que se deje de medir las consignas

no es impedimento para que estas sigan activas. Apagar el sistema de entrega de consignas

hace que al encender la fuente o volverla a utilizar tras trabajar con ella de forma remota,

no sólo no tenga ningún valor de consigna activo, si no que estas estén a cero. De no

proceder así, tras la desconexión, la fuente podría seguir entregando tensión y corriente,

lo que podría provocar daños a equipos o lesiones a personas puesto que no se tendría

ningún control sobre la fuente que no fuese presencial. El que las consignas retomen

siempre un valor absoluto de 0 impide que, si por error o desconocimiento se activara el

sistema de disparo de consignas, estas puedan provocar algún tipo de daño a los usuarios

o equipos ya conectados a ella subministrando los valores establecidos en su último uso.

Tras todas estas comprobaciones, se invoca a la función ‘cierre_Com’ de los

objetos de comunicación creados desconectándonos así de los instrumentos en uso. Es

importante mencionar que el instrumento de medida BK 891 no tiene ninguna instrucción

que detenga las medidas que esté realizando. Esto se debe a que el instrumento empieza

a realizar medidas nada más ser encendido, por lo que con desconectarnos de él nos sería

suficiente puesto que no supone ningún riesgo que este quede encendido sin que tengamos

control sobre él de forma remota.

3.9. Terminal de usuario

Se trata del último hilo de ejecución creado. Su funcionamiento consiste en

mantener de forma constante en la terminal de ejecución del programa la opción de cerrar

la comunicación y desconectarse de los instrumentos deteniendo las medidas y, si se

encuentra conectada, la opción de modificar las consignas de la fuente de tensión N5752A

en tiempo real.

La ejecución se lleva a cabo en los módulos Terminal.py y adquisicion_datos.py,

siendo este último necesario sólo para llevar a cabo las modificaciones de consigna de la

fuente. Tras crear y poner en marcha el hilo de ejecución mediante la función ‘Terminal’,

inicialmente se comprueba la cantidad de fuentes N5752A conectadas. Es importante

tener en cuenta que puede haber hasta dos fuentes de tensión en uso a la vez y que se debe

modificar la consigna de cada una de ella por separado y de forma totalmente

independiente. Dependiendo de la cantidad de fuentes conectadas se mostraran diferentes

opciones en la terminal. Si tan sólo hay una fuente conectada, se mostrará un mensaje

indicando que se debe pulsar la tecla numérica ‘1’ para pasar al menú de modificación de

consigna. En caso de haber dos fuentes conectadas, se indicará que se debe pulsar la tecla

‘1’ para modificar los valores de la primera fuente o ‘2’ para los de la segunda. Estos

valores se establecen según el orden de conexión con las fuentes. El usuario conocerá

dicho orden puesto que previamente habrá tenido que seleccionarlas de forma manual y

habrá tenido el identificador IP propio de cada fuente. Además, el usuario conocerá qué

consignas desea modificar puesto que también las habrá seleccionado previamente de

manera manual. Tanto en el caso de haber una o dos fuentes conectadas, como en el caso

de que no hubiera ninguna, en todo momento se mostrará la opción de desconectarse de

los equipos en uso presionando cualquier tecla. Debido a cómo funciona la terminal, tras

Page 33: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

33

presionar una tecla para introducir cualquier comando es necesario presionar la tecla

Enter. De tal manera, si se presiona directamente esta tecla nos ahorraríamos tener que

introducir cualquier otra previamente, ganando así en tiempo. Es importante destacar este

punto puesto que el cierre de comunicación y desconexión con los instrumentos pretende

ser tratado, como ya se mencionó con anterioridad, como una parada de emergencia para

evitar posibles daños o accidentes en caso de error al introducir datos no deseados en el

programa, o para detener la entrega de consigna de las fuentes de tensión.

Si lo que se desea es modificar alguna de las consignas de las fuentes de tensión,

desde la función ‘Terminal’ se llamará a la función ‘Mod_Consigna_N5752A’

indicándole qué fuente se ha seleccionado, la 1 o la 2. Este dato será de vital importancia

para que más adelante se modifiquen las consignas de la fuente correcta. Dentro de esta

función, se le pedirá al usuario que seleccione si desea modificar la tensión o la corriente

entregada, y una vez seleccionado, se invocará a la función ‘Consigna_N5752A’ del

módulo adquisición_datos. Hasta el momento actual, será posible desconectarse de los

instrumentos en uso. Una vez dentro de la última función mencionada, no se podrá forzar

esta desconexión hasta haber seleccionado una nueva consigna. El código a ejecutar por

esta función para modificar la consigna es idéntico al de la función ‘Keysight_N5752A’

del módulo Lista_Instrucciones ya explicado anteriormente. El único añadido es la

distinción entre qué fuente debe ser la que modifique sus valores. A su vez, esta distinción

es la que obliga a que exista la función ‘N5752A’ dentro del módulo adquisicion_datos

en lugar de volver a utilizar la función ‘Keysight_N5752A’ del módulo

Lista_Instrucciones, como sería lo más lógico. La creación de una nueva función para

modificar las consignas se debe a que, tras seleccionar los nuevos valores de consigna,

estos deben ser enviados al instrumento utilizando el objeto de comunicación pertinente,

dependiendo de si estamos modificando la primera o la segunda fuente en uso. Puesto que

este objeto se crea justo antes de empezar a adquirir los datos de las medidas en el módulo

adquisición_datos, las consignas deben ser modificadas en el mismo módulo para poder

utilizar los objetos de comunicación y transmitir los nuevos valores a entregar. De no

hacerlo así, habría que interrumpir la comunicación cerrándola y creando otro objeto

distinto cada vez que se pretenda modificar una consigna, lo que interrumpiría las

medidas que ya estuviesen en curso.

3.10. Representación gráfica de datos

Durante la toma de datos, estos podrán ser visualizados mediante un plot, gracias

al cual podremos tener una rápida visualización del progreso del experimento. Puesto

que este plot es meramente de apoyo, ya que los datos serán tratados con posterioridad

gracias al archivo .csv, se mostrará una interfaz gráfica lo suficientemente simple como

para no sobrecargar el procesador en caso de estar trabajando sobre la Raspberry.

Este proceso se lleva a cabo en el módulo PLOT, recibiendo la información

necesaria y la orden de inicio desde el programa principal. En este, previa a la creación y

arranque del thread, tras haber obtenido el nombre de los instrumentos y las distintas

instrucciones de medida a realizar, se invoca a la función ‘Label_name’. Esta función es

la encargada de recibir todos los datos mencionados, los cuales son necesarios para, una

vez mostrado el plot en pantalla, diferenciar los distintos datos representados indicando a

qué instrumento corresponde cada uno. Tras recibir los datos, se hace una llamada a la

Page 34: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

34

función ‘Create_Figure’. Esta función es de gran importancia puesto que en ella es dónde

se indicará según los datos obtenidos cuál será la configuración que tomará el plot.

Inicialmente se indica la creación de una única figura o ventana. Tras ello, según si hay

uno o dos instrumentos en uso, se indicará que en la misma ventana se deben mostrar uno

o dos plots diferentes. Una vez establecido el número de gráficos a mostrar, según se

tenga una o dos instrucciones, se indicará para cada plot cuantos tipos de datos se deben

mostrar, si uno o dos. En caso de que se deban mostrar dos datos distintos, estos deben

compartir el eje x de tiempo, lo cual también debe ser indicado en esta configuración

inicial. Tras recibir los datos y configurar el estilo de la ventana del plot, la ejecución es

devuelta al programa principal.

Tras el inicio de las medidas, y aún en el programa principal, se crea el thread que

ejecutará de forma constante la interfaz gráfica del plot. Tras ello, se comprueba que se

haya obtenido la ruta de guardado del archivo .csv. Esta ruta se obtiene en el programa

principal mediante la función ‘Leer_Pathname’ del módulo SAVE justo después de haber

creado el archivo. Tras la comprobación, se da paso al inicio del thread utilizando para

ello la función ‘Go_plot’ del módulo PLOT.

Desde la función ‘Go_plot’ se utilizan dos recursos propios de la librería pública

‘matplotlib’. Estos recursos consisten en las funciones ‘FuncAnimation’ y ‘show’. La

primera se encarga de ejecutar en bucle, según ciertos parámetros, una función

determinada. Esos parámetros consisten en indicar el nombre de la ventana creada, el

nombre de la función a ejecutar y el intervalo de tiempo de espera entre ejecuciones. Este

intervalo de espero es el tiempo de refresco del plot. Debemos saber que el modo de

funcionamiento del plot mediante este método consiste en redibujar punto a punto todos

los valores que se indiquen en la función seleccionada. Este redibujado se dará, en el caso

de nuestro programa, cada segundo. Es decir, la información mostrada en el plot se

actualizará cada segundo mientras se estén tomando medidas. La función ‘show’ tiene el

cometido de mantener la ventana del plot abierta hasta que el usuario la cierre o termine

la ejecución del código.

Como se ha dicho, la función ‘FuncAnimation’ propia de la librería ‘matplotlib’,

ejecuta cíclicamente una función determinada. Esta función recibe el nombre de

‘Plotting’. El cometido de esta nueva función no es más que el de indicar qué valores

deben ser dibujados en cada plot a cada ciclo de ejecución. Para ello, llama a la función

‘Plot_Data’ para recibir cada vez una lista de los distintos valores a dibujar. Estos valores

se van añadiendo cada vez al array de valores a ser redibujados, es decir, no se recibe un

valor nuevo cada vez, si no que se recibe un valor nuevo más todos los anteriores. Esto

es necesario por la forma que tiene de trabajar este método de dibujo gráfico. Dentro de

la función ‘Plot_Data’ se abre en modo lectura el fichero .csv, se obtienen todos sus datos

y se vuelve a cerrar para evitar posibles problemas en futuras lecturas. Tras ello, los datos

se separan por líneas y a continuación por comas simples, obteniendo así los datos de

cada una de las lecturas por separado. Tras ello, y como se explicó en el apartado 3.8.1

sobre la adquisición de datos, ya que estos van a ser mostrados en un gráfico, se debe

comprobar que ninguno de los datos leídos sea una cadena string que indique una lectura

errónea. Si no es así, los datos se añaden a distintos arrays según en qué eje vayan a ser

dibujados para ser devueltos a la función ‘Plotting’. Si alguno de los datos es un mensaje

de error, ya que no se puede graficar una cadena de strings, este mensaje es substituido

Page 35: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

35

por un valor predefinido para mostrar de manera gráfica que se ha dado un error en las

lecturas. Este valor predefinido se ha establecido en 0. Tras ello, se almacena de manera

normal en el array correspondiente para ser devuelto y graficado. Es destacable mencionar

que estas comprobaciones se han hecho mediante el método ya explicado ‘try-except’,

comprobando si el dato puede ser convertido o no en un tipo float para ser representado.

Finalmente, tras obtener todos los datos hasta el momento del archivo .csv, dentro

de la función ‘Plotting’, se procede a indicar qué datos deben ser graficados en el ciclo de

ejecución en el que se encuentre el programa. Para ello, mediante las distintas variables

de representación creadas en la función ‘Create_Figure’ durante la configuración del plot,

se indica para cada una de ellas los datos a dibujar, el color de la línea, las distintas

etiquetas de cada eje para la distinción de los distintos datos y la cantidad de puntos

temporales a dibujar. Estas indicaciones se dan mediante el uso de distintas funciones

propias de la librería ‘matplotlib’.

Cabe mencionar que el plot, puesto que se encuentra ejecutándose en un hilo

propio, se mantendrá abierto hasta que el usuario cierre la ventana de este aunque haya

finalizado la toma de medidas. Si el usuario cierra la ventana del plot durante la toma de

medidas, esta no podrá ser abierta de nuevo.

Figure 17. Imagen de la ventana de interfaz gráfica con 1 plot

Figure 18. Imagen de la ventana de interfaz gráfica con 2 plots

Page 36: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

36

3.11. Librerías utilizadas

Durante la creación del software se han utilizado diferentes librerías de carácter

público, como se ha mencionado en los puntos anteriores, para el lenguaje de

programación Pyhton 2.7. Estas librerías son de total necesidad para el correcto

funcionamiento del programa, es decir, deben estar instaladas en el equipo dónde el

software vaya a ser utilizado. En caso de ser necesaria una modificación del código, es

importante tener en cuenta que algunas de estas librerías pueden ser substituidas por otras,

como en el caso de las librería para la creación del plot, pero eso conllevaría la creación

de un código completamente nuevo. A su vez, hay librerías que no pueden ser substituidas

por ninguna otra, como podrían ser las librerías para el uso del socket de comunicación o

la librería de funcionalidades sobre el sistema operativo.

A continuación se muestra una lista de las distintas librerías utilizadas durante el

desarrollo junto con una breve explicación de su motivo de uso.

socket

Librería necesaria para la comunicación remota vía internet del equipo con los

diferentes instrumentos a utilizar.

time

Librería para gestión y conversión de tiempo. Utilizada para crear esperas en los

distintos hilos de ejecución y determinar el tiempo mínimo entre las distintas

lecturas de cada instrumento.

numpy

Librería básica para computación científica. Compuesta, entre otros elementos, de

objetos para dimensionar arrays de N dimensiones, herramientas para algebra

linear, transformaciones de Fourier, e implementación de la capacidad de uso de

números aleatorios. Pese a que no se utiliza de forma directa, es necesaria para

dar apoyo a otras librerías como la de dibujado del plot. Se ha utilizado la versión

para Python 2.7 +32.

matplotlib

Librería que permite la creación, uso y parametrización de diferentes herramientas

gráficas para la representación de datos. Utilizada para crear y modificar el plot

en el que se muestran los datos tomados en tiempo real.

wx

Librería que proporciona diferentes herramientas gráficas para el uso de interfaces

nativas en Windows, Linux y Mac. Utilizada para crear la ventana de guardado

del archivo .csv mediante interfaz gráfica.

csv

Librería que da soporte a la creación y manipulación de archivos tipo ‘.csv’

(Comma Separated Values). Utilizada para la creación del archivo .csv.

os

Librería que permite utilizar funcionalidades del sistema operativo sobre el que se

Page 37: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

37

ejecuta el programa. Utilizada para obtener la ruta de ejecución del programa para

la creación del archivo de seguridad en caso de ser necesario.

datetime

Librería que proporciona herramientas para la obtención y manipulación de datos

referentes a fechas y horas. Utilizada para la obtención de la hora de cada lectura

además de la hora de creación del archivo de seguridad en caso de ser necesario.

Page 38: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

38

4. Manual de usuario

Este apartado pretende ser una guía para el usuario del uso del software sin entrar

en detalles técnicos sobre la programación de este. En esta guía se mostrará cómo crear

el archivo ejecutable del código, el funcionamiento paso a paso del programa y cómo

obtener una correcta interpretación de los datos obtenidos mediante el archivo .csv que

generará el programa.

4.1 Creación del archivo ejecutable

Para poder ejecutar y utilizar el software, es necesario obtener un fichero

ejecutable. Para ello, en primer lugar se necesitan todos los módulos o archivos con la

extensión .py que contienen el código fuente del programa. En segundo lugar, es necesaria

la obtención de un software que permita convertir los archivos .py en archivos ejecutables

tipo .exe. A continuación se describe el método a seguir para la creación de dicho archivo

ejecutable mediante el uso del software externo PyInstaller.

Es importante mencionar que al tratarse de código escrito en Python, este puede

ser ejecutado directamente mediante el archivo .py que inicialice el programa, en nuestro

caso el archivo ‘__init__.py’, evitando así el proceso de creación de un archivo .exe. Pese

a ello, se recomiende encarecidamente la creación del archivo ejecutable para evitar

modificaciones o vulnerabilidades en el código fuente ya que este es encriptado y no

permite modificaciones directas sobre él.

PyInstaller

Se trata de un programa orientado específicamente a empaquetar archivos con

extensión .py, convirtiéndolos en ficheros ejecutables estándar tipo .exe para poder ser

ejecutados sobre cualquier sistema operativo. Como ventaja principal sobre otras

herramientas, podemos destacar que permite trabajar tanto con Python 2.7 como con

versiones superiores como la 3.3 y 3.6, creando ejecutables de menor tamaño que otras

herramientas con la misma funcionalidad.

En primer lugar, debemos descargar el programa en nuestro equipo a través de la

web2 oficial del software. El archivo a descargar lleva el siguiente nombre: ‘PyInstaller

3.3.1 (tar.gz)’. Tras haberlo descargado, debemos descomprimir el archivo, utilizando

cualquier herramienta que tengamos en nuestro equipo para ello, en la ruta que el usuario

quiera. Seguidamente debemos ejecutar la consola del sistema también conocida como

CMD. Desde la consola, debemos dirigirnos a la carpeta donde se haya descomprimido

el archivo descargado. Suponiendo que estemos realizando este proceso en la Raspberry

PI, deberíamos escribir algo parecido a lo siguiente: ‘cd /home/pi/Downloads/PyInstaller-

3.3.1’. Mediante la instrucción ‘cd /’, se accede a la carpeta o ruta que se indique a

continuación, siendo esta ruta en la que se ha instalado el programa descargado. Si se está

trabajando sobre Windows, se debe seguir exactamente el mismo procedimiento mediante

la instrucción ‘cd /‘, modificando únicamente la ruta en la que se ha descomprimido el

archivo. Una vez dentro de este directorio, y utilizando todavía la consola del sistema,

debemos ejecutar la siguiente instrucción: ‘sudo python setup.py install’. Tras ello se

2 http://www.pyinstaller.org/downloads.html

Page 39: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

39

instalará el software, mostrando un mensaje en la misma terminal indicando que todo ha

ido correctamente.

Tras la correcta instalación podemos pasar a crear el archivo ejecutable de nuestro

software. Para ello, y mediante el uso de la terminal del sistema ya sea en Windows o

sobre la Raspberry, debemos ir al directorio donde se encuentren los archivos de

extensión .py que contienen el código fuete. De igual modo que durante la instalación del

programa, debemos utilizar la instrucción ‘cd /’ añadiendo a continuación el directorio

donde se encuentren esos archivos. Una vez dentro del directorio, crearemos el fichero

ejecutable utilizando la instrucción ‘pyinstaller __init__.py’. Mediante esta instrucción,

ejecutamos el programa instalado indicándole que archivo debe convertir. Este archivo

debe ser el módulo que lleva por nombre ‘__init__’ debido a que es el módulo principal

que permite que el programa empiece a ejecutarse, además de importar todos los demás

módulos que forman el conjunto del software creado.

Una vez realizado los pasos anteriores, en el mismo directorio donde hemos

creado el archivo ejecutable, aparecerán dos carpetas distintas. El archivo ejecutable se

encontrará en la carpeta de nombre ‘dist’, bajo el nombre ‘__init__.exe’.

4.2 Uso del software

A continuación se muestra un ejemplo de uso del programa mediante el uso de

dos equipos de manera simultánea, la fuente de tensión N5752A y el BK 891.

1. Detección de los instrumentos en uso.

Tras iniciar el programa, este intentará conexionar automáticamente con los

instrumentos del inventario, los cuales deben estar en el formato que se especificó

en el apartado 3.2 dentro de un fichero.txt. Durante este proceso, se indicará con

qué instrumentos se ha podido establecer comunicación y finalmente aparecerán

listados en orden para que el usuario pueda escoger con cuales trabajar.

Figure 19. Pantalla de ejecución. Intento de conexión remota con los distintos instrumentos

2. Selección de instrumentos a utilizar.

Tras obtener la lista de instrumentos conectados, el usuario deberá elegir hasta un

máximo de dos de ellos para trabajar. Esta selección se llevará a cabo mediante la

introducción en la terminal del número asignado a cada instrumento. En caso de

sólo querer utilizar uno de los instrumentos listados, se debe presionar la tecla

Page 40: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

40

‘Enter’ cuando el programa pida el número del segundo instrumento. En este caso,

se mostrará un mensaje indicando que tan sólo hay un instrumento en uso. Si no

se desea utilizar ninguno, el usuario debe introducir el valor 0, lo que dará fin a la

ejecución del programa. En caso de haber sólo un instrumento conectado, si se

selecciona para su uso, no se pedirá seleccionar un segundo instrumento.

Figure 20. Pantalla de ejecución. Selección de instrumentos. Sólo BK 891 en uso.

3. Selección de instrucciones y consignas

Una vez seleccionados los instrumentos, se pasará a la introducción de las

consignas o selección de instrucciones, según instrumento. En caso de haber

seleccionado la fuente de tensión N5752A, se pedirá por pantalla que se

introduzca una consigna para el límite de corriente y a continuación para la tensión

de trabajo. La consigna no será disparada hasta el inicio de la toma de datos. A su

vez, mientras se eligen las consignas, se mostrarán los valores máximos

permitidos. En caso de utilizar cualquier otro instrumento, el programa pedirá que

se seleccionen los tipos de medida a realizar. En el caso del BK 891, por ejemplo,

se seleccionará el tipo de medida principal, según el número asignado a cada una,

y a continuación aparecerán las medidas secundarias posibles asociadas a la

principal.

Figure 21. Pantalla de ejecución. Introducción de consignas para fuente de tensión N5752A.

Page 41: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

41

Figure 22. Pantalla de ejecución. Selección de parámetro principal de medida con BK 891

Figure 23. Pantalla de ejecución. Selección de parámetro secundario de medida según parámetro principal con BK 891

En caso de haber seleccionado cualquier dataloguer modelo 34972A, inicialmente

se pedirá cuántos tipos de medida se desean realizar, pudiendo elegir hasta dos

tipos de medidas distintas. Tras ello, y según la cantidad elegida, se procederá a

seleccionar el tipo de medida a realizar del mismo modo que en los casos

anteriores. Puesto que los dataloguers toman los datos mediante el uso de canales,

una vez indicados los tipos de medias, se pedirá que se seleccionen los canales en

los que realizarlas. Si se selecciona una medida a 4 hilos, el programa emitirá un

mensaje indicando qué canales deben ser cableados según la selección del usuario.

Figure 24.Pantalla de ejecución. Selección de cantidad de tipos de medida a realizar. Keysight 34972A.

Figure 25. Pantalla de ejecución. Selección de medidas con Keysight 34972A.

Page 42: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

42

Figure 26. Pantalla de ejecución. Selección de canales para tipo de medida. Keysight 34972A.

4. Selección de la ruta de guardado del archivo .csv

Una vez se ha terminado con la selección de tipos de medida o con la introducción

de consignas, se mostrará en pantalla una ventana para que el usuario seleccione

la ruta de guardado del archivo .csv que contendrá los datos tomados. La

apariencia de esta ventana puede variar dependiendo del sistema operativo en que

se ejecute el programa, pero su contenido será el mismo en todos.

Figure 27. Ventana de guardado de archivo .csv

5. Representación gráfica de los datos

Tras haber realizado los pasos anteriores, aparecerá una nueva ventana en la que,

una vez se dé inicio a la toma de medidas de forma automática, se mostrarán en

tiempo real los datos tomados durante todo el experimento. Esta ventana

permanecerá abierta hasta que el usuario la cierre de manera manual. El hecho de

finalizar las medidas y desconectarse de los instrumentos no afecta al muestreo de

los datos, permitiendo así realizar capturas de pantalla o guardar la imagen

obtenida si así lo desea el usuario. Los datos de la representación gráfica se

actualizarán automáticamente cada dos segundos. No se podrá volver a abrir la

ventana en caso de cerrarla durante la toma de datos.

Page 43: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

43

Figure 28. Ventana con la representación gráfica en tiempo real de los datos tomados

6. Terminal de espera

Tras seleccionar la ruta de guardado y mostrarse la ventana del plot, se hará el

disparo de las consignas de la fuente de tensión si es necesario y se dará inicio a

la toma de medidas. Tras ello, en la terminal de ejecución se mostrará un mensaje

para finalizar la toma de datos en cualquier momento. Esto conllevará la

desconexión con los instrumentos y la finalización del programa. Si se encuentra

conectada una fuente de tensión, a la vez que la opción de finalizar las medidas,

se dará también la opción de modificar la consigna, tanto de tensión como de

corriente, de las fuentes conectadas. Durante la modificación de las consignas no

se podrá detener el programa hasta haber finalizado la introducción de estas.

Figure 29. Pantalla de ejecución. Finalización de las medidas y desconexión con los instrumentos

Page 44: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

44

Figure 30. Pantalla de ejecución. Modificación de las consignas de tensión y corriente durante las medidas

4.3 Interpretación del archivo .csv

Una vez finalizada la ejecución del programa, tendremos acceso al archivo de

extensión .csv con los datos obtenidos durante el experimento realizado. El archivo se

encontrará en la ruta de guardado que el usuario haya especificado, o en la misma carpeta

desde donde se haya ejecutado el programa en caso de no haber elegido una ruta.

Tras abrir el archivo, podremos observar que los datos se encuentran separados

por comas y estarán encasillados en distintas celdas de forma vertical (Fig. 19). Para

organizar los datos en distintas celdas, separándolos en filas y columnas, para poder

tratarlos más tarde, debemos seguir el siguiente procedimiento.

1. Seleccionar la columna ‘A’ en su totalidad haciendo clik sobre el nombre de la

columna.

2. Seleccionar la pestaña de ‘Datos’

3. Seleccionar la opción ‘Texto en columnas’

4. Marcar la opción ‘Delimitados’ y hacer clik en ‘siguiente’

5. Dentro del cuadro de ‘Separadores’, seleccionar la opción ‘Coma’

6. Hacer clik en ‘Finalizar

Figure 31. Datos con el formato base, separados por coma simple.

Page 45: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

45

Figure 32.Opcion 'Delimitados' para dar formato a los datos

Figure 33. Opción para la separación de los datos

Page 46: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

46

Tras seguir los pasos indicados, el resultado obtenido es el que se muestra en la

Figura 22, donde los datos ya han sido separados en sus respectivas celdas y columnas.

Este procedimiento es el mismo independientemente de la cantidad de instrumentos o

medidas almacenadas en el fichero.

Figure 34. Formato de datos modificado para su correcto tratado

Tras la modificación de la estructura de los datos, podemos apreciar que estos aún

no son del todo correctos para su tratado debido al formato de las horas de la primera

columna. Para corregir este error de formato, seguiremos el procedimiento siguiente.

1. Seleccionar todo el contenido de la primera columna haciendo clik sobre la letra

‘A’ que la representa.

2. Ir a la pestaña ‘Inicio’

3. En el desplegable del apartado ‘Número’, modificar ‘General’ por ‘Hora’

Figure 35. Menú principal EXCEL para modificación de formato horario

Page 47: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

47

Figure 36. Formato final corregido de los datos obtenidos

Page 48: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

48

5. Resultados

En este apartado se comentarán los resultados obtenidos durante la realización de

dos test del programa final, obteniendo los datos de forma remota mediante el uso las

parejas de instrumentos Keysight 34972A y BK Precision 891 y Bk Precision y Agilent

N5752A.

Los datos obtenidos se muestran en las tablas 1 y 2 de los anexos.

En ambos casos se han realizado medidas durante varios minutos para demostrar

que el tiempo de duración del experimento no supone un hándicap para la ejecución del

programa. La obtención de los datos demuestra que no se han producido errores de

ejecución durante el almacenaje de estos ni durante la creación del archivo .csv. A su vez,

se ha podido comprobar que las instrucciones entregadas a los distintos instrumentos se

envían y se ejecutan de forma correcta. Durante el uso de la fuente de tensión se ha

comprobado que las consignas pueden ser modificadas de forma tanto remota como

manual, utilizando el panel frontal del instrumento, sin que esto provoque errores de

ejecución o errores en la toma de medidas de consigna. A su vez, se ha comprobado el

correcto funcionamiento del paro de emergencia y la desactivación del sistema de entrega

de consigna.

Page 49: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

49

6. Mejoras

Como posibles mejoras a implementar en futuras revisiones del software, podrían

considerarse las listadas a continuación.

Añadir más variedad de instrumentos para ser utilizados de forma remota.

Añadir la posibilidad de conexión con más de dos instrumentos a la vez.

Añadir la posibilidad de realizar más de dos medidas simultáneas con los

instrumentos que así lo permitan.

Comprobación y aviso de la potencia entregada por la fuente de tensión N5752A.

Confirmación de las consignas de tensión y corriente entregadas por la fuente de

tensión N5752A.

Creación de una interfaz gráfica para substituir la consola de comandos del

sistema (CMD)

Creación de un menú de ajustes de valores internos como el tiempo entre lecturas,

el tiempo de redibujado del plot o el valor predeterminado para la representación

de errores en el plot.

Permitir que se pueda volver a abrir el plot durante las lecturas si este se cierra.

Page 50: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

50

7. Conclusiones

Nos encontramos ante un software creado desde cero bajo unas condiciones

previas establecidas por el demandante. Esto ha supuesto para el proyectista el

aprendizaje de un nuevo lenguaje de programación y del uso de librerías públicas y

software libre desconocido para él hasta la realización del proyecto. Además, la

realización de este, ha obligado a realizar un estudio y profundización de herramientas de

programación utilizadas con anterioridad, lo que ha supuesto un aumento en el

conocimiento de estas, tanto a nivel teórico como práctico.

A nivel de hardware, el proyecto está basado en especificaciones creadas a partir

de proyectos anteriores. Esto ha obligado a realizar un estudio de dichos proyectos

además del estudio y familiarización pertinente con el hardware utilizado, también

desconocido para el proyectista. Además, ha sido necesario el estudio minucioso de todos

los instrumentos que debían ser integrados en el proyecto, tanto a nivel de software como

de hardware.

Durante la realización del proyecto se han incorporado mejoras que no habían sido

demandadas en un principio debido a la necesidad de estas durante el desarrollo y

creación del software. A su vez, se han añadido medidas de protección tanto para los datos

obtenidos en futuros experimentos, como para los usuarios que los realicen y deban

manipular equipos que puedan ocasionar daños o lesiones.

Finalmente, como resultado, se ha obtenido un programa que cumple con todas

las especificaciones requeridas al inicio del proyecto. Se han añadido mejoras a estas

especificaciones y se han implementado medidas de seguridad para evitar daños en la

medida de lo posible. Se ha obtenido un programa totalmente funcional que ha pasado

por diferentes etapas, tanto de creación como de corrección de errores. Estos errores han

sido corregidos mediante ensayos con cada uno de los instrumentos, probando la gran

mayoría de los casos posibles que podían llevar a error durante la ejecución. Además, el

software ha sido programado para que sea lo más modular posible para futuras revisiones,

y se ha tenido en cuenta que los usuarios no tienen por qué tener conocimientos previos

sobre programación o electrónica para poder utilizarlo sin ningún tipo de inconveniente.

Page 51: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

51

8. Presupuesto

Artículo Coste

Unitario Unidades Total

Raspberry Pi 3 Modelo B 29,5 € 1 29.50 €

Conectores, carcasa, disipador y ventilador 15 € 1 15.00 €

Power Supply Agilent N5752A LXI 2830,19 € 1 2830.19 €

Bench LCR meter BK Precision 891 1.524,09 € 1 1524.09 €

Dataloguer Keysight 34972A LXI 2041,27 € 1 2041.27 €

Programación del software 25 € 480 12000.00 € Total sin I.V.A 14567.64 € I.V.A 21.00% 3872.41 € TOTAL 18440.05 €

Page 52: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

52

9. Pliego de condiciones

Este apartado no es de aplicación ya que se trata de un proyecto de investigación

para la Universidad

Page 53: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

53

10. Referencias Bibliográficas

[1] Documentación oficial de Raspberry Pi. Fundación Raspberry Pi. Página web

gratuita, consultada el día 16/10/2017.

https://www.raspberrypi.org/documentation/

[2] Guía interactiva de los pines I/O GPIO de Raspberry Pi. Página web gratuita,

consultada el día 17/10/2017. https://pinout.xyz/

[3] Curso web interactivo de programación en Python. Página web gratuita y de pago,

consultada el día 23/10/2017. https://www.codecademy.com/learn/learn-python

[4] Guía de usuario básica para Python. Página web gratuita, consultada el día

06/11/2017. https://wiki.python.org/moin/BeginnersGuide/Programmers

[5] Referencia de la biblioteca de Python. Página web gratuita, consultada el día

20/11/2017 http://pyspanishdoc.sourceforge.net/lib/lib.html

[6] Sweigart, A. (2015). Automate the Boring Stuff with Python. 1st ed. [ebook] San

Francisco: William Pollock., consultada el día 22/11/2017. Available at:

http://pyspanishdoc.sourceforge.net/lib/lib.html

[7] Documentación oficial de la versión 2.7 de Python. Página web gratuita,

consultada el día 22/11/2017. https://docs.python.org/2/contents.html

[8] Documentación oficial Python 2.7 PEP-8. Guía de estilo de programación.

Página web gratuita, consultada el día 22/11/2017.

https://www.python.org/dev/peps/pep-0008/#code-lay-out

[9] Tutorial sobre uso de métodos en Python. Página web gratuita, consultada el día

05/02/2018. https://www.tutorialspoint.com/python/index.htm

[10] Documentación oficial Python 2.7. Errores y excepciones. Página web gratuita,

consultada el día 15/02/2018. http://docs.python.org.ar/tutorial/3/errors.html

[11] Web oficial de Keysight. Foro de consulta sobre puerto de conexión Ethernet en

instrumentos de la marca Keysight y Agilent. Página web gratuita, consultada el

día 20/10/2017. https://community.keysight.com/thread/18857

[12] Foro de desarrollo en Python. Creación de comunicación remota vía socket.

Página web gratuita, consultada el día 22/10/2017.

http://developeando.net/sockets-python/

[13] Foro de desarrollo en Python. Creación de comunicación remota vía socket.

Página web gratuita, consultada el día 22/10/2017.

http://www.pythondiario.com/2015/01/simple-programa-clienteservidor-

socket.html

[14] Foro de desarrollo en Python. Creación de comunicación remota vía socket.

Página web gratuita, consultada el día 22/10/2017.

http://mundogeek.net/archivos/2008/04/12/sockets-en-python/

[15] Foro de desarrollo en Python. Uso de ficheros de texto en Python. Página web

gratuita, consultada el día 16/02/2018.

http://pitando.australiando.es/2015/10/01/ficheros-de-texto-en-python/

[16] Web oficial de PyInstaller. Documentación sobre el uso del software PyInstaller.

Página web gratuita, consultada el día 03/05/2018. http://www.pyinstaller.org/

[17] Documentación oficial de Python. Librería se lectura y escritura de ficheros

CSV. Página web gratuita, consultada el día 13/02/2018.

https://docs.python.org/3.4/library/csv.html

Page 54: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

54

[18] Foro de desarrollo y programación. Página web gratuita, consultada el día

14/02/2018. https://es.stackoverflow.com/

[19] Web oficial de la librería Matplotlib de Python. Guía de uso. Consultada el día

02/04/2018.https://matplotlib.org/users/index.html

[20] Web oficial de Keysight. Manual de instrucciones SCPI para programación de

instrumentos. Página web gratuita, consultada el día 11/04/2018.

http://rfmw.em.keysight.com/bihelpfiles/Truevolt/WebHelp/US/Content/__I_SC

PI/MEASure_Subsystem.htm#RES-FRES

[21] Foro de desarrollo en Python. Documentación oficial de la librería Wx. Página

web gratuita, consultada el día 16/12/2017.

https://newville.github.io/wxmplot/plotpanel.html

[22] Web oficial de la librería Matplotlib de Python. Ejemplos de uso. Página web

gratuita, consultada el día 12/04/2018.

https://matplotlib.org/examples/index.html

[23] Web oficial de la librería Matplotlib de Python. Documentación oficial. Página

web gratuita, consultada el día 12/04/2018.

https://matplotlib.org/api/pyplot_summary.html

[24] Web oficial de la librería Wx de Python. Documentación oficial. Página web

gratuita, consultada el día 15/12/2017.

https://wiki.wxpython.org/Getting%20Started

[25] Linda, Y. (2015-17) BK Precission. Model: 981. 300 kHz Bench LCR Metre.

User’s Manual. Available at:

https://bkpmedia.s3.amazonaws.com/downloads/manuals/en-us/891_manual.pdf

[26] Keysight Technologies (2009-2014) Keysight 34970A/34972A Data Acquisition

/Switch Unit. User’s Guide. 4th edition. Available at:

https://literature.cdn.keysight.com/litweb/pdf/34972-90001.pdf

[27] Agilent Technologies, Inc. (1997-2003). Keysight 34970A/34972A Data

Acquisition /Switch Unit. Quick Reference Guide. SCPI Command Summary.

March 2003. Available at: http://instructor.physics.lsa.umich.edu/adv-

labs/Tools_Resources/HP%2034970A%20quick%20reference%20guide.pdf

[28] Keysight Technologies (2004-2015) Keysight Series N5700 System DC Power

Supply. User’s Guide. 8th Edition. Available at:

http://literature.cdn.keysight.com/litweb/pdf/5969-2917.pdf

Page 55: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

55

11. Anexos

11.1 Tablas de datos

Keysight 34972A B&K Precision 891

Hora Lectura

2-Wire Resistance (Ω) CS (nF) R (kohm)

16:56:15 9.93E+11

10.19 9.918

16:56:17 9.93E+11

10.19 9.918

16:56:19 9.93E+11

10.19 9.918

16:56:20 9.93E+11

10.19 9.918

16:56:22 9.93E+11

10.19 9.918

16:56:23 9.93E+11

10.19 9.919

16:56:24 9.93E+11

10.19 9.918

16:56:26 9.93E+11

10.19 9.918

16:56:28 9.93E+11

10.19 9.918

16:56:29 9.93E+11

10.19 9.918

16:56:31 9.93E+11

10.19 9.918

16:56:32 9.93E+11

10.19 9.917

16:56:34 9.93E+11

10.19 9.917

16:56:36 9.93E+11

10.19 9.918

16:56:37 9.93E+11

10.19 9.919

16:56:38 9.93E+11

10.19 9.918

16:56:40 9.93E+11

10.19 9.918

16:56:42 9.93E+11

10.19 9.919

16:56:43 9.93E+11

10.19 9.918

16:56:44 9.93E+11

10.19 9.918

16:56:46 9.93E+11

10.19 9.918

16:56:48 9.93E+11

10.19 9.918

16:56:49 9.93E+11

10.19 9.918

16:56:51 9.93E+11

10.19 9.918

16:56:52 9.93E+11

10.19 9.918

16:56:54 9.93E+11

10.19 9.918

16:56:55 9.93E+11

10.19 9.918

16:56:57 9.93E+11

10.19 9.918

16:56:58 9.93E+11

10.19 9.918

16:57:00 9.93E+11

10.19 9.918

16:57:01 9.93E+11

10.19 9.918

16:57:03 9.93E+11

10.19 9.918

16:57:04 9.93E+11

10.19 9.918

16:57:06 9.93E+11

10.19 9.918

16:57:07 9.93E+11

10.19 9.917

16:57:09 9.93E+11

10.19 9.917

16:57:10 9.93E+11

10.19 9.918

16:57:12 9.93E+11

10.19 9.918

Page 56: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

56

16:57:13 9.93E+11

10.19 9.917

16:57:15 9.93E+11

10.19 9.918

16:57:16 9.93E+11

10.19 9.918

16:57:18 9.93E+11

10.19 9.918

16:57:19 9.93E+11

10.19 9.917

16:57:21 9.93E+11

10.19 9.917

16:57:22 9.93E+11

10.19 9.917

16:57:24 9.93E+11

10.19 9.917

16:57:25 9.93E+11

10.19 9.917

16:57:27 9.93E+11

10.19 9.917

16:57:28 9.93E+11

10.19 9.917

16:57:30 9.93E+11

10.19 9.917

16:57:31 9.93E+11

10.19 9.917

16:57:33 9.93E+11

10.19 9.918

16:57:34 9.93E+11

10.19 9.918

16:57:36 9.93E+11

10.19 9.916

16:57:37 9.93E+11

10.19 9.918

16:57:39 9.93E+11

10.19 9.917

16:57:40 9.93E+11

10.19 9.918

16:57:42 9.93E+11

10.19 9.917

16:57:43 9.93E+11

10.19 9.917

16:57:45 9.93E+11

10.19 9.917

16:57:46 9.93E+11

10.19 9.917

16:57:48 9.93E+11

10.19 9.917

16:57:49 9.93E+11

10.19 9.918

16:57:51 9.93E+11

10.19 9.917

16:57:52 9.93E+11

10.19 9.917

16:57:54 9.93E+11

10.19 9.917

16:57:55 9.93E+11

10.19 9.917

16:57:57 9.93E+11

10.19 9.917

16:57:59 9.93E+11

10.19 9.917

16:58:00 9.93E+11

10.19 9.917

16:58:02 9.93E+11

10.19 9.917

16:58:03 9.93E+11

10.19 9.917

16:58:05 9.93E+11

10.19 9.917

16:58:06 9.93E+11

10.19 9.917

16:58:08 9.93E+11

10.19 9.917

16:58:09 9.93E+11

10.19 9.916

16:58:11 9.93E+11

10.19 9.917

16:58:12 9.93E+11

10.19 9.917

16:58:14 9.93E+11

10.19 9.917

16:58:15 9.93E+11

10.19 9.917

16:58:17 9.93E+11

10.19 9.917

16:58:18 9.93E+11

10.19 9.917

Page 57: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

57

16:58:20 9.93E+11

10.19 9.916

16:58:21 9.93E+11

10.19 9.917

16:58:23 9.93E+11

10.19 9.916

16:58:24 9.93E+11

10.19 9.917

16:58:26 9.93E+11

10.19 9.917

16:58:27 9.93E+11

10.19 9.917

16:58:29 9.93E+11

10.19 9.916

16:58:30 9.93E+11

10.19 9.917

16:58:32 9.93E+11

10.19 9.917

16:58:33 9.93E+11

10.19 9.917

16:58:35 9.93E+11

10.19 9.917

16:58:36 9.93E+11

10.19 9.917

16:58:38 9.93E+11

10.19 9.917

16:58:39 9.93E+11

10.19 9.916

16:58:41 9.93E+11

10.19 9.917

16:58:42 9.93E+11

10.19 9.917

16:58:44 9.93E+11

10.19 9.916

16:58:45 9.93E+11

10.19 9.916

16:58:47 9.93E+11

10.19 9.917

16:58:48 9.93E+11

10.19 9.917

16:58:50 9.93E+11

10.19 9.916

16:58:51 9.93E+11

10.19 9.916

16:58:53 9.93E+11

10.19 9.917

16:58:54 9.93E+11

10.19 9.917

16:58:56 9.93E+11

10.19 9.917

16:58:57 9.93E+11

10.19 9.917

16:58:59 9.93E+11

10.19 9.917

16:59:00 9.93E+11

10.19 9.916

16:59:02 9.93E+11

10.19 9.916

16:59:03 9.93E+11

10.19 9.916

16:59:05 9.93E+11

10.19 9.917

16:59:06 9.93E+11

10.19 9.917

16:59:08 9.93E+11

10.19 9.917

16:59:09 9.93E+11

10.19 9.916

16:59:11 9.93E+11

10.19 9.917

16:59:12 9.93E+11

10.19 9.916

16:59:14 9.93E+11

10.19 9.917

16:59:15 9.93E+11

10.19 9.916

16:59:17 9.93E+11

10.19 9.917

16:59:18 9.93E+11

10.19 9.917

16:59:20 9.93E+11

10.19 9.916

16:59:21 9.93E+11

10.19 9.917

16:59:23 9.93E+11

10.19 9.916

16:59:24 9.93E+11

10.19 9.917

Page 58: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

58

16:59:26 9.93E+11

10.19 9.916

16:59:27 9.93E+11

10.19 9.917

16:59:29 9.93E+11

10.19 9.916

16:59:30 9.93E+11

10.19 9.916

16:59:32 9.93E+11

10.19 9.917

16:59:33 9.93E+11

10.19 9.917

16:59:35 9.93E+11

10.19 9.917

16:59:36 9.93E+11

10.19 9.916

16:59:38 9.93E+11

10.19 9.916

16:59:39 9.93E+11

10.19 9.916

16:59:41 9.93E+11

10.19 9.916

16:59:42 9.93E+11

10.19 9.916

16:59:44 9.93E+11

10.19 9.916

16:59:45 9.93E+11

10.19 9.916

16:59:47 9.93E+11

10.19 9.916

16:59:48 9.93E+11

10.19 9.916

16:59:50 9.93E+11

10.19 9.917

16:59:51 9.93E+11

10.19 9.916

16:59:53 9.93E+11

10.19 9.916

16:59:54 9.93E+11

10.19 9.916

16:59:56 9.93E+11

10.19 9.915

16:59:57 9.93E+11

10.19 9.917

Table 1.Datos experimentales tomados con Keysight 34972A y BK Precision 891

Agilent Technologies N5752A

B&K Precision 891

Hora Lectura

Voltage (V)

Current (A)

CS (nF) R (kohm)

17:07:47 5.05E+06 2.80E+03 10.27 4.064

17:07:49 3.42E+06 2.80E+03 10.27 4.070

17:07:51 3.42E+06 2.80E+03 10.27 4.083

17:07:53 3.43E+06 2.80E+03 10.27 4.061

17:07:54 3.43E+06 2.80E+03 10.27 4.083

17:07:56 3.43E+06 2.80E+03 10.27 4.077

17:07:58 3.43E+06 2.80E+03 10.27 4.083

17:07:59 3.43E+06 2.80E+03 10.27 4.066

17:08:01 3.43E+06 2.80E+03 10.27 4.072

17:08:03 3.43E+06 2.80E+03 10.27 4.092

17:08:05 3.43E+06 2.80E+03 10.27 4.094

17:08:06 3.42E+06 2.80E+03 10.27 4.068

17:08:08 3.43E+06 2.80E+03 10.27 4.072

17:08:10 3.43E+06 2.80E+03 10.27 4.068

17:08:11 3.43E+06 2.80E+03 10.27 4.081

Page 59: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

59

17:08:13 3.43E+06 2.80E+03 10.27 4.094

17:08:14 3.43E+06 2.80E+03 10.27 4.088

17:08:16 3.44E+06 2.80E+03 10.27 4.099

17:08:18 3.43E+06 2.80E+03 10.27 4.064

17:08:19 3.43E+06 2.80E+03 10.27 4.097

17:08:21 3.42E+06 2.80E+03 10.27 4.085

17:08:22 3.42E+06 2.80E+03 10.27 4.085

17:08:24 3.42E+06 2.80E+03 10.27 4.094

17:08:26 3.41E+06 2.80E+03 10.27 4.092

17:08:28 4.50E+06 3.90E+03 10.27 4.099

17:08:29 4.51E+06 4.00E+03 10.27 4.094

17:08:31 4.50E+06 4.00E+03 10.27 4.094

17:08:33 4.50E+06 4.00E+03 10.27 4.109

17:08:34 8.65E+06 8.30E+03 10.27 4.105

17:08:36 8.65E+06 8.30E+03 10.27 4.099

17:08:38 8.65E+06 8.30E+03 10.27 4.094

17:08:39 4.50E+06 4.00E+03 10.27 4.096

17:08:41 4.49E+06 4.00E+03 10.27 4.105

17:08:43 4.49E+06 4.00E+03 10.27 4.107

17:08:44 4.49E+06 4.00E+03 10.27 4.096

17:08:46 4.48E+06 4.00E+03 10.27 4.094

17:08:48 4.49E+06 4.00E+03 10.27 4.094

17:08:49 8.64E+06 8.30E+03 10.27 4.103

17:08:51 8.64E+06 8.30E+03 10.27 4.096

17:08:53 8.64E+06 8.30E+03 10.27 4.070

17:08:54 8.64E+06 8.30E+03 10.27 4.101

17:08:56 8.64E+06 8.30E+03 10.27 4.099

17:08:58 1.28E+07 1.25E+04 10.27 4.114

17:08:59 1.28E+07 1.25E+04 10.27 4.114

17:09:01 1.29E+07 1.68E+04 10.27 4.108

17:09:03 1.70E+07 2.21E+04 10.27 4.097

17:09:04 2.11E+07 2.11E+04 10.27 4.094

17:09:06 2.11E+07 2.11E+04 10.27 4.099

17:09:07 2.11E+07 2.11E+04 10.27 4.101

17:09:09 2.11E+07 2.12E+04 10.27 4.097

17:09:11 2.11E+07 2.12E+04 10.27 4.103

17:09:12 2.11E+07 2.12E+04 10.27 4.097

17:09:14 2.09E+07 2.09E+04 10.27 4.105

17:09:16 2.09E+07 2.09E+04 10.27 4.114

17:09:17 2.09E+07 2.09E+04 10.27 4.110

17:09:19 2.08E+07 2.09E+04 10.27 4.103

17:09:20 2.08E+07 2.09E+04 10.27 4.099

17:09:22 2.08E+07 2.09E+04 10.27 4.107

17:09:24 2.11E+07 2.13E+04 10.27 4.103

Page 60: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

60

17:09:25 2.11E+07 2.13E+04 10.27 4.090

17:09:27 2.53E+07 2.57E+04 10.27 4.110

17:09:29 2.53E+07 2.58E+04 10.27 4.101

17:09:30 2.53E+07 2.59E+04 10.27 4.099

17:09:32 2.53E+07 2.59E+04 10.27 4.088

17:09:34 1.69E+07 1.71E+04 10.27 4.092

17:09:35 1.69E+07 1.71E+04 10.27 4.114

17:09:37 1.69E+07 1.70E+04 10.27 4.114

17:09:38 1.69E+07 1.70E+04 10.27 4.101

17:09:40 1.69E+07 1.70E+04 10.27 4.090

17:09:42 1.69E+07 1.70E+04 10.27 4.079

17:09:43 1.69E+07 1.69E+04 10.27 4.083

17:09:45 1.69E+07 1.69E+04 10.27 4.103

17:09:47 1.69E+07 1.69E+04 10.27 4.099

17:09:48 1.69E+07 1.69E+04 10.27 4.090

17:09:50 1.69E+07 1.69E+04 10.27 4.099

17:09:52 1.69E+07 1.69E+04 10.27 4.096

17:09:53 1.69E+07 1.69E+04 10.27 4.077

17:09:55 1.69E+07 1.69E+04 10.27 4.086

17:09:56 1.69E+07 1.68E+04 10.27 4.095

17:09:58 1.69E+07 1.69E+04 10.27 4.101

17:10:00 1.69E+07 1.68E+04 10.27 4.097

17:10:02 1.69E+07 1.68E+04 10.27 4.092

17:10:03 1.69E+07 1.68E+04 10.27 4.079

17:10:05 1.69E+07 1.68E+04 10.27 4.084

17:10:07 1.69E+07 1.68E+04 10.27 4.084

17:10:09 1.69E+07 1.68E+04 10.27 4.075

17:10:10 1.69E+07 1.68E+04 10.27 4.086

17:10:12 1.69E+07 1.67E+04 10.27 4.086

17:10:14 1.69E+07 1.67E+04 10.27 4.088

17:10:15 1.69E+07 1.67E+04 10.27 4.105

17:10:17 1.69E+07 1.67E+04 10.27 4.079

17:10:19 1.69E+07 1.67E+04 10.27 4.073

17:10:20 1.69E+07 1.67E+04 10.27 4.086

17:10:22 1.69E+07 1.66E+04 10.27 4.090

17:10:23 4.20E+05 0.00E+00 10.27 4.077

17:10:25 4.00E+05 0.00E+00 10.27 4.055

17:10:27 4.00E+05 0.00E+00 10.27 4.073

17:10:28 3.90E+05 0.00E+00 10.27 4.068

Table 2. Datos experimentales tomados con Agilent N5752A y BK Precision 891

Page 61: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

61

11.2 Código fuente

11.2.1 __init__.py

#!/usr/bin/env python

import Comunicacion

import LAN

import adquisicion_datos

import SAVE

import CSV_Data

import PLOT

import Lista_Instrucciones

import Select_Chan

import PIN_Instrumento

import Terminal

import Main

import time

def START():

Main.programa_principal()

time.sleep(5)

if __name__ == "__main__":

START()

11.2.2 Main.py

#!/usr/bin/env python

import threading

import adquisicion_datos

import PLOT

import PIN_Instrumento

import SAVE

import Terminal

import Lista_Instrucciones

import Select_Chan

def programa_principal():

#Instento de conexion con los distintos instrumentos del

inventario

CONEXION=PIN_Instrumento.Leer_inventario()

if CONEXION is not True:

return(0) #Si no hay conexion con instrumentos, fin del

programa

#Seleccion de instrumento a usar

CONEXION,IP_1,IP_2,NAME_1,NAME_2,MODELO_1,MODELO_2=PIN_Instrumento.INS

TRUMENTS()

if CONEXION is not True:

return(0) #Si ninguno de los instrumentos conectados es

necesario

#Insruciones SCPI, nombre de la instruccion(estetico) y cantidad

de instrucciones (1/2)

#Instrumento 1

Page 62: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

62

MEAS_1A,MEAS_1B,MEAS_NAME_1A,MEAS_NAME_1B=Lista_Instrucciones.Instrucc

ion_medir(MODELO_1,NAME_1)

#Instrumento2

if MODELO_2!='':

MEAS_2A,MEAS_2B,MEAS_NAME_2A,MEAS_NAME_2B=Lista_Instrucciones.Instrucc

ion_medir(MODELO_2,NAME_2)

#NO hay segundo instrumento

if MODELO_2=='':

MEAS_2A,MEAS_2B,MEAS_NAME_2A,MEAS_NAME_2B=Lista_Instrucciones.No_Instr

ument()

#Autodeteccion de canales o demanda de ellos, segun caso.

#Instrumento1

CANAL_1A,CANAL_1B,BI_CHAN_1=Select_Chan.Diferenciar_Modelo(MODELO_1,NA

ME_1,MEAS_NAME_1A,MEAS_NAME_1B)

#Instrumento2

if MODELO_2!='':

CANAL_2A,CANAL_2B,BI_CHAN_2=Select_Chan.Diferenciar_Modelo(MODELO_2,NA

ME_2,MEAS_NAME_2A,MEAS_NAME_2B)

#NO hay segundo Instrumento

if MODELO_2=='':

CANAL_2A,CANAL_2B,BI_CHAN_2=Select_Chan.No_Instrument()

#Nombre de las medidas para el archivo .csv

SAVE.Nombre_instrumento(NAME_1,MODELO_1,MEAS_NAME_1A,MEAS_NAME_1B,NAME

_2,MODELO_2,MEAS_NAME_2A,MEAS_NAME_2B)

pn=SAVE.Leer_Pathname()

#Nombre de las medidas para etiquetas de los ejes del plot

TITLE_1=NAME_1+' '+MODELO_1

TITLE_2=NAME_2+' '+MODELO_2

PLOT.Label_name(MEAS_NAME_1A,MEAS_NAME_1B,MEAS_NAME_2A,MEAS_NAME_2B,TI

TLE_1,TITLE_2)

#Paso de parametros para inicializar la comunicacion

Autorizar_Medida=1

Cerrar_Com=0

adquisicion_datos.Control_Com(Autorizar_Medida,Cerrar_Com)

adquisicion_datos.Datos_para_lectura(IP_1,CANAL_1A,CANAL_1B,MEAS_1A,ME

AS_1B,BI_CHAN_1,MODELO_1,

IP_2,CANAL_2A,CANAL_2B,MEAS_2A,MEAS_2B,BI_CHAN_2,MODELO_2)

#Creacion y arranque del Thread de lectura

thread_datos=threading.Thread(target=adquisicion_datos.Adquirir_Datos,

name='DATOS_INSTRUMENTO')

thread_datos.start()

#Creacion del Thread para plot en tiempo real de datos

thread_plot=threading.Thread(target=PLOT.Go_plot, name='PLOTTING')

Page 63: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

63

ruta_csv=False

while(not ruta_csv): #Espera hasta tener la ruta del archivo

.csv de donde leera el plot

if(pn):

thread_plot.start() #Arranque Thread Plot

ruta_csv=True

#Creacion y arranque del Thread para Cierre de Comunicacion

Autorizar_Medida=0

Cerrar_Com=1

th_Terminal=threading.Thread(target=Terminal.Terminal(MODELO_1,MODELO_

2), name='Terminal')

th_Terminal.start()

return(0)

11.2.3 Comunicacion.py

#!/usr/bin/env python

import socket

class comunicacion_instrumento (socket.socket):

def __init__(self,IP,PORT,BUFFER_SIZE,TIMEOUT):

socket.socket.__init__(self, socket.AF_INET,

socket.SOCK_STREAM,) #Inicializacion de la calse padre socket

self.TCP_IP = IP #IP para conexion

self.TCP_PORT = PORT #Puerto de conexion

self.BUFFER_SIZE = BUFFER_SIZE #Size del buffer de

datos

self.settimeout(TIMEOUT) #Tiempo de espera para

la conexion con instrumento (segundos)

try:

self.connect((self.TCP_IP, self.TCP_PORT)) #Conexion

con IP y puerto

except socket.error:

pass #NO hay conexion con instrumento.

def enviar_dato(self,dato_enviar): #Se envia un dato mediante

el metodo send(dato) de la clase socket

dato_enviar=dato_enviar+'\n'

self.send(dato_enviar)

def recibir_dato(self): #Se recibe un dato mediante

el metodo recv(buffer_sicze) de la casle socket

try:

dato_recibido=self.recv(self.BUFFER_SIZE)

return dato_recibido

except socket.error:

pass

def cerrar_puerto(self): #Se cierra la comunicacion

del socket.

self.close()

Page 64: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

64

11.2.4 LAN.py

#!/usr/bin/env python

import Comunicacion

import time

class LAN (Comunicacion.comunicacion_instrumento):

def __init__(self,IP,PORT,BUFFER_SIZE,TIMEOUT): #Constructor

clase 'comunicacion_instrumento'

Comunicacion.comunicacion_instrumento.__init__(self,IP,PORT,BUFFER_SIZ

E,TIMEOUT)

#Funcion para datos auxiliares tipo PIN, tipo de consigna

(N5752A), etc. que retorna un valor

def Dato_Auxiliar(self,Comand_Aux):

self.enviar_dato(str(Comand_Aux))

dato_aux=self.recibir_dato()

return str(dato_aux)

#Funcion para datos auxiliar. Establecer tipos de medida (BK_981),

instruccion 'ABOR' etc. No retorna ningun valor

def Dato_Auxiliar_2(self,Comand_Aux):

self.enviar_dato(str(Comand_Aux))

#Funcion para la toma de datos

def hacer_medida(self,CANAL, TIPO_MEDIDA, BI_CHANEL):

if BI_CHANEL==True: #34972A

self.enviar_dato(TIPO_MEDIDA+' (@'+CANAL+')')

valor=self.recibir_dato()

else:

self.enviar_dato(TIPO_MEDIDA)

time.sleep(0.2)

valor=self.recibir_dato()

return str(valor)

#Cierre de la comunicacion

def cierre_Com(self):

self.close()

11.2.5 adquisicion_datos.py

#!/usr/bin/env python

import LAN

import time

from datetime import datetime

import CSV_Data

def Adquirir_Datos():

#Datos fijos para comunicacion

PORT=5025 #Puerto Ethernet

BUFFER_SIZE=1024 #tamanio buffer

TIMEOUT=10 #TIMEOUT sufucientemente grande como para

permitir lecturas

global com_lan_1

Page 65: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

65

com_lan_1=LAN.LAN(IP_1,PORT,BUFFER_SIZE,TIMEOUT) #Constructor

de clase para comunicacion del instrumento 1

if(IP_2!=''):

global com_lan_2

com_lan_2=LAN.LAN(IP_2,PORT,BUFFER_SIZE,TIMEOUT)

#Constructor de clase para comunicacion del instrumento 2

else: com_lan_2=False #NO hay segundo instrumento para

realizar medidads

#Bucle para lectura continuada hasta cancelar autorizacion (Cerrar

comunicacion)

while Cerrar_Comunicacion==0:

data=['','','',''] #Array 4 posiciones para almacenar y

enviar los datos recibidos

if MODELO_1=='N5752A' and Autorizar_Medida==1:

com_lan_1.Dato_Auxiliar_2('INIT') #Inicia

el sistema para disparo de consigna

com_lan_1.Dato_Auxiliar_2('OUTP ON') #OUTPUT

ENABLE

com_lan_1.Dato_Auxiliar_2('TRIG') #Disparo

de las consignas entregadas a N5752A

if MODELO_2=='N5752A' and Autorizar_Medida==1:

com_lan_2.Dato_Auxiliar_2('INIT') #Inicia

el sistema para disparo de consigna

com_lan_2.Dato_Auxiliar_2('OUTP ON') #OUTPUT

ENABLE

com_lan_2.Dato_Auxiliar_2('TRIG') #Disparo

de las consignas entregadas a N5752A

while ((Autorizar_Medida==1)and(Cerrar_Comunicacion==0)):

# Toma de datos del primer instrumento

dato_1A=com_lan_1.hacer_medida(CANAL_1A,MEAS_1A,BI_CHAN_1)[:-1]

#Lectura DATO_1 Instrumento 1

#print dato_1A

if (MEAS_1B!=''):

dato_1B=com_lan_1.hacer_medida(CANAL_1B,MEAS_1B,BI_CHAN_1)[:-1]

#Lectura DATO_2 Instrumento 1

else:

dato_1B=''

#Toma de datos del segundo instrumento

if (com_lan_2 is not False):

dato_2A=com_lan_2.hacer_medida(CANAL_2A,MEAS_2A,BI_CHAN_2)[:-1]

#Lectura DATO_1 Instrumento 2

if(MEAS_2B!=''):

dato_2B=com_lan_2.hacer_medida(CANAL_2B,MEAS_2B,BI_CHAN_2)[:-1]

#Lectura DATO_2 Intrumento 2

else:

dato_2B=''

else:

Page 66: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

66

dato_2A=''

dato_2B=''

#Si estamos recibiendo datos del BK 891 (los datos

se reciben juntos por un mismo canal de comunicacion)

if MODELO_1=='891':

dato_1A,dato_1B=BK_DATA(dato_1A)

if MODELO_2=='891':

dato_2A,dato_2B=BK_DATA(dato_2A)

data[0]=dato_1A

data[1]=dato_1B

data[2]=dato_2A

data[3]=dato_2B

#Hora de las lecturas.

hora_lectura=str(datetime.now().strftime('%H:%M:%S.%f')[:-5])

#Hora de la lectura

#La hora de la lectura almacenada en el .csv es la

correcta. Al mostrar los datos en celdas en el .csv,

#hay que modificar el tipo de dato y ponerlos en

Hora (Suele estar en 'General')"""

#Enviamos los datos para ser almacenados en el .csv

CSV_Data.escribir(hora_lectura,data)

time.sleep(1) #Tiempo de espera tras lectura

time.sleep(0.5) #Espera para cerrar comunicación

#Termina/Abortar la lectura o la consigna entergda

#Solo para los Keysight/Agilent. El BK NO tiene esta instruccion.

if MODELO_1!='891':

com_lan_1.Dato_Auxiliar_2('ABOR') #Finalizacion de

la lectura Instrumento_1

if MODELO_1=='N5752A':

com_lan_1.Dato_Auxiliar_2('OUTP OFF') #Cierre de la

salida. Conigna=0 (Solo para N5752A)

if MODELO_2!='891' and com_lan_2 is not False:

com_lan_2.Dato_Auxiliar_2('ABOR') #Finalizacion de

la lectura Intrumento_2

if MODELO_2=='N5752A':

com_lan_2.Dato_Auxiliar_2('OUTP OFF') #Cierre de la

salida. Conigna=0 (Solo para N5752A)

com_lan_1.cierre_Com() #Cierre de

comunicacion Instrumento_1

if com_lan_2 is not False:

com_lan_2.cierre_Com() #Cierre de

comunicacion Instrumento_2

def BK_DATA(dato_XA):

#Separamos el dato en dos datos distintos (Medida 1 y Medida 2)

a,b=dato_XA.split(',')

A=BK_Num_Transform(a) #Eliminamos letras y espacios del dato

recibido

Page 67: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

67

B=BK_Num_Transform(b) #Eliminamos letras y espacios del dato

recibido

return A,B

def BK_Num_Transform(num):

#Los datos del BK se reciben tal que asi: ' 47.35 nF , 5.580

kohm'. Necesitamos que solo sea '47.53' y '5.580'

#Comprobamos el string recibido caracter por caracter. Si es un

numero o un '.' nos lo quedamos

dato=''

letras=''

for x in num:

if x.isdigit()==True or x=='.':

#Add numero o punto decimal al dato

dato=dato+x

else:

if x!=' ':

#Eliminamos espacios en blanco

letras=letras+x

if letras=='+Over' or letras=='-Over' or

letras=='Non': #Error en la medida

dato=letras

#Se mantiene el nombre del error para el .csv

return dato

def Consigna_N5752A(key,param):

global com_lan_1

global com_lan_2

if param==1: #Param_1 = Voltage

OK=0

while (not OK):

try:

print ('\nIntroduce Voltage (V):')

vol_level=(float(raw_input('NOTE: MAX Voltage allowed:

600 V\n')))

if vol_level>=0.0 and vol_level<600.1:

if key=='1': #Key_1 = Primer

Instrumento

com_lan_1.Dato_Auxiliar_2('VOLT

'+str(vol_level))

if key=='2': #Key_2 = Segundo

Instrumento

com_lan_2.Dato_Auxiliar_2('VOLT

'+str(vol_level))

print 'Supply level: '+str(vol_level)+ ' V'

OK=1

else:

print 'Out of Voltage range'

except ValueError:

print 'Error Input - Do not introduce characters'

except:

Page 68: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

68

print '\tCom_Error'

print('NOTE: Values can be modified in the front panel of the

instrument\n')

if param==2: #Param_2 = Current

OK=0

while (not OK):

try:

print ('\nIntroduce current max (A):')

curr_level=(float(raw_input('NOTE: MAX Current

allowed: 1.3 A\n')))

if curr_level>=0.0 and curr_level<1.3:

if key=='1':

com_lan_1.Dato_Auxiliar_2('CURR

'+str(curr_level)) #Entregamos consigna de corriente maxima

if key=='2':

com_lan_2.Dato_Auxiliar_2('CURR

'+str(curr_level)) #Entregamos consigna de corriente maxima

print 'Current limited to '+str(curr_level)+ '

A\n'

OK=1

else:

print 'Out of Current range\n'

except:

print 'Error Input - Do not introduce characters\n'

def Control_Com(Medir,Cerrar):

#Variables de control para autrizar o detener la lectura y

comunicacion con intrumentos

global Autorizar_Medida

global Cerrar_Comunicacion

Autorizar_Medida=Medir

Cerrar_Comunicacion=Cerrar

def

Datos_para_lectura(Ip_1,Canal_1A,Canal_1B,Meas_1A,Meas_1B,Bi_Chan_1,Mo

delo_1,

Ip_2,Canal_2A,Canal_2B,Meas_2A,Meas_2B,Bi_Chan_2,Modelo_2):

#Variables Instrumento 1

global IP_1

global CANAL_1A

global CANAL_1B

global MEAS_1A

global MEAS_1B

global BI_CHAN_1

global MODELO_1

#Variables Instrumento 2

global IP_2

global CANAL_2A

global CANAL_2B

global MEAS_2A

global MEAS_2B

global BI_CHAN_2

global MODELO_2

Page 69: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

69

IP_1=Ip_1

CANAL_1A=Canal_1A

CANAL_1B=Canal_1B

MEAS_1A=Meas_1A

MEAS_1B=Meas_1B

BI_CHAN_1=Bi_Chan_1

MODELO_1=Modelo_1

IP_2=Ip_2

CANAL_2A=Canal_2A

CANAL_2B=Canal_2B

MEAS_2A=Meas_2A

MEAS_2B=Meas_2B

BI_CHAN_2=Bi_Chan_2

MODELO_2=Modelo_2

11.2.6 SAVE.py

#!/usr/bin/env python

import wx

import csv

import CSV_Data

import PLOT

import os

from datetime import datetime

def save(self, event):

global pathname

#Creacion de ventana de guardado de archivos

save_window=wx.FileDialog(self, "Creating new .csv

file",wildcard="CSV Files (*.csv)|*.csv",style=wx.FD_SAVE |

wx.FD_OVERWRITE_PROMPT)

#Si cerramos la ventana de guardar archivo sin elegir la ruta de

guardado, se crea automaticamente un archivo de

#seguridad para almacenar las medidas. De no ser asi, se crearia

una excepcion y terminaria el programa.

if save_window.ShowModal() == wx.ID_CANCEL:

date=str(datetime.today())[:-10] #Year-Month-

Day_Hour-Min

date_today=''

for x in date:

if x==':': x='.' #Eliminamos ':' por

ser caracter prohibido al guardar un archivo

if x==' ': x='_' #Eliminamos el

espacio entre fecha y hora por estetica

date_today=date_today+x

with open('Security_file'+'_'+date_today+'.csv', 'w') as f:

path=os.getcwd() #Directorio actual

de ejecucion

pathname=path+'/Security_file'+"_"+date_today+'.csv'

print '\nSave window closed. A security file has been

created to store data.'

print 'Security file created in: '+pathname

f.close()

else:

Page 70: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

70

pathname = save_window.GetPath() #Obtencion de la

ruta de guardado seleccionada

CSV_Data.Rec_Path(pathname) #Enviamos el

pathname del .csv para escritura

PLOT.Rec_Path(pathname) #Enviamos el

pathname del .csv para lectura en el plot

try:

with open(pathname, "wb") as f:

writer = csv.writer(f, delimiter=',')

INSTRU_1=NAME_1+' '+MODELO_1 #Nombre

del instrumento 1

INSTRU_2=NAME_2+' '+MODELO_2 #Nombre

del instrumento 2

writer.writerow(('',INSTRU_1,'', INSTRU_2)) #Primera

line de texto con el nombre del los instrumentos

#Hora lectura y nombre de las instruciones

writer.writerow(("Hora

Lectura",MEAS_NAME_1A,MEAS_NAME_1B,MEAS_NAME_2A,MEAS_NAME_2B))

f.close()

except IOError:

wx.LogError("An error has ocurred creating the .csv file.

Reboot the program please.")

return

def exe(): #Mantiene la ventana abierta

app = wx.App(False)

frame = save(None,"")

app.MainLoop()

def

Nombre_instrumento(nombre_1,modelo_1,dato_1a,dato_1b,nombre_2,modelo_2

,dato_2a,dato_2b):

global NAME_1, MODELO_1, MEAS_NAME_1A,MEAS_NAME_1B

global NAME_2,MODELO_2, MEAS_NAME_2A,MEAS_NAME_2B

NAME_1=nombre_1

MODELO_1=modelo_1

MEAS_NAME_1A=dato_1a

MEAS_NAME_1B=dato_1b

NAME_2=nombre_2

MODELO_2=modelo_2

MEAS_NAME_2A=dato_2a

MEAS_NAME_2B=dato_2b

exe() #Ejecucion de la ventana de creacion de archivo .csv

def Leer_Pathname():

#Se utiliza en MAIN para obtener el pathname

return pathname

11.2.7 CSV_Data.py

#!/usr/bin/env python

cnt=1 #Contador para printear cantidad de lecturas (no necesario)

def escribir(data_time, data):

Page 71: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

71

global cnt

data_1A=data[0] #Dato 1/Instrumento 1

data_1B=data[1] #Dato 2/Instrumento 1

data_2A=data[2] #Dato 1/Instrumento 2

data_2B=data[3] #Dato 2/Instrumento 2

try:

with open(pathname, 'a') as f:

f.write(data_time+","+data_1A+","+data_1B+','+data_2A+','+data_2B+'\n'

) #Escritura de datos recibidos

f.close()

#print 'Hora lectura: '+data_time

#print("Num. escrituras: "+str(cnt))

cnt=cnt+1

except IOError:

print 'An error has occurred. Data is not been stored. \n \tIf

you have the .csv file opened, close it to continue.'

def Rec_Path(PATH):

#Recibimos el pathname del archivo .csv desde el modulo SAVE

global pathname

pathname=PATH

11.2.8 PLOT.py

#!/usr/bin/env python

import matplotlib.pyplot as plt

import matplotlib.animation as animation

import matplotlib.ticker as mtiker

from matplotlib import style

def Plot_Data():

#////////////////////////////////////////// DATA

//////////////////////////////////////////

error_value=0 #Valor que tomara el dato para ser ploteado si el

original es un error

with open(pathname,'r') as f: #Apertura del archivo a leer

graph_data=f.read() #Lectura del archivo

f.close #Cierre del archivo para

permitir actualizaciones

lines = graph_data.split('\n') #Separacion de las distintas

lineas leidas

TIME=[] #Arrays almacenador de datos de tiempo

y1=[] #Arrays almacenador de datos de eje Y Izquierda -

Instrumento 1

y2=[] #Arrays almacenador de datos de eje Y Derecha -

Instrumento 1

y3=[] #Arrays almacenador de datos de eje Y Izquierda -

Instrumento 2

y4=[] #Arrays almacenador de datos de eje Y Derecha -

Instrumento 2

Page 72: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

72

cnt=0 #Contador para evitar leer las primeras lineas de

texto (no datos) del .csv

for line in lines:

if cnt>2 and line!='': #Evitamos leer primera y

segunda linea (texto) y ultima(espacio en blanco)

t,L_1,R_1,L_2,R_2=line.split(',') #Separacion de cada

linea por datos (tiempo, medida_1, medida2)

TIME.append(str(t)) #conv. a string de las

horas para mostrar en plot. Add to array TIME[]

try:

y1.append(float(L_1)) #conv. a float para

representacion grafica de DATO_1. Add to array y1[]

except: #Si es un str no se

puede convertir a float - Dato Erroneo - Dato=0 para representacion

L_1=error_value

y1.append(float(L_1))

if(LABEL_1B!=''):

try:

y2.append(float(R_1)) #conv. a float para

representacion grafica de DATO_2. Add to array y2[]

except: #Si es un str no se

puede convertir a float - Dato Erroneo - Dato=0 para representacion

R_1=error_value

y2.append(float(R_1))

if (LABEL_2A!=''):

try:

y3.append(float(L_2)) #conv. a float para

representacion grafica de DATO_3. Add to array y3[]

except: #Si es un str no se

puede convertir a float - Dato Erroneo - Dato=0 para representacion

L_2=error_value

y3.append(float(L_2))

if (LABEL_2B!=''):

try:

y4.append(float(R_2)) #conv. a float para

representacion grafica de DATO_4. Add to array y4[]

except: #Si es un str no se

puede convertir a float - Dato Erroneo - Dato=0 para representacion

R_2=error_value

y4.append(float(R_2))

else: cnt=cnt+1 #Incremento de contador

de lineas leidas

return TIME,y1,y2,y3,y4

def Plotting(i):

TIME,y1,y2,y3,y4=Plot_Data() #Actualizacion de los datos a

plotear

#////////////////////////////////////////// PLOT

//////////////////////////////////////////

Page 73: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

73

#--------------------------------- Eje X, Eje Y_Izquierda, 1r DATO ---

------------------------------

ax1.plot(TIME, y1, marker='o', color='blue')

#Dibujado de valores 1

ax1.autoscale()

#Atoescala

ax1.set_xlabel('time (s)')

#Etiqueta eje X

ax1.set_ylabel(str(LABEL_1A), color='blue')

#Etiqueta eje Y izquierda

ax1.tick_params('y', colors='blue', labelsize='small')

#Numeros escala izquierda

#ax1.grid(color='#4285f4') #Color

rejilla

ax1.grid(False)

#Rejilla izquierda (sin rejilla)

ax1.xaxis.set_major_locator(mtiker.MaxNLocator(20))

#Cantidad maxima de valores en eje X

#--------------------------------- Eje Y_Derecha, 2o DATO ------------

----------------------

#Solo si hay segundo dato

if (LABEL_1B!=''):

ax2.plot( y2, marker='D', color='green')

#Dibujado de valores 2

ax2.autoscale()

#Autoescala

ax2.set_ylabel(str(LABEL_1B), color='green')

#Etiqueta eje Y derecha

ax2.tick_params('y', colors='green', labelsize='small')

#Numeros escala derecha

#ax2.grid(color='#742157') #color

rejilla

ax2.grid(False)

#Rejilla derecha (sin rejilla)

else:

#Ponemos el eje Y_Derecho en blanco para ocultarlo en caso de

solo haber 1 dato

ax2.tick_params('y', colors='white', labelsize='small')

######################################### PLOT SEGUNDO INSTRUMETO

#########################################

#--------------------------------- Eje X, Eje Y_Izquierda, 1r DATO ---

------------------------------

if (LABEL_2A!=''):

ax3.plot( TIME, y3, marker='X', color='purple')

#Dibujado de valores 1

ax3.autoscale()

#Atoescala

ax3.set_xlabel('time (s)')

#Etiqueta eje X

ax3.set_ylabel(str(LABEL_2A), color='purple')

#Etiqueta eje Y izquierda

ax3.tick_params('y', colors='purple', labelsize='small')

#Numeros escala izquierda

#ax3.grid(color='#4285f4')

#Color rejilla

Page 74: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

74

ax3.grid(False)

#Rejilla izquierda (sin rejilla)

ax3.xaxis.set_major_locator(mtiker.MaxNLocator(10))

#Cantidad maxima de valores en eje X

#--------------------------------- Eje Y_Derecha, 2o DATO ------------

----------------------

#Solo si hay segundo dato

if (LABEL_2B!=''):

ax4.plot(y4, marker='D', color='red')

#Dibujado de valores 2

ax4.autoscale()

#Autoescala

ax4.set_ylabel(str(LABEL_2B), color='red')

#Etiqueta eje Y derecha

ax4.tick_params('y', colors='red', labelsize='small')

#Numeros escala derecha

#ax4.grid(color='#742157')

#color rejilla

ax4.grid(False)

#Rejilla derecha (sin rejilla)

else:

#Ponemos el eje Y_Derecho en blanco para ocultarlo en caso

de solo haber 1 dato

ax4.tick_params('y', colors='white', labelsize='small')

fig.tight_layout() #Autoajuste a pantalla

fig.autofmt_xdate() #Formato numeros exe X en vertical

def Go_plot():

#Muestra y mantiene el plot abierto

ani=animation.FuncAnimation(fig, Plotting, interval=1000)

#interval(ms).Intervalo de redibujado

plt.show() #Mostrar plot

def Label_name(name_1A,name_1B,name_2A,name_2B,titulo_1,titulo_2):

#Obtencion de las etiquetas de cada dato

global LABEL_1A

global LABEL_1B

global LABEL_2A

global LABEL_2B

global TITLE_1

global TITLE_2

LABEL_1A=name_1A

LABEL_1B=name_1B

LABEL_2A=name_2A

LABEL_2B=name_2B

TITLE_1=titulo_1

TITLE_2=titulo_2

#Para creacion de segndo plot. Se creara un segundo plot en la

misma ventana si hay datos de un segundo instrumento

Create_Figure(LABEL_2A)

def Rec_Path(PATH):

#Recibimos el pathname del archivo .csv desde el modulo SAVE para

leer

global pathname

pathname=PATH

Page 75: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

75

def Create_Figure(Second_plot):

#---------------------- Configuracion del PLot -----------------------

--------

global fig

global ax1, ax2, ax3, ax4

#style.use('bmh') #Posible estilo artistico del plot

style.use('seaborn') #Estilo artistico del plot

fig=plt.figure() #Creacion de la figura (ventana)

if Second_plot=='': #Si no hay segundo instrumento

ax1=fig.add_subplot(111) #1 plot en ventana

ax2=ax1.twinx() #ax2 comparte eje X con ax1

plt.title(TITLE_1)

else: #Si hay segundo instrumento

ax1=fig.add_subplot(211) #2 plots en ventana. Posicion UP

ax2=ax1.twinx()

plt.title(TITLE_1) #ax2 comparte eje X con ax1

ax3=fig.add_subplot(212) #2 plots en ventana. Posicion DOWN

ax4=ax3.twinx() #ax4 comparte eje X con ax3

plt.title(TITLE_2)

fig.tight_layout() #Autoajuste a pantalla

fig.autofmt_xdate() #Formato numeros exe X en vertical

11.2.9 Lista_Instrucciones.py

#!/usr/bin/env python

"""*******************************************************************

***********************************************

Este modulo es llmado entre 1 y 2 veces durante la ejecucion del

programa principal, dependiendo de si hay 1 o 2

instrumentos en uso.

Recibe el modelo y el nombre(estetico, para mostrar por pantalla y

diferenciar, pero indispensable) del instrumento.

Segun el modelo, se mostraran por pantala las distintas opciones de

medida y si se da el caso (Agilent/Keysight_34972A-

BK 891), se preguntara la cantidad de tipos de medidas (1 o 2) que se

desean realizar entre las distintas opciones.

El modulo retorna la instruccion SCPI para enviar al instrumento y su

nombre (estetico pero necesario).

En caso de solo haber 1 instruccion, se retornara un espacio en blanco

'' siempre.

**********************************************************************

********************************************"""

import LAN

def Instruccion_medir(MODELO, NAME):

if MODELO == '34972A':

Num_Meas('Agilent/Keysight 34972A') #Pedir cantidad de

tipos de medidas a realizar con el instrumento (1/2)

MEAS_1,MEAS_2,MEAS_NAME_1,MEAS_NAME_2 =

Agilent_Keysight_34972A(NAME)

Page 76: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

76

if MODELO == '891':

MEAS_1,MEAS_2,MEAS_NAME_1,MEAS_NAME_2 = BK_891()

if MODELO == 'N5752A': #Power supply.

MEAS_1,MEAS_2,MEAS_NAME_1,MEAS_NAME_2=Keysight_N5752A()

if MODELO == '33521A': #Waveform generatior.

MEAS_1,MEAS_2,MEAS_NAME_1,MEAS_NAME_2=Keysight_33521A()

return MEAS_1,MEAS_2,MEAS_NAME_1,MEAS_NAME_2

def Num_Meas(name):

global num_meas

OK=0

while (not OK):

try:

num_meas=int(raw_input('\nTypes of measurements to do with

'+name+'? (1/2)\n'))

if (num_meas==1 or num_meas==2): OK=1

if (not OK): print 'ERROR INPUT - Out of range'

except:

print 'Error Input - Do not introduce characters'

def Agilent_Keysight_34972A(NAME):

#NAME sirve para diferenciar entre Agilent y Keysight

#Lista de comandos SCPI para Agilent/Keysight_34972A

Agi_Key_measures='1':'MEAS:VOLT:DC?','2':'MEAS:VOLT:AC?','3':'MEAS:RE

S?','4':'MEAS:FRES?','5':'MEAS:CURR:DC?',

'6':'MEAS:CURR:AC?','7':'MEAS:FREQ?','8':'MEAS:PER?','9':'MEAS:TEMP?'

#Lista de nombres para mostrar por pantalla

Agi_Key_names='1':'Voltage DC (V)','2':'Voltage AC (V)','3':'2-

Wire Resistance (Ohm)','4':'4-wire resistance (Ohm)','5':'Current DC

(A)',

'6':'Current AC (A)','7':'Frequency (Hz)','8':'Period

(seg)','9':'Temperature'

#Instruciones para elegis comandos SCPI

Ag_Ke=""""============================================================

======================="

"""+NAME+""" 34972A

1)Voltage DC 2)Voltage AC 3)2-Wire Resistance 4)4-Wire

Resistance

5)Current DC 6)Current AC 7)Frequency 8)Period

9)Temperature

"""

print Ag_Ke

#---------------------------------- Primera Medida ---------------

--------------------------------------------

OK=0 #Variable de control para bulce

while(not OK):

x=str(raw_input('Choose NUMBER of FIRST measure: '))

#Eleccion de comando para primer tipo de medida

try:

x=int(x)

if (x in range (1,10)):OK=1

if (OK==0): print 'ERROR INPUT - Out of range'

except:

Page 77: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

77

print 'ERROR INPUT - Introduce a number'

x=str(x)

meas_1=Agi_Key_measures[x] #Eleccion de comando SCPI 1 segun

numero introducido

meas_name_1=Agi_Key_names[x] #Nombre del comando 1 para .csv y

plot

print meas_name_1

#if meas_name_1=='4-wire resistance (Ohm)':

#num_meas=1

if (num_meas==1): #Solo se realiza una medida

meas_2=''

meas_name_2=''

return (meas_1,meas_2,meas_name_1,meas_name_2) #Retornamos

comandos pedidos para medidas

#---------------------------------- Segunda Medida ---------------

--------------------------------------------

OK=0 #Variable de control para bulce

while(not OK):

y=str(raw_input('Choose NUMBER of SECOND measure: '))

#Eleccion de comando para segundo tipo de medida

try:

y=int(y)

if (y in range (1,10)):OK=1

if (OK==0): print 'ERROR INPUT - Out of range'

except:

#Error al convertir a integer

print 'ERROR INPUT - Introduce a number'

y=str(y)

meas_2=Agi_Key_measures[y] #Eleccion de comando SCPI 2 segun

numero introducido

meas_name_2=Agi_Key_names[y] #Nombre del comando 2 para .csv y

plot

print meas_name_2

return (meas_1,meas_2,meas_name_1,meas_name_2) #Retornamos

comandos pedidos para medidas

def BK_891():

#Lista de comandos SCPI para BK Precision 891

BK_meas='CSQ':'MEAS:FUNC CSQ','CSD':'MEAS:FUNC

CSD','CSR':'MEAS:FUNC CSR','CPQ':'MEAS:FUNC CPQ','CPD':'MEAS:FUNC

CPD',

'CPR':'MEAS:FUNC CPR','CPG':'MEAS:FUNC CPG','LSQ':'MEAS:FUNC

LSQ','LSD':'MEAS:FUNC LSD','LSR':'MEAS:FUNC LSR',

'LPQ':'MEAS:FUNC LPQ','LPD':'MEAS:FUNC LPD','LPR':'MEAS:FUNC

LPR', 'LPG':'MEAS:FUNC LPG', 'ZTH':'MEAS:FUNC ZTH',

'YTH':'MEAS:FUNC YTH','RX':'MEAS:FUNC RX','GB':'MEAS:FUNC

GB','DCR':'MEAS:FUNC DCR'

Page 78: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

78

BK_meas_prim='1':'CS','2':'CP','3':'LS','4':'LP','5':'Z','6':'Y','7':

'R','8':'G','9':'DCR'

BK_meas_second='1':'Q','2':'D','3':'R','4':'G','5':'X','6':'B'

#Instruciones para elegis comandos SCPI

BK_Prim="""===========================================================

===================================

"BK Precision 891"

Primary parameters:

1) CS- Capacitance value measured using a series equivalent circuit

model

2) CP- Capacitance value measured using a parallel equivalent circuit

model

3) LS- Inductance value measured using a series equivalent circuit

model

4) LP- Inductance value measured using a parallel equivalent circuit

model

5) Z- Impedance value

6) Y- Admittance value

7) R- Resistance value using a specified AC frequency and level

8) G- Conductance value

9) DCR- Resistance value using a DC bias

"""

BK_Second_1="""

Secondary Parameters:

Q- Quality factor

D- Dissipation factor

R- Equivalent resistance

"""

BK_Second_2="""

Secondary Parameters:

Q- Quality factor

D- Dissipation factor

R- Equivalent resistance

G- Conductance

"""

BK_Second_3="""

Secondary parameters:

TH- Thevenin

"""

BK_Second_4="""

Secondary Parameters:

X- Reactance

"""

BK_Second_5="""

Secondary Parameters:

B- Susceptance

"""

BK_CS="""1)CS-Q 2)CS-D 3)CS-R"""

BK_CP="""1)CP-Q 2)CP-D 3)CP-R 4)CP-G"""

BK_LS="""1)LS-Q 2)LS-D 3)LS-R"""

BK_LP="""1)LP-Q 2)LP-D 3)LP-R 4)LP-G"""

BK_ZTH="""1)Z-TH"""

BK_YTH="""1)Y-TH"""

BK_RX="""1)R-X"""

BK_GB="""1)G-B"""

BK_DCR="""DCR - Secondary parameters not alowed"""

Page 79: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

79

#-------------------------------- Parametros principales -------------

------------------------------

print BK_Prim #Parametros principales

OK=0

while (not OK):

prim=str(raw_input('Choose the number of primary parameter:

'))

try:

prim=int(prim) #Conversion a int

if prim in range (1,10):

OK=1

x=BK_meas_prim[str(prim)] #Nombre de la instruccion

primaria

print x

if prim not in range(1,10):

print 'Error Input - Out of range' #Fuera de rango

except:

print 'Error Input - Introduce a number' #No se ha

introducido un int

#-------------------------------- Parametros secundarios -------------

------------------------------

if prim == 9:

print BK_DCR #9)DCR

inst='DCR'

else:

if prim==1 or prim == 3: #1)CS 2)LS

print BK_Second_1 #Q/D/R

if prim==1: print BK_CS #Instrcciones CS

if prim==3: print BK_LS #Instrucciones LS

OK=0 #Peticion de numero de instrucion

while (not OK):

second=str(raw_input('Choose the number of secondary

parameter: '))

try:

second=int(second)

if second in range (1,4):

OK=1

y=BK_meas_second[str(second)] #Nombre de la

instruccion primaria

inst=x+y

print inst

if second not in range(1,4):

print 'Error Input - Out of range'

except:

print 'Error Input - Introduce a number'

if prim==2 or prim==4: #2)CP 3)LP

print BK_Second_2 #Q/D/R/G

if prim==2: print BK_CP #Instruciones CP

if prim==4: print BK_LP #Instruciones LP

OK=0 #Peticion de numero de instrucion

while not OK:

second=str(raw_input('Choose the number of secondary

parameter: '))

try:

Page 80: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

80

second=int(second)

if second in range (1,5):

OK=1

y=BK_meas_second[str(second)] #Nombre de la

instruccion primaria

inst=x+y

print inst

if second not in range(1,5):

print 'Error Input - Out of range'

except:

print 'Error Input - Introduce a number'

if prim==5 or prim==6 or prim==7 or prim==8: #5)ZTH

6)YTH 7)RX 8)GB

if prim==5:

print BK_Second_3 #TH

print BK_ZTH #Instruciones Z

y='TH'

if prim==6:

print BK_Second_3 #TH

print BK_YTH #Instruciones Y

y='TH'

if prim==7:

print BK_Second_4 #X

print BK_RX #Instruciones R

y='X'

if prim==8:

print BK_Second_5 #B

print BK_GB #Instruciones G

y='B'

OK=0 #Peticion de numero de instrucion

while not OK:

second=str(raw_input('Choose the number of secondary

parameter: '))

try:

second=int(second)

if second==1:

OK=1

inst=x+y

print inst

if second!=1:

print 'Error Input - Out of range'

except:

print 'Error Input - Introduce a number'

#---------------------------------------------------------------------

--------------------------------

medida=BK_meas[inst] #Instrucion SCPI para establecer tipo de

medida

IP='10.30.235.170' #IP Para la comunicacion previa a la

medida (set del tipo de medida)

PORT=5025

Buffer_Size=1024

TIMEOUT=10 #TIMEOUT sufucientemente grande como para

permitir lecturas

com_lan=LAN.LAN(IP,PORT,Buffer_Size,TIMEOUT) #Constructor

de clase para comunicacion

Page 81: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

81

com_lan.Dato_Auxiliar_2(medida) #Establecemos

el tipo de medida a realizar

aux_data=com_lan.Dato_Auxiliar('MEAS:RESU?') #Medida

temporal para tomar las unidades

com_lan.cierre_Com() #Cerramos la

comunicacion

uds_1,uds_2=BK_Unidades(aux_data)

#Los datos del BK981 se reciben juntos por el mismo canal de

medida, por lo que hay que separarlos al recibirlos

#Esto se hace en el modulo de adquisicion de datos. Aun asim hay

que indicar el nombre de la segunda medida como

#si se recibiesen de forma separada.Fisicamente, NO se puede hacer

solo la medida principal (excepto la DCR)

meas_1='MEAS:RESU?' #instrucion para pedida de datos.

meas_name_1=x+' '+'('+uds_1+')'

meas_2=''

meas_name_2=y+' '+'('+uds_2+')'

return (meas_1, meas_2, meas_name_1, meas_name_2) #Retornamos

comandos pedidos para medidas

def BK_Unidades(num):

#Los datos del BK se reciben tal que asi: ' 47.35 nF , 5.580

kohm'. Necesitamos que solo sea 'nF' y 'kohm'

#Comprobamos el string recibido caracter por caracter. Si es una

letra nos lo quedamos

un_1='' #Si no se obtiene ningun

dato o si el dato no tiene unidades se retornara ''

un_2=''

try:

a,b=num.split(',') #Separamos los dos datos

mediante las comas

for x in a: #Primer dato. Lectura

caracter a caracter

if x.isalpha()==True:

un_1=un_1+x #Si el caracter es una

letra, se actualiza

for x in b: #Segundo dato. Lectura

caracter a caracter

if x.isalpha()==True:

un_2=un_2+x #Si el caracter es una

letra, se actualiza

except:

print 'Units label not obtained' #Error de lectura. No se

ha obtenido ningun dato

return un_1,un_2

def Keysight_N5752A():

Page 82: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

82

IP='10.30.240.134' #IP para la comunicacion para el envio y

disparo de consignas

PORT=5025

Buffer_Size=1024

TIMEOUT=10 #TIMEOUT sufucientemente grande como para

permitir lecturas

com_lan=LAN.LAN(IP,PORT,Buffer_Size,TIMEOUT) #Constructor

de clase para comunicacion. Conexion

OK=0

while (not OK):

try:

print ('\nIntroduce current max (A):')

curr_level=(float(raw_input('NOTE: MAX Current allowed:

1.3 A\n')))

if curr_level>=0.0 and curr_level<1.3:

print 'Current limit: '+str(curr_level)+ ' A\n'

OK=1

else:

print 'Out of Current range'

except:

print 'Error Input - Do not introduce characters'

OK=0

while (not OK):

try:

print ('\nIntroduce Voltage (V):')

vol_level=(float(raw_input('NOTE: MAX Voltage allowed: 600

V\n')))

if vol_level>=0.0 and vol_level<600.1:

print 'Supply level: '+str(vol_level)+ ' V'

OK=1

else:

print 'Out of Voltage range'

except:

print 'Error Input - Do not introduce characters'

print('NOTE: Values can be modified in the front panel of the

instrument\n')

com_lan.Dato_Auxiliar_2('CURR:TRIG '+str(curr_level))

#Entregamos consigna de corriente maxima

com_lan.Dato_Auxiliar_2('VOLT:TRIG '+str(vol_level))

#Entregamos consigna de voltage

com_lan.cierre_Com()

#Cerramos comunicacion

#Retornamos el paedido de medidas de voltage y corriente.

return('MEAS:VOLT?','MEAS:CURR?','Voltage (V)','Current (A)')

def Keysight_33521A():

pass

#Lista de intrucciones no implementada debido a que el instrumento

no es necesario por el momento.

def No_Instrument():

#Retorna espacios en blanco para indicar que no hay ninguna medida

Page 83: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

83

#Lo hacemos en una funcion a parte para no 'ensuciar' el programa

principal

return ('','','','')

11.2.10 Select_Chan.py

#!/usr/bin/env python

"""*******************************************************************

************************************

Este modulo diferencia entre los intrumentos que necesitan un canal y

los que no para tomar las medidas.

#Los unicos intrumentos que necesitan selecionar un canal para tomar

medidas son los dataloguers.

**********************************************************************

*********************************"""

def Diferenciar_Modelo(MODELO,NAME,MEAS_NAME_1,MEAS_NAME_2):

if MODELO=='34972A' or MODELO=='34970A': #Instrumentos con 2

caneles de medida

if(MEAS_NAME_2==''):NUM=0 #1 tipo de medida

if(MEAS_NAME_2!=''):NUM=1 #2 tipos de medida

CANAL_1,CANAL_2=CHANELS(NUM, MODELO, NAME,

MEAS_NAME_1,MEAS_NAME_2)

BI_CHAN_INSTR=True

else:

CANAL_1=''

CANAL_2=''

BI_CHAN_INSTR=False

return (CANAL_1,CANAL_2,BI_CHAN_INSTR )

def CHANELS(NUM, MODELO, NAME, MEAS_NAME_1,MEAS_NAME_2):

print("""\nCHANELS: Xnn\nX=Slot [1,2,3]\nnn=Channel [1...22]\n""")

#----------------------------------------- Primer Canal --------------

------------------------------------------

OK=0

while (not OK):

try:

chan_1=int(raw_input('Introduce first channel to read

'+MEAS_NAME_1+' with '+NAME+' '+MODELO+': \n'))

if (chan_1 in range (101,122)):OK=1

if (chan_1 in range (201,222)):OK=1

if (chan_1 in range (301,322)):OK=1

if (OK==0): print "ERROR INPUT - Out of range.\n"

#Numero no valido

if ((OK==1)and(MEAS_NAME_1=='4-wire resistance (Ohm)')):

chan=chan_1+10

print 'NOTE: As you have select 4-wire resistance

measure for the '+str(chan_1)+' channel, be sure you have wired the

'+str(chan)+' channel\n'

else:

#Para evitar la aparacicion de un error, si la medida

no es a 4 hilos, chan=chan_1

chan=chan_1

except:

Page 84: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

84

print 'Error Input - Do not introduce characters.\n'

if (not NUM): #Solo hay 1 canal en uso. NUM=0

return (str(chan_1),'')

#----------------------------------------- Segundo Canal -------------

-------------------------------------------

OK=0

while (not OK):

try:

chan_2=int(raw_input('Introduce second channel to read

'+MEAS_NAME_2+' with '+NAME+' '+MODELO+': \n'))

if ( (chan_2 in range (101,122)) and (chan_2!= chan_1) and

chan_2!= chan ):OK=1

if ( (chan_2 in range (201,222)) and (chan_2!= chan_1) and

chan_2!= chan ):OK=1

if ( (chan_2 in range (301,322)) and (chan_2!= chan_1) and

chan_2!= chan ):OK=1

if (OK==0): print "ERROR INPUT - Out of range or channel

already selected.\n" #Numero no valido

if ((OK==1)and(MEAS_NAME_2=='4-wire resistance (Ohm)')):

chan=chan_2+10

print 'NOTE: As you have select 4-wire resistance

measure for the '+str(chan_2)+' channel, be sure you have wired the

'+str(chan)+' channel\n'

except:

print 'Error Input - Do not introduce characters.\n'

return (str(chan_1),str(chan_2))

def No_Instrument():

return ('','','')

#CHANELS(1, 'MODELO', 'NAME', '4-wire resistance','4-wire resistance')

11.2.11 PIN_Instrumento.py

#!/usr/bin/env python

import LAN

import Comunicacion

import time

def Leer_inventario():

#El archivo 'Inventario_Instrumentos.txt' debe encontrarse en la

carpeta del archivo ejecutable

#que contenga el codigo. Los datos almacenados deben estar en este

formato:

#10.30.239.203,Keysight 34972A,6

#10.30.240.134,Agilent N5752A,0.5

# .

# .

# .

Page 85: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

85

with open("Inventario_Instrumentos.txt",'r') as f: #Leemos

fichero

lectura = f.read() #Guardamos

texto leido

f.close() #Cerramos

fichero

lines = lectura.split('\n') #Sepramos

lectura en lineas

IPs=[] #Arrays para alamcenar datos leidos

INST=[]

TIMEOUT=[]

for line in lines:

if line!='': #Evitamos lineas en blanco. Si no, da error en

cantidad de argumentos

ip,inst,timeout = line.split(',') #Separamos

elementos de cada linea por comas

IPs.append(str(ip)) #Guardamos

las IPs de cada instrumento

INST.append(str(inst)) #Guardamos

lso nombres de cada instrumento

TIMEOUT.append(str(timeout)) #Guardamos

los timeouts de cada instrumento

conexion=PIN(IPs,INST,TIMEOUT) #Comprobacion de conexion a

la red de los distintos instrumentos

return (conexion) #Retornamos si ha habido conexion con

algun instrumento

def PIN(IPs,INST,TIMEOUT):

PORT=5025 #Puerto Ethernet

BUFFER_SIZE=1024 #tamanio buffer

global arr_IP #Arrays para guardar datos de instrumentos

global arr_NAME

global arr_MODELO

global x #Contador cantidad de instrumentos

arr_IP=[]

arr_NAME=[]

arr_MODELO=[]

arr_TIME=[]

x=0 #Contador de instrumentos

indice=0 #Indice de cada instrumento conectado

for timeouts in TIMEOUT:

arr_TIME.append(float(timeouts)) #Obtenemos los tiempos de

espera para cada instrumento del inventario

print ('Searching for instruments from inventary.........')

for ip_try in IPs:

print 'Trying connexion with '+INST[indice]+' '+'->'+ip_try

Page 86: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

86

com_lan=LAN.LAN(ip_try,PORT,BUFFER_SIZE,arr_TIME[indice])

#Constructor de clase para comunicaciones. TIMEOUT en fichero .txt

indice+=1

IDN='' #Vaciamos el IDN para comprobacion de cada

instrumento

try:

IDN=com_lan.Dato_Auxiliar('*IDN?') #Preguntamos ID del

instrumento (SCPI)

com_lan.cierre_Com() #Cerramos

comunicacion

if IDN=='HEWLETT-PACKARD,34970A,0,1012-1-

2\n':IDN='Keysight,34972A'

if IDN!='' and IDN!= 'None':

print 'Connected'

arr_IP.append(ip_try)

instru_name=IDN.split(',')

NAME=str(instru_name[0]) #Guardamos

fabricante y modelo del instrumento

arr_NAME.append(NAME)

MODELO=str(instru_name[1]) #Modelo

instrumento. Se utilizara para la lista de instruciones

arr_MODELO.append(MODELO)

x+=1 #Incremento del

contador de instrumentos detectados

except:

com_lan.cierre_Com() #Cerramos comunicacion para evitar

problemas en caso de no haber comuncacion

if x==0:

conexion=False

print ("Ther are no instruments connected.")

else:

conexion=True

return conexion

def INSTRUMENTS():

NAME=[] #Arrays para guardar datos de los instrumentos

MODELO=[]

IP=[]

if x==1:

print '\n'+str(x)+" INSTRUMENT DETECTED: "

if x>1:

print '\n'+str(x)+" INSTRUMENTS DETECTED: "

for cnt in range(x):

#Print del listado de instrumentos conectados

print str(cnt+1)+') '+ arr_NAME[cnt] + ' ' + arr_MODELO[cnt]+'

-> IP: '+arr_IP[cnt]

print '\nChoose a maximum of 2 to work with. If there are

different instruments and only one is needed, press ENTER after first

one.'

print 'If none of the detected instruments is needed, press 0'

OK=0 #Seleccion del primer instrumento

Page 87: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

87

while(not OK):

num_1=str(raw_input('Select firs instrument: '))

try: #Hacemos 'try:'

para comprobar conversion a int y evitar strings

num_1=int(num_1)

if num_1==0:

CONEXION=False #No se quiere

utilizar ningun insturmento listado.

print '\n-------------End of execution'

time.sleep(2)

return (CONEXION,0,0,0,0,0,0) #No se quiere

utilizar ningun instrumento listado.

if(num_1 in range (1,x+1)):

NAME.append(arr_NAME[num_1-1]) #Almacenamos

NOMBRE del instrumento (Fabricante)

MODELO.append(arr_MODELO[num_1-1]) #Almacenamos

MODELO del instrumento (Num.Serie)

IP.append(arr_IP[num_1-1]) #Almacenamos IP

del instrumento

OK=1

CONEXION=True

if(num_1 not in range (1,x+1)):

print 'ERROR INPUT - Out of range'

except: #Conversion a

int fallida

print 'ERROR INPUT - Do not introduce characters'

#-----------------------------------------------------------------

------

if x==1:

NAME.append('') #Almacenamos '' al no haber segundo

instrumento

MODELO.append('') #Almacenamos '' al no haber segundo

instrumento

IP.append('') #Almacenamos '' al no haber segundo

instrumento

print 'Only '+NAME[0]+' '+MODELO[0]+' in use.\n'

if x>1:

OK=0 #Seleccion del segundo instrumento

while (not OK):

num_2=str(raw_input('Select second instrument: '))

if (num_2==''): #No se quiere un segundo instrumento de

los detectados o solo hay uno

OK=1

NAME.append('') #Almacenamos '' al no usar

segundo instrumento

MODELO.append('') #Almacenamos '' al no usar

segundo instrumento

IP.append('') #Almacenamos '' al no usar

segundo instrumento

print 'Only '+NAME[0]+' '+MODELO[0]+' in use.\n'

break

try: #Hacemos 'try:' para

comprobar conversion a int y evitar strings

num_2=int(num_2)

if( ( num_2 in range (1,x+1) ) and ( num_2!=num_1 )):

#Segundo instrumento

Page 88: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

88

NAME.append(arr_NAME[num_2-1])

MODELO.append(arr_MODELO[num_2-1])

IP.append(arr_IP[num_2-1])

OK=1

if (num_2==num_1):print 'Instrument already

selected\n' #Instrumento ya seleccionado

except:

print 'ERROR INPUT - Do not introduce characters'

#Conversion a int fallida

#Condicion temporal. Comprobacion de conexion con Keysight_33521A

(Arbitrary Waveform Generator)

#Comuicacion con el instrumento. Instrucciones no implementadas

debido a que no es necesario su uso de momento.

n=0

for model in MODELO:

if model=='33521A':

IP[n]=''

NAME[n]=''

MODELO[n]=''

print ('Non-implemented instrument.\nPlease, contact with

the responsible technician if you need to use it.')

n+=1

return (CONEXION,IP[0],IP[1],NAME[0],NAME[1],MODELO[0],MODELO[1])

11.2.12 Terminal.py

#!/usr/bin/env python

import adquisicion_datos

def Terminal(modelo_1,modelo_2):

global main_bucle

main_bucle=False

cnt=0 #Contador de instrumentos N5752A (Power Supply)

conectados

if modelo_1=='N5752A':cnt+=1

if modelo_2=='N5752A':cnt+=1

while main_bucle==False:

if cnt==0:

key=raw_input('Press any key to close comunication\n')

if key or key=='':

Cierre_Com (0,1) #Medir=0, Cerrar=1

main_bucle=True

if cnt==1:

key=raw_input('\nPress (1) to change N5752A

parametres.\nPress any other key to close comunication\n')

if key=='1':

Mod_Consigna_N5752A(key)

if key!='1':

Cierre_Com (0,1) #Medir=0, Cerrar=1

main_bucle=True

if cnt==2:

Page 89: Antonio Vargas Gómez Automatización, mediante Raspberry pi ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2540pub.pdf · Python 2.7. El motivo de la realización de este proyecto es

89

key=raw_input('\nPress (1) to change first N5752A

parametres. Press (2) to change second N5752A parametres.\nPress any

other key to close comunication\n')

if key=='1':

Mod_Consigna_N5752A(key)

if key=='2':

Mod_Consigna_N5752A(key)

if key!='1' and key!='2':

Cierre_Com (0,1) #Medir=0, Cerrar=1

main_bucle=True

return 0

def Cierre_Com(Medir,Cerrar):

Medir=0

Cerrar=1

adquisicion_datos.Control_Com(Medir,Cerrar) #Cierre de

comunicacion. Consignas = OFF

print("COMUNICACION CERRADA")

return 0

def Mod_Consigna_N5752A(key):

global main_bucle

Medir=0

Cerrar=1

bucl=False

while not bucl:

param=raw_input('\nSelect the number of the parametre to

change.\nPress any other key to close comunication.\n1) Voltage

2)Current\n')

try:

param=int(param)

if param in range (1,3):

adquisicion_datos.Consigna_N5752A(key,param)

bucl=True #Salimos del bucle de

encuesta para coger consigna

else:

Cierre_Com(Medir,Cerrar) #Se selecciona

cualquier numero que no sea 1 o 2

main_bucle=True #Saldremos del bucle

principal sin volver a preguntar

bucl=True

except:

Cierre_Com(Medir,Cerrar) #Se selecciona

cualquier tecla que no sea un numero

main_bucle=True #Saldremos del bucle

principal sin volver a preguntar

bucl=True #Salimos del bucle de

encuesta para coger consigna

return 0