miércoles, 28 de mayo de 2014

Ampliando el alcance del Blog

El dia de hoy por fin me aventuraré a hacer algo que desde hace tiempo tenia cusriosidad de hacer, y es extender el alcance de este blog.

Cuando inicie con la Raspberry Pi hace cerca de dos años, fue mi primer experiencia con un equipo de computo embebido, un SoC. Por fin conoci la posibilidad de controlar de manera sencilla equipo electrónico básico sin tanta complicación como habia sucedido en los años de la universidad.

Tenia en mis manos una equipo que me alejaba un poco del tradicional esquema de la computadora de escritorio como solución cara, grande, ruidosa y me acercaba mas a la posibilidad de soluciones portatiles, de enfoque especializado y con interfaces mas amigables para una solución que pudiera ser desatendida.

Comence a pensar en como desarrollar enclosures con las caracteristicas necesarias para poder agregar una pantalla tactil, lo cual me llevo a investigar que tipos de pantallas tactiles hay, como se conectan y cuales son sus capacidades. Obviamente un sistema asi necesitaria ser inalambrico y por consecuencia con una fuente de poder autónomo. Habia que investigar eso, como conectarlas, ¿WiFi era la unica opcion? ¿cuales otras existen? ¿Bluetooth, interesante, pero es viable?, ¿alguna otra para una aplicación pensada para un pequeño restaurante?, ¿es la misma solución viable para equipos de control en una granja?... infinidad de preguntas me surgieron, unas llegaron a respuestas satisfactorias, algunas aun no han sido contestadas, y otras estoy en proceso de entender que es lo que necesito, en otras palabras, necesito reformular mis preguntas para poder preguntar bien.

En este camino me he topado con montones de cosas que no creia estuvieran al alcance del hobbista novato. Desde los clasicos botones y palancas de arcade hasta equipo electronico complejo para funciones como GPS. Todo al alcance del bolsillo promedio (no mas de $30 USD por pieza, que si no barato, es asequible con un poco de esfuerzo).

Cuando pedi mi primer modulo de GPS para probar con la Raspberry Pi, comence a documentarme para saber que es lo que buscaba y me tope con cosas como el protocolo NMEA 0183, algo bastante sencillo y que podia ser implementado solo conectado el modulo adecuado al puerto RS-232 de la Raspberry Pi. Fui feliz.

La Raspberry Pi necesitaba mostrar los resultados, por lo que necesitaba una pantalla. Algo no muy complejo, no muy caro, que no necesitara fuente de alimentación externa, etcetera. Encontre unas pantallas de 1.8" de solo 128x160 pixeles, incluia un lector/escritor de memorias SD y que es controlado por I2C y SPI.

Con esto me documente acerca del formato para intercambio de informacion GPS, mejor conocido como GPX y comence a cablear mi GPS con la Raspberry Pi, agregue la pantalla, recompile multiples veces el kernel para lograr que se visualizara bien y ¡voila! funciono.

Esto era demasiado esfuerzo. Tengo funcionando un equipo que tiene 512 MB de RAM y 700 MHz para obtener un dato por segundo desde el GPS, grabarlo en un archivo y mostrarlo en una pantalla de definición limitada.

Durante la investigación de todo esto, en muchos lugares vi mencionado Arduino por aqui, Arduino por alla, Arduino Uno R3, Arduino Leonardo, Arduino no se que mas. Así que me propuse investigar que era esto y si me podria servir.

Y en este punto es donde tanto yo, como este blog a partir de hoy ha ampliado su alcance, donde tambien les compartire mis experiencias de novato con Arduino, donde trabajaremos con Raspberry Pi + Arduino, donde les pondremos cables entre los dos dispositivos, donde los conectaremos por red, donde mandaremos mensajes de uno a otro por diferentes medios, todo para alcanzar algun objetivo.

Asi que a partir de hoy, este playground incluirá entradas dedicadas a Arduino, no sin antes comentar acerca de las características, similitudes y diferencias de este dispositivo con referencia a la Raspberry Pi.

Espero con esto, tener mas herramientas para publicar contenido de manera mas frecuente y que ademas esto les sea de interes y utilidad.

Gracias por leer el blog. Saludos a todos!


lunes, 28 de abril de 2014

Raspberry Pi procesando eventos MIDI con Python (Parte 2)

Al estar leyendo esta segunda parte de este artículo, se asume que ya se tienen cubiertos todos los requisitos técnicos y de conocimientos cubiertos en la primera parte, si aún no estan completos, te invito a que des un click aquí y la visites.


Enfocandonos en MIDI


Ya tenemos sonido en nuestra Raspberry Pi, ya reproduce archivos de onda, ahora ¿que hace falta para reproducir archivos MIDI? ¿Que hace falta para que obtengamos sonido de un archivo MIDI?

El acercamiento que tendremos en este proyecto sera muy similar a lo que en seguridad informatica se le conoce como "Man-in-the-middle" en el cual tendremos como origen, el programa reproductor de archivos MIDI aplaymidi que es parte del paquete ALSA que ya instalamos (ver la primera parte de este artículo), en el medio nuestro script de python, y en el otro extremo, el sintetizador de sonido. De esta manera, el reproductor obtiene del archivo todos y cada uno de los eventos MIDI almacenados en el archivo, nuestro script recibira esos mensajes y actuará de acuerdo al los datos enviados en el mensaje, reenviando el mensaje (sin modificarlo, es decir, haciendo la función de MIDI THRU) hacia el sintetizador que finalmente reproducira el sonido.

El reproductor MIDI

Como ya se menciono, utilizaremos aplaymidi como nuestro reproductor MIDI, este se encargará de extraer la informacion de nuestro archivo origen y de enviarla a nuestro script de python. La linea de comando es muy sencilla, tal como se muestra a continuación:

aplaymidi /path/a_nuestro/archivo.mid --port 129

Aunque es nuestra fuente de información, esto sera lo ultimo que ejecutaremos, pues necesitamos tener completo todo lo demás para que funcione como esperamos.

Nuestro script de Python


Para poder recibir, poder interpretar y reenviar los mensajes MIDI a otro cliente, necesitamos poder comunicarnos en el mismo medio que es a traves de ALSA, por lo que les sugiero el uso de la librería alsaseq desarrollada por Patricio Paez Serrato (home page pp.com.mx) que tiene las interfaces con Python para la comunicación con secuenciadores ALSA.

El sitio original donde esta la información para la instalación de la libreria es http://pp.com.mx/python/alsaseq/project.html y donde puden descargar la versión mas reciente de alsaseq que al momento de escribir este articulo es la 0.4.1 es http://pp.com.mx/python/alsaseq/ 

Una vez instalada la libreria alsaseq, solo es necesario copiar y pegar el siguiente script en su editor de texto favorito y guardarlo en una ruta conocida con el nombre midilights.py,

import RPi.GPIO as GPIO
import alsaseq

# Set up the GPIO mode
GPIO.setmode(GPIO.BOARD)

#Initialize a list with the GPIO pin numbers we are going to use
gpiopins = [7,8,10,11,12,13,15,16,18,19,21,22]

# Set up pins listed as outputs
print "Setting up pins ",
for p in gpiopins :
 print str(p) + " ",
 GPIO.setup(p, GPIO.OUT)
 GPIO.setup(p, GPIO.LOW)
print "for OUPUT - LOW completed."

#Initialize all LEDs to off
for y in range(0,12) :
  GPIO.output(gpiopins[y],False)

alsaseq.client( 'MIDI Lights', 1, 1, False )
alsaseq.connectfrom( 0, 20, 0 )
alsaseq.connectto( 1, 128, 0 )

while 1:
    if alsaseq.inputpending():
      ev = alsaseq.input()
      alsaseq.output(ev)
      if ev[7][0] != 9:
        #print ev
        event = ev[0]
        note  = ev[7][1]%12
        dura  = ev[7][2]
        if event == 7:
          #print "Turn off ", note
          GPIO.output(gpiopins[note],False)
        elif event == 6:
          if dura == 0:
            #print "Turn off ", note
            GPIO.output(gpiopins[note],False) 
          else:
            #print "Turn on ", note
            GPIO.output(gpiopins[note],True)
        else:
          print "Not handled : ", ev

# to reset every channel that has been set up by this program to INPUT with no pullup/pulldown and no event detection.
GPIO.cleanup()

Como se puede ver este script inicializa los siguientes puertos GPIO como salidas 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21 y 22 por lo que puedes suponer que para obtener el resultado deseado deberemos de conectar un LED a cada uno de ellos.

En este punto asumo que ya sabes como hacer el circuito básico para hacer esto, si no, te recomiendo leer esta entrada del blog :

Controlar un LED con los GPIOs de la Raspberry Pi


El sintetizador de sonido

Podriamos pensar en esto como la cereza del pastel, es decir, donde por fin obtendremos audio y podremos confirmar que las luces responden a los sonidos que inician y terminan durante la reproduccion de la música.

En lo personal les recomiendo Timidity++ que es un sintentizador de muy alta calidad, sin embargo tal vez sea algo demasiado pesado para una computadora sencilla como la Raspberry Pi, pues requiere demasiado CPU para poder ofrecer la calidad que tiene. Para el alcance de este artículo les dare las instrucciones de como instalar Timidity++, sin embargo los invito a que ustedes prueben con otros sintentizadores para que comparen resultados y los compartan con los lectores de este blog.

Timidity++ esta disponible en los repositorios oficiales de Raspbian, por lo que su instalación es sencilla. Primero que nada procederemos a actualizar nuestros repositorios. Desde la consola ejecutar los siguientes comandos;

$ sudo apt-get update

$ sudo apt-get install timidity freepats timidity-daemon pmidi fluid-soundfont-gm fluid-soundfont-gs

tras la ejecución del segundo comando el sistema preguntará si desean descargar e instalar un monton de paquetes mas de los que dependen los que deseamos instalar, hay que aceptar para que tengamos todo instalado correctamente.

Una vez descargados e instalados los paquetes requeridos por Tmidity y sus dependencias, te recomiendo reiniciar tu Raspberry Pi para que de esta manera el daemon de Timidity++ arranque durante el proceso de inicio del sistema y nos olvidemos de el, pues estara disponible cuando lo necesitemos a partir de ese momento.

Iniciemos el show


Cuando el sistema este reiniciado, ya sea que accedamos a el de manera remota (SSH) o de manera local en el teclado y monitor, necesitaremos abrir dos consolas, si lo haces por SSH, solamente conectate dos veces y listo, si lo haces de manera local si estas en modo gráfico (no lo recomiendo), solamente habre dos ventanas de terminar, si estas por consola presiona CTRL+ALT+F2 y te cambiara a una segunda consola, para volver a la primera presiona CTRL+ALT+F1

En una de las dos consolas iremos a la ruta donde guardamos el script arriba mencionado y ejecutaremos el comando:

sudo python midilights.py

Este comando nos dara una salida sencilla avisandonos que configuro los puertos GPIO y que esta a la espera de mensajes MIDI en el puerto 129.

Nos cambiamos a la siguiente ventana/consola/conexión para ejecutar el siguiente comando

aconnect -o

este comando desplegara una salida similar a esta:

client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
client 128: 'TiMidity' [type=user]
    0 'TiMidity port 0 '
    1 'TiMidity port 1 '
    2 'TiMidity port 2 '
    3 'TiMidity port 3 '
client 129: 'MIDI Lights' [type=user]

    0 'Input port      '

lo que nos importa ver es ese cliente numero 129, de nombre 'MIDI Lights' que lo que nos confirma es que nuestro script esta listo para recibir conexiones en el puerto 129.

Ahora si, estamos listos para enviarle los mensajes a nuestro script, esto lo haremos ejecutando el programa reproductor de archivos MIDI, el cual estará direccionado al puerto 129, para que nuestro script haga su trabajo de procesar y reenviar al sintetizador.

Antes de ejecutar este comando no olvides tener unas bocinas conectadas a tu Raspberry Pi para escucharla ejecutar tu archivo

El ultimo comando a ejecutar sera:

aplaymidi /ruta/a_algun/archivo.mid --port 129

si todo ha sido ejecutado y validado con cuidado, a partir de este momento deberiamos tener sonido y un pequeño show de luces como en el siguiente video:


Como siempre, agradezco su atención leyendo este blog y para cualquier duda o comentario, estoy a sus ordenes, solo tengan paciencia si no les contesto pronto pero siempre intentare ayudarles aunque sea tarde.