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.
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.
La instalación continuará sin hacer más preguntas y llevará algunos minutos. Aquí también han simplificado mucho respecto al pasado.
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.
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.
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.
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
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:
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).
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.
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.
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.
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).
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
Buenísimo, Gabriel. Puede que esto me anime a lanzarme a probar la Raspberry Pi.
Saludos.
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é
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
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.
¡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
Respecto a tu consejo sobre el error, es correcto. Veamos si nuestro lector José lo resuelve.
Un abrazo.
Gabriel
Comparto este comentario al 100% y los tutoriales de Gabriel están muy bien hechos.
Tengo 75 años, he vuelto a programar y he elegido Python. Como tenía una carrera de informatica (soy jubilado) ha sido muy fácil ponerme a programar en este lenguaje.
Todavía no he hecho nada en Raspberry solo con mi portátil y linux mint/ubuntu, no voy a tardar…
Ánimos para todos!
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.
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 traduce 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
Hola a todos:
Hace muy pocos meses, cuando me enteré de la existencia y el poder de la Raspberry, se me metió en la cabeza hacer una aplicación para algo que necesito para mi «supervivencia», jeje.
El problema era que no tenía la Raspberry, y más importante aún, absolutamente ni la menor idea de por dónde empezar.
Leyendo este artículo, no sólo me quedó claro por dónde empezar (con la claridad habitual en Inventable:)). Leí un poco de Python (un manual de introducción) y algo (mucho menos) del Raspbian, y vi que entre los dos tienen exactamente lo que necesito para hacer el aparato.
Me falta elaborar muchísimo, pero si hago algún avance, les cuento.
En mi primer comentario, hace ya dos años, dije que ya no necesitaba «copiar». Me retracté unos momentos después porque me pareció soberbio, lo que no era mi intención.
Ahora me retracto aún más, porque aunque no necesite copiar, con este artículo me di cuenta de que lo que sí necesité muchas veces fue una guía para empezar. El camino después lo recorre uno mismo.
Así que gracias. Gabriel, no tenés ni idea de lo que esto puede significar para mí (no estoy hablando de dinero). Después les cuento más.
Gracias por todo.
Un abrazo para todos,
Juan
Amigo Juan, me alegra mucho tu comentario. Sabés, tuve dudas antes de publicar este artículo porque se aleja de la línea clásica de Inventable que se basa principalmente en proyectos simples. Por otro lado, hacer un nuevo post para Inventable me obliga a ordenar mis ideas, a documentarme y a no dejar cabos sueltos. Esto me es muy útil si estoy aprendiendo un nuevo argumento como este y por lo tanto seguí adelante. Yo, como vos, estaba medio perdido porque Linux, Raspberry y Python son temas complejos que no conozco. En síntesis: no sabía por donde empezar y necesitaba una guía que me ayudara en esto. Así fue que nació este proyecto. Actualmente estoy desarrollando, en el poco tiempo que tengo, algunas cosas un poco más complejas con Python y Raspberry: una interfaz gráfica de control para los puertos (en tkinter) y próximamente una pagina web (con flask) accesible desde el teléfono. Me entusiasma que te pongas a trabajar con esto. Quizás podamos publicar cosas en modo conjunto.
Un abrazo.
Gabriel
Hoy mismo conseguí permiso (que me autoricen el gasto 🙂 ) para comprar una Raspberry 3, pero primero tengo que terminar otras cosas. Al cliente el proyecto le encantó así que voy a empezar apenas pueda. Después cuento más, no quiero hablar demasiado por ahora hasta que tenga algo más o menos encarado. Para que te des una idea, el cliente gastará 80 dólares en lugar de 2900 🙂
Además estoy entusiasmado con algo por fin nuevo. Veremos qué pasa.
Un abrazo,
Juan
Hola a todos:
Con el entusiasmo que me produjo el artículo, hoy me puse a buscar información un poco más completa de Python y encontré
http://docs.python.org.ar/tutorial/pdfs/TutorialPython3.pdf,
un libro escrito por el propio Rossum, pero traducido al español por la comunidad de Python de Argentina.
Todavía sigo sin saber el poder que tiene el lenguaje (todavía no llegué a la mitad), pero sí tengo que reconocer que es muy fácil de aprender.
Veremos qué pasa.
Gracias por todo,
Juan
Hola Gabriel, una pregunta: ¿de dónde sacaste esos cables maravillosos que usaste para conectar la Rpi al proto?
Hola Juan, te respondo de metido que soy,ya que la consulta es para Gabriel… pero apuesto que se compran en china por dos mangos.
Saludos
HJ
Acabo de verificar, y acá, mediante merado libre también se consiguen, pero un poco mas de dos mangos… jejeje
https://listado.mercadolibre.com.ar/cables-para-protoboard
Saludos
HJ
¡Hola Héctor! No, no era específica para Gabriel. Lo pregunté así porque supuse que era algo típico de Europa; ni se me había ocurrido buscar acá 🙁
Nunca los había visto, pero me hubieran salvado más de un par de veces.
Y lo del precio, no sé: los juegos de 40 cables cuestan menos que un paquete de puchos, y supongo que durarán más 🙂
¡Gracias!
Saludos,
Juan
Estos cables estaban dentro a un kit que compré con el micro de la BBC y yo también me pregunté donde encontrarlos. Ahora, gracias a las indicaciones de HJ me pondré a buscarlos en ebay, versión internacional de mercado libre. Gracias!!