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!
RasPi Playground
Aquí estaré publicando las pruebas y resultados que obtenga con el uso de la Raspberry Pi con diferentes objetivos. Desde interacción con hardware hasta computadora de uso personal o servidor.
miércoles, 28 de mayo de 2014
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.
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.
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.
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,
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 :
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.
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:
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.
Etiquetas:
ALSA,
MIDI,
Python,
Raspberry Pi,
RPi.GPIO
viernes, 4 de octubre de 2013
Raspberry Pi procesando eventos MIDI con Python (Parte 1)
Otro de mis pasatiempos, y para el que no soy muy bueno por cierto, es la música. He intentado aprender a tocar algunos instrumentos pero no he tenido la paciencia necesaria para desarrollar las habilidades, sin embargo gracias a familiares cercanos que viven de la música he aprendido un poco de las bases y esto me ha servido para poder ayudarles en el escenario como parte de su staff conectando cables tanto de audio como MIDI, llevandome a trasladar esos conocimientos a mi area de comfort, las computadoras.
Desde los inicios de la computación casera, las computadoras han sido capaces de generar sonido, las antiguas computadoras traian una bocinita integrada al chasis, que era incapaz de reproducir la gran gama de sonidos que actualmente son capaces de reproducirse gracias a las tarjetas de sonido y sintetizadores integrados.
Esto último es importante entenderlo y diferenciarlo para el alcance de este proyecto.
La reproducción de archivos de onda es la generación de sonido teniendo como datos de entrada los valores de los muestreos de la amplitud de onda a determinada frecuencia, es decir, los valores discretos de la onda a una frecuencia y resolucion determinadas, un ejemplo de esto es la reproducción de un CD de música y archivos WAV (entre otros) que tienen valores típicos de frecuencia de muestreo de 44.1 KHz (o 44100 muestras por segundo) con una resolución de 16 bits (2^16 = 65536) para los valores de la amplitud de onda por cada canal.
Una de las ventajas de este acercamiento es que la reproducción es independiente del dispositivo y debería de sonar igual en todos lados (sin considerar variables como amplificadores o altavoces) pues la onda original se esta reconstruyendo de la manera mas fiel posible con referencia a la fuente.
Estos archivos suelen ser muy grandes en tamaño para mantener su fidelidad y son ideales para ser procesados en cualquier DAW (Digital Audio Workstation).
MIDI es el acrónimo en ingles para Musical Instrument Digital Interface que describe todo un protocolo, interfaz digital y conectores que permiten el intermabio de información entre instrumentos musicales electrónicos, computadoras y dispositivos compatibles.
La tecnología MIDI fue estandarizada en 1983, por lo que debemos de entender que es algo un poco viejo, sin embargo es un estandar actualmente muy utilizado en la industria musical actual, a pesar de sus 30 años de vida.
Si han puesto atención habrán notado que hasta el momento jamas he hablado de sonido relacionado con MIDI, y es porque el sonido no se transmite a traves de las conexiones MIDI, lo unico que viaja entre dispositivos son mensajes MIDI que el dispositivo receptor interpretará de acuerdo a su implementación, esto puede ser algo como un tick de reloj o el evento de reproducir la nota B# de un piano de cola por 123 milisegundos, que hacer con cierto mensaje, depende totalmente de quien recibe el mensaje, nada mas.
El sonido generado por un dispositivo MIDI es una característica muy particular del dispositivo en si, es decir, si uno tiene dos sintetizadores MIDI de diferente marca y ambos reciben el mismo mensaje de reproducir una cierta nota de un instrumento especifico, no sonarán igual, y es posible que aún dos dispositivos de la misma marca y modelo, expuestos a diferentes situaciones de trabajo, temperatura y uso generen sonido diferente para el mismo evento.
La razón del comportamiento anterior es que el sonido es generado por la circuitería que sintetiza la onda del sonido solicitado, por lo que cada implementación es única. Existe también la opcion de sintetizar el sonido por software, y esta es la opción que mas adelante nosotros utilizaremos.
Ya para finalizar solo queda mencionar que el tamaño de los archivos MIDI es muy pequeño, pues solo guarda los mensajes que deben ser enviados, no el sonido en si, para escucharlos se requiere de un sintetizador, ya sea por software o por hardware y que a pesar de todo tienen grandes ventajas como poder variar los instrumentos que se reproducen, cambiar el tempo y hasta generar la partitura de la música almacenada.
Ya que tenemos conocimiento de las bases sobre las que sustentaremos nuestro proyecto, comenzaremos con la configuración del sonido en la Raspberry Pi.
Dependiendo de la versión de Raspbian instalada en su computadora, el módulo de sonido puede estar o no configurado por default. Para saberlo, haremos la siguiente prueba:
lsmod | grep snd_bcm2835
Si este comando nos devuelve algo, significa que el módulo esta cargado en memoria y puedes evitar los siguientes pasos de esta sección.
Al leer esta linea, asumo que el módulo de sonido no esta instalado y que necesitas un poco de guia al respecto, asi que sigamos los siguientes pasos.
Primero, instalar ALSA que es el acrónimo de Advanced Linux Sound Architecture, para esto, hay que ejecutar los siguientes comandos para instalar ALSA y sus utilerias y posteriormente reiniciar el equipo:
Las computadoras y el sonido
Desde los inicios de la computación casera, las computadoras han sido capaces de generar sonido, las antiguas computadoras traian una bocinita integrada al chasis, que era incapaz de reproducir la gran gama de sonidos que actualmente son capaces de reproducirse gracias a las tarjetas de sonido y sintetizadores integrados.
Bocina integrada al chasis de la computadora
Al dia de hoy, es muy sencillo y hasta natural esperar sonido de alta definición en nuestras computadoras ya sea originado por procesamiento de ondas o por síntesis.
Esto último es importante entenderlo y diferenciarlo para el alcance de este proyecto.
Archivos de onda
La reproducción de archivos de onda es la generación de sonido teniendo como datos de entrada los valores de los muestreos de la amplitud de onda a determinada frecuencia, es decir, los valores discretos de la onda a una frecuencia y resolucion determinadas, un ejemplo de esto es la reproducción de un CD de música y archivos WAV (entre otros) que tienen valores típicos de frecuencia de muestreo de 44.1 KHz (o 44100 muestras por segundo) con una resolución de 16 bits (2^16 = 65536) para los valores de la amplitud de onda por cada canal.
Discretización de una onda análoga
Estos archivos suelen ser muy grandes en tamaño para mantener su fidelidad y son ideales para ser procesados en cualquier DAW (Digital Audio Workstation).
Archivos MIDI
MIDI es el acrónimo en ingles para Musical Instrument Digital Interface que describe todo un protocolo, interfaz digital y conectores que permiten el intermabio de información entre instrumentos musicales electrónicos, computadoras y dispositivos compatibles.
La tecnología MIDI fue estandarizada en 1983, por lo que debemos de entender que es algo un poco viejo, sin embargo es un estandar actualmente muy utilizado en la industria musical actual, a pesar de sus 30 años de vida.
Si han puesto atención habrán notado que hasta el momento jamas he hablado de sonido relacionado con MIDI, y es porque el sonido no se transmite a traves de las conexiones MIDI, lo unico que viaja entre dispositivos son mensajes MIDI que el dispositivo receptor interpretará de acuerdo a su implementación, esto puede ser algo como un tick de reloj o el evento de reproducir la nota B# de un piano de cola por 123 milisegundos, que hacer con cierto mensaje, depende totalmente de quien recibe el mensaje, nada mas.
El sonido generado por un dispositivo MIDI es una característica muy particular del dispositivo en si, es decir, si uno tiene dos sintetizadores MIDI de diferente marca y ambos reciben el mismo mensaje de reproducir una cierta nota de un instrumento especifico, no sonarán igual, y es posible que aún dos dispositivos de la misma marca y modelo, expuestos a diferentes situaciones de trabajo, temperatura y uso generen sonido diferente para el mismo evento.
La razón del comportamiento anterior es que el sonido es generado por la circuitería que sintetiza la onda del sonido solicitado, por lo que cada implementación es única. Existe también la opcion de sintetizar el sonido por software, y esta es la opción que mas adelante nosotros utilizaremos.
Ya para finalizar solo queda mencionar que el tamaño de los archivos MIDI es muy pequeño, pues solo guarda los mensajes que deben ser enviados, no el sonido en si, para escucharlos se requiere de un sintetizador, ya sea por software o por hardware y que a pesar de todo tienen grandes ventajas como poder variar los instrumentos que se reproducen, cambiar el tempo y hasta generar la partitura de la música almacenada.
Sonido en la Raspberry Pi
Ya que tenemos conocimiento de las bases sobre las que sustentaremos nuestro proyecto, comenzaremos con la configuración del sonido en la Raspberry Pi.
Dependiendo de la versión de Raspbian instalada en su computadora, el módulo de sonido puede estar o no configurado por default. Para saberlo, haremos la siguiente prueba:
lsmod | grep snd_bcm2835
Si este comando nos devuelve algo, significa que el módulo esta cargado en memoria y puedes evitar los siguientes pasos de esta sección.
Al leer esta linea, asumo que el módulo de sonido no esta instalado y que necesitas un poco de guia al respecto, asi que sigamos los siguientes pasos.
Primero, instalar ALSA que es el acrónimo de Advanced Linux Sound Architecture, para esto, hay que ejecutar los siguientes comandos para instalar ALSA y sus utilerias y posteriormente reiniciar el equipo:
$ sudo reboot
Espera que la Raspberry Pi reinicie, una vez reiniciada, cargaremos el módulo de sonido de manera manual
- $ sudo modprobe snd_bcm2835
y lo configuraremos para que utilice la salida de audio de 3.5mm
- $ sudo amixer cset numid=3 1
En este punto deberiamos de ser capaces de escuchar algo al conectar bocinas o audifonos a la computadora. Podemos probar instalando el reproductor de linea de comando mpg321, el siguiente comando lo hará por nosotros:
$ sudo apt-get -y install mpg321
Una vez instalado mpg321 y sus dependencias, descarguemos un MP3 y reproduzcamoslo:
$ wget http://www.flashkit.com/imagesvr_ce/flashkit/soundfx/Cartoon/Laughter/demonic_-daniel_a-8513/demonic_-daniel_a-8513_hifi.mp3
$ mpg321 demonic_-daniel_a-8513_hifi.mp3
Debes de haber escuchado una risa malevola como la que cualquiera haría una vez que ha configurado el sonido por primera vez en linux :)
Por el momento dejare hasta aqui esta entrada, sabiendo que quienes estan siguiendola ya tienen el sonido configurado, en la segunda parte nos dedicaremos a la parte MIDI y a procesarlos con Python para obtener algo similar a esto
Como siempre, si tienen cualquier duda o comentario, no duden en hacerlo!
Saludos y hasta la próxima!
Etiquetas:
ALSA,
MIDI,
Python,
Raspberry Pi,
RPi.GPIO
sábado, 28 de septiembre de 2013
Raspberry Pi ejecutando MAME controlado con un WiiMote
El día de hoy, después de muchos meses sin actualizar el blog, quiero compartirles este proyecto que puede ser bastante atractivo en mas de un sentido, pues si eres gamer retro o tienes curiosidad en entrar en el mundo del control inalámbrico e interactivo esto te puede dar algunas ideas.
Lo primero que tenemos que saber es que el control WiiMote se comunica de manera inalámbrica usando Bluetooth, lo cual nos lleva a tener como requisito un dispositivo Bluetooth USB compatible.
El segundo requerimiento es obviamente el emulador MAME, la version que se ejecuto al grabar este video fue instalada siguiendo las instrucciones de este sitio http://blog.sheasilverman.com/2012/06/raspberry-pi-and-mame-part-2/ , una vez instalado el emulador. necesitaremos algunas ROMS para jugar, en este enlace pueden descargar algunas de estas ROMS que son 100% legales http://www.mamedev.org/roms/ .
El siguiente requisito es cargar en memoria el módulo de kernel uinput con el siguiente comando:
sudo modprobe uinput
tras la ejecución del comando, si no están firmados en el sistema como root, les pedirá su contraseña, y una vez introducida, no se obtendrá mas salida. Para confirmar que el módulo esta cargado, ejecutamos el siguiente comando:
Los requerimientos
Lo primero que tenemos que saber es que el control WiiMote se comunica de manera inalámbrica usando Bluetooth, lo cual nos lleva a tener como requisito un dispositivo Bluetooth USB compatible.
El segundo requerimiento es obviamente el emulador MAME, la version que se ejecuto al grabar este video fue instalada siguiendo las instrucciones de este sitio http://blog.sheasilverman.com/2012/06/raspberry-pi-and-mame-part-2/ , una vez instalado el emulador. necesitaremos algunas ROMS para jugar, en este enlace pueden descargar algunas de estas ROMS que son 100% legales http://www.mamedev.org/roms/ .
El siguiente requisito es cargar en memoria el módulo de kernel uinput con el siguiente comando:
sudo modprobe uinput
tras la ejecución del comando, si no están firmados en el sistema como root, les pedirá su contraseña, y una vez introducida, no se obtendrá mas salida. Para confirmar que el módulo esta cargado, ejecutamos el siguiente comando:
lsmod
este nos listará los módulos que esten cargados en memoria, y su salida será algo similar a esto:
Module Size Used by
uinput 6599 0
snd_bcm2835 16432 0
snd_pcm 77728 1 snd_bcm2835
snd_seq 53482 0
snd_timer 20110 2 snd_pcm,snd_seq
snd_seq_device 6462 1 snd_seq
snd 58744 5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
snd_page_alloc 5169 1 snd_pcm
leds_gpio 2243 0
led_class 3570 1 leds_gpio
MAME funciona por default con el teclado, es decir, ciertas teclas se usan para control de dirección y las diferentes acciones que se requieran en el juego, por lo que necesitaremos crear un "traductor" que reciba la información del WiiMote a traves del dispositivo Bluetooth y envie al emulador el evento de teclado adecuado de acuerdo a la acción.
El Código
De nuevo recurriremos a Python para este objetivo, la libreria cwiid es la que tiene toda la lógica para la comunicación con el WiiMote, y la libreria uinput es la que nos permitirá generar los eventos de teclado para que MAME los use como entrada.
Antes de iniciar con el código, quiero darle credito a Brian Hensley por su script wiimotest.py y a Chris Swan por su script rpi-gpio-jstk.py en los cuales me basé para crear este código.
#-------------------------------------------------------------------------------
# Name: Wii Mame
# Purpose: Script that connects a Wiimote via Bluetooth using cwiid to read
# inputs and send keystrokes using uinput
#
# Author: Ismael Martinez based on scripts
# wiimotest.py by Brian Hensley and
# rpi-gpio-jstk.py by Chris Swan
#
# Created: 01/10/2012
# Copyright: OpenSource
#-------------------------------------------------------------------------------
#!/usr/bin/env python
import cwiid
import time
import sys
import uinput
def main():
events = (uinput.KEY_LEFT, uinput.KEY_RIGHT, uinput.KEY_UP, uinput.KEY_DOWN, uinput.KEY_1, uinput.KEY_5, uinput.KEY_LEFTCTRL, uinput.KEY_ESC, uinput.KEY_ENTER)
device = uinput.Device(events)
# Bools to keep track of movement
btn_a = False
btn_b = False
btn_one = False
btn_two = False
btn_pls = False
btn_min = False
btn_up = False
btn_dwn = False
btn_lft = False
btn_rgt = False
debug = False
attempt = 0
max_attempts = 3
while attempt < max_attempts:
attempt = attempt + 1
print 'Press button 1 + 2 on your Wii Remote...'
time.sleep(1)
try:
wm=cwiid.Wiimote()
break
except:
if attempt <= max_attempts:
print 'Press button 1 + 2 on your Wii Remote... attempt #', attempt,' of ',max_attempts
else:
print 'No Wii Remote found after ', max_attempts, ' attempts. Finishing execution.'
sys.exit(0)
print 'Wii Remote connected...'
print '\nPress [A]+[B] buttons to disconnect the Wii and end the application'
time.sleep(1)
wm.rpt_mode = cwiid.RPT_BTN
while True:
bitmask = bin(wm.state['buttons'])[2:].rjust(13, '0')
#print bitmask
if bitmask[-1] == "1": #wm.state['buttons'] == 1:
if debug:
print ' [2] pressed \n'
if (not btn_two) :
btn_two = True
device.emit(uinput.KEY_LEFTCTRL, 1)
else:
if btn_two:
btn_two = False
device.emit(uinput.KEY_LEFTCTRL, 0)
if bitmask[-2] == "1": #wm.state['buttons'] == 2:
if debug:
print ' [1] pressed \n'
if (not btn_one) :
btn_one = True
device.emit(uinput.KEY_LEFTCTRL, 1)
else:
if btn_one:
btn_one = False
device.emit(uinput.KEY_LEFTCTRL, 0)
if bitmask[-3] == "1": #wm.state['buttons'] == 4:
if debug:
print ' [B] button pressed \n'
if (not btn_b) :
btn_b = True
device.emit(uinput.KEY_1, 1)
else:
if btn_b:
btn_b = False
device.emit(uinput.KEY_1, 0)
if bitmask[-4] == "1": #wm.state['buttons'] == 8:
if debug:
print ' [A] button pressed \n'
if (not btn_a) :
btn_a = True
device.emit(uinput.KEY_5, 1)
else:
if btn_a:
btn_a = False
device.emit(uinput.KEY_5, 0)
if bitmask[-5] == "1": #wm.state['buttons'] == 16:
if debug:
print ' [-] button pressed \n'
if (not btn_min) :
btn_min = True
device.emit(uinput.KEY_LEFTCTRL, 1)
else:
if btn_min:
btn_min = False
device.emit(uinput.KEY_LEFTCTRL, 0)
if bitmask[-8] == "1": #wm.state['buttons'] == 128:
if debug:
print ' [Home] button pressed \n'
device.emit(uinput.KEY_ESC, 1)
time.sleep(0.25)
device.emit(uinput.KEY_ESC, 0)
time.sleep(0.25)
device.emit(uinput.KEY_DOWN, 1)
time.sleep(0.25)
device.emit(uinput.KEY_DOWN, 0)
time.sleep(0.25)
device.emit(uinput.KEY_ENTER, 1)
time.sleep(0.25)
device.emit(uinput.KEY_ENTER, 0)
time.sleep(0.25)
if bitmask[-9] == "1": #wm.state['buttons'] == 256:
if debug:
print ' [Down] button pressed \n'
if (not btn_dwn) :
btn_dwn = True
device.emit(uinput.KEY_DOWN, 1)
else:
if btn_dwn:
btn_dwn = False
device.emit(uinput.KEY_DOWN, 0)
if bitmask[-10] == "1": #wm.state['buttons'] == 512:
if debug:
print ' [Up] button pressed \n'
if (not btn_up) :
btn_up = True
device.emit(uinput.KEY_UP, 1)
else:
if btn_up:
btn_up = False
device.emit(uinput.KEY_UP, 0)
if bitmask[-11] == "1": #wm.state['buttons'] == 1024:
if debug:
print ' [Right] button pressed \n'
if (not btn_rgt) :
btn_rgt = True
device.emit(uinput.KEY_RIGHT, 1)
else:
if btn_rgt:
btn_rgt = False
device.emit(uinput.KEY_RIGHT, 0)
if bitmask[-12] == "1": #wm.state['buttons'] == 2048:
if debug:
print ' [Left] button pressed \n'
if (not btn_lft) :
btn_lft = True
device.emit(uinput.KEY_LEFT, 1)
else:
if btn_lft:
btn_lft = False
device.emit(uinput.KEY_LEFT, 0)
if bitmask[-13] == "1": #wm.state['buttons'] == 4096:
if debug:
print ' [+] button pressed \n'
if (not btn_pls) :
btn_pls = True
device.emit(uinput.KEY_LEFTCTRL, 1)
else:
if btn_pls:
btn_pls = False
device.emit(uinput.KEY_LEFTCTRL, 0)
if wm.state['buttons'] > 0 :
if debug:
print ' <-'
if wm.state['buttons'] == 12 :
print 'closing Bluetooth connection. Good Bye!'
exit(wm)
time.sleep(.02) # Poll every 20ms (otherwise CPU load gets too high)
if __name__ == '__main__':
main()
El resultado y algunos detalles acerca del orden de ejecución en el siguiente video.
Gracias por seguirme, Saludos!
Etiquetas:
Bluetooth,
MAME,
Python,
Raspberry Pi,
WiiMote
domingo, 31 de marzo de 2013
Controlar una matriz de LEDs de 5x5 con Raspberry Pi, Python y GPIOs
Controlar una matriz de LEDs de 5x5 con Raspberry Pi, Python y GPIOs
Tras una larga ausencia que raya en el descuido de este blog, me encuentro de nuevo por aqui para platicarles como hacer una matriz de LEDs de 5x5 para el despliegue de texto.
Ya que tenemos el Cubo de LEDs de 3x3x3 pareceria que hacer un matriz de 5x5 sería ir un paso atras en cuanto a complejidad, sin embargo este proyecto nos ayudara a perfeccionar el manejo de algunos elementos de Python como lo son las listas.
En esta ocasión tomaremos ventaja de un efecto visual denominado POV (Persistencia de la Visión por sus siglas en inglés) el cual nos permite engañar a nuestro sentido de la vista haciéndonos creer que múltiples LEDs están encendidos cuando en realidad prendiendo y apagando a un ritmo muy rápido.
El material
Para armar la matriz necesitaremos 25 LEDs, 5 transistores NPN, cable (preferentemente de dos colores diferentes) cautín y soldadura.
El material seleccionado para hacer la base es una espuma recubierta de cartón delgado de 5mm que es ligero, barato y puede darnos una estructura sólida para nuestra matriz. Ademas de un cutter, bisturí o exacto para poder hacer cortes precisos y pegamento para unir las piezas.
Se corta un cuadrado de 27cm por lado que sera la base, además se cortarán 8 rectángulos de 5cm x 27 cm para las divisiones internas, 2 rectángulos de 28 cm x 5.5 cm y por ultimo 2 rectángulos de 27 cm x 5.5 cm.
La construcción
Sobre la base cuadrada se harán marcas en cada uno de los cuatro lados a las siguientes distancias de la orilla:
- 5 cm
- 5.5 cm
- 10.5 cm
- 11 cm
- 16 cm
- 16.5 cm
- 21.5 cm
- 22 cm
ahora uniremos con lápiz las lineas correspondientes de tal forma que queden definidos 25 cuadrados, ademas quedarán identificadas las lineas donde estarán las 8 divisiones (4 horizontales y 4 verticales).
Les recomiendo trazar también unas lineas diagonales que dividan todos los cuadrados en dos triángulos rectángulos y después trazar las diagonales opuestas para de esta manera tener identificado el centro de cada uno de los cuadrados, que será la posición donde colocaremos nuestros LEDs.
Los 8 rectángulos de 5 cm x 27 cm tambien tendrán las mismas marcas por el lado largo que los lados del cuadrado ademas, por el lado corto, habra que hacer una marca a 2.5 cm de cada lado y unirla con lápiz a todo lo largo.
En estos 8 rectángulos cortaremos esas pequeñas áreas de 5mm x 2.5 cm (todas por el mismo lado del rectángulo) que nos permitirán inter-conectar estas piezas para armar el entrelazado de las divisiones interiores. Una vez inter-conectadas las piezas nos aseguraremos de que esten bien alineadas para poder poner pegamento por uno de sus lados y afianzarlo a la base cuadrada en su posición.
Ya para finalizar, tenemos dos pares de rectángulos, uno de ellos ligeramente mas largo que el otro. Estos nos servirán paralos bordes de la matriz, asegúrese de pegar primero el par de rectángulos largos en lados opuestos y al final los mas cortos para terminar con la matriz.
El circuito
Para controlar la matriz, utilizaremos solo 10 pines de la Raspberry Pi, 5 para las filas y 5 para las columnas. Todas las filas estarán conectando entre sí los ánodos y al final iran a uno de los pines de la Raspberry Pi, las columnas unirán los cátodos e irán conectados a la salida de los transistores NPN, tal como lo hicimos en el cubo de 3x3x3.
El código
Como se menciono al inicio de este post, el hacer este ejercicio nos ayudara a perfeccionar nuestras habilidades para usar listas en Python, la razón de esto es que cada uno de los caracteres que desplegaremos en la matriz lo deberemos de definir nosotros en una lista de 5x5 que tendra 1 o 0 en cada una de sus posiciones, correspondiendo directamente a LED encendido o apagado. A continuación les muestro el código que se uso para generar los caracteres numéricos. Para facilitar la visualización y legibilidad, el número 0 ha sido realzado en los elementos de la lista.
#numbers
chars.append([
"01110",
"10011",
"10101",
"11001",
"01110"
])
chars.append(["00100","01100","00100","00100","11111"])
chars.append(["11110","00001","01110","10000","11111"])
chars.append(["11110","00001","00110","00001","11110"])
chars.append(["10001","10001","01111","00001","00001"])
chars.append(["11111","10000","11110","00001","11110"])
chars.append(["01111","10000","11110","10001","01110"])
chars.append(["11111","00010","00100","00100","00100"])
chars.append(["01110","10001","01110","10001","01110"])
chars.append(["01110","10001","01111","00001","00110"])
Este es el código que mostrará los caracteres en la matriz:
#!/usr/bin/env python
# Import required libraries
import time
import RPi.GPIO as GPIO
# Set up the GPIO mode
GPIO.setmode(GPIO.BCM)
#Initialize a list with the GPIO pin numbers we are going to use
gpiopins = [14,15,18,21,23,24,10,25,8,7]
# 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 completed."
cols = [14,18,23,10,8]
rows = [7,25,24,21,15]
chars = []
chars.append([...
...
...])
def getLetter(letter):
return chars[ord(str(letter))]
def drawMatrix(mtx):
#print mtx
t = time.clock() + 0.4
while t > time.clock() :
for i in range(0,5) :
for j in range(0,5) :
if mtx[i][j] == "1" :
GPIO.output(cols[j],True)
GPIO.output(rows[i],True)
#time.sleep(0.005)
GPIO.output(cols[j],False)
GPIO.output(rows[i],False)
def drawString(text):
text = text + chr(32)
for l in range(len(text)):
drawMatrix(getLetter(text[l]))
time.sleep(0.4)
def scrollText(text):
mtx = ["","","","",""]
text = chr(32) + text.strip() + chr(32)
l1 = getLetter(text[0])
for i in range(len(text)-1):
l2 = getLetter(text[i+1])
for j in range(0,5):
mtx[j] = l1[j] + "000" + l2[j]
#print mtx
drawScrollingMatrix(mtx)
l1 = l2
#time.sleep(0.05)
def drawScrollingMatrix(mtx):
for offset in range(0,8):
t = time.clock() + 0.14
while t > time.clock() :
for i in range(0,5) :
for j in range(0,5) :
if mtx[i][j+offset] == "1" :
GPIO.output(cols[j],True)
GPIO.output(rows[i],True)
GPIO.output(cols[j],False)
GPIO.output(rows[i],False)
#initialize all LEDs to off
for i in range(0,5) :
GPIO.output(cols[i], False)
GPIO.output(rows[i], False)
#control variables
delay = 0.5
print "Start patterns"
drawString("RASPBERRY PI & PYTHON & GPIO")
scrollText("RASPBERRY PI & PYTHON & GPIO")
El resultado
Saludos!
Etiquetas:
LED,
Python,
Raspberry Pi,
RPi.GPIO
Suscribirse a:
Entradas (Atom)