El propósito de esta entrada es doble: 1) dejar anotados los pasos que he seguido por si en algún momento yo mismo necesito consultarlos y 2) que cualquier poseedor de un Raspberry Pi que quiera hacer algo así encuentre todo lo necesario reunido en un mismo lugar. El resto puede dejar de leer aquí mismo.
El Raspberry Pi, entre otras muchas cosas, es una excelente solución de bajo consumo y silenciosa para tener en casa un servidor personal más que digno funcionando las 24 horas. Sobre estas líneas veis el mío en su estado actual. Está conectado doblemente al router blanco que se ve detrás: lo alimenta a través de una salida USB y le proporciona conectividad Ethernet. Además, se ven dos unidades USB conectadas:
- La de debajo, pequeña y blanca, que apenas se ve, contiene el sistema operativo. Antes lo tenía en la tarjeta SD, pero al poco tiempo se acabaron corrompiendo los archivos porque escribía bastante. Mi decisión fue dejar el boot en la SD, que se cambia muy de vez en cuando, y trasladar el resto del sistema a una unidad flash: ese USB. Desde entonces, ningún problema.
- La unidad de arriba es simplemente de almacenamiento, tal y como se puede deducir de ese «128G».
Este servidor me proporciona acceso a la red de casa desde el exterior y, además, hace de centro de descargas y servidor de archivos, puesto que lo tengo funcionando ininterrumpidamente. El problema era que abrir un gran número de conexiones en redes P2P es exigente de cara al procesador y esto hacía que se calentara mucho: subía de los 70 ºC. A continuación, explico cómo añadir refrigeración mediante un ventilador con velocidad controlada en función de la temperatura.
En realidad es muy sencillo. Se puede optar por escoger un ventilador y modificar una caja de Raspberry o hacerse una a medida, pero ya hay soluciones precocinadas. Yo opté por este kit que podéis encontrar en eBay (por si en algún momento el enlace deja de estar disponible, algunas palabras clave: acrylic case with fan, heat sink, overclock kit). Contiene una caja de metacrilato a piezas, muy fácil de montar, con el agujero hecho y un microventilador de 0.5 W encajado. Dicha caja es muy compacta porque lleva el ventilador por dentro, muy cerquita de la placa, a diferencia de otras soluciones, y además la tapa es abatible (se puede abrir y cerrar una vez montada). También trae unos pequeños disipadores para pegar en los microcontroladores.
Con este kit sería más que suficiente. Conectando el ventilador al terminal de 3.3 V, la placa se mantiene a 35 ºC. No obstante, ni se requiere una temperatura tan baja ni es deseable que el ventilador esté permanentemente encendido a máxima velocidad, puesto que hace algo de ruido (poco, todo hay que decirlo). La solución es regular la velocidad en función de la temperatura. ¿Cómo? Con un simple transistor BJT como muestra la figura a continuación.
Como se ve, el transistor NPN se coloca a continuación de la carga y su base se conecta al PIN 18 que nos proporciona una salida digital PWM, que no es más que una señal cuadrada cuyo valor máximo es 3.3 V y el mínimo es 0 V. Nótese que, cuando la señal se encuentra en su valor alto, el transistor tiene ambas uniones en polarización directa y trabaja en saturación: es un interruptor cerrado, la corriente fluye impulsando el ventilador. Por el contrario, cuando la señal se encuentra en su valor bajo, el transistor está en corte y no fluye corriente por la rama del ventilador.
Por tanto, basta con modular el porcentaje del tiempo que la señal digital aplicada a la base del transistor está en el valor alto, 3.3 V, para obtener el mismo porcentaje de la velocidad máxima del ventilador a dicha tensión. Y esto puede hacerse en función de la temperatura, con un programa que monitorice esta última y habilite la señal correspondiente a través del PIN 18. Afortunadamente, alguien ya ha escrito el código por nosotros y lo ha compartido amablemente. Lo he recogido aquí y el lugar de publicación original es este foro.
Una solución sencilla y brillante. ¿Gracias por compartirlo!
Hola, el montaje te ha quedado genial. Estoy buscando exactamente lo que has explicado pero tengo un par de dudas, si puedes me echas una mano.
– ¿Qué transistor has usado exactamente? yo tengo bastantes pero no se si alguno de ellos es BJT.
– ¿Hay que compilar el programa o se puede ejecutar directamente como un script de bash?
Por último, ¿tienes algún enlace donde saber cómo hacer que la Raspi arranque desde una unidad USB? me ha gustado eso de tener una memoria USB para tal fin.
Gracias!! :)
@Fernando:
Da igual el modelo exacto porque trabaja en saturación. En el transistor vendrá algo escrito, que es el modelo. Búscalo en Google y te saldrá la hoja de especificaciones. Ahí puedes ver si es BJT o no, pero ni siqueira es imprescindible que sea BJT porque, como digo, está puesto para que trabaje en saturación.
Sí: es un programa en C. Las instrucciones de compilación vienen al final del fichero.
Realmente no arranca desde el USB: sigues necesitando una SD porque la Raspberry solo es capaz de arrancar desde ahí. Lo que se puede hacer, en cambio, es mover el resto del sistema al USB. Es decir, la SD contiene solo el /boot (la imagen del kernel) y el USB lo demás. Tienes bastantes tutoriales, por ejemplo aquí y aquí.
Hola Iñaki, por fin he podido ponerme a intentar el invento. Gracias por tu respuesta.
Al final todo me ha ido perfectamente y he visto además que en el archivo config.txt que se genera durante el arranque del programa una vez compilado puedes variar las temperaturas a las que el ventilador arranca o se para…
Sin embargo, todo eso es en teoría porque no he conseguido que el ventilador arranque y se que es el transistor que he usado (BC337) porque cuando se supone que tenia que ponerse en marcha en la base tengo esos 3,3 V en el colector 5V (lo he conectado al pin 2 del GPIO) pero en el emisor apenas se superan los 2V totalmente insuficiente para hacer girar el ventilador, hace el amago, pero no empieza…
Esta tarde probaré con otros transistores pero si es posible, dime el que usaste tú por si acaso. Gracias por todo.
Vale, déjalo, ya funciona. Había dos cosas mal, una era el ventilador que por lo que sea no comienza a girar al menos que tenga una tensión mínima y por otro lado, había seguido este esquema: https://dl.dropbox.com/u/22659349/fan-case/circuit-diagram.png que no funciona porque la carga (ventilador) está entre el emisor y masa. Siguiendo tu esquema, poniendo la carga entre +5v y el colector funciona perfectamente. El transistor vale cualquiera, desde el BC337 hasta el BC548B y derivados.
Gracias.
@Fernando: Me alegro. Gracias a ti. ;-)
Se que ya no tiene mucho que ver con el montaje, pero quizá esté bien comentarlo.
He encontrado digamos un inconveniente y un «bug», que no se si te pasa a ti también. Lo primero es que si quiero lanzar el programa en el arranque, el poner el «&» al final de la instrucción en el rc.local le da exactamente lo mismo y sigue mostrando los mensajes de temperaturas en la consola, no se cómo resolverlo (quizá tú pasaste por eso). Por otro lado, el programa deja de funcionar si desde otro terminal arranco el entorno gráfico con startx. En cuanto termina de cargar el ventilador gira al máximo y ahí se queda. Entiendo que por alguna razón o bien bloquea el programa o sobreescribe el valor del pin GPIO18 poniéndolo a «1» constante.
Estoy viendo la manera de hacer un programita mucho más sencillo en bash, no se si lo conseguiré, pero parece mucho más fácil manipular los GPIOs con la librería wiringPI ya que después podemos manipular el giro del ventilador con solo usar dos comandos:
gpio -g mode 18 pwm
gpio -g pwm 18 (valor entre 0 y 1023)
Lo primero que tengo que hacer es aprender a programar en algo! :D
@Fernando: El ampersand lo que hace es hacer un fork del programa/comando, de forma que se ejecuta en un subshell aparte. Digamos que se «desacopla» del shell donde se lanza, pero la salida de dicho programa (stdout y stderr) sigue asociada al shell padre desde donde se lanzó. Hay que redirigir explícitamente la salida. Por ejemplo:
$ comando &> /dev/null &
Aquí, «&>» redirige todo (stdout y stderr) en este caso a /dev/null.
El tema del entorno gráfico… no sé decirte porque yo uso el Raspberry Pi solo como servidor headless, sin entorno gráfico. ¿Has comprobado la temperatura? Se me ocurre que quizás el entorno gráfico es tan exigente con el procesador que está muy caliente constantemente.
Y sí, se puede hacer en Bash (o Python, etc.) perfectamente. Esa era mi idea al principio, pero encontré ese programa en C que funcionaba y apliqué el «si algo funciona, no lo toques». ;-) Te animo a que lo subas a Github y compartas el enlace por aquí si finalmente haces ese programita en Bash.
Muchas gracias, le estuve dando mil vueltas al /dev/null y no lo conseguí al 100%, pero lo ha explicado muy bien, lo probaré y ya te comento.
Lo del entorno gráfico también lo he mirado, yo tampoco lo uso mucho y me di cuenta de casualidad, porque quise darle caña para probar el control de revoluciones del ventilador y siempre se quedaba activo. Me he dado cuenta que al entrar en ese entorno, parece que los pines del GPIO se quedan activados, o sea que se sobre escribe cualquier valor que se haya modificado desde consola. Ya lo estudiaré mas adelante.
Con respecto al programa, pues para no tener mi puñetera idea, al final lo he conseguido y funciona muy bien la verdad. Hay que instalar la librería wiringPI para poder hacer uso de la característica PWM del pin 18 en Bash (de otra forma creo que es imposible). El programa se divide en tres partes, ventilador parado por debajo de una temperatura (todas definibles, lógicamente), control de revoluciones entre dos temperaturas y máximas revoluciones por encima de otra temperatura que se considera «peligrosa». También muestra los grados en pantalla y se actualizan solos, así como un mensaje de ventilador activo o parado para saber cómo está la cosa si no lo tienes cerca. Se podría también hacer que te envíe un mail si sube mucho la temperatura como alarma o similar, pero vamos, que complicarlo se puede y mucho. La verdad es que no estoy familiarizado con Github (nunca he subido nada ahí) aunque si eso dejo el código por aquí para que lo pruebes/modifiques/mejores si se diera el caso.
Un saludo.
@Fernando: Puedes pasármelo al correo de contacto del blog y lo cuelgo yo en mi cuenta de Github, en un Gist, como este.
Ya te lo he enviado. He encontrado algunos cambios que hacer al código, ya que si se ejecuta desde un terminal funciona perfecto, pero si la ejecución se hace desde el rc.local no funciona. He conseguido solucionarlo simplemente dando la ruta completa al comando gpio (no se por qué no funciona si no lo hago) y metiendo dentro del bucle while la declaración del pin 18 como PWM. Esto último también solventa lo que comentaba del entorno gráfico y pasa también en otras distribuciones que arrancan algún tipo de programa gráfico, al hacerlo se sobreescriben (no se por qué) todas las definiciones de los pines GPIO.
Por otro lado y con respecto a la ejecución del programa en segundo plano, solo funciona correctamente si en vez de esto:
$ comando &> /dev/null &
pongo esto
$ comando > /dev/null &
Saludos.
Gracias por el aporte: está muy bien ;-). Lo he colgado aquí. Me he tomado la libertad de introducir algunos cambios menores.
Tiene que haber alguna forma de hacerlo sin WiringPi, efectivamente, porque WiringPi no hace magia… Por aquí hablan del subsistema
/sys/class/rpi-pwm
, por si le quieres echar un ojo, pero en mi Raspbian no existe esa ruta.