Controlando leds con una Raspberry PI

Raspberry junto a la protoboard con los leds trabajando.

Hola gente, hoy publico un proyecto que consiste en controlar las entradas y las salidas de una Raspberry PI con un simple programa hecho en lenguaje Python. Aclaro que mis conocimientos sobre Python, Linux y Raspberry son limitados, me considero mas bien un aprendiz. De cualquier manera, siguiendo el acostumbrado estilo de Inventable, he tratado de ser preciso y exhaustivo.

Entradas y salidas de la Raspberry

Para este proyecto he usado una vieja Raspberry PI Modelo B que tenía abandonada en un cajón. Ya he hablado de la Raspberry PI en mi artículo "Interfaz experimental para Raspberry PI", especialmente sobre el conector con entradas y salidas. Las primeras Raspberry tenían un conector de 26 pines. Modelos más recientes disponen de uno más grande de 40 pines y por lo tanto con una mayor cantidad de entradas y salidas.

Pines del conector de la Raspberry PI de todos los modelos (versiones de 26 pines y de 40 pines)
Pines del conector de la Raspberry PI de todos los modelos (versiones de 26 pines y de 40 pines).

Por suerte, en este cambio de conectores se ha mantenido la misma distribución de los primeros 26 pines iniciales por lo que la descripción de este proyecto es aplicable para todos los modelos de Raspberry, viejos y nuevos.

Instalación del sistema operativo

Como SD (o microSD en los modelos más modernos) podemos usar una de 8 Giga con buena velocidad (Clase 10). Desde el sito oficial de Raspberry PI bajamos el software NOOBS en formato zip, sigla de "New Out of the box software". En el momento que escribo este artículo la última versión es la 2.4.4. Al interno de NOOBS se encuentra el sistema operativo Raspbian (Linux Debian para Raspberry PI). El file zip pesa alrededor de 1,5 Gigabytes.

El software NOOBS es estupendo, basta descomprimirlo y copiar su contenido en la SD que usaremos. Metemos la SD en la Raspeberry y conectamos la alimentación de 5V a la plaqueta. Me recuerdo que años atrás el procedimiento era mucho más complicado. Una vez encendida la tarjeta, el software pregunta si queremos instalar Raspbian o LibreELEC_RPi, elegimos Raspbian.

Selección de Raspbian para instalar desde el software NOOBS
Selección de Raspbian para instalar desde el software NOOBS.

La instalación continuará sin hacer más preguntas y llevará algunos minutos. Aquí también han simplificado mucho respecto al pasado.

Imagen en la pantalla durante la instalación de Raspbian
Imagen en la pantalla durante la instalación de Raspbian.

Una vez instalado todo, aparece el desktop de Linux Raspbian y desde la barra del menú ubicada en alto de la pantalla seleccionamos "Preference" y después Raspberry Pi Configuration.

Imagen de la pantalla una vez instalado Raspbian.
Imagen de la pantalla una vez instalado Raspbian.

Aquí podemos elegir el idioma, el tipo de teclado que estamos usando, la zona horaria donde nos encontramos y si lo deseamos podemos cambiar el nombre de usuario y la password aunque si esto último no es necesario. He preferido de mantener la versión en inglés del sistema operativo en el caso que este artículo sea traducido en otros idiomas.

Ventana para la configuración de Raspbian (nombre usuario, tipo de teclado, idioma, zona horaria, etc.)
Ventana para la configuración de Raspbian (nombre usuario, tipo de teclado, idioma, zona horaria, etc.)

Para la conexión WiFi tuve que agregar un módulo externo porque la mía Raspberry no lo tenía incorporado como en las últimas versiones. Una vez conectado en el puerto USB, en la derecha de la barra del menú del desktop (zona de notificaciones), hay un icono que permite de elegir la red a la cual conectarse.

Actualización del sistema operativo

Todos los programas necesarios para este proyecto se encuentran ya instalados en la distribución de Raspbian incluida en el file NOOBS que hemos bajado.

Indicación para abrir el terminal
Indicación para abrir el terminal

De cualquier manera, antes de continuar, es conveniente actualizar el sistema operativo. Para ello, abrimos el terminal y escribimos:

sudo apt-get update  <RETURN>

Este comando actualiza la lista de los software con las versiones más recientes pero no instala nada. Una vez que ha terminado, para efectuar la verdadera actualización de los paquetes, escribimos el comando:

sudo apt-get upgrade  <RETURN>

A un cierto punto apt-get nos preguntará si confirmamos la actualización. Tocamos la tecla "Y" y después hará todo el trabajo (puede llevar algunos minutos). Una vez que ha terminado podemos cerrar el terminal y estamos listos para iniciar el proyecto.

La conexión de leds y pulsadores

Conexión de los leds y de los pulsadores directamente sobre el conector de la Raspberry.
Conexión de los leds y de los pulsadores directamente al conector de la Raspberry.

Elenco de materiales

4 leds (no importa el color)
2 resistencias de 4,7K
4 resistencias de 470 ohms
2 pulsadores (indicados en el circuito como "push").

Podemos conectar todo al vuelo, directamente sobre el conector de las Raspberry, usar una base experimental (breadboard) como yo he hecho o cualquier otro método. El circuito es muy sencillo e pueden verlo en la figura siguiente:

Circuito con los leds y los pulsadores conectados a la Raspberry PI.
Circuito con los leds y los pulsadores conectados a la Raspberry PI.

Podemos observar que los pulsadores trabajan en modo invertido porque se encuentran conectados a masa. En condiciones de reposo, las dos líneas de entrada de los pulsadores están a positivo de 3,3V (nivel lógico 1) a través de las dos resistencias de 4,7K. Cuando presionamos los pulsadores, estás líneas irán a masa (nivel lógico 0).

Preparando todo para escribir el programa

Antes de empezar, nos conviene crear una nueva carpeta llamada Inventable (o cualquier otro nombre que les guste). Para ello abrimos el File Manager (icono con el diseño de carpetas).

File Manager abierto en el directorio PI donde se ve la nueva carpeta "Inventable"
File Manager abierto en el directorio PI donde se ve la nueva carpeta "Inventable".

Al abrirlo nos mostrará el contenido de la carpeta principal PI. Hacemos click con la tecla derecha del mouse en una parte vacía de la ventana de la derecha. Nos aparece un menú contextual, elegimos New -> Folder y escribimos el nombre de la nueva carpeta.

Indicación para abrir el editor de texto
Indicación para abrir el editor de textos

Ahora abrimos dos programas: el terminal y el editor de textos (Menu Accessories -> Text Editor). Distribuimos las dos ventanas para poder verlas contemporáneamente en la pantalla.

Programas "Terminal" y "Editor de textos", abiertos contemporáneamente para trabajar mejor.
Programas "Terminal" y "Editor de textos", abiertos contemporáneamente para trabajar mejor.

En el editor de textos abrimos el menú "Options" y hacemos click sobre "Line Number" y también sobre "Auto Indent". Después guardamos el nuevo file (que por ahora está vacío) con el nombre "test_leds1.py" en la carpeta Inventable que habíamos creado.

Ahora en el editor, escribimos el siguiente texto:


1
2
3
4
#!usr/bin/env python

import RPi.GPIO as io
import time

Guardamos nuevamente el file "test_leds1.py" con el menú "Save"

Desde el terminal que teníamos abierto escribimos:

cd  Inventable  <RETURN>

Después escribimos:

python3   test_leds1.py  <RETURN>

Si no aparece ningún mensaje de error significa que Python está funcionando y que encontró las dos librerías necesarias.

El primer programa

Volvemos a nuestro editor y escribimos la primera versión de nuestro programa que enciende un solo led en modo intermitente cuando activamos el primer pulsador mientras que el segundo pulsador nos sirve para terminar el programa.

Este es el código completo:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!usr/bin/env python            # Necesario para el interprete Python

import RPi.GPIO as io           # Import libreria de I/O (entradas / salidas)
import time                     # Import libreria para los retardos

led1 = 9                        # led 1 conectado al gpio 9 del micro

button1 = 11                    # boton 1 conectado al gpio 11 del micro
button2 = 10                    # boton 2 conectado al gpio 10 del micro

io.setmode(io.BCM)              # modo in/out pin del micro
io.setwarnings(False)           # no señala advertencias de pin ya usados

io.setup(led1,io.OUT)           # set pin led 1 como salida

io.setup(button1,io.IN)         # set pin pulsador 1 como entrada
io.setup(button2,io.IN)         # set pin pulsador 2 como entrada

for a in range(100):            # Ciclo de espera hasta que se acciona
    time.sleep(0.5)             # el pulsador 1
    if not io.input(button1):
        break                   # Con el pulsador 1 accionado (a masa)
                                # termina el ciclo de espera

while io.input(button2):        # Ciclo hasta que se acciona il pulsador 2
    io.output(led1,1)           # Enciende el led
    time.sleep(0.5)             # Espera medio segundo
    io.output(led1,0)           # Apaga el led
    time.sleep(0.5)             # Espera otro medio segundo

Para probarlo, escribimos nuevamente en el terminal (que hemos dejado abierto):

python3   test_leds1.py  <RETURN>

El led inicialmente tendría que esta apagado, cuando accionamos el pulsador 1, empezará a destellar en modo intermitente hasta que accionamos el pulsador 2 que termina el programa. El terminal se recuerda los textos que hemos escrito. Para seleccionarlos basta moverse con las flechas del teclado.

Ahora explico como funciona el programa. El extraño texto en el primer renglón (#!usr/bin/env python) sirve para decirle a Python que efectivamente este es un programa Python. En el renglón 3 importamos la parte GPIO de la librería RPi y que maneja los puertos de entrada y salida de las Raspberry. Observen que usando "as io" decimos a Python que desde este momento para referirnos a esta parte del la librería escribiremos solo "io" en vez de RPi.GPIO porque es más sintético.

En el renglón 4 importamos la librería "time" que nos permite de crear retardos y temporizaciones.

En los renglones 6, 8 y 9 le decimos a Python que el led 1 se encuentra conectado a la GPIO 9 del microcontrolador mientras que los pulsadores están conectados a los GPIO 10 y 11. Para este primer programa usaremos solo un led para no complicar demasiado las cosas.

La Raspberry PI conectada a la protoboard con los leds y los pulsadores.
La Raspberry PI conectada a la protoboard con los leds y los pulsadores.

En el renglón 11, con el comando io.setmode (io.BCM), decimos a Python que los números que estamos usando corresponden a las entradas y a las salidas del micro. Si hubiésemos usado io.setmode (io.BOARD) los números corresponderían a los números de los pines del conector de las Raspberry. Yo por tradición prefiero referirme al micro.

En el renglón 12, con io.setwarnings(False) le decimos a Python de no mostrarnos advertencias de pines ya ocupados para otras funciones.

En el renglón 14 decimos a Python que el pin conectado al led 1 es una salida mientras que en los renglones 16 y 17 le decimos que los pines conectados a los pulsadores son entradas.

En el renglón 19 creamos un bucle (loop) que espera hasta que activamos el pulsador 1. He usado un "for" de 100 ciclos en lugar de "while" porque en el caso de problemas con la activación del pulsador 1 (por ejemplo en el caso de error en la conexiones), después de 50 segundos (100 ciclos de medio segundo), termina "si o si" el bucle evitando que el programa quede bloqueado en un loop infinito sin saber si el programa está funcionando.

En el renglón 25 empieza el bucle de intermitencia del led, a través de la instrucción while y seguirá adelante hasta que activemos el pulsador 2. Observen que el código del programa en algunas partes se encuentra separado del margen izquierdo por espacios. Esto se llama identación (derivado del inglés identation) o más correctamente es castellano: sangrado y es muy importante en Python porque sirve para distinguir los bloques de código (como en el caso de las instrucciones end if o next del basic o los símbolos {  } del C o derivados).

Conexiones a la Rasberry PI
Conexiones a la Rasberry PI

Los expertos de Python aconsejan de usar una identación (o sangrado) de 4 espacios y sin usar tabulaciones. Quizás en futuro hablaré más de este tema pero por ahora les digo de respetar correctamente este sangrado porque si no lo hacen el programa no funcionará correctamente.

El estilo de los programas en Python

No obstante Python sea un lenguaje muy intuitivo y fácil de aprender, la comunidad que lo sostiene mantiene una actitud muy rigurosa respecto al estilo del código escrito. Creo que esto se debe a dos motivos: el primero está relacionado a su creador: Guido van Rossum que da mucha importancia a la estética y a la elegancia del código. El segundo motivo (y no menos importante) es que el código Python es fundamentalmente "open source"  y se condivide en todo el mundo (especialmente a través de las librerías), por lo tanto es necesario que el código escrito sea bien legible y claro. Las indicaciones de estilo más importantes se encuentran en un documento llamado PEP-8 que aconsejo de leer a los que empiecen (como yo) a trabajar con Python.

El segundo programa

Una vez que el programa funciona correctamente podemos escribir una versión más sofisticada del mismo que usa los 4 leds. Desde el editor creamos un nuevo file que lo llamaremos test_leds2.py y lo guardamos. Después escribimos lo siguiente:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!usr/bin/env python         # Necesario para el interprete Python
"""
Programa simple que enciende 4 leds conectados
a una Raspberry PI en modo secuencial.
(CC) BY_NC_SA por Gabriel Rapetti para Inventable

Uso:
-----
1. Accionar el pulsador 1 para activar la secuencia
2. Accionar el pulsador 2 para terminar el programa
"""


import RPi.GPIO as io        # Import libreria de I/O (entradas / salidas)
import time                  # Import libreria para los retardos

led1 = 9                     # led 1 conectado al gpio 9 del micro
led2 = 8                     # led 2 conectado al gpio 8 del micro
led3 = 7                     # led 3 conectado al gpio 7 del micro
led4 = 4                     # led 4 conectado al gpio 4 del micro

button1 = 11                 # boton 1 conectado al gpio 11 del micro
button2 = 10                 # boton 2 conectado al gpio 10 del micro

io.setmode(io.BCM)           # modo in/out pin del micro
io.setwarnings(False)        # no señala advertencias de pin ya usados

io.setup(led1,io.OUT)        # set pin led 1 como salida
io.setup(led2,io.OUT)        # set pin led 2 como salida
io.setup(led3,io.OUT)        # set pin led 3 como salida
io.setup(led4,io.OUT)        # set pin led 4 como salida

io.setup(button1,io.IN)      # set pin pulsador 1 como entrada
io.setup(button2,io.IN)      # set pin pulsador 2 como entrada

for a in range(100):         # Ciclo de espera hasta que se acciona
    time.sleep(0.5)          # el pulsador 1
    if not io.input(button1):
        break                # Con el pulsador 1 accionado (a masa)
                             # termina el ciclo de espera

while io.input(button2):     # Ciclo hasta que se acciona el pulsador 2
    io.output(led4,0)        # Apaga el led 4
    io.output(led1,1)        # Enciende el led 1
    time.sleep(0.1)          # Espera medio segundo

    io.output(led1,0)        # Apaga el led 1
    io.output(led2,1)        # Enciende el led 2
    time.sleep(0.1)          # Espera otro medio segundo

    io.output(led2,0)        # Apaga el led 2
    io.output(led3,1)        # Enciende el led 3
    time.sleep(0.1)          # Espera otro medio segundo

    io.output(led3,0)        # Apaga el led 3
    io.output(led4,1)        # Enciende el led 4
    time.sleep(0.1)          # Espera otro medio segundo

io.output(led4,0)            # Apaga el led 4 antes de terminar el programa

El programa es muy similar al primero, con la diferencia que hemos declarado 4 leds en lugar de uno y que el ciclo "while" enciende y apaga los leds en secuencia. El funcionamiento de los pulsadores es similar.

Conclusiones

Las técnicas de programación en Python pueden ser muy simples o muy sosfisticadas (por ejemplo con la programación orientada a objetos). En este proyecto he tratado de reducir la complejidad (ni siquiera funciones he usado) para ser lo más didáctico posible. Python, Raspberry y Linux son argumentos muy extensos sobre los cuales pueden encontrar toneladas de artículos en Internet y también tantos libros. En este artículo quise demostrar que es posible controlar entradas y salidas de una Raspberry PI en modo sencillo y sin complicaciones, empezando desde cero . Así fue y esto abre perspectivas muy interesantes en la integración de software de alto nivel y electrónica.

Hasta la próxima.

Gabriel

- Indice de todos los artículos de Inventable -

Los contenidos de este blog son originales y están bajo una licencia Creative Commons BY_NC_SA

Controlando leds con una Raspberry PI ultima modifica: 2017-10-15T21:53:22+00:00 da inventable

8 thoughts on “Controlando leds con una Raspberry PI”

  1. Hola, muy interesante el proyecto. He probado a construirlo usando una raspberry modelo B+ con el conector más grande pero cuando corro el primer programa me aparece este error: line 20 time.sleep(0.5) SyntaxError: unexpected indent y no hace nada.
    ¿Sabes donde puede estar el error?
    José

    1. Hola José, sólo soy un colaborador, y te aclaro que de Python no sé nada, excepto que es muy quisquilloso con el formato. Deberías darle una leída al documento PEP-8 que está indicado en el artículo.
      Fíjate que la línea del error es la primera que está indentada. Debes asegurarte de usar espacios y no tabulaciones para esto. O puede que hayas olvidado los dos puntos finales de la instrucción anterior.
      Espero que no me malinterpreten, porque no estoy discutiendo las preferencias de nadie, pero francamente no sé qué le ven a este lenguaje ni porqué se hizo tan famoso.
      Me parece mucho más intuitivo el BASIC, en el que cada bloque está bien delimitado por su End y no hace tanto escándalo si uno puso un espacio de más o de menos. Pero bueno, es sólo mi opinión.

      Espero que puedas resolverlo.

      Saludos,
      Juan

      1. Tené cuidado Juan con los comentarios, que los pythonianos son muy orgullosos y se enojan 🙂
        Hablando en serio, yo también era medio crítico con los delimitadores de bloques pero una vez que le agarrás la mano, es bastante simple. Basta usar un editor de código (como Idle o Geany) e indicarle que agregue espacios cuando usás la tecla TAB. Respecto al lenguaje te puedo asegurar que tiene una potencia impresionante, te permite de hacer cosas increíbles, impensables con el basic y sin las complicaciones del C, Java, PHP, etc. Yo fui siempre muy conservador en materia de lenguajes pero en este caso lamento de no haberlo estudiado y trabajado con él antes. Ahora que empecé a prestar más atención descubro que Python está por todos lados, inclusive en los server, reemplazando el PHP.
        Un abrazo.

        1. ¡Jajajaja! Sí, ya sé, no creo que se haya hecho famoso nada más que por el nombre.

          De paso, en mi ignorancia sobre el tema, le di una pista a José, pero no sé si es correcta.

          Un abrazo,
          Juan

          1. Respecto a tu consejo sobre el error, es correcto. Veamos si nuestro lector José lo resuelve.
            Un abrazo.

            Gabriel

      2. Buenas noche, agradezco a Juan y a Gabriel por las explicaciones muy completas. Si, el error estaba en la línea 20 porque faltaba un espacio. Ahora el programa funciona bien. Entiendo el comentario de Juan porque tanto los espacios como las tabulaciones no se distinguen a simple vista y que un programa no funcione por estas cosas me parece medio exagerado.
        Sigo adelante con el segundo programa.
        Hasta luego.

        1. Hola José. nos alegra que hayas podido solucionarlo.

          Dado que este es un artículo sobre progamación, me tomo la libertad de hacer un comentario. Si no es adecuado, siéntanse libres de borrarlo.

          Una vez tuve que hacer un parser (intérprete, pero en la jerga se le dice parser) para una aplicación mía, y me resultó más difícil de lo que había imaginado al principio.
          El parser tiene que interpretar lo que el programador quiso decir, independientemente de la forma en que lo dijo. Es más complicado de lo que suena (al menos lo fue para mí).

          En el caso del Python, y luego de lo que estuvimos comentando, me quedé pensando y se me ocurrió una posible explicación del porqué de la rigidez del formato.

          El Python es un lenguaje interpretado, o sea que cada instrucción se interpreta en el momento de ejecutarla.
          Se me ocurre, y es sólo una suposición mía y luego de mi experiencia, que si uno ya sabe de antemano el formato de cada línea del programa, haría más fácil su interpretación y por ende, aceleraría el proceso, lo que en un lenguaje interpretado es muy importante.
          Me parece una explicación razonable, aunque no sé si es cierta o no.

          Bueno, nada más.
          Saludos a todos,
          Juan

Deja un comentario

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