Ejecuta programas al inicio de tu Raspberry Pi

Es posible que nos apetezca configurar uno de nuestros proyectos de tal forma que se ejecute automáticamente al encender la Raspberry Pi, o el PC si tenemos Linux. Esto puede servir, por ejemplo, para automatizar el proyecto del fotomatón, con el que tanto hemos trabajado estos últimos meses, para que comience a funcionar con el arranque de la Raspberry Pi. Aunque puede servir para cualquier cosa y en cualquier sistema Linux hay docenas de programas configurados al inicio del sistema, eso fue lo que me estuvo preguntando Alfonso García por correo electrónico.

Inicio de una variante de Raspbian (Minibian). Imagen de Luca Soltoggio (minibian: https://minibianpi.wordpress.com/)
Inicio de una variante de Raspbian (Minibian). Imagen de Luca Soltoggio (minibian: https://minibianpi.wordpress.com/)

Lo que haremos en este artículo va a ser ver paso a paso lo que tenemos que hacer para automatizar un programa al inicio de Linux usando el capítulo de inicialización del sistema de la norma Linux Standard Base (que podéis leer aquí, en inglés), que es la forma estándar que los Linux tipo Debian (como es Raspbian) tienen de interpretar los contenidos de un directorio llamado init.d para ir ejecutando todo lo que allí encuentren. Si usáis una distribución basada en Red Hat Linux podréis encontrar alguna diferencia.

Haremos nuestra tarea de una forma responsable y cumplidora con los requisitos de lo especificado por la LSB, pero también algo simplificada. Un primer paso para que luego, cada uno, profundice en este tema lo que desee o necesite.

Niveles de ejecución y subsistemas en Linux

Linux es un sistema operativo cuya vida discurre entre varios modos de ejecución, concretamente 6. Desde que arranca hasta que para, el sistema operativo va cambiando de uno a otro de forma secuencial. En cada nivel, que está orientado a unas determinadas tareas, uno o varios usuarios pueden ejecutar programas para sus propios fines, pero el sistema también arranca una serie de subsistemas específicos de forma automática. Un subsistema puede ser, por ejemplo, el sistema de sonido, una capa de seguridad para protegernos de ataques si nos conectamos a internet, o el entorno gráfico para mostrar un escritorio y que el usuario pueda interactuar con él mediante un ratón. Sin embargo, una aplicación interactiva como un navegador web o una hoja de cálculo no se consideran subsistemas.

Los niveles que hay son los siguientes, y vamos a ver para qué sirven de forma que quede claro el párrafo anterior:

  • 0: nivel de parada. Cuando el sistema pasa a este nivel, todos los subsistemas se paran de forma ordenada, dándoles tiempo a “recoger la casa y dejarla limpia”, para luego detener por completo el sistema operativo y la máquina. shutdown -h now como superusuario pone el sistema en nivel 0.
  • 1: modo de mantenimiento. En este modo de ejecución sólo se arrancan los subsistemas imprescindibles para que un usuario pueda hacer tareas de mantenimiento muy específicas. Si el ordenador se arranca en modo mantenimiento, el arranque desemboca en este modo de ejecución y se ofrece un terminal directamente, sin pedir usuario ni contraseña.
  • 2, 3: modo “normal” de funcionamiento. Todos los subsistemas se arrancan, incluyendo el de autenticación de usuarios (el que permite introducir usuario y contraseña). Son equivalentes, aunque el 2 tiene menos capacidades de red y se mantiene por razones históricas. Normalmente, si arrancas un ordenador con Linux en modo texto estarás en este modo. La inmensa mayoría de servidores que usan Linux terminan su arranque en el nivel de ejecución 3.
  • 4: sin uso.
  • 5: modo de escritorio. Es equivalente al 3, pero con el entorno gráfico arrancado por defecto. La configuración por defecto de la mayoría de ordenadores personales con Linux, como la Raspberry Pi.
  • 6: equivalente al 0, pero que en lugar de detener por completo el sistema y la máquina efectúa un reinicio. Es una de las cosas que ocurren cuando ejecutamos el comando shutdown -r now  como superusuario.

Podemos cambiar de nivel de ejecución manualmente y consultar la secuencia de niveles por los que ha pasado el sistema con los comandos telinit y runlevel, pero te los dejo a ti para que los consultes en el manual y experimentes con ellos: en este artículo no serán de gran interés.

Arrancar subsistemas en secuencia: directorios init.d y rc1.d, rc2.d,… rc5.d

Para arrancar un programa como subsistema debemos programar un guión (o script) en el directorio /etc/init.d, con unos permisos adecuados para que el sistema de arranque de Linux lo pueda ejecutar. 0755, o rwxr-xr-x, son suficientes. Los subsistemas allí presentes, una vez configurados en los niveles de ejecución adecuados para sus fines (normalmente 2,3,4 y 5 como hemos discutido arriba), aparecen como enlaces simbólicos en los directorios /etc/rcN.d, donde N es el nivel de ejecución. Un enlace simbólico es como se llama en Linux a un acceso directo un poco especial, con más capacidades que los que estamos acostumbrados a manejar como usuarios.

En estos directorios rcN.d, los enlaces simbólicos tienen un nombre cuya estructura indica al sistema si sirven para detener el subsistema, arrancarlo, pararlo y con qué prioridad; esto es: si debe arrancarlo antes o después que otro. Por ejemplo, en /etc/rc3.d solemos encontrar un enlace de nombre S12syslog. Éste indica que hay que arrancar (S, de start) el servicio syslog, que toma nota de todos los mensajes de estado del sistema (logs) y los pone a disposición del usuario en una ubicación concreta, con prioridad 12 (mayor prioridad cuanto menor valor). Si vemos que hay otro enlace, por ejemplo S56rawdevices, sabremos que arrancará el subsistema rawdevices con una prioridad menor (56) que syslog (12), y por lo tanto después.

¿Cómo se configura un subsistema en un nivel de ejecución y con una prioridad? Con la estructura de los guiones que colocaremos bajo init.d que, como ya os adelantaba, en Debian y Raspbian siguen un convenio recogido en el capítulo de inicialización del sistema de la “norma” Linux Standard Base.

A partir de este punto voy a simplificar, aunque sin caer en la chapuza. La estructura de init.d es algo muy completo y que hacerlo pulcra y correctamente constituye de por sí una capacidad profesional avanzada y bastante cotizada; en este blog lo que quiero es poner este tipo de cosas a vuestro alcance (y al mío, porque no os voy a engañar: no soy un experto en estos temas), pero no puedo ir hasta el último rincón. Os voy a presentar directamente un guión que sirve para arrancar el prototipo del fotomatón, cumpliendo con lo estrictamente necesario de la especificación de Linux Standard Base, y lo vamos a analizar paso a paso.

#!/bin/sh
### BEGIN INIT INFO
# Provides:     fotomatond
# Should-Start:
# Required-Start:   $local_fs $remote_fs
# Required-Stop:    $local_fs $remote_fs
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
# Short-Description:    Fotomaton basado en Raspberry Pi
# Description:      Script de inicio para Debian para el fotomaton
#          basado en la Raspberry Pi, un prototipo y el modulo
#          de camara.
### END INIT INFO


. /lib/lsb/init-functions

DAEMON=/home/pi/pitando/fotomaton_dropbox.py
NOMBRE=fotomatond
LOGFILE=/var/log/fotomatond.log
ERRFILE=/var/log/fotomatond.err
DESCRIPCION="Servicio de fotomaton"

test -x $DAEMON || exit 0

set -e

case "$1" in

    start) 
        log_daemon_msg "Arrancando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --start --background --pidfile /var/run/$NOMBRE.pid --make-pidfile --quiet --startas /bin/bash -- -c "exec $DAEMON >$LOGFILE 2>$ERRFILE"
        log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Parando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NOMBRE.pid
        log_end_msg $?
        ;;
    restart)
        log_daemon_msg "Reiniciando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NOMBRE.pid
        sleep 1
        start-stop-daemon --start --background --pidfile /var/run/$NOMBRE.pid --make-pidfile --quiet --startas /bin/bash -- -c "exec $DAEMON >$LOGFILE 2>$ERRFILE"
        log_end_msg $?
        ;;
    force-reload)
        restart
        ;;
    *)
        log_failure_msg "Uso: /etc/init.d/$NOMBRE {start|stop|restart|force-reload}"
esac

exit 0

De todas las operaciones obligatorias recogidas en la norma, nos dejamos la que todavía está en un estado de candidatura, aunque de facto ya es obligatoria, que es status. Status debería devolver un código que represente el estado de ejecución (arrancando, ejecutándose, parando, parada,…) del subsistema o servicio. En este artículo la dejaremos fuera, pero no descartéis una actualización o una continuación.

Usando este script vuestro fotomatón arrancará con el arranque del sistema y se detendrá correctamente con la parada del mismo, y lo mejor de todo es que sabréis por qué y podréis generalizarlo para cualquier otro propósito. Sin embargo, si queréis programar un servicio de modo profesional deberéis consultar la  documentación y practicar mucho. Vamos a ver su estructura a continuación.

Comentarios del inicio

Además del ya conocido comentario #!/bin/sh por el que comienza todo script de terminal, este fichero tiene una buen retahíla de comentarios al principio:

### BEGIN INIT INFO
# Provides:     fotomatond
# Should-Start:
# Required-Start:   $local_fs $remote_fs
# Required-Stop:    $local_fs $remote_fs
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
# Short-Description:    Fotomaton basado en Raspberry Pi
# Description:      Script de inicio para Debian para el fotomaton
#          basado en la Raspberry Pi, un prototipo y el modulo
#          de camara.
### END INIT INFO

Aunque sean comentarios, son obligatorios. Indican lo siguiente por este orden:

  • El nombre del servicio que gestionan, en este caso fotomatond
  • Los servicios que deberían estar arrancados antes (should start), opcionalmente. Lo dejo en blanco porque no hay dependencias opcionales.
  • Los servicios que deben estar arrancados antes porque, si no, nuestro servicio no funcionaría (required start). En mi caso pongo las variables de sistema que hacen referencia al montaje de todos los sistemas de fichero ya que nuestro fotomatón almacena y lee fotografías en la tarjeta SD de la Raspberry Pi. Así pues,  $local_fs $remote_fs
  • Los servicios que deben parar después del nuestro ya que si no, nuestro fotomatón podría no ser capaz de terminar su ejecución de una manera ordenada (required stop). En nuestro caso y en la mayoría de los casos hay que poner lo mismo que en la opción anterior.
  • Los niveles de ejecución en los que este servicio se va a arrancar (default start), que en este caso son todos los que suponen una ejecución normal, con o sin entorno gráfico: 2 3 4 5 .
  • Los niveles de ejecución en los que este servicio se debe parar (default stop); para ser consistentes deberíamos poner todos los demás: 0 1 6
  • Descripciones corta (una línea) y larga (varias líneas que comienzan por un tabulador o dos espacios).

Con estos comentarios, el sistema de configuración del arranque creará correctamente los enlaces simbólicos que reseñaba en apartados anteriores (con la S, la prioridad,…)

Incorporar funciones, variables y comprobaciones preliminares

Examinamos ahora este bloque de código:

. /lib/lsb/init-functions

DAEMON=/home/pi/pitando/fotomaton_dropbox.py
NOMBRE=fotomatond
LOGFILE=/var/log/fotomatond.log
ERRFILE=/var/log/fotomatond.err
DESCRIPCION="Servicio de fotomaton"

test -x $DAEMON || exit 0

set -e
  •  La primera línea, . /lib/lsb/init-functions , incluye una serie de funciones de terminal que nos servirán principalmente para enviar mensajes a los logs del sistema: un lugar donde podemos grabar nuestra actividad con información útil.
  • Las siguientes 5 líneas definen unas variables que nos servirán para identificar correctamente el programa a arrancar.
    • Fijaos que la primera de ellas apunta directamente al directorio de usuario pi: esto es mejorable ya que un programa al inicio del sistema debería guardarse en un directorio de sistema.
    • Las dos siguientes definen dos ficheros de log diferentes al de sistema, que usaré para guardar los mensajes que imprimimos por pantalla desde Python con la función print (fichero de extensión .log), y los errores que vuelque el intérprete en caso de haberlos (fichero de extensión .err).
    • La variableDESCRIPCION incluye una descripción corta para reconocer fácilmente nuestros mensajes en los logs del sistema.
  • La sentencia test -x $DAEMON || exit 0 comprueba si el programa ya se encuentra en ejecución, y en caso afirmativo termina el guión sin errores (código de salida 0).
  • Por último, set -e configura el script para que, si cualquier cosa fallase devolviendo un código de salida diferente a 0 a partir de ese punto, el propio script se detendría devolviendo ese mismo valor. Es una forma abreviada de terminar ante un error, propagando aquello que nos hayan devuelto.

Arranque, parada, reinicio y recarga del subsistema

Son operaciones obligatorias (pero no las únicas posibles) para programar un subsistema al inicio de Linux: start , stop , restart  y force-reload. El guión que coloquemos bajo /etc/init.d debe contemplar las 4, y para eso suele usarse una estructura de control case:

case "$1" in

    start) 
        log_daemon_msg "Arrancando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --start --background --pidfile /var/run/$NOMBRE.pid --make-pidfile --quiet --startas /bin/bash -- -c "exec $DAEMON >$LOGFILE 2>$ERRFILE"
        log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Parando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NOMBRE.pid
        log_end_msg $?
        ;;
    restart)
        log_daemon_msg "Reiniciando $DESCRIPCION" "$NOMBRE"
        start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NOMBRE.pid
        sleep 1
        start-stop-daemon --start --background --pidfile /var/run/$NOMBRE.pid --make-pidfile --quiet --startas /bin/bash -- -c "exec $DAEMON >$LOGFILE 2>$ERRFILE"
        log_end_msg $?
        ;;
    force-reload)
        restart
        ;;
    *)
        log_failure_msg "Uso: /etc/init.d/$NOMBRE {start|stop|restart|force-reload}"
esac

La estructura de control case superior examina el primer parámetro del guión. Si este es start ejecutará una secuencia de sentencias orientada a arrancar el programa del Fotomatón en Python; en caso de stop hará lo propio para pararla, y así sucesivamente. restart es una mezcla del contenido de start y stop, y force-reload, cuyo comportamiento es “recargar la configuración del subsistema y, si no es posible, reiniciarlo”, en este caso llama directamente a restart porque no hay configuración que recargar.

Vamos a examinar los bloques de sentencias que paran y arrancan el programa del fotomatón:

start) 
    log_daemon_msg "Arrancando $DESCRIPCION" "$NOMBRE"
    start-stop-daemon --start --background --pidfile /var/run/$NOMBRE.pid \ 
        --make-pidfile --quiet \ 
        --startas /bin/bash -- -c "exec $DAEMON >$LOGFILE 2>$ERRFILE"
    log_end_msg $?
    ;;

La primera línea define el caso en el que nos encontraríamos: que el primer argumento del guión fuese igual a start. La siguiente escribe un mensaje usando una de las funciones cargadas al principio del script mediante la librería init-functionslog_daemon_msg. A juzgar por el texto que escribimos, podemos esperar que el mensaje escrito tenga las variables sustituidas por su valor, y así será.

La siguiente línea es digna de comentar completamente: start-stop-daemon es un programa que ayuda a controlar la ejecución de subsistemas. Concretamente, lo que hacemos en esa línea es:

  • –start: arrancamos el programa.
  • –background: en segundo plano, es decir: el guión no espera a que el programa termine. Esto es muy conveniente porque nuestro programa, recordadlo, es un bucle infinito.
  • –pidfile /var/run/$NOMBRE.pid –make-pidfile va a asegurarse de crear un fichero de nombre /var/run/fotomatond.pid cuyo contenido va a ser un identificador de proceso en Linux, es decir: un número que identifica inequívocamente al programa del fotomatón cuando se esté ejecutando. Muy útil para pararlo, por ejemplo.
  • –quiet reduce la cantidad de información que esta orden devolverá por pantalla.
  • –startas /bin/bash — -c “exec $DAEMON >$LOGFILE 2>$ERRFILE” va a ejecutar el programa del fotomatón (contenido de la variable $DAEMON) de tal forma que la salida estándar que sacamos en el programa se almacene en el fichero /var/log/fotomatond.log y los errores, si los hubiese, en el fichero /var/log/fotomatond.err. Si nuestro programa estuviese mejor codificado y escribiese su información en un fichero, este último trozo de la sentencia sería notablemente más sencilla (–exec $DAEMON).

La última línea anota el resultado de la ejecución del comando start-stop-daemon.

Vamos ahora con la parada:

stop)
    log_daemon_msg "Parando $DESCRIPCION" "$NOMBRE"
    start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NOMBRE.pid
    log_end_msg $?
    ;;

Realmente, la única diferencia es el uso de start-stop-daemon, mucho más sencillo. En este caso sólo hay que decirle que pare (–stop) el proceso cuyo identificador está almacenado en el fichero /var/run/fotomatond.pid, haciendo correcto uso de las variables definidas.

Por último, el programa termina correctamente con código 0, a no ser que se haya producido un error en algún punto, en cuyo caso habrá salido con un código diferente gracias a la sentencia set -e

exit 0

Unos retoques al programa del fotomatón antes de continuar

Para que el programa funcione correctamente hay que hacer un par de cambios: especificar las rutas de los ficheros de imagen de forma absoluta y modificar los mensajes que sacamos por consola para que se emitan inmediatamente. El código del programa quedaría como veis a continuación, y en él he marcado con comentarios las modificaciones:

#!/usr/bin/python3

import dropbox
import RPi.GPIO as GPIO
import time
import picamera

## Obtener una referencia a la cámara
camera = picamera.PiCamera()

## Conexión a la cuenta de Dropbox
# Sustuye estos valores por los que has copiado, conservando
# las comillas.
app_key = "APP_KEY" 
app_secret = "APP_SECRET"
# Las dos primeras claves no son en absoluto necesarias aquí, sirven
# para programar un flujo que generaría la siguiente (flujo de autori-
# zación OAuth2)
cuenta = "ACCESS_TOKEN"

print("Conectando a la cuenta de Dropbox...", flush=True) #Modificado
client = dropbox.client.DropboxClient(cuenta)
print("Cuenta de " + client.account_info().get("display_name") + " conectada.", flush=True) #Modificado
print("Oprime el pulsador para hacer la primera foto", flush=True) #Modificado

## Configuración GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings (False)
GPIO.setup(6, GPIO.IN)
GPIO.setup(12, GPIO.OUT)

## Bucle infinito del fotomatón
# Número total de fotos, para Dropbox
total = 0
# Número de fotos en la tarjeta SD, entre 0 y 10. Así no llenaré
# nunca el sistema de ficheros (sólo guardo 10 fotos en la
# Raspberry, "en local")
local = 0
try:
    while True:
        if (not GPIO.input(6)):
            # Modificado: rutas absolutas
            nombre_local = "/home/pi/pitando/captura_" + str(local) + ".jpeg"
            nombre_dropbox = "/home/pi/pitando/captura_" + str(total) + ".jpeg"
            
            # Uso del LED para guiar al "modelo" de la foto
            print ("Cuando se apague el LED se hará la foto", flush=True) #Modificado
            GPIO.output(12, GPIO.HIGH)
            for i in range(0, 3):            
                print(str(3 - i) + "...", flush=True) #Modificado
                time.sleep(1)
            GPIO.output (12, GPIO.LOW)
            print ("¡Foto!", flush=True) #Modificado
            # Hacemos la foto
            camera.capture(nombre_local)
                
            # Subir la foto a Dropbox
            f = open(nombre_local, 'rb')

            print("Subiendo la foto a Dropbox de " + client.account_info().get("display_name") + "...", flush=True) #Modificado
            response = client.put_file(nombre_dropbox, f)
            
            tamanho = str(round(int(response.get("bytes")) / 1024,1))
            print("Foto '" + nombre_dropbox + " cargada: " + tamanho + " kB.", flush=True) #Modificado

            # Incrementar contadores; 'local' siempre entre 0 y 10
            local = (local + 1) % 10 # resto de dividir local + 1 entre 10.
            total = total + 1
            print("Oprime el pulsador para hacer otra foto", flush=True) #Modificado
            
except dropbox.rest.ErrorResponse as e:
    print("Error al acceder a Dropbox: ", e.user_error_msg, flush=True) #Modificado
except KeyboardInterrupt:
    print("\nInterrupción del usuario, saliendo del programa", flush=True) #Modificado
finally:
    camera.close()
    GPIO.cleanup()
    print ("Fin del programa", flush=True) #Modificado

Configurar el servicio en el arranque de la Raspberry Pi

Para que el servicio arranque con la Raspberry Pi y se pare con ella, debemos hacer lo siguiente:

  • Una vez preparado el programa en Python como en el apartado anterior, asegúrate de que tiene permisos de ejecución 0755 ó rwxr-x .
  • Guarda en /etc/init.d/fotomatond el script que define el servicio fotomatond y que hemos estado discutiendo a lo largo de este artículo (etiquetado como Listado del servicio fotomatond). Otórgale los mismos permisos: 0755 ó rwxr-x .
  • Con la siguiente orden configurarás el servicio en el arranque con las prioridades adecuadas y creando los enlaces simbólicos bajo los directorios /etc/rcN.d, gracias a la cabecera de comentarios que analizamos:
sudo update-rc.d /etc/init.d/fotomatond defaults

Si quisiéramos desinstalarlo, ejecutaríamos su contrapartida:

sudo update-rc.d -f /etc/init.d/fotomatond remove

A partir de este momento y si todo ha ido bien, tan pronto reiniciemos la Raspberry Pi nuestro fotomatón debería funcionar.

Una vez reiniciada podríamos comprobar su funcionamiento (más allá de los leds de la cámara y de que las imágenes aparecen en el directorio correspondiente) mediante las siguientes órdenes que os dejo como ejercicio sencillo:

tail -n 100 /var/log/syslog
tail -n 100 /var/log/fotomatond.log
cat /var/run/fotomatond.pid
ps aux | grep fotomaton_dropbox.py | grep -v grep

Sobre las órdenes anteriores:

  1. Localiza los mensajes que emite el servicio de fotomatón
  2. Relaciona esos mensajes con sentencias concretas del script /etc/init.d/fotomatond y con sentencias de código Python
  3. Compara los identificadores de proceso de las órdenes 3ª y 4ª.

Y esto es todo. A partir de ahora podréis automatizar muchos de los programas que hagáis para que se ejecuten al encender la Raspberry Pi, porque lo que hemos visto aquí, aunque es básico, cubre la mayoría de las necesidades de los programas que podamos hacer con el objetivo de experimentar. Espero que lo encontréis útil. Recordad consultar la documentación para ampliar vuestro conocimiento:

Linux Standard Base – System Intialization

Podéis dejarme cualquier comentario en este mismo artículo o en el formulario de contacto, usando también la dirección de correo electrónico que hallaréis allí si lo preferís.

22 comentarios en “Ejecuta programas al inicio de tu Raspberry Pi

  1. Muy interesante!! Yo buscaba algo tan simple como que al arrancar raspbian inicializace con un logo y la tipica barra del progreso de carga. Es posible con este tuto?

    1. No, lo siento. Este sólo sirve para hacer que un programa se arranque automáticamente al encender el sistema. ¡Si veo alguna forma de hacerlo os lo haré saber!

  2. Después de descubrir, primero tu podcast y ahora tu blog, creo que era el impulso final que necesitaba, voy a hacerme con una Raspberry Pi. Pero también veo en otros canales de Youtube otras placas, también muy interesantes.

    1. ¡Bienvenido!, y gracias por tu comentario.

      Sí, la verdad es que hay mucha variedad y todas muy interesantes, aunque a menudo cada una tiene su propio nicho. Por ejemplo, la Raspberry Pi y muchas otras placas parecidas (a menudo copias) son ordenadores completos, con todas las de la ley: puedes hacer con ellas cualquier cosa que harías con un PC o un Mac, aunque con prestaciones limitadas. Por otro lado, otras como Arduino / Genuino y muchas otras imitaciones y placas parecidas, son microcontroladores: sirven para desarrollar proyectos mucho más específicos y concretos, a menor coste que usando un ordenador de propósito general. Por ejemplo, controlar la intensidad de una lámpara en función de la luz ambiente es una aplicación propia de un microcontrolador.

      De estos temas (microcontroladores, ordenadores, microprocesadores, autómatas programables) tratará el próximo episodio del podcast. Ya lo llevo retrasando una temporada y creo que es interesante definir cada uno.

  3. Perdón, en el comentario anterior se me olvidó la pregunta que te quería hacer.
    ¿Donde o que webs de fiar me puedo pedir una Raspberry Pi 3?

    1. Yo suelo comprar en Amazon, por la comodidad que me supone y la protección al comprador que proporciona. Al margen de eso, existen muchas: en http://raspberrypi.org tienes enlaces a las tiendas oficiales, de las cuales Element 14 sirve a España a través de una subsidiaria llamada farnell (http://es.farnell.com/). Me han recomendado otras, como Mod My Pi (http://www.modmypi.com/shop), pero todavía no las he probado.

      Ahora mismo, al no haber necesitado comprar nada por fuera de Amazon, no sabría orientarte en cuanto a plazos de entrega y gastos de envío, lo siento.

      1. Muchas gracias. Es que, como comentabas en tu último podcast con respecto a la Micro bit, que hay mucho revendedor fraudulento por ahí, por eso te lo quería preguntar.

        Sólo he escuchado este último podcast y otro sobre la Raspberry Pi y ya estoy deseando llegar a una área de servicio con WiFi para descargarme los otros anteriores. Muy interesante todo lo que nos cuentas, muchas gracias y
        Enhorabuena por este trabajo realizas.

  4. hola ,tengo el siguiente problema al ejecutar
    sudo update-rc.d /etc/init.d/fotomatond defaults

    me arroja lo siguiente
    update-rc.d: error: initscript does not exist: /etc/init.d/

    1. Hola

      Asegúrate de que el script fotomatond lo hemos grabado con ese nombre, es decir, existe, en el directorio /etc/init.d, y que tiene los permisos necesarios de lectura y ejecución (0755 ó rwxr-x). Comprueba también la cabecera que indica cuál es el intérprete de ejecución, #!/bin/sh: prueba también que dicho intérprete está en la ruta que le estamos indicando, con el comando `which sh` o `ls /bin/sh`.

  5. Cordial saludo

    Primero para felicitarlo por este tutorial. Estaba trabajando en Python y realice pruebas y correcto. pero cuando realizo pruebas con un archivo en c, he tenido problemas, disculpa tienes algun tutorial sobre este tema. Gracias

    1. Hola. No tengo ningún tutorial en C, pero no deberías tener ningún problema siempre que compiles el programa como siempre has hecho y tenga permisos de ejecución. Si te falla porque no encuentra alguna librería prueba a comprobar que los permisos de las mismas están bien para el usuario que ejecute el programa, y mira también en las opciones del compilador si puedes de alguna forma empaquetarlas con el ejecutable (ya no me acuerdo si se podía, ni cómo).

  6. Buen día.
    Me permito enviar un cordial saludo y felicitarle por toda la información proporcionada.
    Quiero saber si pudiera ud. sugerirme algo para poder correr mi aplicación.
    Estoy intentando iniciar automáticamente una distribución echa desde myopenlab, eh intentado algunas opciones pero sin éxito.
    En varios intentos recibo el error: unable to access jarfile
    Agradezco de antemano si es posible alguna sugerencia o pequeña gran orientación.
    Saludos.

    1. Parece que no encuentra algún componente Java (JAR –> Java ARchive), pero desconozco myopenlab y cómo empaqueta distribuciones.

  7. Buenos dias,

    Impresionante y muy completo articulo. Gracias, lo guardaré entre mis favoritos para consultas. Quiero hacerte una pregunta. Yo tengo en mi raspberry en el /etc/init.d/ un script con la cabecera que indicas y que levanta un demonio que revisa la temperatura de la CPU cada 30 segundos y enciende o apaga el ventilador usando un GPIO. Funciona a la perfección, solo tiene una pega, cuando el demonio arranca la hora del sistema aun no se ha actualizado y los ficheros de log que me crea el demonio tienen fecha de la ultima vez que se apagó el sistema, aunque luego las lineas de log una vez ha finalizado el arranque si indican bien las horas de los eventos.

    ¿Como puedo forzar a mi script para que se ejecute justo después de que la raspberry haya actualizado su hora? Escucho otras alternativas tambien eh?

    Un saludo y gracias de antemano.

  8. buenas, e conseguido que funcione todo excepto que cuando se inicia el programa hace las fotos automaticamente sin tener q pulsar el microinterruptor ni nada . alguien sabe como activar los gpio para que pueda funcionar pulsado el boton .

    1. Para eso puedes usar un temporizador en Python y usar solamente la librería de la cámara, no tienes que hacer nada con los GPIO. Entiendo que lo que quieres hacer es una suerte de cámara automática… me estoy estableciendo en Australia, pero cuando pueda y “recupere mi material” vuelvo a estar activo y os ayudo más con todo esto, os pido disculpas por mi ausencia.

  9. Muchas gracias por este programa y explicación respectiva, yo estoy intentando realizar un programa de arranque que compare el valor de la variable serial del procesador rpi3 SERIAL=”$(cat /proc/cpuinfo | grep Serial | cut -d ‘:’ -f 2) contra un valor asignado en la tarjeta SD,, no sé si voy por buen camino pero gracias y un saludo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *