mercredi 4 décembre 2019

Communication nRF24L01 avec cartes ESP32 et ESP8266

Voyons aujourd'hui comment utiliser un émetteur-récepteur nRF24L01 avec un ESP32 ou un ESP8266. Les modules nRF24L01 permettent d'établir une communication radio entre deux microcontrôleurs à une fréquence de 2,4 GHz.

Préparation de l'IDE Arduino

Puisque l'ESP sera programmé avec l'IDE Arduino, les cartes appropriées doivent avoir été installées dans l'IDE au moyen du gestionnaire de cartes (voir les instructions détaillées pour l'ESP8266 et pour l'ESP32).

La bibliothèque RF24 mise au point par TMRh20 doit également être installée (ça peut se faire par l'entremise du gestionnaire de bibliothèques). Il s'agit de la même bibliothèque qu'on utilise pour une carte Arduino conventionnelle (Uno, etc.).

Connecteurs du module nRF24L01

La figure ci-contre pourrait se révéler utile pour identifier les connecteurs du module nRF24L01.

Certains modèles, généralement verts, comportent 10 broches alors que d'autres, généralement noirs, en comportent 8.

La répartition des broches sur deux rangées ne permettent pas l'insertion du module sur une breadboard.

Connexions du nRF24L01 à l'ESP32

J'ai branché le module nRF24L01 à ma carte ESP32 de la façon suivante:
  • GND du nRF24L01 - GND de l'ESP32
  • VCC du nRF24L01 - 3V3 de l'ESP32
  • CE du nRF24L01 - D4 de l'ESP32
  • CSN du nRF24L01 - D5 de l'ESP32
  • SCK du nRF24L01 - D18 de l'ESP32
  • MOSI du nRF24L01 - D23 de l'ESP32
  • MISO du nRF24L01 - D19 de l'ESP32
  • IRQ du nRF24L01 - Pas branché


Connexions du nRF24L01 à l'ESP8266

J'ai branché le module nRF24L01 à ma carte Wemos D1 Mini de la façon suivante:
  • GND du nRF24L01 - GND de l'ESP8266
  • VCC du nRF24L01 - 3V3 de l'ESP8266
  • CE du nRF24L01 - GPIO4 (D2) de l'ESP8266
  • CSN du nRF24L01 - GPIO5 (D1) de l'ESP8266
  • SCK du nRF24L01 - GPIO14 (D5) de l'ESP8266
  • MOSI du nRF24L01 - GPIO13 (D7) de l'ESP8266
  • MISO du nRF24L01 - GPIO12 (D6) de l'ESP8266
  • IRQ du nRF24L01 - Pas branché


Sketch #1: émission d'un message

Voici un sketch minimaliste pour l'émission d'un message (il s'agit du même sketch déjà publié pour l'utilisation d'un nRF24L01 avec un Arduino, seule la numérotation des broches est différente).

-
-

Sketch #2: réception d'un message

Voici un deuxième sketch minimaliste qui rapporte dans le moniteur série tous les messages reçus par le nRF24L01.

-
-

Sketch #3: réception d'un message et publication dans une page web

Ce troisième exemple utilise également les possibilités WiFi de l'ESP32 ou de l'ESP8266: les messages reçus par le nRF24L01 sont publiés dans une page web. On peut ainsi concevoir un réseau de microcontrôleurs qui transmettraient les mesures de leurs capteurs à un ESP32 ou un ESP8266 qui se chargerait de transmettre les données par WiFi (les données peuvent être émises par une carte Arduino ou par un carte STM32, par exemple).

-
-

L'adresse IP de l'ESP32 ou de l'ESP8266 s'affiche dans le moniteur série au démarrage du programme.


En recopiant cette adresse dans un navigateur web, on atteint une page web qui indique le message le plus récent reçu par le module nRF24L01.

À lire également

Vous trouverez sur ce blogs d'autres tutos qui vous guideront dans l'utilisation d'un module nRF24L01 avec un Arduinoun STM32un Raspberry Piun MSP430 Launchpad.

Dans le passé, j'ai aussi utilisé le nRF24L01 pour fabriquer un véhicule téléguidé et un système MIDI sans fil.

Finalement vous trouverez sur cette page une liste de tous les articles impliquant l'ESP32 et l'ESP8266.


Yves Pelletier   (TwitterFacebook)

dimanche 1 décembre 2019

Analyse d'une communication SPI



Développé par Motorola dans les années 1980, SPI (acronyme de Serial Peripheral Interface) est un protocole de communication série conçu pour permettre à un microcontrôleur (le "maître") de communiquer à haute vitesse avec un ou plusieurs périphériques (les "esclaves").

Une communication SPI implique 4 lignes de transmissions: MOSI, MISO, SCLK et CS.

1) MOSI (Master Out, Slave In) est utilisée pour la transmission de données du microcontrôleur vers le périphérique. Elle est contrôlée par le microcontrôleur maître.

2) MISO (Master In, Slave Out) est utilisée pour la transmission de données du périphérique vers le microcontrôleur. C'est la seule des quatre lignes qui est contrôlée par le périphérique esclave.

3) SCLK (Serial Clock) transmet un signal d'horloge généré par le microcontrôleur maître. Il sert à synchroniser  l'esclave avec le maître. Contrairement à la communication UART, la communication SPI est donc une communication synchrone.

4) CS ou SS (Chip Select ou Slave Select) est utilisée pour activer un esclave. Contrairement à MOSI, MISO et SCLK, qui sont partagées par tous les périphériques esclaves branchés au microcontrôleur maître, chaque périphérique esclave doit avoir sa propre ligne CS. La ligne CS d'un périphérique doit être mise au niveau logique BAS pour que ce périphérique tienne compte des messages envoyés par le maître sur la ligne MOSI. De cette façon, le maître communique avec un esclave à la fois.

C'est une communication full duplex, ce qui signifie que des données circulent du maître à l'esclave et de l'esclave au maître au même moment.

Sur un Arduino Uno, MOSI est la broche 11, MISO est la broche 12 et SCLK est la broche 13. On utilise souvent la broche 10 pour CS, mais ce n'est évidemment pas obligatoire puisque plusieurs lignes CS différentes seront nécessaire en présence de plusieurs périphériques esclaves.

Des exemples de périphériques qui communiquent en SPI

Voici quelques exemples de périphériques qui communiquent en SPI avec un Arduino: lecteur de cartes SD, module de communicaton radio nRF24L01module RFID-RC522lecteur de fichiers mp3 VS1053, écran couleur ST7735, afficheur TM1638, potentiomètre numérique MCP41100, etc.

Observation d'une transaction SPI

Pour observer une communication SPI au moyen d'un analyseur logique, j'ai branché un convertisseur analogique-numérique (ADC) MCP3008 à un Arduino Uno. Ce circuit intégré comporte 8 entrées analogiques dont l'état est transmis de façon numérique par une communication SPI.
J'ai branché le MCP3008 à l'Arduino de la façon suivante:

  • Broche 5 du MCP3008: potentiomètre permettant de faire varier la tension entre 0 et  5 V.
  • Broches 9 et 14 du MCP3008: GND de l'Arduino
  • Broches 15 et 16 du MCP3008: 5 V de l'Arduino
  • Broche 10 du MCP3008: broche 10 de l'Arduino et canal 0 de l'analyseur logique
  • Broche 11 du MCP3008: broche 11 de l'Arduino et canal 3 de l'analyseur logique
  • Broche 12 du MCP3008: broche 12 de l'Arduino et canal 2 de l'analyseur logique
  • Broche 13 du MCP3008: broche 13 de l'Arduino et canal 1 de l'analyseur logique


L'ajout d'un analyseur logique m'a permis de visualiser la communication SPI avec le logiciel Pulseview.

Le sketch que j'ai utilisé est présenté plus loin dans cet article: il consiste à établir une connexion avec le MCP3008 et de lui demander la valeur mesurée sur son canal 4.

Puisque le MCP3008 est un ADC à 10 bits, les valeurs obtenues peuvent varier entre 0 et 1023. Le potentiomètre a d'abord été réglé de façon à produire une valeur de 562:


Voici une transaction SPI au cours de laquelle l'Arduino demande la valeur du canal 4, ainsi que la réponse du MCP3008 (vous pouvez agrandir l'image en cliquant dessus). Remarquez que la ligne CS, qui était initialement l'état logique HAUT, se met temporairement à l'état logique BAS pendant toute la durée de la transaction.

Dans le cas du MPC3008, cette transaction nécessite l'échange de 3 octets. L'horloge (SCLK) a donc accompli trois séries consécutives de 8 oscillations. L'état logique des lignes MOSI et MISO est lu à chaque front ascendant de l'horloge.



Analysons chacun des 3 octets d'une façon plus détaillée:

Le premier octet est le message d'initialisation envoyé par le microcontrôleur au périphérique (sur la ligne MOSI, donc): il s'agit du nombre binaire "00000001". Pendant cette phase, l'état de la ligne MISO n'a aucune importance. Cet octet est émis à la ligne 41 du sketch (voir plus bas). Sur le diagramme ci-dessous, j'ai ajouté des gros points noirs pour indiquer à quel moment ces valeurs sont lues, pendant le front ascendant du signal d'horloge:

Dans le deuxième octet, le microcontrôleur indique au périphérique l'adresse de l'entrée analogique dont il désire lire la valeur. Selon la fiche technique du MCP3008, pour lire le canal numéro 4, il faut que les 4 premiers bits sur la ligne MOSI soient "1100"; la valeur des 4 derniers bits n'a aucune importance (on envoie généralement 0); ce signal est généré à la ligne 49 du sketch :


Sur la ligne MISO, le périphérique utilise les deux derniers bits de ce deuxième octet pour transmettre les deux premiers bits de sa réponse (qui en comportera ultimement 10). Ici, ces deux bits sont 1 et 0:

Finalement, les 8 derniers bits de la réponse du périphérique sont communiqués dans le troisième octet, sur la ligne MISO. Pour ce troisième octet, l'état de la ligne MOSI n'a aucune importance. Ici, le signal reçu est 00110010.


En mettant bout à bout les deux derniers bits du deuxième octet (10) et les 8 bits du troisième octet (00110010), nous obtenons le nombre binaire 1000110010, ou 562 en décimal: c'est bien à cette valeur que le potentiomètre avait été réglé.

Voici une transaction lorsque le potentiomètre est à la position minimale (0); les dix derniers bits retournés sur la ligne MISO sont 0000000000:


...et une autre lorsque le potentiomètre est à la position maximale (1023); les dix derniers bits retournés sur la ligne MISO sont 1111111111:


Le sketch utilisé

Sur Arduino, la communication SPI est gérée par la bibliothèque du même nom, qui est fournie par défaut avec l'IDE Arduino.

À la ligne 35 du sketch ci-dessous, on initie une transaction SPI en spécifiant 3 paramètres:la fréquence, le boutisme et le mode SPI (dans ce cas: 2 MHz, le bit de poids fort en premier, et le mode SPI 0):

SPI.beginTransaction (SPISettings(2000000, MSBFIRST, SPI_MODE0));

Un Arduino Uno peut sans problème établir une communication SPI à une fréquence de 4 MHz, mais il faut également tenir compte de la fréquence maximale que peut supporter le périphérique. Des fils conducteurs trop longs peuvent aussi nous obliger à diminuer la fréquence. Il existe 4 modes de communication SPI. Le plus fréquemment utilisé est le mode 0, dans lequel l'horloge est au niveau logique BAS quand elle est inactive, et la lecture des données s'effectue pendant le front montant de l'horloge.

SPI.transfer() permet simultanément l'envoi d'un octet du maître vers l'esclave sur la ligne MOSI et la réception d'un octet de l'esclave vers le maître sur la ligne MISO:

octet_recu = SPI.transfer(octet_envoyé);

À la ligne 41, on envoie le premier des 3 octets (00000001). Puisque la réponse de l'ADC est sans importance à cette étape, on ne se donne pas la peine de la stocker dans une variable.

SPI.transfer (0b00000001);

Le deuxième octet est envoyé à la ligne 45. C'est la commande qui indique qu'on désire lire le canal numéro 4. Cette fois, la réponse est stockée dans la variable octet_recu_1, puisque les deux derniers bits de la réponse constituent une information utile.

octet_recu_1 = SPI.transfer(0b11000000);

À la ligne 49, on envoie un troisième octet qui n'est qu'une suite de zéros, puisque ce message sera ignoré par le MCP3008. C'est strictement le message reçu qui nous intéresse: nous le stockons dans la variable octet_recu_2:

octet_recu_2 = SPI.transfer(0b00000000);

La ligne 59 consiste à mettre, dans une même variable, les deux derniers bits de la variable octet_recu_1, suivis des 8 bits de la variable octet_recu_2. Si la syntaxe vous donne du fil à retordre, relisez l'article sur les opérations bit à bit!

resultat = (octet_recu_1 & 0b00000011)<< 8 | octet_recu_2;

-
-

À lire aussi

Cet article a été précédé par l'analyse d'une communication UART; dans un proche avenir, j'ai bien l'intention de compléter cette série d'articles par l'observation d'une communication I2C.

Le MCP3008 n'en est pas à sa première apparition dans ce blog: je l'avais utilisé afin d'ajouter des entrées analogiques au Raspberry Pi ainsi qu'à l'ESP8266.

Yves Pelletier   (TwitterFacebook)