Dans ce guide, vous apprendrez comment échanger des données entre deux cartes ESP32 à l’aide du protocole de communication I2C. Une carte ESP32 sera définie comme maître I2C et l’autre carte comme esclave I2C. Les cartes ESP32 seront programmées à l’aide de l’IDE Arduino.

Avez-vous besoin d’un protocole de communication sans fil ? Essayez le protocole de communication ESP-NOW avec l’ESP32 pour échanger des données entre les cartes.
Table des matières
Dans ce guide, nous aborderons les sujets suivants :
Présentation d’I2C
I²C signifie Inter Integrated Circuit (il se prononce I-squared-C) et il s’agit d’un protocole de communication synchrone, multi-maître et multi-esclave. Vous pouvez vous connecter :
- Plusieurs esclaves vers un maître : par exemple, votre ESP32 lit à partir d’un capteur BME280 en utilisant I2C et écrit les lectures du capteur sur un écran OLED I2C.
- Plusieurs maîtres contrôlant le même esclave : par exemple, deux cartes ESP32 écrivant des données sur le même écran OLED I2C.
Interfaces de bus ESP32 I2C
L’ESP32 prend en charge la communication I2C via ses deux interfaces de bus I2C qui peuvent servir de maître ou d’esclave I2C, selon la configuration de l’utilisateur. Conformément à la fiche technique de l’ESP32, les interfaces I2C de l’ESP32 prennent en charge :
- Mode standard (100 Kbit/s)
- Mode rapide (400 Kbit/s)
- Jusqu’à 5 MHz, mais limité par la force de traction SDA
- Mode d’adressage 7 bits/10 bits
- Mode double adressage. Les utilisateurs peuvent programmer des registres de commandes pour contrôler les interfaces I²C, afin d’avoir plus de flexibilité
Pour une introduction plus détaillée à la communication I2C avec l’ESP32, lisez notre guide :
ESP32 maître et ESP32 esclave
Pour la communication I2C entre deux cartes ESP32, nous utiliserons
- La bibliothèque Wire.h par défaut
- Les broches I2C par défaut sur les deux cartes (celles-ci peuvent varier en fonction du modèle de votre carte)
Connexion de deux cartes ESP32 via I2C
Commencez par connecter les deux cartes ESP32 entre elles. Utilisez les broches I2C par défaut pour les cartes que vous utilisez. N’oubliez pas de connecter les broches GND ensemble.

| Maître ESP32 | Esclave ESP32 |
| SDA (GPIO 21)* | SDA(GPIO21)* |
| SCL (GPIO 22)* | SCL (GPIO 22)* |
| GND | GND |
* dans mon cas, je teste cela avec la carte ESP32 DOIT V1. Les broches I2C par défaut sont GPIO 21 (SDA) et GPIO 22 (SCL). Si vous utilisez un ESP32-C3, ESP32-S3 ou un autre modèle, les broches I2C par défaut peuvent être différentes. Veuillez vérifier le brochage de la carte que vous utilisez.
Communication I2C entre 2 cartes ESP32
Voici comment fonctionne la communication I2C entre deux cartes ESP32 :
| Maître ESP32 | Esclave ESP32 |
| Définit son adresse I2C Définit les fonctions de rappel : – lire les messages reçus ; – pour traiter les demandes. |
|
| Initialise le bus I2C sur l’adresse I2C esclave Démarre la communication I2C sur le bus I2C |
|
| Envoie un message via I2C (démarre la transmission) | |
| Lit le message reçu | |
| Demande des données à l’esclave | |
| Envoie des données au maître |
Esclave ESP32 I2C – Code Arduino
Pour tester la configuration de l’ESP32 en tant qu’esclave I2C, nous utiliserons l’exemple par défaut de la bibliothèque Wire.h.
/*********
Rui Santos & Sara Santos - Raspberryme.com
Complete project details at https://Raspberryme.com/esp32-i2c-master-slave-arduino/
ESP32 I2C Slave example: https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/examples/WireSlave/WireSlave.ino
*********/
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t i = 0;
void onRequest() {
Wire.print(i++);
Wire.print(" Packets.");
Serial.println("onRequest");
Serial.println();
}
void onReceive(int len) {
Serial.printf("onReceive[%d]: ", len);
while (Wire.available()) {
Serial.write(Wire.read());
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.onReceive(onReceive);
Wire.onRequest(onRequest);
Wire.begin((uint8_t)I2C_DEV_ADDR);
/*#if CONFIG_IDF_TARGET_ESP32
char message[64];
snprintf(message, 64, "%lu Packets.", i++);
Wire.slaveWrite((uint8_t *)message, strlen(message));
Serial.print('Printing config %lu', i);
#endif*/
}
void loop() {
}
Afficher le code brut
Comment fonctionne le code ?
Jetons un coup d’œil rapide au fonctionnement du code esclave.
Y compris la bibliothèque Wire
Tout d’abord, vous devez inclure la bibliothèque Wire.h.
#include "Wire.h"
Définissez l’adresse I2C que vous souhaitez donner à votre appareil I2C. Dans ce cas, il s’agit de 0x55, mais vous pouvez définir n’importe quelle autre adresse à condition d’utiliser la même sur l’appareil maître.
#define I2C_DEV_ADDR 0x55
Attribuer des fonctions de rappel
Dans setup(), vous devez attribuer deux fonctions de rappel : une lorsque la carte reçoit des données du maître et une autre lorsque la carte reçoit une demande du maître (envoyer des données au maître).
Wire.onReceive(onReceive);
Wire.onRequest(onRequest);
Fonction de rappel onReceive()
La fonction onReceive() lira les données envoyées par le maître et les imprimera sur le moniteur série.
void onReceive(int len) {
Serial.printf("onReceive[%d]: ", len);
while (Wire.available()) {
Serial.write(Wire.read());
}
Serial.println();
}
Vous vérifiez s’il y a des données disponibles à lire à l’aide de Wire.available().
while (Wire.available()) {
Ensuite, vous lisez les octets reçus avec Wire.read().
Serial.write(Wire.read());
Fonction de rappel onRequest()
La fonction onRequest() enverra des données au maître sur demande.
void onRequest() {
Wire.print(i++);
Wire.print(" Packets.");
Serial.println("onRequest");
Serial.println();
}
Pour envoyer des données au maître, nous utilisons Wire.print().
Wire.print(i++);
Wire.print(" Packets.");
Dans la documentation, il est mentionné que vous devez utiliser Wire.slaveWrite() dans le cas de l’ESP32, afin qu’il écrive la réponse dans le tampon avant de recevoir un message du maître. Cependant, dans notre cas, cela fonctionne bien sans Wire.slaveWrite() (c’est pourquoi nous avons commenté cette section).
En fonction de votre carte, vous devrez peut-être utiliser la méthode slaveWrite() comme suit.
/*#if CONFIG_IDF_TARGET_ESP32
char message[64];
snprintf(message, 64, "%lu Packets.", i++);
Wire.slaveWrite((uint8_t *)message, strlen(message));
Serial.print('Printing config %lu', i);
#endif*/
Initialiser I2C
Dans le setup(), vous devez également initialiser la communication I2C sur l’adresse I2C définie précédemment. Utilisez la méthode start() comme suit. Cela initialisera I2C sur les broches I2C par défaut de l’ESP32.
Wire.begin((uint8_t)I2C_DEV_ADDR);
Vous pouvez également transmettre les broches I2C et la fréquence du bus à cette méthode :
bool Wire.begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency);
Maître ESP32 I2C – Code Arduino
Pour tester la configuration de l’ESP32 en tant que maître I2C, nous utiliserons l’exemple par défaut de la bibliothèque Wire.h.
/*********
Rui Santos & Sara Santos - Raspberryme.com
Complete project details at https://Raspberryme.com/esp32-i2c-master-slave-arduino/
ESP32 I2C Master Example: https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/examples/WireMaster/WireMaster.ino
*********/
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t i = 0;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.begin();
}
void loop() {
delay(5000);
// Write message to the slave
Wire.beginTransmission(I2C_DEV_ADDR);
Wire.printf("Hello World! %lu", i++);
uint8_t error = Wire.endTransmission(true);
Serial.printf("endTransmission: %u\n", error);
// Read 16 bytes from the slave
uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);
Serial.printf("requestFrom: %u\n", bytesReceived);
if ((bool)bytesReceived) { //If received more than zero bytes
uint8_t temp[bytesReceived];
Wire.readBytes(temp, bytesReceived);
log_print_buf(temp, bytesReceived);
}
}
Afficher le code brut
Comment fonctionne le code ?
Jetons un coup d’œil rapide au fonctionnement du code maître ESP32 I2C.
Y compris la bibliothèque Wire
Tout d’abord, vous devez inclure la bibliothèque Wire.h.
#include "Wire.h"
Adresse I2C de l’esclave
Définissez l’adresse I2C du périphérique esclave (définie sur le code précédent) :
#define I2C_DEV_ADDR 0x55
Initialiser I2C
Dans setup(), initialisez la communication I2C à l’aide de Wire.begin(). Cela initialisera I2C sur les broches I2C par défaut.
Wire.begin();
Vous pouvez également transmettre les broches I2C et la fréquence du bus à cette méthode :
bool Wire.begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency);
Démarrer la communication avec l’esclave
Dans la boucle(), nous envoyons un message à l’esclave pour l’informer que nous allons démarrer la transmission I2C :
// Write message to the slave
Wire.beginTransmission(I2C_DEV_ADDR);
Wire.printf("Hello World! %lu", i++);
uint8_t error = Wire.endTransmission(true);
Serial.printf("endTransmission: %u\n", error);
Tout d’abord, vous devez appeler la méthode beginTransmission() et transmettre l’adresse de l’esclave avant d’écrire un message.
Wire.beginTransmission(I2C_DEV_ADDR);
Ensuite, vous écrivez un message dans le tampon en utilisant la méthode printf().
Serial.printf("endTransmission: %u\n", error);
Enfin, pour envoyer le message mis en mémoire tampon, vous devez utiliser la méthode endTransmission().
uint8_t error = Wire.endTransmission(true);
Demander des données à l’esclave
Ensuite, nous demandons des données à l’esclave en utilisant Wire.requestFrom(). Passez en argument l’adresse de l’esclave et le nombre d’octets demandés.
// Read 16 bytes from the slave
uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 16);
Ensuite, concaténez tous les octets et imprimez les données reçues.
Serial.printf("requestFrom: %u\n", bytesReceived);
if ((bool)bytesReceived) { //If received more than zero bytes
uint8_t temp[bytesReceived];
Wire.readBytes(temp, bytesReceived);
log_print_buf(temp, bytesReceived);
}
Échange de données entre deux cartes ESP32 via I2C – Démonstration
Téléchargez les croquis I2C maître et esclave sur vos cartes ESP32. Ouvrez deux instances de l’IDE Arduino pour voir le moniteur série des deux cartes simultanément.
Vous devriez voir le maître initialiser une communication avec l’esclave et recevoir les paquets de données.
Voici ce que vous devriez obtenir sur l’esclave (un message Hello World ! suivi d’un compteur et de la fonction onRequest déclenchée) :

Sur le maître, vous recevrez les paquets envoyés par l’esclave.

Conclusion
Dans ce tutoriel, nous vous avons montré comment configurer l’ESP32 comme esclave I2C et comme maître I2C et comment échanger des données entre deux cartes EPS32 à l’aide du protocole de communication I2C.
Pour plus de détails sur l’utilisation de la bibliothèque Wire pour la communication I2C, consultez la documentation officielle : Documentation de l’API Arduino-ESP32 I2C.
Nous avons d’autres tutoriels I2C avec l’ESP32 qui pourraient vous être utiles :
Si vous souhaitez échanger des données sans fil entre deux cartes ESP32, nous vous recommandons plutôt d’utiliser ESP-NOW :
Nous espérons que ce tutoriel sera utile. Apprenez-en plus sur l’ESP32 avec nos ressources :
Cette vidéo vous emmène dans l’histoire de Raspberry Pi :

-
Carte de développement ESP32, ESP32 WROOM 32U pour Arduino, ESP-32-DevKitC V4 Carte avec Antenne 3 dBi Câble U.FL vers SMA Femelle Compatible Prototypage IoT Bluetooth BLE WiFi pour Raspberry Pi STM32
-
ELEGOO 3PCS Carte de Développement ESP-32 Type-C, 2,4 GHz WiFi + Bluetooth
