A continuación se muestra una lista con los componentes que deben tenerse a mano para comenzar con la manipulación de la pequeña placa embebida:
Las características indicadas para la tarjeta de memoria son las mínimas. Si se cuenta con una tarjeta de mayores prestaciones es recomendable utilizarla.
El primer paso es formatear la tarjeta SD mediante cualquier aplicación que se tenga a la mano (no formatear con algún teléfono celular). Acto seguido, dirigirse a la página de la Fundación Raspberry Pi https://www.raspberrypi.org/ y luego a la sección de Descargas.
raspberrypi.org
En dicha sección obtendremos el sistema operativo que instalaremos en la tarjeta SD. De las dos opciones que saltan a la vista, nos quedaremos con la descarga de Raspbian (debemos asegurarnos que es la versión para Raspi, más abajo está otra que es para PC, no bajar esa última).
raspbian
Al dar clic en la imagen nos brindará tres opciones. Por cuestiones de facilidad, escogemos la versión completa «with desktop and recommended software». Es recomendable que al terminar la descarga, no se descomprima.
El archivo zip será muy pesado y lento para hacerlo. Lo ideal es utilizar una aplicación llamada Etcher, la cual es libre y puede descargarse de su página oficial: https://www.balena.io/etcher/. La aplicación es sumamente sencilla de utilizar: en la misma pantalla se selecciona la imagen a montar, luego la tarjeta (si solo hay insertada una tarjeta SD, esa será seleccionada por defecto). Clic en Flash! y listo.
etcher
Insertamos la tarjeta en la ranura adecuada de la Raspi. Conectamos el cable HDMI y los periféricos enlistados arriba. La alimentación de corriente se conecta al final. Al realizarse esto último deben encenderse dos leds de la placa: uno rojo y uno verde. El rojo indica que está energizada. El verde debe estar parpadeando y así indica lectura de la tarjeta SD. Por otro lado, en el monitor debió aparecer un flash multicolor, señal de que la salida de video es correcta. Esperamos un poco a que cargue todo y debería aparecer algo así en pantalla:
desktop
La ventana que aparece en la captura es el gestor de configuración de la Raspberry. Es buena idea adecuar la localización al país de uso (México) en la última pestaña. Con eso hecho, hay que ejecutar unos cuantos comandos para irse familiarizando con el sistema operativo (el cual es Linux). Conectamos la placa a internet mediante WiFi o ethernet, actualizamos la lista de repositorios y enseguida actualizamos el sistema.
Actualizar los repositorios nos sirve para encontrar las actualizaciones disponibles para el software instalado. En sistemas Linux basados en Debian (tales como Raspbian, Ubuntu, Linux Mint o Kali) esto se realiza mediante el comando:
sudo apt update
Para aplicar las actualizaciones disponibles se ejecuta:
sudo apt upgrade
En caso de ser necesario instalar alguna aplicación, esto se hace con:
sudo apt install aplicación-necesaria
Si instalamos algo innecesario podemos eliminarlo con:
sudo apt remove aplicación-innecesaria
Y si queremos eliminar dependencias de aplicaciones eliminadas:
sudo apt autoremove
Tenemos disponible la versión 3 de la placa. Ya tiene incluidas las conexiones WiFi y Bluetooth, por lo que ya no es necesario comprar los módulos pertinentes. Lo que más nos interesa son los pines que sobresalen bastante de la misma placa. Les llamamos GPIO. Son las conexiones que nos permitirán controlar motores y focos o recibir mediciones de los sensores conectados. Es muy importante tener a la mano la numeración de los mismos, ya que no sigue un orden físico. El orden de los GPIO –mirando la raspi desde arriba y con los puertos USB apuntando al suelo–, es el siguiente:
Etiqueta | Posición física | Posición física | Etiqueta |
---|---|---|---|
3.3V | 1 | 2 | 5V |
GPIO2 | 3 | 4 | 5V |
GPIO3 | 5 | 6 | GND |
GPIO4 | 7 | 8 | GPIO14 |
GND | 9 | 10 | GPIO15 |
GPIO17 | 11 | 12 | GPIO18 |
GPIO27 | 13 | 14 | GND |
GPIO22 | 15 | 16 | GPIO23 |
3.3V | 17 | 18 | GPIO24 |
GPIO10 | 19 | 20 | GND |
GPIO9 | 21 | 22 | GPIO25 |
GPIO11 | 23 | 24 | GPIO8 |
GND | 25 | 26 | GPIO7 |
DNC (GPIO0) | 27 | 28 | DNC (GPIO1) |
GPIO5 | 29 | 30 | GND |
GPIO6 | 31 | 32 | GPIO12 |
GPIO13 | 33 | 34 | GND |
GPIO19 | 35 | 36 | GPIO16 |
GPIO26 | 37 | 38 | GPIO20 |
GND | 39 | 40 | GPIO21 |
Donde el número enseguida de la palabra GPIO es el número de GPIO al que debemos hacer referencia cuando lo utilicemos en el código. Por ejemplo, el GPIO18 es el que físicamente ocupa la posición 12. Pero si en nuestro código ponemos 12 como identificador, en realidad estaremos referenciando físicamente al pin 32.
El circuito es sumamente sencillo. Solo hay que asegurarse de que se respeta la polaridad del LED: la patita más corta debe conectarse a la resistencia y luego a tierra (GND) y la otra al GPIO elegido (GPIO18).
LED-01
El código es también bastante sencillo. Para comenzar a programar abrimos Menú Inicio > Desarrollo > Python 3 (IDLE). Creamos un archivo nuevo File > New File y lo guardamos (File > Save) con el nombre que queramos en una ubicación sencilla de acceder.
El código consta primero de la importación de la clase LED
desde la librería GPIO Zero
.
from gpiozero import LED
Asignamos la variable led
al GPIO18
.
led = LED(18)
Encendemos el LED con el método on()
.
led.on()
Presionamos F5 para ejecutar el código y el LED debería encenderse. Podemos detener el programa con la combinación CTRL + C. El código completo debería verse así:
from gpiozero import LED
led = LED(18)
led.on()
Comenzamos importando la clase LED
. Después importamos la función sleep
desde la librería time
.
from time import sleep
Asignamos la misma variable al mismo GPIO
del código anterior, pero ahora no mantendremos encendido el LED de manera permanente, si no que lo haremos parpadear con un segundo de diferencia. Para ello haremos uso de un loop infinito que encienda y apague el LED en intervalos iguales de 1, utilizando los métodos on()
y off()
y para permanecer un segundo la función sleep(1)
.
while True:
led.on()
sleep(1)
led.off()
sleep(1)
Presionamos F5 para ejecutar el código y el LED debería estar parpadeando. El código final debería verse así:
from gpiozero import LED
from time import sleep
led = LED(18)
while True:
led.on()
sleep(1)
led.off()
sleep(1)
Podemos conseguir el mismo efecto con menos líneas de código, utilizando el método blink()
.
from gpiozero import LED
from signal import pause
led = LED(18)
led.blink()
pause()
El método permite especificar el tiempo de encendido, de apagado, número de parpadeos y si se ejecuta como un subproceso de fondo.
blink(on_time=1, off_time=1, n=None, background=True)
Documente el procedimiento para controlar el encendido de un LED mediante la Raspberry Pi. Incluya imágenes del circuito real y el código utilizado.
Prácticamente es el mismo circuito que la práctica anterior, pero triplicado.
from gpiozero import LED
from time import sleep
rojo = LED(14)
ambar = LED(15)
verde = LED(18)
verde.on()
ambar.off()
rojo.off()
while True:
sleep(10)
verde.off()
ambar.on()
sleep(1)
ambar.off()
rojo.on()
sleep(10)
ambar.on()
sleep(1)
verde.on()
ambar.off()
rojo.off()
Modifique el semáforo programado, para mejorar su comportamiento y acercarlo al de un semáforo más realista. Documente el proceso con imágenes y el código empleado.
Uno de los inconvenientes de trabajar con la placa es que es necesario conectarla a un monitor externo. En ocasiones es bastante incómodo o complicado. Sin embargo, teniendo una conexión estable y permanente a internet se puede resolver el problema. Encienda la Raspberry y asegúrese de que el servidor VNC se encuentre habilitado. Es fácil: el icono se encontrará coloreado en la bandeja, al lado de los indicadores de conexión a internet y bluetooth. Si se encuentra sombreado significa que está activado pero no hay acceso a la red. Si simplemente no se encuentra el indicador es porque no está activado VNC Server. Para activarlo, nos dirigimos a Menú Inicio -> Preferencias -> Configuración de Raspberry Pi. Aparecerá una ventana con cuatro pestañas, pero las que nos interesan son la de Sistema y la de Interfaces. Nos dirigimos a la primera y damos clic en el botón de Cambiar Clave, ahí nos pedirá que ingresemos la nueva contraseña para evitar intrusos, no olvidarla. Ahora nos vamos a la pestaña Interfaces y nos aseguramos de activar SSH y VNC. Le damos en aceptar y reiniciamos la Raspberry. Al volver a entrar a Raspbian, ya debería estar activo el servidor.
Ahora es necesario preparar el dispositivo por el cual se desplegará remotamente el escritorio de la Raspberry Pi. Debemos descargar la aplicación adecuada (si es una laptop asegurarnos de descargar la versión adecuada al sistema operativo, en el caso de utilizar un teléfono celular, existen versiones disponibles para Android y para iOS, incluso para el navegador Chrome) desde la página oficial de VNC: https://www.realvnc.com/es/connect/download/viewer/. Instalamos la aplicación y la ejecutamos (debemos aceptar una licencia) .
Ya estando activo el servidor en la raspberry, nos dirigimos a donde se encuentra el indicador en la barra de tareas. Damos clic derecho y enseguida se abre una ventana con la información de la raspberry en cuanto a la conexión. Nos interesa la dirección IP. La copiamos porque a ella nos conectaremos con el visor.
Ahora nos vamos al cliente y ahí accedemos a la ventana principal (después de cerrar la de bienvenida). En la caja de texto introducimos la dirección IP de la raspberry, tomando en cuenta que ambos dispositivos, cliente y servidor, deben estar conectados a la misma red. Nos pedirá que aceptemos conectarnos al servidor ya que no se ha detectado una conexión anterior. Aceptamos y enseguida debemos aportar las credenciales necesarias, el usuario por defecto es pi, mientras que la contraseña es la que se cambió en la primera parte de la práctica. Al ser autenticados, debe verse ya el escritorio de la raspberry en la pantalla del dispositivo cliente.
Existe una manera de acceder remotamente con un dispositivo cliente a la raspberry sin que se encuentren ambos conectados a la misma red. Esto sería muy útil también para cuando la placa no estará conectada a un monitor y no se puede saber la dirección IP y/o no se quiere fijar la misma. Para ello es necesario crearse una cuenta desde el dispositivo cliente en la página de RealVNC https://www.realvnc.com/es/, o desde la propia Raspberry en el indicador VNC, dando clic derecho y entrando a Aplicación de licencias. En la primera opción damos clic en «regístrese en línea» y se abrirá el navegador Chromium con las instrucciones pertinentes.
Con la cuenta ya creada, volvemos a ese apartado y seleccionamos la misma primera opción, damos clic en Next e introducimos nuestras credenciales. Ahora volvemos al cliente y con el visor ejecutado, damos clic en Iniciar sesión. Introducimos nuestros datos y autorizamos la conexión tanto en el correo que se nos enviará como en VNC Viewer. Posteriormente damos clic en el apartado donde aparece nuestro nombre registrado (aparece como Usuario’s Team (Home)). A la derecha estarán los dispositivos enlazados a la cuenta, damos doble clic y estaremos ya frente al escritorio de la Raspi.
El botón no tiene polaridad. Si es de cuatro pines hay que insertarlo en el canal central de la tablilla, de modo que dos pines queden en una mitad y los restantes en la otra. Si es de dos pines no es importante la ubicación.
Circuito del botón
Primero importamos la clase Button
desde gpiozero
.
from gpiozero import Button
Asignamos la variable boton al GPIO18
:
boton = Button(18)
Y ahora agregamos el método wait_for_press()
para que el script
se detenga hasta que el botón se active al ser presionado. Agregamos un mensaje que nos avise que el botón fue activado:
boton.wait_for_press()
print("El botón ha sido presionado")
wait_for_release(timeout=None)
Comportamiento análogo al método wait_for_press
, con la salvedad de que pausa el script
hasta que el botón es desactivado o el timeout
es alcanzado.
when_pressed
La función a correr cuando el botón cambia de inactivo a activo.
when_released
La función a correr cuando el botón cambia de activo a inactivo.
Esperar el cambio de estado del botón y avisar sobre dicho cambio:
from gpiozero import Button
button = Button(18)
while True:
if button.is_pressed:
print("Botón presionado")
else:
print("Botón no presionado")
Utilice lo visto anteriormente y diseñe una aplicación que encienda al LED solo al pulsar un botón. Así mismo, al soltar el botón, el LED debe apagarse.
Es relativamente sencillo el armado, solo hay que mencionar que el LED RGB tiene cuatro pines, de los cuales, el más largo se corresponde con tierra. Si estamos viendo el LED de «frente», dicho pin será el segundo, contando de izquierda a derecha. Los demás se corresponden a la secuencia RGB, es decir: rojo el primero, verde el tercero y azul el último.
Contrario al LED normal, en este caso conectaremos las resistencias a los pines que irán a los GPIO, como se muestra a continuación:
Definimos nuestra variable y jugamos con los parámetros de la clase RGBLED
, tomando en cuenta que los mismos se corresponden con la intensidad de los colores rojo, verde y azul.
from gpiozero import RGBLED
from time import sleep
led = RGBLED(14,15,18)
led.red = 1
sleep(1)
led.red = 0.5
sleep(1)
led.color = (0, 1, 0)
sleep(1)
led.color = (1, 0, 1)
sleep(1)
led.color = (1, 1, 0)
sleep(1)
led.color = (0, 1, 1)
sleep(1)
led.color = (1, 1, 1)
sleep(1)
led.color = (0, 0, 0)
sleep(1)
for n in range(100):
led.blue = n/100
sleep(0.1)
Mucho cuidado con la polaridad del sensor. Aunque se alimenta con \(5V\), entrega solo \(3.3V\), así que no requiere un circuito adicional. La resistencia es para proteger la raspi de la carga absorbida por el LED.
from gpiozero import MotionSensor, LED
from signal import pause
pir = MotionSensor(14)
led = LED(16)
pir.when_motion = led.on
pir.when_no_motion = led.off
pause()
El sensor de proximidad o de distancia mide, propiamente dicho, la distancia existente desde e propio sensor hasta un obstáculo dado.
Se debe tener especial cuidado en el arreglo de las resistencias, ya que el sensor de distancia emite una señal de echo de 5V, la cual puede dañar la Raspberry. Para adecuarlo a 3.3V, se utiliza el par de resistencias mostrado en el circuito (en el pin de echo se conecta la de \(270\Omega\), mientras que para tierra se conecta la resistencia de \(470\Omega\)):
Para la clase DistanceSensor
se deben escribir los GPIO en el siguiente orden: primero el GPIO que recibirá la señal echo y enseguida el GPIO que recibirá la señal de trigger.
from gpiozero import DistanceSensor
from time import sleep
sensor = DistanceSensor(23, 18)
while True:
print('La distancia es', sensor.distance, 'mts')
sleep(1)
En esta práctica controlaremos el sentido de giro de un pequeño motor de corriente directa, presente en varios coches de juguete de control remoto. El código es bastante sencillo, utilizando la librería GPIOZero
: apenas seis líneas. Sin embargo, ahora incluimos un circuito integrado, el SN754410 (o su equivalente literal, el L293D). Este CI es conocido como un puente H, por la forma en la que se dibuja en los diagramas. También se le conoce como driver para motores. Este driver permite controlar hasta dos motores y nos evita utilizar transistores y diodos en nuestro circuito.
NO DEBE CONECTARSE JAMÁS EL MOTOR DIRECTAMENTE A LA RASPBERRY, NI ALIMENTAR ESTE CIRCUITO CON LOS 5V DE LA MISMA. TAMPOCO CONECTARSE A TIERRA. LA ALIMENTACIÓN Y CONEXIÓN A TIERRA DEBEN VENIR DESDE UNA FUENTE EXTERNA. Es muy importante respetar el sentido del CI, ya que podemos dañarlo fácilmente. Por esta razón, cuenta con una muesca en uno de sus extremos, la cual nos indica cómo debe colocarse. En el diagrama del circuito mostrado a continuación, se muestra el CI con la muesca en el extremo izquierdo. Respetemos el orden propuesto, que se observa mejor en la segunda imagen.
En esta imagen se muestran con mayor detalle los pines del SN754410. Deben energizarse los pines 1, 8, 9 y 16 con los \(5V\) provenientes de una fuente de alimentación, jamás desde la propia Raspberry. Los pines 1 y 9 se energizan para habilitar el puente para el motor correspondiente; mientras que los pines 8 y 16 son el voltaje que hará funcionar a cada motor. Los pines 2 y 7 son para el control del motor «izquierdo», mientras que los pines 10 y 15 son su contraparte para el motor «derecho». Estos pines deben ir a algún GPIO cada uno. Los pines 3 y 6 se conectan al motor que se controlará con los pines 2 y 7. Caso parecido con los pines 11 y 14. Debe asegurarse de conectar los pines marcados como GND a tierra (se corresponden con los pines 4, 5, 12 y 13).
En este código el motor se estará moviendo hacia adelante durante diez segundos y enseguida hacia atrás en el mismo lapso de tiempo:
from gpiozero import Motor
from time import sleep
motor = Motor(forward=4, backward=14)
#el primer GPIO activa movimiento hacia delante, el segundo la reversa.
while True:
motor.forward()
sleep(10)
motor.backward()
sleep(10)
Es prácticamente el mismo que el circuito que controla un motor único, con la salvedad de que se conectan los pines correspondientes al segundo y a su control.
El siguiente código hará que los motores giren en cierta secuencia (si tuvieran acopladas ruedas y estuvieran montados en un chásis, seguirían burdamente una trayectoria cuadrada).
from gpiozero import Robot
from time import sleep
robot = Robot(left=(4, 14), right=(10, 25))
#se separan ambos lados por motor, y al igual que en el anterior, el primer GPIO activa el movimiento adelante.
for i in range(4):
robot.forward()
sleep(10)
robot.right()
sleep(1)
from gpiozero import Robot, Button
from signal import pause
robot = Robot(left=(4, 14), right=(17, 18))
left = Button(26)
right = Button(16)
fw = Button(21)
bw = Button(20)
fw.when_pressed = robot.forward
fw.when_released = robot.stop
left.when_pressed = robot.left
left.when_released = robot.stop
right.when_pressed = robot.right
right.when_released = robot.stop
bw.when_pressed = robot.backward
bw.when_released = robot.stop
pause()