miércoles, 30 de enero de 2013

[Proyecto] Cliente torrent con Transmission y Raspberry Pi - Parte 1: Introducción

Aunque la reciente llegada de MEGA puede revitalizar las descargas directas, desde hace años he sido partidario del uso de BitTorrent. Empecé a utilizarlo hace bastantes años, cuando el mundo de las descargas estaba dominado por eMule y, al principio no le terminaba de ver las ventajas respecto de aquel programa, que tenía buscador integrado y que permitía descargar los archivos de manera más cómoda.

Con el tiempo, he visto el declive de eMule, Kazaa, Pando, Peer2Mail y seguro que me dejo alguno. La ventaja del protocolo BitTorrent es que es descentralizada y por tanto no depende de un servidor central que pueda cerrar. El caso más claro lo tenemos con la difunta Megaupload, que de momento sigue cerrada y sin permitir a sus usuarios el acceso a sus propios archivos.

Otra ventaja de BitTorrent es que, a diferencia de un servidor de descargas convencional, la disponibilidad del archivo se incrementa con el aumento de personas compartiéndolo, disminuyendo así posibles congestiones debidos a descargas masivas. Esto ha hecho que muchas compañías, desde Blizzard hasta Canonical, hagan uso del protocolo BitTorrent para compartir actualizaciones para sus juegos o las versiones de su sistema operativo, respectivamente.

El inconveniente de este sistema es que si sólo nosotros tenemos un determinado archivo compartiendo por torrent, tenemos que tener un PC encendido con conexión a Internet o nadie podrá descargarlo. Aunque en muchos casos podemos simplemente descargar el archivo y apagar el PC, habrá otros en los que queramos dejar ese archivo compartiendo. Sin embargo, un PC convencional puede gastar unos 70~100W encendido, por lo que no es lo más adecuado si queremos tenerlo compartiendo por torrent a todas horas, ya que el gasto en electricidad es considerable.

Y ahí es donde entra el Raspberry Pi, que aunque poco potente, al fin y al cabo es un ordenador, con alguna peculiaridad, pero un ordenador al fin y al cabo. El Raspberry Pi consume muy poco, apenas 2 o 3W según las especificaciones (y como nosotros no utilizaremos la GPU, consumirá aún menos). Si le añadimos un HDD de bajo consumo como un WD Caviar Green o un HDD de 2.5’’ podemos tener un sistema para descargar y compartir por torrent barato de construir y con un consumo muy bajo.

Digo que el Raspberry Pi es un ordenador con peculiaridades porque existen algunos inconvenientes que limitarán en cierta medida el proyecto. A priori se me ocurren los siguentes:
  • Por lo que he visto en foros, al escribir en un HDD con formato NTFS, que es el predeterminado de Windows, la CPU del Raspberry Pi se pone en torno a un 90% y el rendimiento es pobre. Tengo que mirar si existe alguna solución, pero creo que optaré por formatear el HDD directamente en Ext3.
  • He visto también en varios sitios que sin una configuración adecuada, el Raspberry tiende a bloquearse descargando por torrent, debido seguramente a que no es capaz de gestionar el alto número de conexiones y peticiones de red. Tendré que averiguar porqué pasa y ver qué configuración es la adecuada para evitar esto. Ya he visto en varios foros configuraciones que en principio no dan problemas, pero quiero enterarme de todos modos cuál es exactamente el problema.
  • Aunque el Raspberry tiene 2 puertos USB 2.0 y un puerto de red RJ45, realmente los tres van por la misma línea de datos USB 2.0, por lo que es de esperar que la velocidad de descarga baje al transferir archivos y viceversa. De hecho, creo que una de las cosas que más echo de menos del Raspberry es un puerto SATA al que conectar un HDD y no depender de conexiones USB y menos compartidas. Un puerto Gigabit hubiese estado también muy bien, aunque si la línea de datos tiene el ancho de banda de un USB 2.0 no hubiese servido para mucho.
  • El Raspberry no tiene suficiente potencia en los puertos USB para alimentar un HDD, por lo que o bien habrá que usar un HDD con alimentación externa o, como recomiendan en la página principal, un Hub USB autoalimentado.
A pesar de que a priori parezcan muchos problemas, creo que se puede conseguir algo bastante decente, y además nos despreocuparemos del ruido, del calor generado, del consumo y del tamaño; no todo iba a ser malo.

Este proyecto será corto, aunque quizá lo amplíe en un futuro para añadir alguna nueva funcionalidad, por ahora, lo que iremos desarrollando en siguientes entradas será lo siguiente:
  1. Instalación de Raspbian y configuración inicial.
  2. Montaje de HDD para descargas y configuración.
  3. Instalación de Transmission Daemon y configuración.
  4. Acceder a los archivos descargados de forma remota.
Con esto tendremos ya el sistema listo y funcionando. Es posible que en un futuro pueda ampliar el proyecto añadiendo un servidor DLNA o similar, pero prefiero mantenerlo simple de momento, y asegurarme de que esté terminado en un tiempo razonable (no como el anterior proyecto de la radio, que sigue parado de momento).

Nos vemos en el siguiente post, donde instalaremos Raspbian y configuraremos nuestra red doméstica para conseguir una IP fija y una redirección del puerto 80 del router para poder utilizar más tarde la interfaz web de Transmission.

miércoles, 23 de enero de 2013

Cómo añadir nuevas fuentes al Kindle Paperwhite

Una de las mejoras del nuevo Kindle Paperwhite son las nuevas fuentes que se pueden elegir a la hora de leer libros. En mi antiguo Kindle 3, siempre usé la fuente predeterminada, Caecilia, ya que me parece una de las fuentes mejor pensadas para leer. Las letras se distinguen bien, está suficientemente condensada para que podamos leer bastante texto antes de pasar de página y se puede leer cómodamente aunque se utilice un tamaño de fuente pequeño. Además se adaptaba muy bien a la resolución de 600x800 del Kindle 3, mientras que en otras se notaban más los píxeles debido supongo a la forma de las letras.
Sin embargo, el Kindle Paperwhite aumenta la resolución de la pantalla hasta 768x1024, por lo que representa más nítidamente las letras al tener más píxeles disponibles. Aunque estaba contento con Caecilia, quería probar las nuevas tipografías disponibles: Baskerville, Futura, Helvetica y Palatino. Baskerville y Palatino son fuentes serif, a priori más adecuadas para leer textos largos. Helvética y Futura, sin embargo, son san serif, más adecuadas para artículos cortos y títulos.
De las cuatro nuevas fuentes me ha encantado Palatino, que es la que estoy utilizando actualmente, hasta el punto de que ha sustituido a Caecilia como mi fuente por defecto para leer. Sin embargo, recordé haber leído que era posible añadir más fuentes al Kindle 3 para tener disponibles por ejemplo Times New Roman, Georgia o Arial. Tras buscar si se podía hacer lo mismo con el Kindle Paperwhite, encontré un post en mobileread con la solución:
  1. Conectamos el Kindle Paperwhite por USB al PC y abrimos el directorio raíz en el explorador.
  2. Creamos un nuevo archivo y lo renombramos como: USE_ALT_FONTS Hay que tener especial cuidado con eliminar cualquier extensión que pudiera poner el sistema operativo.
  3. Creamos una nueva carpeta en el directorio raíz de nuestro Kindle y la renombramos a fonts.
  4. Copiamos las fuentes que queramos añadir dentro de la carpeta fonts. Es recomendable copiar tanto la versión normal de la fuente (regular) como la negrita (bold), cursiva (italic) y negrita-cursiva (bold-italic) para que el Kindle pueda utilizarlas cuando sea necesario.
  5. Desconectamos el Kindle del PC.
  6. Reiniciamos el Kindle pulsando en el menú y accediendo a configuración. Una vez ahí, volvemos a pulsar en el menú y elegimos reiniciar.
En la imagen de abajo podemos ver el resultado:
Kindle-Paperwhite-2
Como dicen en el post, además de las fuentes que hemos añadido, aparecen otras que tiene instaladas Kindle pero no se muestran por defecto. Veré si hay alguna manera de mostrar sólo las que hayamos añadido nosotros.

lunes, 21 de enero de 2013

[Libros] Cómo funciona la economía para Dummies

 

81ddqxl3UNL._AA1500_Hace unos días terminé de leer este libro, del escritor y profesor Leopoldo Abadía. Recuerdo que me leí su artículo “La crisis ninja” hace unos años y me pareció bastante esclarecedor. En el libro, Abadía vuelve a explicar su visión de la crisis económica actual, centrándose más tarde en las pequeñas y medianas empresas, en las dificultades que sufren actualmente y en su importancia, en la opinión del autor, para salir de la crisis.

Si bien es cierto que para alguien que no haya leído mucho acerca de la crisis económica actual y le interese informarse, el libro presenta un lenguaje claro y sencillo para comprender por encima las causas y el estado actual de las cosas; creo que Abadía ha acabado escribiendo (no se si intencionadamente) un libro poco imparcial, en el sentido de que deja su opinión en casi todos los temas que trata. Aunque en bastantes aspectos estoy de acuerdo con él, no creo que sea una forma adecuada para explicar algo, hubiese preferido una postura lo más imparcial posible y formarme mi opinión sin ideas preconcebidas.

Otro aspecto que no me ha gustado demasiado es el tono que usa el libro para las explicaciones: el autor se esfuerza por utilizar un lenguaje “de andar por casa”, que en mi opinión queda forzado en muchas ocasiones. Veo bien que se intenten explicar los términos complejos de la jerga económica en un lenguaje sencillo, pero varias veces he tenido la sensación de que el tono no es el más adecuado para tratar estos temas.

En la última parte del libro, el autor da su opinión de que la crisis actual, además de económica, es una crisis de decencia; de que la falta de decencia de muchas de las personas (especialmente las que tienen o tenían puestos de responsabilidad en los bancos o la política) es también una causa a considerar cuando se analiza la situación actual. En ese sentido estoy de acuerdo con lo que dice, aunque a lo largo del libro se recalca demasiado este tema.

El libro finaliza con una serie de ideas que podrían dar un empujón para salir de esta situación cuanto antes. En este caso, las propuestas son bastante realistas, sin fórmulas mágicas ni ideas descabelladas. Sin embargo creo que, por sí solas, las propuestas del autor no serán suficientes: hace falta que quieres tienen realmente el poder de la economía remen también en la misma dirección para que realmente haya alguna posibilidad de cambiar de rumbo.

En resumen, un libro entretenido de leer y que puede aportar una idea de las causas de la crisis actual, nuestra situación, y cómo intentar salir de ella. No creo que alguien que haya dedicado tiempo a informarse sobre el tema encuentre nada nuevo, pero puede ser un buen punto de partida para empezar.

Después de esto, me apetece ponerme con algo de literatura. Quizá me vuelva a leer El Conde de Montecristo, que lo leí hace mucho tiempo y apenas recuerdo nada. A ver si consigo una buena versión para Kindle.

sábado, 12 de enero de 2013

[Libros] Festín de cuervos

El blog está un poco parado, ya que en septiembre empecé de nuevo el trabajo, además un máster en mecatrónica y un curso de inglés, por lo que el tiempo que me ha quedado para el proyecto de la radio se ha reducido mucho, y la he dejado aparcada de momento. Por otro lado, con lo que voy aprendiendo en el máster, es posible que pueda incluir alguna cosilla más cuando lo retome.

Una de las cosas que quería hacer es llevar una cuenta de los libros que voy leyendo y releyendo cada año. Así que he pensado en llevarla por aquí aprovechando que estamos ya en enero, y hacer un resumen a final de año como he visto hacer en otros blogs. Empiezo hoy con Festín de Cuervos, que me he estado leyendo estas navidades y que es el cuarto libro de la saga Canción de Hielo y Fuego, que presumiblemente tendrá siete libros en total de los cuales se han publicado cinco hasta el momento.

Esta es una de mis sagas favoritas, así que dejo pendiente escribir entradas para los tres primeros libros de la saga. De momento me centraré en el cuarto.

Festín de Cuervos continúa la historia que dejó Tormenta de Espadas pero en este caso no están presentes todos los personajes de la trama principal, ya que se supone que el quinto libro (Danza de Dragones) tiene el mismo marco temporal que Festín de Cuervos, pero desde el punto de vista de los personajes que no aparecen en éste.

Mi sensación con Festín de Cuervos es el de un libro de transición, como lo fue Choque de Reyes en su día. Eso no significa que sea un mal libro ni mucho menos, y en este caso, el tener menos personajes a la vez me parece una buena idea, ya que permite seguir mejor las historias al centrarse en menos tramas paralelas, veremos si con Danza de Dragones tengo la misma sensación. No se me ha hecho largo ya que me resultó muy ameno de leer, y da vida a personajes que me parecían algo sosos en anteriores libros. Lo único que he echado de menos es más capítulos para Arya, y a algunos personajes que aparecerán en Danza de Dragones.

En resumen, quizá sea el libro más flojo de los cuatro que llevo de la saga, aunque mantiene el nivel. Ahora toca un descansito antes de empezar con Danza de Dragones.

sábado, 1 de septiembre de 2012

Ejecutando la radio al inicio automáticamente

Dado que ya tengo la radio mínimamente funcional, una de las cosas que quería hacer es ejecutarla automáticamente al inicio del sistema, para que pueda utilizarla sin necesidad de conectarme al RPi por SSH para iniciar el programa.

En Internet he encontrado muchas formas de hacerlo, yo explico aquí una, pero seguramente habrá otras muchas que sirvan perfectamente. La información la obtuve de un post de StackOverflow.

En la mayoría de sistemas Linux, el proceso de arranque es el siguiente:

  • El bootloader termina de cargar.
  • Se ejecutan los scripts de /etc/rc.sysinit
  • Se consulta en qué runlevel debe establecerse el sistema consultando /etc/inittab
  • Se ejecutan los scripts del runlevel correspondiente, situados en /etc/rcX.d, donde X es el runlevel del sistema (0, 1, 2…)
  • Por último, se ejecutan los scripts de /etc/rc.local

Como queremos que nuestro sistema sea completamente funcional cuando arranquemos nuestra radio, debemos iniciarla desde /etc/rc.local. Para ello basta con abrir este archivo con permisos de administrador con un editor de texto:

sudo nano /etc/rc.local

Y añadir al final del fichero, justo antes del exit, nuestro programa como podemos ver en la imagen:

image

Ya sólo queda guardar el texto (Ctrl+O), Cerrar nano (Ctrl+X) y reiniciar el sistema. Si todo ha sido correcto, la radio debería arrancar automáticamente. Dejo un vídeo de cómo me funciona a mí:

Mejorando el código (I)

Hasta ahora hemos conseguido mostrar las canciones de la radio en el display del LCDKeypad y controlar la reproducción con uno de los botones. Sin embargo, el código actual es bastante chapucero, por lo que se producen algunos “fallos” un poco extraños. Hoy nos centraremos en corregir algunos de ellos:

Conexión serie sin necesidad de configuración

Un problema que tenía hasta ahora es que para que funcionase bien la conexión serie entre el Arduino y el RPi, tenía que ejecutar primero el programa minicom (del que hablamos en una entrada anterior), el RPi se conectaba correctamente y, al cerrar el programa y conectar mediante el programa en Python no había problemas.

Sin embargo, si no usaba minicom, la conexión se bloqueaba. Después de leerme la documentación de PySerial e ir probando con los distintos parámetros de conexión, comprobé que si habilitaba el flag “rtscts”, que activa el control de flujo por hardware, la conexión se establecía correctamente. El problema es que con esta opción activada, el RPi no se podía comunicar con el Arduino (al contrario no había problema), por lo que aunque podía utilizar los botones, no se mostraba nada en la pantalla.

Mi solución, al menos por ahora, ha sido crear y abrir una conexión serie con el rtscts activado, cerrarla y volverla a abrir con los parámetros por defecto. Creo que es algo parecido a lo que hacía con el minicom antes, donde dejaba que minicom hiciese una primera configuración y luego me permitía abrir sin problemas la conexión en Python. De todas formas, si alguien sabe más del tema, le agradecería que me comentase la forma más correcta de hacerlo, porque en este tema estoy un poco perdido. El código final de la conexión es el siguiente:

  1: # Sets the serial connection
  2: print "Opening serial port..."
  3: portOpened = False
  4: 
  5: while(not portOpened):
  6: 	if(sys.platform == 'win32'):
  7: 		try:
  8: 			ser = serial.Serial('COM4', 9600, rtscts=1)
  9: 			ser.close()
 10: 			ser = serial.Serial('COM4', 9600)
 11: 		except:
 12: 			print "Could not open port"
 13: 	else:
 14: 		try:
 15: 			ser = serial.Serial('/dev/ttyUSB0', 9600, rtscts=1)
 16: 			ser.close()
 17: 			ser = serial.Serial('/dev/ttyUSB0', 9600)
 18: 		except:
 19: 			print "Could not open port"
 20: 	
 21: 	if(ser.name != ""):
 22: 		print "Port opened!",ser
 23: 		portOpened = True
 24: 	else:
 25: 		print "Port can't be opened, retrying..."
 26: 		portOpened = False
 27: 
 28: # Trying with infinite timeout
 29: ser.timeout = None

Ahora esperamos hasta que el Arduino y el RPi están conectados correctamente entre sí antes de iniciar la radio, evitando posibles envíos perdidos.


Exclusión mutua con variable isPlaying


Recordemos que la variable isPlaying controla cuándo se está reproduciendo o no un stream en la radio. Esta variable es global y compartida entre varios hilos, que pueden leer y escribir en ella. Por tanto, si no controlamos el acceso exclusivo a la misma, podemos tener problemas. En mi caso, lo que ocurría es que a veces pulsaba el botón SELECT para parar la reproducción y la radio se volvía loca, ya que se creía que estaba en pausa cuando no lo estaba y viceversa. La solución es utilizar cerrojos para leer y escribir la variable, y evitar así condiciones de carrera y problemas de sincronización. Python tiene varios tipos de directivas de sincronización. Yo he usado la clase Lock.

  1: # Globals
  2: isPlaying = False
  3: # Locks
  4: isPlayingLock = threading.Lock()
  5: 
  6: '''This function receives button interaction from Arduino and respond to them'''	
  7: def button_receiver():
  8: 	print "Receiver started"
  9: 	global isPlaying
 10: 	while(True):
 11: 		serial_in = ser.readline();
 12: 		serial_out = ""
 13: 		
 14: 		if(serial_in == 'BTNSEL\r\n'):
 15: 			if(not isPlaying):
 16: 				print "[A->R] Received SEL: Playing..."
 17: 				# Put mpc to play
 18: 				args = shlex.split("mpc play")
 19: 				subprocess.check_output(args)
 20: 				# Send the info to Arduino
 21: 				serial_out = "DW Play"
 22: 				serial_out += '\n'
 23: 				ser.write(serial_out)
 24: 				serial_out = ""
 25: 				# Sets isPlaying to True
 26: 				time.sleep(1)
 27: 				isPlayingLock.acquire()
 28: 				try:
 29: 					isPlaying = True
 30: 				finally:
 31: 					isPlayingLock.release()
 32: 			else:
 33: 				print "[A->R] Received SEL: Stopping..."
 34: 				# Sets isPlaying to False
 35: 				isPlayingLock.acquire()
 36: 				try:
 37: 					isPlaying = False
 38: 				finally:
 39: 					isPlayingLock.release()
 40: 				# Stop mpc
 41: 				args = shlex.split("mpc stop")
 42: 				subprocess.check_output(args)
 43: 				# Send the info to Arduino
 44: 				serial_out = "DW Stop"
 45: 			
 46: 		elif(serial_in == 'BTNLFT\r\n'):
 47: 			serial_out = "DW BTNLFT OK"
 48: 		elif(serial_in == 'BTNRGT\r\n'):
 49: 			serial_out = "DW BTNRGT OK"
 50: 		elif(serial_in == 'BTNUP\r\n'):
 51: 			serial_out = "DW BTNUP OK"
 52: 		elif(serial_in == 'BTNDWN\r\n'):
 53: 			serial_out = "DW BTNDWN OK"
 54: 			
 55: 		if(serial_out != ""):
 56: 			print "[R->A]",serial_out
 57: 			serial_out += '\n'
 58: 			ser.write(serial_out)
 59: 		else:
 60: 			pass

En la línea 4 creamos un lock, este objeto se puede adquirir, bloqueando el acceso al las variables a las que se acceda hasta que se libere. Podemos ver su funcionamiento en las líneas 27 a 31. Básicamente, activamos el lock con el método acquire, intentamos poner la variable isPlaying a False, y lo consigamos o no liberamos el lock con el método release. Liberar un lock después de utilizarlo es muy importante, ya que en caso contrario podría quedarse bloqueado y no permitir el acceso a isPlaying.


Una vez liberado el lock, el resto de hilos pueden acceder libremente a la variable isPlaying. El caso es que no termino de acordarme (estudié estos mecanismos hace bastante tiempo), pero creo que el lock habría que utilizarlo en cada acceso a isPlaying, y no sólo en accesos de escritura, que es como está ahora mismo. Miraré mis apuntes y lo corregiré si es el caso. De hecho, estoy pensando en hacer una pequeña clase que se encargue de manejar las lecturas y escrituras mediante candados.


Para más detalles, en Wikipedia se explica mucho mejor esta directiva y su uso.


Cambio de play/pause por play/stop


Hasta ahora, al pulsar el botón SELECT mientras se estaba reproduciendo un stream de audio, la radio pausaba el stream, y al volverlo al pulsar reanudaba la reproducción. Esto tiene un pequeño inconveniente: como estamos en una radio online y no con archivos de audio locales, aunque nosotros pausemos la reproducción, ésta continúa en el servidor remoto. Si pausamos unos pocos segundos no pasa nada, pero si la pausa es algo más larga, el búfer del reproductor se llena y al reanudar la canción que estaba sonando se corta al poco tiempo.


Por ello, he decidido que, cuando se pulse el botón SELECT, lo que hará la radio es parar la reproducción, y al volverlo a pulsar, seguirá por lo que esté retransmitiendo la radio en ese momento. Este comportamiento es mucho más lógico que el anterior, ya que al fin y al cabo estamos escuchando una radio, la cual por definición emite independientemente de si la estamos escuchando o no.


Los cambios se pueden ver en las líneas 21 y41 del código anterior, donde en lugar de utilizar mpc toggle, utilizamos mpc play y mpc stop.


Comprobación de la conexión a Internet


Para escuchar la radio por Internet lo primero que necesitamos es, obviamente, una conexión a Internet activa. Hasta ahora no comprobábamos esto, lo que podría dar lugar a errores o a que simplemente no se reproduzca nada. Para evitarlo, haremos un chequeo de la conexión antes de iniciar la radio en sí. La función la he encontrado y adaptado de un post de StackOverflow:

  1: ''' This functon tests the Internet connection '''		
  2: def connectedToInternet():
  3: 	try:
  4: 		urllib2.urlopen("http://www.google.com", timeout=3)
  5: 	except urllib2.URLError:
  6: 		return False
  7: 	return True

Como se puede ver, lo único que hacemos es intentar abrir la página de Google (lo que suelo hacer yo para comprobar si hay Internet en mi casa), y devolver True o False según pueda cargar la página o no. Si Google desapareciese o se cayese, la radio no funcionaría aunque hubiese Internet, pero estoy dispuesto a asumir este riesgo.


Para hacer la comprobación se ha utilizado la librería urllib2 de Python. Esta librería viene incluida en la distribución estándar de Python, por lo que lo único que hay que hacer es importarla al programa.


Comprobando conexiones antes de iniciar el programa


La última modificación que he hecho es comprobar que haya conexión tanto a Internet como al Arduino antes de iniciar los hilos del programa:

  1: if __name__ == "__main__":
  2: 	arduinoReady = False
  3: 	while(not arduinoReady):
  4: 		serial = ser.readline()
  5: 		if(serial == "INITOK\r\n"):
  6: 			arduinoReady = True
  7: 			print "Arduino connected!"
  8: 			ser.write("UP RPi Connected!\n")
  9: 		else:
 10: 			print "Waiting Arduino connection..."
 11: 			time.sleep(1)
 12: 			
 13: 	while(not connectedToInternet()):
 14: 		print "Testing internet connection..."
 15: 		ser.write("DW Waiting Inet...\n")
 16: 		time.sleep(1)
 17: 		
 18: 	ser.write("DW Inet. Connected!\n")
 19: 		
 20: 	rec = threading.Thread(target=button_receiver,name='ButtonReceiverTh')
 21: 	sen = threading.Thread(target=display_sender,name='DisplaySenderTh')
 22: 	rec.start()
 23: 	sen.start()

En el código se comprueba que se haya recibido el INITOK del Arduino para confirmar que esté conectado, y que haya Internet. Cuando todo está correcto, se mostrará un mensaje por el display del LCDKeypad y ya se podrá utilizar la radio.


Corrigiendo sketch de Arduino


Hay veces que al pulsar un botón del Arduino, se me han enviado dos pulsaciones de ese botón. Esto es especialmente molesto en el botón SELECT, ya que si queremos detener la reproducción, al enviarse dos pulsaciones, el stream se detendrá y se volverá a activar.


El “fallo” parece ser de hardware: creo que lo que ocurre es que, después de dejar de pulsar el botón, durante un pequeño intervalo de tiempo, lcd.button vuelve a detectar que el botón se ha pulsado (aunque no se haya hecho). Para solucionarlo, lo único que he hecho es añadir un pequeño retardo de 30ms para evitar esto. No estoy del todo seguro de que ésta sea la causa, pero no se me ocurre otra cosa, ya que lcd.button tiene que detectar que se ha dejado de pulsar el botón antes de enviar la pulsación. Si a alguien tiene otra explicación, le agradecería que la comentase.

  1: // Returns the pressed button
  2: int buttonPressed(){
  3:   int aux = lcd.button();
  4:   if(aux != KEYPAD_NONE){
  5:     while(lcd.button() != KEYPAD_NONE){
  6:     }
  7:     delay(30);
  8:     return aux;
  9:   }
 10:   return KEYPAD_NONE;
 11: }
 12: 

Con estas correcciones la radio comprueba que haya conexión a Internet, se conecta automáticamente al Arduino y funciona sin problemas aparentes. El código ahora es un poco más largo (aunque no llega a 200 líneas), pero todo funciona mejor.


PD: Como indiqué en la entrada anterior, he creado un repositorio con el código del proyecto, por lo que cualquiera que quiera ver el código completo, descargarlo y utilizarlo o modificarlo, puede hacerlo sin problemas.

Repositorio del proyecto Wifi Radio

Para tener todo más organizado y que cualquiera pueda descargarse el código de forma cómoda y pueda ir viendo los cambios, he creado un repositorio en GitHub con el proyecto, y he incluido la librería LCDKeypad que me costó bastante encontrar y tuve que modificar un par de detalles para que funcionase con la IDE de Arduino nueva (1.0.1). Lo pongo aquí para quien le interese.

https://github.com/mpedrero/wifi_radio