Communication avec MIT App Inventor pour publier une température et contrôler une LED de la NUCLEO-WB55

Ce exemple montre comment configurer notre carte NUCLEO-WB55 en périphérique pour qu’elle puisse se connecter sur un smartphone sous Android exécutant une application conçue avec l’interface de développement par blocs MIT APP Inventor qui fera office de central. Le cas d’usage que nous allons étudier est résumé par la figure qui suit :


MIT APP Inventor 1 use case


C’est exactement celui déjà expliqué ici, le principal changement étant que l’application ST BLE Sensor sera remplacée par une application construite avec MIT App Inventor.

Avertissement

Le comportement des applications réalisées avec MIT App Inventor peut être très différent d’une machine Android à une autre. Aussi, si notre application ne fonctionne pas sur votre smartphone, testez là sur un autre terminal en priorité avant d’y rechercher des erreurs. Notamment la version actuelle (20200828) de l’extension BluetoothLE pour App Inventor ne fonctionne pas sur Android 12 et plus. Son développeur travaille sur le sujet (voir ce lien), donc, wait and see… Une solution de contournement consiste à ajouter dans l’application App Inventor les blocs pour activer l’accès au Bluetooth, comme expliqué ici.
Nous rappelons aussi que cette extension indispensable à l’utilisation du BLE ne marche pas sur iOS.

Matériel requis

  1. La carte NUCLEO-WB55
  2. Un smartphone Android pour y installer l’application créée avec MIT App Inventor.
  3. Un shield de base Grove pour Arduino (optionnel)
  4. Un module Grove de mesure pression, température et humidité BME280 (optionnel)

Attention, il est possible que vous deviez mettre à jour le firmware BLE HCI de votre carte NUCLEO-WB55, la procédure est expliquée ici.

Les codes MicroPython pour le périphérique

Vous pouvez télécharger les scripts MicroPython de ce tutoriel (entre autres) en cliquant ici.

Pour ce tutoriel, l’implémentation BLE repose sur deux scripts :

  1. ble_advertising.py, une bibliothèque de fonctions qui seront utilisées pour construire les trames d’avertising du protocole GAP, lancé pour et avant la connexion à un central.
  2. ble_sensor.py, une bibliothèque qui appelle ble_advertising.py pour démarrer le protocole GAP et qui implémente aussi le protocole GATT. C’est ce fichier qui paramétrise les services, les caractéristiques et leurs UUID conformément à Blue-ST. Grâce au fichier ble_sensor.py nous allons pouvoir créer un objet BLE ayant 1 service et 2 caractéristiques qu’il faudra modifier pour changer le profil BLE, si besoin.

Ces fichiers sont construits avec la classe Microbluetooth documentée ici et adaptés des scripts disponibles ici.

Le fichier main.py qui contiendra le code du programme utilisateur ; il importera ble_advertising.py et ble_sensor.py. Ce script montre deux alternatives pour générer les températures : soit par un appel à un générateur de nombres aléatoires pour les simuler, soit par une mesure à l’aide d’un capteur I2C BME280. Dans ce deuxième cas, il faudra bien sûr disposer aussi de la bibliothèque pilote qui convient : bme280.py.

Comme pour tous les autres tutoriels il faudra copier tous ces fichiers dans le disque USB PYBFLASH associé à l’espace de stockage de l’USB USER de la NUCLEO-WB55.

Le script ble_sensor.py

On retrouve presque exactement le script déjà présenté par le tutoriel sur ST BLE Sensor, avec des changements uniquement dans la méthode set_data_temperature :

	# On écrit la valeur de la température dans la caractéristique "temperature" 
	def set_data_temperature(self, temperature, notify):
		self._ble.gatts_write(self._temperature_handle, pack('<f', temperature))
		if notify:
			for conn_handle in self._connections:
				# Signale au Central que la valeur de la caractéristique vient d'être
				# rafraichie et qu'elle peut donc être lue.
				self._ble.gatts_notify(conn_handle, self._temperature_handle)

Pour simplifier le décodage de la caractéristique de température par MIT App Inventor, nous n’envoyons plus l’information d’horodatage de la mesure et nous codons celle-ci comme un nombre à virgule flottante (‘<f’).

Le programme principal

Éditez le script main.py contenu dans le répertoire du disque USB virtuel associé à la NUCLEO-WB55 : PYBFLASH et copiez-y ce code :

# Cet exemple montre comment programmer un périphérique BLE avec la norme Blue-ST pour 
# envoyer des mesures de température et contrôler une LED en utilisant un service 
# contenant une caractéristique de température.
# La température est mesurée par un capteur de température I2C BME280 toutes 
# les cinq secondes et notifiée à la même fréquence à un éventuel central BLE.
# Si vous n'avez pas de capteur BME280, il suffit de préciser SENSOR = False 
# pour simuler les mesures de température avec un générateur de nombres aléatoires.

import ble_sensor # Implémentation du BLE GATT selon Blue-ST
import bluetooth # Pour la gestion du BLE
from time import sleep_ms # Pour la gestion des temporisations

# Est-ce qu'un module I2C capteur de température BME280 est connecté à la NUCLEO-WB55 ?
SENSOR = True

# Si vous ne disposez pas d'un capteur de température
if not SENSOR:

	print("Aucun capteur BME280, les mesures seront simulées")
	from random import randint

# Si vous disposez d'un capteur de température
else:

	print("Mesures avec le capteur BME280")
	from machine import I2C # Pilote du contrôleur de bus I2C
	import bme280 # Pilote du capteur

	# On utilise l'I2C n°1 de la carte NUCLEO-WB55 pour communiquer avec le capteur
	i2c = I2C(1)

	# Pause d'une seconde pour laisser à l'I2C le temps de s'initialiser
	sleep_ms(1000)

	# Liste des adresses I2C des périphériques présents
	print("List of I2C addresses: " + str(i2c.scan()))

	# Instanciation du capteur
	bme = bme280.BME280(i2c=i2c)

# Instantiation du BLE
ble = bluetooth.BLE()
ble_device = ble_sensor.BLESensor(ble)

while True:

	if not SENSOR:
		# Valeur aléatoire entre -20 et 90 °C
		temperature = randint(-20, 90)
	else:
		# Lecture des valeurs mesurées par le BME280
		bme280 = bme.values
		temperature = round(bme280[0],1)
	
	print("Température: " + str(temperature) + "°C")
	
	# Envoi en BLE de la température en choisissant de notifier l'application
	ble_device.set_data_temperature(temperature, notify=1) 
	
	# Temporisation de cinq secondes
	sleep_ms(5000)

L’application MIT App Inventor pour notre central

Le code source au format “.aix” est disponible dans l’archive BLE.ZIP.

1. Initialisation du projet

Dans un premier temps, nous allons créer un nouveau projet depuis l’application MIT APP Inventor et analyser l’interface de développement.

Vous pourrez accéder au site de MIT APP Inventor en cliquant ici.

Pour démarrer un nouveau projet il suffit de cliquer sur Create Apps!.



Vous pourrez, à partir de ce moment là, changer de langue (en haut à droite) et passer à la langue française : notre tutoriel est fait à partir du site en français. Une fois votre compte créé vous pourrez cliquer sur Commencer nouveau projet.... Nous appellerons notre projet “BLE_CENTRAL_BLUEST”.

L’interface de développement de MIT APP Inventor est séparée en 2 parties : la partie design et la partie code.



Vous pourrez passer d’une fenêtre à l’autre en cliquant sur les boutons Designer et Blocs situés en haut à droite de l’écran.

Bien évidemment, plutôt que partir de zéro, vous pouvez aussi importer le programme finalisé, dans le fichier BLE_CENTRAL_BLUEST.aia que vous aurez récupéré dans la section “Téléchargements”. Dans ce cas, il faut aller dans le menu Projets (en haut à gauche de page de MIT APP Inventor, après connexion), puis choisir Importer le projet (.aia) de mon ordinateur..., cliquer sur Choisir un fichier, aller chercher BLE_CENTRAL_BLUEST.aia et valider avec OK.

2. Conception de l’interface graphique de l’application

Dans un premier temps nous allons travailler sur le design de notre application. Nous allons devoir déterminer quels sont les éléments (boutons, label, listes …) nécessaires.

Sur le côté gauche, dans le menu Palette, vous disposez de plusieurs boites à outils contenant toutes les fonctionnalités que vous pouvez apporter à votre application.

Pour ajouter un élément à notre application il suffit de le faire glisser sur le dessin de l’écran de téléphone (la fenêtre Interface). Vous pouvez voir ici le contenu de cette fenêtre pour notre application terminée ; nous allons expliquer sa construction :



Pour la bonne disposition des éléments sur l’écran, nous allons les placer dans des conteneurs ou arrangements. Ceux-ci sont disponibles dans la boite à outils accessible avec l’onglet Disposition, sur le côté gauche. Sélectionnez un Arrangement horizontal et faites-le glisser sur l’interface.

  • Dans la colonne Propriétés, à droite, sélectionnez Alignement horizontal : Centrer et Alignement vertical : Haut.
  • Dans la colonne Composants, juste à côté, apparait désormais une entrée “Arrangement_horizontal1” ; cliquez sur le bouton Renommer, en bas, et changez son nom en “Arrangement_scan”.



Choisissez à présent la boite à outils Interface utilisateur et faites glisser tour à tour quatre éléments Bouton dans Interface. Suivant la procédure expliquée juste avant, renommez les en “ButtonScan”, “ButtonStopScan”, “ButtonConnect” et “ButtonDisconnect”. Pour chacun de ces boutons, utilisez la colonne Propriétés et modifiez le champ texte de sorte que leurs intitulés sur l’interface soient “Rech.”, “Fin rech.”, “Connexion” et “Déconnexion”. Votre interface devrait ressembler à ceci :



Pour la gestion du BLE, nous allons devoir importer l’extension BluetoothLE. Pour ce faire, commencez par vous rendre sur cette page et téléchargez la dernière version du fichier edu.mit.appinventor.ble.

Allez ensuite dans le menu Palette, choisissez l’entrée Extension puis Import extension. Dans la boite de dialogue qui s’affiche, cliquez sur le bouton Choisir un fichier puis sélectionnez le fichier de l’extension :



Cliquez sur le bouton Import. Une entrée BluetoothLE apparait alors sous Extension dans la palette. Glissez-déposez celle-ci dans l’interface, une indication Composant non-visible : BluetoothLE1 apparait alors dans la fenêtre Interface, sous le dessin du smartphone :



Pour finir l’écran d’accueil, nous rajoutons les éléments suivants dans l’interface :

  • Un Label, renommé “LabelStatus”, initialisé avec le texte “Aucun appareil connecté”.
  • Une Vue liste, renommée “ListBLE”
  • Un Arrangement vertical, renommé “Fonctionnalités”
  • Un Switch, renommé LED, agrémenté du texte “Allumez / Éteignez la LED : “ et positionné dans l’arrangement vertical “Fonctionnalités”
  • Un Arrangement horizontal renommé “Temp”, qui contient deux labels : “Texte” et “Température”
  • Le label “Texte” a comme texte “Température (°C) : “ et le label “Température” a comme texte “…”.

La figure ci-dessous fait la synthèse de tous ces éléments :



3. Programmation par blocs de l’application

Passons à présent à la programmation de l’application. Basculez dans la partie Blocs. Le programme complet ressemble à ceci :



Les différents blocs sont regroupés par thèmes dans la boite à outils Blocs. Par exemple, sur l’image qui précède, nous avons sélectionné les outils de la catégorie Listes et nous voyons apparaître tous les blocs correspondants. La manipulation des blocs est conçue pour être intuitive : il suffit de les glisser dans la fenêtre Interfaceet de les imbriquer. Nous ne nous attarderons pas sur ce sujet, la principale difficulté consistant à se familiariser avec le contenu de la boite à outils pour y trouver rapidement les blocs dont on a besoin, ce qui nécessite un peu de pratique. Nous allons directement passer en revue les différents blocs qui constituent notre programme - central BLE.

Les variables gobales

Trois blocs permettent de partager avec l’ensemble des autres blocs les identifiants uniques (UUID) des services et des caractéristiques. Ils encodent ce que l’on appelle d’ordinaire des variables globales.



Le bloc “Screen Initialise”

Ce bloc rassemble les instructions qui configurent l’interface utilisateur au moment du lancement du programme. Elles sont exécutées entre le moment où l’utilisateur appuie sur l’icône de l’application sur son smatrphone et le moment où celle-ci s’affiche à l’écran.



Le bloc “ButtonScan Clic”

Ce bloc gère les appuis sur le bouton ButtonScan, il permet de démarrer la recherche d’advertisers BLE à proximité et d’ajuster l’interface graphique en conséquence.



Le bloc “BluetoothLE Device Found”

Les instructions de ce bloc sont appelées pour chaque advertiser BLE découvert lorsque la fonction de recherche (bloc ci-avant) est en cours d’exécution. Concrêtement, il rajoute dans ListBLE une ligne contenant l’adresse de chaque advertiser BLE découvert.



Le bloc “ButtonStopScan Clic”

Ce bloc gère les appuis sur le bouton ButtonStopScan, il permet d’interrompre la recherche d’advertisers BLE et d’ajuster l’interface graphique en conséquence.



Le bloc “ListBLE Après prise”

Les instructions de ce bloc son exécutées lorsque l’utilisateur sélectionne une entrée de ListBLE, c’est à dire une adresse d’advertiser BLE.



Le bloc “ButtonConnect Clic”

Ce bloc gère les appuis sur le bouton ButtonConnect, il provoque la connexion du central au périphérique sélectionné dans ListBLE.



Le bloc “quand BluetoothLE1 Connected”

Les instructions de ce bloc sont exécutées dès lors que l’application est parvenue à se connecter à un périphérique BLE. Elle met à jour l’interface graphique en conséquence et elle abonne le smartphone aux notifications de la caractéristique “Température” servie par le smartphone.



Le bloc “quand BluetoothLE1 FloatsReceived”

Les instructions de ce bloc capturent les nouvelles valeurs de la caractéristique “Température” chaque fois que celle-ci notifie une mise à jour de son contenu.



Le bloc “quand LED Changé”

Les instructions de ce bloc sont exécutées lorsque le switch LED change d’état. Il permet à l’application d’écrire dans la caractéristique “SWITCH” servie parle périphérique afin que celui-ci allume ou éteigne la LED de la NUCLEO-WB55 en conséquence.



Le bloc “quand ButtonDisconnect Clic”

La seule instruction de ce bloc est exécutée lorsque l’utilisateur appuie sur ButtonDisconnect et a pour effet de mettre fin à la connexion entre le central MIT App Inventor et le périphérique NUCLEO-WB55.



Le bloc “quand BluetoothLE1 Disconnected”

Ce dernier bloc prend effet lorsque l’évènement de déconnexion entre le périphérique et le central survient (après un appui sur ButtonDisconnect). Il reconfigure l’interface graphique pour une éventuelle nouvelle connexion.



4. Utilisation de l’application créée

fin de pouvoir utiliser l’application que vous venez de créer et donc de pouvoir communiquer avec la carte, vous devrez tout d’abord télécharger l’application MIT AI2 Companion que vous trouverez sur le Play Store :



Afin de pouvoir utiliser notre application, vous devez l’exporter sur votre téléphone. Pour cela, ouvrez le menu Connect sur le site de MIT App Inventor :



Maintenant, cliquez sur la section AI Companion dans ce menu :



Cela vous ouvrira la fenêtre suivante :



Sur votre téléphone, ouvrez l’application MIT AI2 Companion. Cette fenêtre apparaîtra :



Deux manières existent pour lancer votre application :

  • Saisir code à 6 lettres ou
  • Scanner un QR code.

Les deux sont affichés sur votre ordinateur ; vous pouvez donc vous connecter de la manière que vous souhaitez. Lorsque vous le ferez, une barre de chargement s’affichera sur l’écran de votre ordinateur :



Une fois celle-ci remplie, vous pourrez voir votre application sur votre téléphone :



Sélectionnez la ligne contenant le nom du périphérique : “WB55-MPY” dans la liste ; la ligne correspondante est l’adresse matérielle (adresse MAC) de la carte : “02:02:27:4E:25:16”. Appuyez sur Connexion. C’est fini, vous pouvez lire la température et contrôler la LED de la NUCLEO-WB55 avec le Switch :