Phytonizando el proyecto PicUSB

El proyecto PicUSB lo encontré cuando buscaba una forma de comunicar a un PIC con una PC por medio del estándar USB directamente y no por medio de la emulación CDC (PDF) que crea un puerto RS232 virtual.

Proyecto original

Los archivos del proyecto los bajé hace mucho tiempo  de aquí pero el driver usado es una versión vieja que no soporta windows 7 (debido a las limitaciones propias del driver y la librería de microchip). Este ejemplo está basado en otro proyecto que sí funciona en Windows Vista en la dirección http://www.todopic.com.ar/foros/index.php?topic=2260.0 está la nueva versión y esta hecha por “J1M”.
Lo que hice fue lo mismo que hizo el autor del post gu1llermo en Visual C pero en python: tomar de la API de microchip mpusbapi.dll versión 1.0.0.0 las funciones para comunicarse con el PIC. Las funciones se pueden tomar del código fuente proporcionado por gu1llermo o desde el archivo funciones_dll.txt.
Si se tiene instalado mingw instalado en Windows, se pueden obtener los nombres de las funciones con:
objdump -p mpusbapi.dll
El proyecto original utiliza una aplicación llamada PicUSB que se muestra a continuación:

Al presionar el botón Nro. de dispositivos busca los dispositivos conectados que tengan el valor PID = 0925 y VID = 1231, si encuentra alguno entonces se mostrará un 1 al lado, si no, mostrará un 0. En la primer caja de texto se escribe un valor que representa a un comando, si el número escrito es 1 el LED conectado al PIC se enciende, si es un 2 el LED  se apaga, el comando enviado aparece al lado. Las cajas de texto restantes contienen “parámetros”, que son solo números que al ser enviados con el botón Transmite2 regresa su valor multiplicado por 2.

El circuito original es el siguiente:


Pero este circuito tiene algunos problemas: no siempre funciona y a veces deja de funcionar completamente.

Introducción al estándar USB

USB (Universal Serial Bus) es un estándar desarrollado a mediados de los 90’s que define los cables, conectores y protocolos usados para la conexión, comunicación y alimentación entre computadoras y dispositivos electrónicos.

Componentes del Bus

Las comunicaciones USB necesitan una computadora host con soporte USB. La computadora host es una PC u otra computadora que posea un controlador de host USB y un concentrador de raíz. El concentrador de raíz o root hub es el primer hub al que se le conecta cualquier dispositivo USB y esta embebido en el controlador de host.

El controlador de host da formato a los datos par la transmisión en el bus y traduce los datos recibidos a un formato que los componentes del sistema operativo puedan entender.

El concentrador de raíz y el controlador de host juntos, detectan los dispositivos conectados y desconectados, se encargan de las peticiones de SALIDA del controlador de host, y pasan datos entre los dispositivos y el controlador host. Además del concentrador de raíz,  el bus puede tener uno o mas hubs externos.

Topología

La topología o arreglo de las conexiones en el bus, es de tipo estrella con niveles. En el centro de cada estrella esta un hub, y cada conexión al hub es un punto en la estrella. El concentrador de raíz esta en el host. Un hub externo tiene una conexión ascendente (lado del host) para la conexión con el host y una o más conectores o conexiones internas descendentes (lado del dispositivo) hacia los dispositivos embebidos.

Hasta 5 hubs externos se pueden conectar en serie con un limite de 127 periféricos y hubs incluyendo el concentrador de raíz. Sin embargo, los límites de ancho de banda y de programación (scheduling) pueden prevenir que un solo controlador host se comunique con esta cantidad de dispositivos. Para incrementar el ancho de banda disponible para los dispositivos USB, muchas PC’s tienen múltiples controladores de host, cada uno controlando independientemente un Bus.

Prueba del acelerómetro BMA180 con PIC y PyQwt

En este ejemplo se tomarán como base los ejemplos anteriores. Así que, tendremos tres gráficas indicando las aceleraciones en tiempo real con su respectivo valor numérico, pero además, un indicador de interrupción y un termómetro.
Comenzaremos con la breakout board de Sparkfun. Esta placa tiene todos los pines del BMA180 separados y dos capacitores como filtros.

Descripción de los pines

VDD: Alimentación del sensor.
GND: Conexión a tierra.
INT: Salida Digital. Indica si un evento de interrupción ha ocurrido. Lógica positiva.
CS: Entrada digital.Chip select. Corresponde al pin CSB. Cuando este pin esta a 0V, se activa la funcionalidad SPI.
SCK: Entrada digital. Entrada de la señal de reloj.
SDO: Entrada/salida digital. Salida SPI o configuración de la dirección I2C.
SDI: Entrada/salida digital. Entrada SPI o datos seriales I2C.
VIO: Entrada de alimentación digital. Corresponde al pin VDDIO. La interfaz serial con el microcontrolador puede manejar voltajes diferentes que la alimentación del sensor. Por ejemplo, el sensor pude ser alimentado a 2.0V y la interfaz serie puede trabajar a 3.6V.

Prueba del acelerómetro MMA7260 con PIC y PyQwt II

En esta ocasión me basaré en la clase QwtDial para crear algo parecido a un indicador de actitud.
De la guía de usuario de qwt:
“La clase QwtDial proporciona un control de intervalo redondeado.
QwtDial esta diseñado para ser una clase base para los indicadores (dial) como velocímetros, brújulas, relojes:
Un dial contiene una escala y una aguja indicando el valor actual del dual. Dependiendo del Modo uno de ellos es fijo y el otro esta rotando…”
De la descripción anterior podemos sacar la conclusión de que un dial se compone de dos elementos básicos: una escala y una aguja. Estos elementos se dibujan “a mano”, es decir, las líneas que componen el dial, los números, las figuras, los colores. No se puede escoger directamente que indicador queremos, sino que tenemos que dibujarlo. Esto es algo complicado pues hay que tener los conceptos básicos de geometría presentes y dominarlos.
La otra opción es tomar las clases de los ejemplos incluidos y ajustarlas a nuestras necesidades, que es lo que hice en este caso. Copié a un archivo clases.py las clases que necesitaba para el indicador de actitud (el tercer indicador de la imagen anterior) que son:
EnumList: Función que es llamada dentro de las clases necesarias.
AttitudeIndicator: Esta clase dibuja el círculo y las escalas del indicador.
AttitudeIndicatorNeedle: Esta clase dibuja la aguja central, que para el indicador de actitud, es un triangulo rojo.

El acelerómetro digital BMA180

El acelerómetro digital de tres ejes BMA180 es producido por Bosch y se puede conseguir en Sparkfun. Puede medir aceleraciones tanto dinámicas como estáticas con una gran precisión. Debido a sus tres ejes perpendiculares da la posición absoluta en un campo de gravedad. Este sensor es un arreglo de dos chips. Un ASIC evalúa los tres canales de salida del elemento sensor micromecánico que funciona de acuerdo al principio de capacitancia diferencial.
El BMA180 proporciona una salida digital completa de 14 bits por medio de la interfaz SPI o I2C. Con el comando apropiado se puede elegir entre el rango completo de aceleraciones que va de 1g hasta 16g. Un filtro de segundo orden Butterworth que va desde los 10Hz hasta los 600Hz es incluido, que proporciona un pre-acondicionamiento de la señal medida. La resolución típica a 2g es de 0.5mg y una precisión por debajo de los 0.25° en aplicaciones de medida de la inclinación.  El consumo de corriente típico es de 650μA a 2.4V en el modo estándar. Además, el sensor puede ser puesto en modo de bajo consumo, donde informa al sistema hosts de un cambio en la aceleración por medio del pin de interrupción. Esta función puede ser utilizada para despertar (wake-up) al sistema host, del modo sleep.

Cubo 3D con OpenGL, pygame y acelerómetro.

En una ocasión se me ocurrió hacer uso de joystick para manejar un servo y que contará con una interfaz gráfica. Como he estado utilizando mayormente el lenguaje Python, busqué un ejemplo y encontré uno del cual base ese ejemplo, sin embargo no he podido encontrar el ejemplo original. Parece que era Basic Motion Graphics with Python pero su pagina web ya no esta disponible.

En este ejemplo se moverá un cubo 3D de colores, con el acelerómetro. Si el acelerómetro se inclina hacia los costados, el cubo se desplazará hacia la derecha o izquierda, si se inclina al frente o atrás, este rotará hacia el adelante o hacia atrás, si se mueve hacia arriba y hacia bajo, el cubo se moverá hacia arriba y hacia abajo.

En la parte final, se encuentra comentado el código para controlar el cubo con un joystick USB.

Los movimientos registrados por el acelerómetro son enviados a la PC por medio de un microcontrolador. El microcontrolador es un PIC12F510 y el firmware del microcontrolador es el mismo que el de la entrada Prueba del acelerómetro MM7260 con PIC y PyQwt.

Los módulos necesarios son:

-PyOpenGL

-PIL

-PyGame

-Pyserial

 

Código:

Prueba del acelerómetro MMA7260 con PIC y PyQwt

En la entrada anterior  se mostraron las características y el funcionamiento de este sensor. Ahora utilizaré la librería gráfica PyQwt para mostrar las mediciones que serán convertidas de analógico a digital mediante el PIC12F510 y serán transmitidas a una PC a través del estándar RS-232.

PIC12F510

El PIC12F510 es un microcontrolador producido por Microchip Technology. Este chip es de la familia Baseline y sus características mas importantes son:
    Encapsulado de 8 pines.     Oscilador interno de precisión de 4/8 Mhz.     3 canales ADC de 8 bits.     Es un microcontrolador de 8 bits.     Bajo consumo de corriente: 100 mA en modo Sleep.     ICSP.     El rango de voltaje es de 2.2V a  5.5V.     Cuenta con un timer de 8 bits.
Este microcontrolador a pesar de ser de bajo costo, cumple con lo necesario para realizar este ejemplo con sus tres ADC de 8 bits.
La programación de este uControlador fue hecha en CCS y es muy sencilla, se puede dividir en tres pasos: Configuración del microcontrolador, Adquisición de datos y envío de datos a la PC. El programa completo se muestra a continuación:
mainp12510accel.h

El acelerómetro analógico MMA7260

Introducción

Un acelerómetro, es un dispositivo electrónico, en el que su señal de salida, es dependiente de la aceleración a la que ha sido sometido.

El acelerómetro MMA7260 de Freescale Semiconductors tiene las siguientes características:

  • Mide la aceleración en tres ejes.
  • Sensibilidad configurable (1.5g/2g/4g/6g)
  • Bajo consumo de corriente: 500 uA.
  • Modo sleep: 3uA.
  • Alta sensibilidad (800 mV/g @ 1.5g)
  • Bajo voltaje de operación: 2.2V – 3.6V.

Y se utiliza típicamente en:

  • Discos duros de reproductores MP3: Detección de caída libre.
  • Laptops.
  • Celulares.
  • En brújulas electrónicas para compensar la inclinación.
  • En juegos: para detectar la inclinación y el movimiento.

Su bajo consumo de corriente lo hace ideal para trabajar en aplicaciones donde su fuente de alimentación principal son baterías.

Plot con pyqt4 y qwt5 primera parte

Python es un lenguaje de programación interpretado muy fácil de aprender y de utilizar, con una gran cantidad de módulos que nos permiten hacer casi cualquier cosa.
En este ejemplo, se muestra como crear una interfaz grafica sencilla hecha en Qt en conjunto con la librería qwt para hacer un grafico de una onda senoidal que podamos manipular. Elegí qwt sobre matplotlib, por que para graficas en tiempo real, es mucho mas rapida la libreria qwt que matplotlib.

Lo que debe hacer la grafica es lo siguiente:

    Dibujar una onda seno y una onda coseno.
    Tener limites el eje X de [0,100] y en el eje Y de [-100,100].

Este ejemplo es de referencia para futuros proyectos.

Por comodidad hice la plantilla en qt designer, utilizando un widget vertical layout como contenedor de la gráfica. Para que el código creado en qt designer pueda ser usado en python, se utiliza pyuic que viene incluido en el paquete PyQt. Con esta línea

pyuic4 -o nombredelarchivodesalida.py nombredelarchivo.ui

el archivo con extension ui es el que se crea en qt designer y se obtiene un archivo de salida que puede ser utilizado en python.

La plantilla de la ventana es la siguiente:

Le quite el tool bar y el status bar. El cuadro rojo es del vertical layout donde se inserta el grafico.
Para poder utilizar la interfaz hecha en qt designer, la importamos como si fuera un modulo:

  1. from Ui_ejemploqwt_ui import Ui_MainWindow

Primero creamos el marco donde se dibujarán todos los elementos que incluyamos en la gráfica, esta clase se llama qwtplot. Esto se hace con la siguiente función:

  1. def createPlot(self, color):
  2.     #en esta parte se crea el plot que seria todo el marco y los numeros "el cascaron"
  3.     plot = Qwt.QwtPlot()
  4.     plot.setCanvasBackground(QtGui.QColor("black"))
  5.     plot.setAxisTitle(Qwt.QwtPlot.xBottom, 'X Axis')
  6.     plot.setAxisTitle(Qwt.QwtPlot.yLeft, 'Y Axis')
  7.     plot.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100)
  8.     plot.setAxisScale(Qwt.QwtPlot.yLeft, -100, 100,10)
  9.     plot.setAxisAutoScale(Qwt.QwtPlot.xBottom)

Corremos el programa y obtenemos la siguiente ventana:

Plot con pyqt4 y qwt5 Segunda parte

En esta segunda parte las funciones que se añadirán a la grafica son las siguientes:

    Una línea (marker) que corte el gráfico por el centro, Y= 0
    Un indicador de coordenadas.
    Marcar cada punto en la grafica en el que se hace clic.
    Además de crear una línea horizontal donde se haga clic que “corte” la grafica.
Para crear el indicador de coordenadas se utiliza la clase QwtPlotPicker. La estructura general de este objeto es la siguiente:
  1. QwtPlotPicker (int xAxis,
  2. int yAxis,
  3. int selectionFlags,
  4. RubberBand rubberBand,
  5. DisplayMode trackerMode,
  6. QwtPlotCanvas *)
Donde:
xAxis: Es el eje de donde toma el valor mostrado con respecto al eje X. El plot puede tener dos ejes X, uno a la izquierda y otro a la derecha. En es elemento se indica de donde se tomará el valor de referencia.
yAxis: Tiene la misma función que xAxis pero tomando el eje Y como referencia.
selectionFlags: Puede seleccionarse entre PointSelection que devuelve un valor tipo QPoint o RectSelection que devuelve un valor tipo QRect.
Rubberband: Establece la forma de las líneas que indican el punto a seleccionar. Puede ser, una cruz que muestra lar coordenadas X y Y, una línea horizontal que solo muestra las coordenadas del eje X, una línea vertical que solo muestra las coordenadas del eje Y, sin líneas, una elipse, y un rectángulo. Estos dos últimos modos, solo se pueden utilizar con el tipo RectSelection.
DisplayMode: Puede ser siempre visible, visible cuando solo cuando se haga clic o invisible.
QwtPlotCanvas: Es el objeto tipo plot al que se le va a insertar el selector (picker).
En el siguiente ejemplo se creará un selector que indique las coordenadas X y Y, que sea visible solo cuando se haga clic en el plot, con el color de texto en blanco, y color de las líneas en color magenta.
  1. picker = Qwt.QwtPlotPicker(Qwt.QwtPlot.xBottom,
  2.         Qwt.QwtPlot.yLeft,
  3.         Qwt.QwtPicker.PointSelection,
  4.         Qwt.QwtPlotPicker.CrossRubberBand,
  5.         Qwt.QwtPicker.ActiveOnly,
  6.     plot.canvas())
  7.     picker.setTrackerPen(Qt.QPen(Qt.Qt.white)) #text color
  8.     picker.setRubberBandPen(Qt.QPen(Qt.Qt.magenta))
Cuando ejecutamos el programa, al hacer clic en cualquier punto del plot obtenemos lo siguiente:
Ahora crearemos una línea horizontal que corta el gráfico por la mitad, esto se hace con un objeto qwtMarker. Solo necesitamos indicar las coordenadas de la línea, si es horizontal o vertical, y el color. Esto se hace de la siguiente manera: