osciloscopio por usb de 40mhz: estructura del software

4
Introducción Una programa gráfico en wxPython consta de una Aplicación y varios Frames, que pertenecen a ella. Estos frames son justamente las diferentes ventanas de la apli- cación. Como en nuestro caso el software tiene una sola ventana, el mismo tiene un solo Frame. Al disparar la aplicación (oscusb.py), ésta abre el frame por defecto (oscframe.py) que es la ventana que se ve cuando se ejecuta el programa. El comunicación con el osciloscopio se realiza a tra- vés del driver que se encuentra implementado en el archi- vo oscctrl.py como una clase de python y es utilizado desde oscframe.py para enviar comando y recibir datos. Control de la Interfaz Gráfica La creación de la ventana se realiza (al igual que en cualquier aplicación gráfica) creando un cuadro (o Frame) el cual controla el funcionamiento de la ventana de la apli- cación gráfica. A dicho cuadro se le asignan controles (botones, etiquetas, cuadro para ingresar texto, etc) en coordenadas específicas. Las coordenadas pueden darse en pixels o en proporciones, lo cual permite que la ventana puede mantener su aspecto al ser maximizada o cambiada de tamaño. A los diferentes controles (por ejemplo, botones) se les define un comportamiento a tra- vés de eventos que son disparados cuando se realiza una acción sobre ellos (por ejemplo, pulsar un botón). Al ser disparados, dichos eventos llaman a una fun- ción especificada predefinida al crear el Frame. Asimismo, otros controles son de salida (por ejemplo, el display del osciloscopio) los cuales pueden ser modifi- cados arbitrariamente desde el código aplicación a través de métodos que éstos proveen (por ejemplo, dibujar una línea, cambiar el color de fondo, etc). Conexión con el osciloscopio La comunicación con el osciloscopio se realiza a tra- vés de la clase provista por el driver (oscctrl.py) al dispa- rarse ciertos eventos. Osciloscopio por USB de 40MHz Séptima Parte: Estructura del Software Conclusión En esta sección estamos brindando la expli cación paso a paso del funcionamiento e implementación de un osciloscopio de 40MHz para utilizarlo en una computadora, a través de su puerto USB, estamos en condi ciones de comenzar a describir el software empleado. Aclaramos que estamos realizan do la descripción completa de este equipo desde hace varias ediciones y que ya publi camos los temas referentes al hardware y firmeware del equipo. A continuación expli - caremos “cómo funciona el software”. Por: Pablo Hoffman y Martín Szmulewicz http://www.pablohoffman.com Saber Electrónica 76 MONTAJE

Upload: diego-vallejo

Post on 23-Mar-2016

225 views

Category:

Documents


2 download

DESCRIPTION

En esta sección estamos brindando la expli - cación paso a paso del funcionamiento e implementación de un osciloscopio de 40MHz para utilizarlo en una computadora, a través de su puerto USB, estamos en condi - ciones de comenzar a describir el software empleado.

TRANSCRIPT

Page 1: Osciloscopio por USB de 40MHz: Estructura del Software

Introducción

Una programa gráfico en wxPython consta de unaAplicación y varios Frames, que pertenecen a ella. Estosframes son justamente las diferentes ventanas de la apli-cación. Como en nuestro caso el software tiene una solaventana, el mismo tiene un solo Frame.

Al disparar la aplicación (oscusb.py), ésta abre elframe por defecto (oscframe.py) que es la ventana que seve cuando se ejecuta el programa.

El comunicación con el osciloscopio se realiza a tra-vés del driver que se encuentra implementado en el archi-vo oscctrl.py como una clase de python y es utilizadodesde oscframe.py para enviar comando y recibir datos.

Control de la Interfaz Gráfica

La creación de la ventana se realiza (al igual que encualquier aplicación gráfica) creando un cuadro (o Frame)el cual controla el funcionamiento de la ventana de la apli-cación gráfica. A dicho cuadro se le asignan controles

(botones, etiquetas, cuadro para ingresar texto, etc) encoordenadas específicas. Las coordenadas puedendarse en pixels o en proporciones, lo cual permite que laventana puede mantener su aspecto al ser maximizada ocambiada de tamaño. A los diferentes controles (porejemplo, botones) se les define un comportamiento a tra-vés de eventos que son disparados cuando se realiza unaacción sobre ellos (por ejemplo, pulsar un botón).

Al ser disparados, dichos eventos llaman a una fun-ción especificada predefinida al crear el Frame.

Asimismo, otros controles son de salida (por ejemplo,el display del osciloscopio) los cuales pueden ser modifi-cados arbitrariamente desde el código aplicación a travésde métodos que éstos proveen (por ejemplo, dibujar unalínea, cambiar el color de fondo, etc).

Conexión con el osciloscopio

La comunicación con el osciloscopio se realiza a tra-vés de la clase provista por el driver (oscctrl.py) al dispa-rarse ciertos eventos.

Osciloscopio por USB de 40MHz Séptima Parte:

Estructura del Software Conclusión

En esta sección estamos brindando la expli -

cación paso a paso del funcionamiento e

implementación de un osciloscopio de

40MHz para utilizarlo en una computadora, a

través de su puerto USB, estamos en condi -

ciones de comenzar a describir el software

empleado. Aclaramos que estamos realizan -

do la descripción completa de este equipo

desde hace varias ediciones y que ya publi -

camos los temas referentes al hardware y

firmeware del equipo. A continuación expli -

caremos “cómo funciona el software”.

Por: Pablo Hoffman y Martín Szmulewicz

http://www.pablohoffman.com

Saber Electrónica

76

MONTAJE

Page 2: Osciloscopio por USB de 40MHz: Estructura del Software

Actualmente la aplicación sigue el siguiente mecanis-mo para conectarse con el osciloscopio:

Intenta conectarse al primer puerto serie disponible

en el PC (COM1 en caso de Windows, /dev/ttyACM0 en

caso de linux).

Si logra conectarse envía un comando VERS (ya lo

veremos en detalle cuando desarrollemos el tema: “pro -

tocolos de comunicación”), de lo contrario prueba con el

siguiente puerto disponible que encuentra.

Si obtiene respuesta al comando VERS, entonces

considera que la comunicación con osciloscopio se ha

realizado exitosamente y despliega la versión de firmwa -

re del mismo (la cual fue obtenida en la respuesta del

comando VERS).

Este mecanismo de barrido fue por un razón decomodidad ya que, debido a que osciloscopio generadinámicamente un puerto serie virtual cada vez que seconecta, éste no siempre era el mismo, aún cuando seconectase el osciloscopio en el mismo puerto USB. Porlo tanto, el barrido nos ahorró el tiempo de estar buscan-do y configurando el puerto virtual del osciloscopio.

Sin embargo, a pesar de contar con dichas ventajas,reconocemos que el mecanismo de barrido debe ser sus-tituido en el producto final puesto que, al enviar informa-ción a todos los puertos, puede interferir con el funciona-miento de algún dispositivo conectado al PC por puertoserie. Para este problema existen dos soluciones, unatrivial y una prolija:

La solución es trivial y consiste simplemente en colo -

car (en la aplicación) un selector del puerto serie a utili -

zar para el osciloscopio.

La solución prolija consiste en desarrollar un driver

USB personalizado para el osciloscopio que no involucre

puertos serie virtuales de por medio.

El único otro momento donde el programa se comu-nica con el osciloscopio es al pulsar el botón Capturar enel cual envía un comando de captura, precedido por loscomandos de configuración de los parámetros de captu-ra (HDIV, DUAL, etc).

Desplegado de Muestras en Pantalla

La graficación de las muestras recibidas del oscilos-copio es realizada a través del objeto wxDC de la libreríawxWidgets, el cual (a diferencia de usar el API de win32,por ejemplo) lo hace independiente de la plataforma.

A continuación se muestra un esbozo reducido de larutina de graficación:

size = dc.GetSize()dc.SetPen(wx.GREEN_PEN)top = min(len(data), size.x)lastx, lasty = 0, 0vdiv = vdivs[self.vdivch.GetSelection()]for i in range(0, top):

val = (data[i] - 128) / 255 / vdivx = iy = int(size.y/2*val)if x > 0:

dc.DrawLine(lastx, lasty, x, y)lastx = xlasty = y

dc.SetPen(wx.NullPen)

Se puede observar que se utilizan las funcionesSetPen y DrawLine del objeto wxWC que permiten selec-cionan el color del trazo y dibujar una línea entre dospuntos, respectivamente.

Comunicación con el Osciloscopio

En particular, resulta de especial importancia comen-tar sobre el uso de hilos para la comunicación con el osci-loscopio, ya que de lo contrario la aplicación funcionaríamuy lenta y poco responsiva. Esto es porque, al activarla captura el programa está continuamente enviandocomandos de captura al osciloscopio y recibiendo susdatos. Entonces, si esto se hace en primer plano (que esla forma trivial de hacerla) el programa queda colgadoesperando los datos del osciloscopio hasta que éstos lle-gan, para finalmente los graficarlos. El problema es que,como el tiempo de transferir los datos del osciloscopio ala PC es mucho mayor comparado con el resto de lostiempos, el programa está continuamente esperandodatos del osciloscopio y mientras esto sucede la ventanano responde, lo cual resulta un efecto extremadamentemolesto para el usuario y deja la aplicación inusable.

Para solucionar este problema se utilizó la tecnologíade hilos en el cual, al presionar el botón de captura laaplicación dispara una especie de sub-programa (llama-do hilo) que corre paralelamente a la aplicación y seencarga de comunicarse con el osciloscopio para adqui-rir los datos y, una vez que los obtiene, notifica del suce-so al programa principal a través de un evento, con elcual también le transfiere los datos.

La aplicación principal, al recibir el evento con losdatos, lo único que tiene que hacer es extraer los datos ygraficarlos, lo cual es un proceso muy rápido y por lotanto la ventana no queda congelada.

Como ya se mencionó anteriormente, python es unlenguaje fuertemente orientado a objetos.

Saber Electrónica

77

Estructura del Software de un Osciloscopio de 40MHz

Page 3: Osciloscopio por USB de 40MHz: Estructura del Software

Por lo cual, en el escenario de captura antes descrip-to, cada rol es cumplido por una clase. Ellas son:

El funcionamiento del programa principal está a cargo

de la clase Frame1.

El sub-programa que se corre en un hilo corre es laclase AcquireThread .

El evento que genera el hilo (AquireThread) y lo envía

al programa principal (Frame1) es la clase AcquireEvent

Finalmente, la clase encargada de comunicarse con el

osciloscopio es Osc.

En el diagrama de la figura 1 se muestra la interacciónque ocurre entras las diferentes clases del software, parallevar a cabo la adquisición de datos del osciloscopio.

Los números rojos indican (de forma ordenada) todoslos pasos ejecutados por cada una de las clases, paraobtener una secuencia de muestras del osciloscopio ydesplegarlas en pantalla.

Esto ocurre cuando el usuario activa el botón Capturarde la interfaz y continúa corriendo ininterrumpidamentehasta que el botón es desactivado. Por lo tanto, mientrasel botón Capturar esté activado, los pasos del 1 al 8 seejecutan cíclicamente.

Como puede verse también en el diagrama, la claseFrame1 (que es la controla el funcionamiento de la inter-faz) sigue interactuando con el usuario independiente-mente del resto de las clases. Sólo interrumpe breve-mente el control de la interfaz cuando llega el eventoAquireThread, del cual extrae los datos y los grafica en lapantalla.

Si el botón Capturar sigue activado, inmediatamentedispara un nuevo hilo de captura (AquireThread) y regre-sa a su tarea de controlar la interfaz. Como el proceso deatender el evento y desplegar los datos ocurre muy rápi-do, el usuario no se percata de la demora y obtiene laimpresión de que la interfaz nunca se cuelga, que es jus-tamente el objetivo de usar los hilos.

Montaje

Saber Electrónica

78

Figura 1

Page 4: Osciloscopio por USB de 40MHz: Estructura del Software

Hilo de Captura

Todo el funcionamiento mencionado en la secciónanterior se realiza utilizando la clase Thread de python yextendiéndola. Esto es lo que hace la claseAcquireThread, que hereda de la clase Thread.

El código de la clase AcquireThread es muy simple yse muestra continuación:

class AcquireThread(Thread):def __init__(self, notify_window):

Thread.__init__(self)self._notify_window = notify_window

def run(self):win = self._notify_windowosc = win.oschd = win.hdivch.GetSelection()size = 512

if win.osc.acquire(count=size):chardata = win.osc.getData()data = []for c in chardata:

data.append(ord(c))

w x . P o s t E v e n t ( s e l f . _ n o t i f y _ w i n d o w,

AcquireEvent(data))else:

w x . P o s t E v e n t ( s e l f . _ n o t i f y _ w i n d o w,AcquireEvent(None))

De particular interés son las líneas wx.PostEventdonde se dispara el evento una vez terminada la capturade datos. En caso de haber algún error (segunda línea dewx.PostEvent) el hilo envía None en lugar de los datos locual notifica al programa principal que hubo un error alcapturar los datos.

Para la notificación y comunicación de datos entre elhilo de captura y la aplicación se utiliza la clasewx.pyEvent de wxPython, extendiéndola para que permi-ta enviar los datos dentro de si misma. El código de dichaclase se presenta a continuación:

class AcquireEvent(wx.PyEvent):def __init__(self, data):

wx.PyEvent.__init__(self)self.SetEventType(EVT_RESULT_ID)self.data = data

Note que aquí la única extensión que se le hizo a laclase base (wx.PyEvent) fue la de agregarle un campo dedatos (data) el cual es usado para transportar los datosdel osciloscopio. ✪

Saber Electrónica

79

Estructura del Software de un Osciloscopio de 40MHz