Réaliser un objet connecté avec CircuitPython - Niveau avancé
Dans ce tutoriel, nous allons réaliser un objet connecté. Celui-ci va utiliser la connexion internet pour récupérer et afficher des informations sur des nombres que l'utilisateur choisira.
Texte légal : Lien avec le programme SNT
Ce projet peut s'inscrire en lien avec le programme SNT de seconde dans plusieurs parties :
Données structurées : Utiliser un site de données ouvertes, pour sélectionner et récupérer des données.
Informatique embarquée et objets connectés : Réaliser une IHM simple d'un objet connecté.
Matériel nécessaire
Pour réaliser ce projet, nous aurons besoin
d'une carte Adafruit M4 sous circuitPython (itsybitsy M4, metro M4 express ...)
d'une carte intégrant un ESP32 pour la connexion internet (comme celle-ci que j'utilise dans ce tutoriel, ou celle-la). Ces cartes coûtent moins de 5 € chacune.
d'un écran oled 0.96" pour l'affichage des informations
d'un potentiomètre et d'un bouton poussoir
d'une plaquette de prototypage
Principe de fonctionnement
La carte Adafruit n'est pas connectée par elle-même. Elle va donc s'appuyer sur la carte ESP32 pour réaliser la connexion internet. Cela se fait grâce à une librairie ESP32SPI développée par Adafruit à cet effet.
Ce tutoriel est écrit avec la version 4.0 beta2 de circuitPython. Il faudra aussi utiliser le dernier pack de librairies : téléchargez le bundle correspondant à la version de circuitPython utilisée et Copier le dossier lib
situé dans l'archive à la racine du lecteur CIRCUITPYTHON de votre carte.
L'utilisateur va sélectionner un nombre entre 0 et 200 à l'aide du potentiomètre. Nous utiliserons donc une entrée analogique pour lire cette information. Ensuite, en pressant le bouton, la carte va se connecter sur le site http://numbersapi.com pour récupérer un fichier au format json contenant les informations sur le nombre désiré. Voir cet exemple pour 43.
Ce tutoriel nous permettra de voir la méthode pour se connecter à internet depuis circuitPython, récupérer un fichier json et en extraire les informations. Cela peut ensuite être réinvesti dans bon nombre de projets similaires (récupération de données météorologiques pour faire une station météo, etc...)
Remarque :
Il est possible de réaliser ce projet exclusivement avec l'ESP32, équipé de MicroPython. Néanmoins, l'utilisation de micropython sur l'esp32 est plus délicate que celle de circuitPython sur les cartes Adafruit.
Installation du micrologiciel sur l'ESP32
Pour être utilisé comme modile wifi, l'ESP32 nécessite un micrologiciel adapté. Vous trouverez celui-ci ici
https://github.com/ladyada/CircuitPython_WiFi_Demos/tree/master/esp32program
Téléchargez le fichier NINA_W102.bin
Pour installer ce micrologiciel sur la carte ESP32, il faudra disposer de l'outil esptool.py. Le plus simple pour se le procurer est d'utiliser l'installateur de paquets pip :
sudo pip3 install esptool
Pour installer le micrologiciel, tapez la commande
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 115200 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0 NINA_W102.bin
Vous aurez peut-être à adapter le port série sur lequel la carte ESP32 est connectée. Sous linux, c'est en général /dev/ttyUSB0
.
Remarque :
Cette opération n'est à faire qu'une seule fois. Ensuite la carte pourra être utilisée pour tout projet exploitant la librairie ESP32SPI d'adafruit.
Câblage
La partie délicate du câblage concerne le branchement du module ESP32. Celui-ci doit en effet être conforme à ce qui est prévu dans la librairie ESP32SPI d'adafruit. Vous n'avez pas trop de lattitude dans le choix des brochages, surtout côté ESP32.
ESP32 | Adafruit M4 | fonction |
---|---|---|
RST / EN | D5 | reset |
GND | GND | ground |
3V | 3V | alim 3,3V |
33 | D10 | ready / busy |
14 | MOSI (MO) | SPI Master Output Slave Input |
23 | MISO (MI) | SPI Master Input Slave Output |
5 | D9 | SPI CS |
18 | SCK | SPI SCK |
Vous pouvez changer les broches D5, D9 et D10 de l'Adafruit à condition d'adapter le programme en conséquence - ces broches sont définies au début du script.
Pour l'écran, il suffit de connecter l'alimentation, puis SDA et SCL sur les broches correspondantes de la carte.
Le câblage du bouton est très simple puisqu'on utilisera le pull-up interne de la carte sur D11. Pour le potentiomètre, celui-ci sera relié à la broche A2 de la carte.
Le programme
Le programme s'appuie sur la librairie ESP32SPI d'adafruit. Celle-ci est livrée dans le pack de librairies proposé par adafruit (assurez-vous d'avoir une version à jour et qui correspond bien à votre version de circuitPython). Si votre installation de circuitPython est complète, vous n'avez donc pas à vous préoccuper du téléchargement de la librairie ESP32SPI, elle est prête à l'emploi. De même pour l'écran.
Voici donc le programme prêt à l'emploi. Il suffira juste de remplacer le SSID et le mot de passe de votre réseau Wifi dans les variables au début du programme.
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
import analogio
import adafruit_ssd1306
import adafruit_bus_device
import adafruit_framebuf
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_esp32spi.adafruit_esp32spi_requests as requests
JSON_URL1 = "http://numbersapi.com/" # adresse du site
JSON_URL2 = "/math?json" # donnees au format JSON
MAX_NB = 200 # valeur maxi des nb a choisir via le potentiometre
LLEN = 21 # longueur d'une ligne
LNB = 5 # nombre de lignes
WIFI_SSID = b'MON_SSID'
WIFI_PASS = b'********'
reset_pin = DigitalInOut(board.D4)
esp32_cs = DigitalInOut(board.D9)
esp32_ready = DigitalInOut(board.D10)
esp32_reset = DigitalInOut(board.D5)
adc = analogio.AnalogIn(board.A2)
bouton = DigitalInOut(board.D11)
bouton.direction = Direction.INPUT
bouton.pull = Pull.UP
i2c = busio.I2C(board.SCL, board.SDA)
oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c, reset=reset_pin)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
requests.set_interface(esp)
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
oled.fill(0)
oled.text("Connexion Wifi",0,0,1)
oled.show()
try:
esp.connect_AP(WIFI_SSID, WIFI_PASS)
except:
oled.text("Erreur de connexion",0,10,1)
oled.text("Appuyer sur RESET",0,30,1)
oled.show()
else:
oled.fill(0)
texte = [""]
numEcran=-1
while True:
oled.fill(0)
nombre = str(adc.value * MAX_NB // 65535)
oled.text(nombre,0,0,1)
if numEcran != -1:
i=0
while i+numEcran*LNB < len(texte) and i<LNB :
# Bidouille infame pour eviter le crash de la librairie ssd1306 sur les caracteres unicode
oled.text(str(texte[i+numEcran*LNB].encode('ascii'))[2:-1],0,10+i*10,1)
i+=1
oled.show()
if not bouton.value: # bouton presse. Logique inversee a cause du pull-up
if numEcran >= 0:
numEcran += 1
if len(texte)<LNB*numEcran :
numEcran = -1
else:
# Telechargement des informations
print("Recuperation infos")
oled.text("......",30,0,1)
oled.show()
r = requests.get(JSON_URL1+nombre+JSON_URL2)
reponse = r.json()
print(reponse)
r.close()
# Decoupage du texte en lignes de longueur LLEN
texte=[]
i=0
t = reponse['text']
l = t[i*LLEN:(i+1)*LLEN]
while l:
texte.append(l)
i+=1
l = t[i*LLEN:(i+1)*LLEN]
# Affichage du texte en plusieurs ecrans
numEcran=0
Complément :
Vous pouvez voir que la partie requêtes sur internet est rendue très simple grâce à la librairie Adafruit. Celle-ci se résume aux commandes
Définition de l'interface : esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
Paramétrage des requêtes via l'ESP32 : requests.set_interface(esp)
Connexion Wifi : esp.connect_AP(WIFI_SSID, WIFI_PASS)
Requête GET pour récupérer l'information : r = requests.get(__URL__)
Transformation du fichier JSON en dictionnaire pour récupérer les données : reponse = r.json()
Conclusion
Ce projet est assez complexe à mettre en œuvre, en particulier parce qu'il nécessite pas mal de matériel entre la carte adafruit M4, le module ESP et l'écran oled, même si ces composants sont facilement accessible et bon marché. Voici un aperçu du projet en fonctionnement :
Pour simplifier ce type de projet nécessitant une connexion internet, circuitPython et un affichage sur écran, Adafruit a conçu une toute nouvelle carte nommée pyPortal. Celle-ci n'est pas encore commercialisée à l'heure ou j'écris ces lignes mais semble prometteuse. Elle réunit sur une seule carte tout le montage réalisé lors de ce projet et permet donc de se focaliser uniquement sur l'aspect logiciel.