BLE en Raspberry Pi

Como hemos visto en una entrada anterior la Raspberry Pi 3 dispone de BLE.

Para comenzar a trabajar con BLE en Raspberry Pi debemos comprobar que está disponible, mediante el comando hciconfig:

pi@raspberrypi:~ $ hciconfig
hci0: Type: Primary Bus: UART
 BD Address: XX:XX:XX:XX:XX:XX ACL MTU: 1021:8 SCO MTU: 64:1
 UP RUNNING 
 RX bytes:822 acl:0 sco:0 events:57 errors:0
 TX bytes:4231 acl:0 sco:0 commands:57 errors:0

En caso de que no esté arrancado hay que activarlo

sudo hciconfig hci0 up

Una utilidad que proporciona más información es blescan

pi@raspberrypi:~ $ sudo blescan
Scanning for devices...
Device (new): xx:xx:xx:xx:xx:xx (random), -91 dBm (not connectable)
Manufacturer: <060001092000c7ce0663439d1e190d97c0a7827dfe0cb225c5cad35fee>

Después de comprobar que BLE está activado podemos arrancar el modo central u observador que escucha en las direcciones más usuales y nos devuelve las direcciones MAC (Se han cambiado el resultado de las MAC, son identificaciones únicas a nivel globalpor XX:XX:XX:XX:XX:XX):

pi@raspberrypi:~ $ sudo hcitool lescan
LE Scan ...
XX:XX:XX:XX:XX:XX (unknown)
XX:XX:XX:XX:XX:XX (unknown)
XX:XX:XX:XX:XX:XX (unknown)
XX:XX:XX:XX:XX:XX Flex
XX:XX:XX:XX:XX:XX (unknown)
XX:XX:XX:XX:XX:XX MTLocomotive

Una vez descubiertos los dispositivos BLE que están emitiendo anuncios o “beacons” podemos con la utilidad gatttool establecer una conexión:

pi@raspberrypi:~ $ gatttool -I -b XX:XX:XX:XX:XX:XX
[XX:XX:XX:XX:XX:XX][LE]>
[XX:XX:XX:XX:XX:XX][LE]> connect
Attempting to connect to XX:XX:XX:XX:XX:XX 
Error: connect error: Connection refused (111)

En este caso Flex se rechaza la conexión pues precisa una autentificación, los parámetros completos de gatttool son:

[XX:XX:XX:XX:XX:XX][LE]> help
help Show this help
exit Exit interactive mode
quit Exit interactive mode
connect [address [address type]] Connect to a remote device
disconnect Disconnect from a remote device
primary [UUID] Primary Service Discovery
included [start hnd [end hnd]] Find Included Services
characteristics [start hnd [end hnd [UUID]]] Characteristics Discovery
char-desc [start hnd] [end hnd] Characteristics Descriptor Discovery
char-read-hnd <handle> Characteristics Value/Descriptor Read by handle
char-read-uuid <UUID> [start hnd] [end hnd] Characteristics Value/Descriptor Read by UUID
char-write-req <handle> <new value> Characteristic Value Write (Write Request)
char-write-cmd <handle> <new value> Characteristic Value Write (No response)
sec-level [low | medium | high] Set security level. Default: low
mtu <value> Exchange MTU for GATT/ATT

Otra utilidad es bluetoothctl:

pi@raspberrypi:~ $ bluetoothctl
 [NEW] Controller XX:XX:XX:XX:XX:XX raspberrypi [default]
 [NEW] Device XX:XX:XX:XX:XX:XX Flex
 [NEW] Device XX:XX:XX:XX:XX:XX MTLocomotive

Los comandos de bluetoolhctl los podemos listar con help:

[bluetooth]# help
 Available commands:
 list List available controllers
 show [ctrl] Controller information
 select Select default controller
 devices List available devices
 paired-devices List paired devices
 power <on/off> Set controller power
 pairable <on/off> Set controller pairable mode
 discoverable <on/off> Set controller discoverable mode
 agent <on/off/capability> Enable/disable agent with given capability
 default-agent Set agent as the default one
 advertise <on/off/type> Enable/disable advertising with given type
 set-advertise-uuids [uuid1 uuid2 ...] Set advertise uuids
 set-advertise-service [uuid][data=[xx xx ...] Set advertise service data
 set-advertise-manufacturer [id][data=[xx xx ...] Set advertise manufacturer data
 set-advertise-tx-power <on/off> Enable/disable TX power to be advertised
 set-scan-filter-uuids [uuid1 uuid2 ...] Set scan filter uuids
 set-scan-filter-rssi [rssi] Set scan filter rssi, and clears pathloss
 set-scan-filter-pathloss [pathloss] Set scan filter pathloss, and clears rssi
 set-scan-filter-transport [transport] Set scan filter transport
 set-scan-filter-clear Clears discovery filter.
 scan <on/off> Scan for devices
 info [dev] Device information
 pair [dev] Pair with device
 trust [dev] Trust device
 untrust [dev] Untrust device
 block [dev] Block device
 unblock [dev] Unblock device
 remove Remove device
 connect Connect device
 disconnect [dev] Disconnect device
 list-attributes [dev] List attributes
 set-alias Set device alias
 select-attribute Select attribute
 attribute-info [attribute] Select attribute
 read Read attribute value
 write <data=[xx xx ...]> Write attribute value
 notify <on/off> Notify attribute value
 register-profile Register profile to connect
 unregister-profile Unregister profile
 version Display version
 quit Quit program

Con esta utilidad podemos encender y apagar BLE:

[bluetooth]# power off
 Changing power off succeeded
 [CHG] Controller XX:XX:XX:XX:XX:XX Powered: no
 [CHG] Controller XX:XX:XX:XX:XX:XX Discovering: no
 [CHG] Controller XX:XX:XX:XX:XX:XX Class: 0x000000
 [bluetooth]# power on
 [CHG] Controller XX:XX:XX:XX:XX:XX Class: 0x6c0000
 Changing power on succeeded
 [CHG] Controller XX:XX:XX:XX:XX:XX Powered: yes
 

Como con gatttool se puede arrancar el modo scan con scan on o ver la versión

[bluetooth]# version
 Version 5.43
 info XX:XX:XX:XX:XX:XX

Y obtener información de un dispositivo en concreto

 [bluetooth]# info XX:XX:XX:XX:XX:XX
 Device XX:XX:XX:XX:XX:XX
 Name: MTLocomotive
 Alias: MTLocomotive
 Paired: no
 Trusted: no
 Blocked: no
 Connected: no
 LegacyPairing: no
 UUID: Vendor specific (XXXXXXXX-4a75-4c14-9ede-c8a5fb84f77b)
 
 [bluetooth]# info XX:XX:XX:XX:XX:XX
 Device XX:XX:XX:XX:XX:XX
 Name: Flex
 Alias: Flex
 Paired: no
 Trusted: no
 Blocked: no
 Connected: no
 LegacyPairing: no
 UUID: Vendor specific (XXXXXXXX-6e7d-4601-bda2-bffaa68956ba)
 ServiceData Key: 0000180a-0000-1000-8000-00805f9b34fb
 ServiceData Value: 0x07
 ServiceData Value: 0x04

Parear

[bluetooth]# pair XX:XX:XX:XX:XX:XX
 Attempting to pair with XX:XX:XX:XX:XX:XX
 [CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
 [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001530-1212-efde-1523-785feabcd123
 [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001800-0000-1000-8000-00805f9b34fb
 [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001801-0000-1000-8000-00805f9b34fb
 [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 98241523-4a75-4c14-9ede-c8a5fb84f77b
 [CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: yes
 [CHG] Device XX:XX:XX:XX:XX:XX Paired: yes
 [NEW] Primary Service
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0008
 00001801-0000-1000-8000-00805f9b34fb
 Generic Attribute Profile
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0008/char0009
 00002a05-0000-1000-8000-00805f9b34fb
 Service Changed
 [NEW] Descriptor
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0008/char0009/desc000b
 00002902-0000-1000-8000-00805f9b34fb
 Client Characteristic Configuration
 [NEW] Primary Service
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service000c
 98241523-4a75-4c14-9ede-c8a5fb84f77b
 Vendor specific
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service000c/char000d
 98241525-4a75-4c14-9ede-c8a5fb84f77b
 Vendor specific
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service000c/char000f
 98241524-4a75-4c14-9ede-c8a5fb84f77b
 Vendor specific
 [NEW] Descriptor
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service000c/char000f/desc0011
 00002902-0000-1000-8000-00805f9b34fb
 Client Characteristic Configuration
 [NEW] Primary Service
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0012
 00001530-1212-efde-1523-785feabcd123
 Vendor specific
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0012/char0013
 00001532-1212-efde-1523-785feabcd123
 Vendor specific
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0012/char0015
 00001531-1212-efde-1523-785feabcd123
 Vendor specific
 [NEW] Descriptor
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0012/char0015/desc0017
 00002902-0000-1000-8000-00805f9b34fb
 Client Characteristic Configuration
 [NEW] Characteristic
 /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0012/char0018
 00001534-1212-efde-1523-785feabcd123
 Vendor specific
 Pairing successful
 [CHG] Device XX:XX:XX:XX:XX:XX Trusted: yes

En una próxima entrada veremos como programar funciones BLE en Phyton

BLE – Bluetooth Low Energy (4.0)

Bluetooth es un protocolo de transmisión de datos via radio (inalámbrico) que opera en la banda de 2,4 GHz (También usada por los hornos de microondas y Wi-Fi) diseñado para la transmisión de datos a corta distancia, pues para coberturas más extensas se usa Wi-Fi o 3G/4G y con modulación GFSK (Gaussian Frequency Shift Keying GFSK). Usa un sistema de salto de canal para combatir las interferencias.

En la versión Bluetooth 4.0 además del modo clásico se incluyó el modo BLE – Bluetooth Low Energy (Bluetooth de Baja Energía) que fue un desarrollo original de Nokia Research Centre llamado “Wibree”.

La Raspberry Pi 3 model B incluye BLE.

EL BLE se caracteriza por un consumo reducido, un pequeño tamaño  y un bajo coste de los dispositivos, un sistema de pareado o enlace más rápido y una gran  interoperabilidad, lo que hace de esta tecnología especialmente indicada para dispositivos móviles y para Internet de las Cosas (IoT Internet of Things), aunque hay otras como ZigBeeZ-Wave.

Dispositivos BLE (Fitbit Flex y Monocacy)

En la actualidad se está trabajando en la versión Bluetooth 5 que permite usando una menor velocidad (Entre 125kbps a 500 kbps en lugar de 1 Mbps) de transmisión señales de mayor energía (20 dBM frente a 10 dBm) que permite un área de cobertura mayor.

BLE usa el protocolo GAP (Generic Access Profile) para definir dos tipos de redes que pueden configurarse con dispositivos que  publicitan su presencia y los dispositivos que los buscan (Broarcasters/Observers si no establecen conexión y Peripherals/Centrals si la establecen). El funcionamiento de la red BLE es sencillo, existen unos  dispositivos periféricos o difusores que transmiten datos de anuncio de su existencia (beacons o Advertising Data) de forma indiscriminada (Como por ejemplo la  pulsera de ejercicio, el pulsómetro, el reloj digital, los llaveros localizadores,   etc.)  a intervalos de entre 20ms y 2s y otros dispositivos llamados centrales u observadores (Como un teléfono móvil, o un ordenador personal, etc)  que están en una espera activa,  y según el tipo de red el Observador recibe la información del Difusor o el central establece   conexión con el periférico para el intercambio de datos.  Observe que también un teléfono móvil podría ser un dispositivo periférico de un ordenador portátil que actuar como un dispositivo central, o una Raspberry Pi puede ser tanto un dispositivo periférico como un dispositivo central según la red o la aplicación.

Por otra parte  GATT (Generic Attribute profile) es el protocolo que permite el intercambio de datos: leer, escribir y notificar, una vez establecida la conexión.

Control de circuitos eléctricos con Raspberry Pi – II : Python

En una entrada anterior hemos visto cómo un programa escrito en Python puede controlar dispositivos conectados a la GPIO de la Raspberry Pi (OUT) como era un  LED, pero que se puede generalizar a otros dispositivos de bajo voltaje como un motor de un juguete o de mayor voltaje mediante un relé. Ahora vamos a ver cómo un dispositivo conectado a la GIO de la Raspberry Pi, como es un pulsador, puede controlar un programa Python (IN).

La entrada es flotante, es decir se detecta una variación relativa del  voltaje de entrada por el conector definido como entrada.

Generación de señal de entrada (Diagrama de eLinux)

En nuestro ejemplo hemos usado como entrada el conector 24 (pin 18) y los +3,3V lo tomamos del pin 1

# led_balancin_2.py 
#
# Cuando se pulsa parpadean las luces hasta que se
# vuelve a pulsar
try:
 import RPi.GPIO as GPIO
 print("GPIO.RPI_INFO = " + str(GPIO.RPI_INFO))
 print("GPIO.VERSION = " + str(GPIO.VERSION))
except RuntimeError:
 print("Error importando RPi.GPIO")
 
try: 
 import time
except RuntimeError:
 print("Error importando RPi.GPIO")
 
# GPIO: Ajuste de los nombres de GPIO: BOARD ó BCM
GPIO.setmode(GPIO.BCM)
# GPIO: Ajuste mensajes de warning a OFF
# (avisos de otros programas trabajando con GPIO)
GPIO.setwarnings(False)

# GPIO: Definicion de canales de IN y OUT
Lista_canales_out = [18,23] 
Lista_canales_in = [24] 
GPIO.setup(Lista_canales_out,GPIO.OUT)
GPIO.setup(Lista_canales_in,GPIO.IN)
GPIO.output(Lista_canales_out,(GPIO.LOW,GPIO.LOW))
pulso = 0 
while pulso < 2:
 if (GPIO.input(24)):
 print("Boton!")
 pulso += 1
 else:
 time.sleep(1)
 if pulso == 1:
 print ("Ni")
 GPIO.output(Lista_canales_out,(GPIO.HIGH,GPIO.LOW))
 time.sleep(1)
 print ("No")
 GPIO.output(Lista_canales_out,(GPIO.LOW,GPIO.HIGH))
 time.sleep(1)
 else:
 time.sleep(1)
GPIO.cleanup()

El siguiente reto, la siguiente entrada, cómo usar un dispositivo con BLE (Bluetooth de baja energia) para controlar un programa Python

Autorun en una Raspberry Pi

En esta entrada vamos a configurar Raspbian para que cuando arranque ejecute directamente un programa sin necesitad de ninguna  intervención manual (teclado, ratón pantalla),  en otras palabras vamos a crear un  autorun. Esta configuración de raspbian es necesaria si usamos Raspberry Pi para controlar remotamente un vehículo o robot, un sistema domótico, etc.

Lo primero que debemos comprobar es que el programa se ejecuta correctamente desde el terminal del sistema:

  • Hacer una copia de seguridad de su tarjeta SD
  • Comprobar los permisos del fichero. En LINUX, los permisos se clasifican en tres bloques que muestra con la siguiente secuencia: los del usuario propietario, los de los usuarios de su grupo y los del resto de usaurios. Cada uno de ellos puede: -No tener permiso, R-lectura, W-escritura y X-ejecución.
pi@raspberrypi:~ $ ls -l /home/pi/proyectos/Python/led_balancin.py
-rw-r--r-- 1 pi pi 1041 ene 27 15:49 /home/pi/proyectos/Python/led_balancin.py
  • Dar permisos de ejecución. Así no necesitaremos que lo ejecute el superusuario sudo o el creador del mismo.
pi@raspberrypi:~ $ sudo chmod +x /home/pi/proyectos/Python/led_balancin.py
pi@raspberrypi:~ $ ls -l /home/pi/proyectos/Python/led_balancin.py
-rwxr-xr-x 1 pi pi 1041 ene 27 15:49 /home/pi/proyectos/Python/led_balancin.py
  • Ejecutar el programa por terminal
pi@raspberrypi:~ $ python3 /home/pi/proyectos/Python/led_balancin.py
  • Hacer una copia de seguridad del archivo que vamos a modificar /etc/rc.local 
pi@raspberrypi:/etc $ sudo cp rc.local rc.bak
  • Modificar el archivo añadiendo el comando a ejecutar con & para que no influya en el arranque normal en caso de ser un bucle infinito y posibilitar el acceso a la Raspberry Pi. Puede comprobar el contenido con el comando cat rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

python3 /home/pi/proyectos/Python/led_balancin.py &

exit 0
  • Cruzar los dedos y  rearrancar la Raspberry pi