Le bus I2C est très utilisé pour récupérer des mesures ou piloter des équipements sur les projets Arduino, ESP32, ESP8266 et Raspberry Pi à l’aide de la librairie standard Wire.h. Le bus I2C est un bus de communication série mis au point par Philips à partir de 1982 qui permet à deux appareils (ou plus) de communiquer. Plus précisément, c’est un bus de données série synchrone bidirectionnel half-duplex. Les appareils connectés au bus peuvent agir en tant qu’équipement principal – c’est à dire l’appareil qui «contrôle» le bus – ou secondaire.
Dans cet article, nous allons aborder le principe de fonctionnement de la librairie Wire.h qui permet de faire communiquer simplement des Arduino entre eux. Par contre nous aborderons pas le fonctionnement technique du bus I2C qui est déjà très bien expliqué sur cette page Wikipedia.
Sommaire
- 1 Présentation rapide du bus I2C
- 2 Les adresses I2C
- 3 Broches i2c par défaut des cartes de développement les plus courantes
- 4 Présentation de la librairie Wire.h pour Arduino, ESP32 et ESP8266
- 5 Limitations de la librairie Wire.h pour les cartes Arduino
- 6 Limitations de la librairie Wire.h pour ESP32 et ESP8266
- 7 Scanner I2C compatible Arduino, ESP32 et ESP8266
Présentation rapide du bus I2C
Le bus I2C est donc une amélioration de la communication série destinée à faire communiquer des accessoires domotiques développé à partir des années 1980 par Philipps. La plupart du temps le bus I2C est constitué d’un équipement principal et un ou plusieurs équipements secondaires, mais la norme permet des organisations plus complexes.
Le bus I2C ne nécessite que deux lignes de communication (fils) pour connecter les appareils entre eux :
- SDA (Serial Data Line), ligne de données bidirectionnelle,
- SCL (Serial Clock Line), ligne d’horloge de synchronisation bidirectionnelle. Le signal est généré uniquement par l’équipement principal
D’un point de vue électrique, tous les équipements doivent être connectés à la même masse électrique GND.
Les deux lignes doivent être connectées à une tension de référence (Vdd) via des résistances pull-up.
Voici un exemple de réseau I2C. Un Arduino Uno constitue l’équipement principal du réseau. Deux équipements secondaires sont connectés au bus I2C. A l’adresse 0x76 est connecté un capteur BME280. A l’adresse 0x5A se trouve un capteur d’intensité lumineuse BH1750FVI.
Le nombre maximum d’équipements est limité par le nombre d’adresses disponibles. Comme l’adressage des périphériques est constitué par un mot de 7 bits, on pourra adresser jusqu’à 128 périphériques (27). Le nombre de périphériques I2C dépend également de la qualité du circuit (sa capacité) ainsi que de la vitesse de transmission désirée.
Cinq vitesses de transmission sont possibles :
- Standard mode (Sm) ≤ 100 kbit/s
- Fast mode (Fm) ≤ 400 kbit/s
- Fast plus mode (Fm+) ≤ 1 Mbit/s
- High-speed mode (Hs-mode) ≤ 3,4 Mbit/s
- Ultra-fast mode (UFm) ≤ 5 Mbit/s, unidirectionnel uniquement.
La vitesse maximale est imposée par le fabricant. La plupart du temps, la vitesse est inférieure à 1 Mbit/s, en général elle se situe entre 100 et 400 kbit/s pour les capteurs.
Les adresses I2C
Chaque équipement secondaire dispose donc d’une adresse unique qui prend la forme d’une chaîne hexadécimale, par exemple 0x69.
Cette adresse est attribuée par le fabricant du composant. Il n’existe pas de norme mais les fabricants s’organisent pour ne pas utiliser une adresse déjà utilisée par un composant existant. En général, une adresse I2C secondaire est disponible. Elle est attribuable par programmation (rarement) ou en modifiant le circuit (à l’aide d’un jumper à souder ou en appliquant une tension pré-définie).
Voici deux exemples
En cas de doute sur l’adresse I2C du breakout, vous pouvez consulter cette liste des modules les plus courant pour les projets Arduino, ESP32, ESP8266 et Raspberry Pi
A LIRE AUSSI :
Adresses I2C des capteurs et actionneurs les plus courants
Broches i2c par défaut des cartes de développement les plus courantes
Il est possible d’attribuer manuellement par programmation (nous verrons comment au prochain paragraphe) les broches du bus I2C. La plupart des fabricants de cartes de développements (Arduino, ESP32, ESP8266, STM32, Raspberry Pi…) exposent les broches I2C standards.
Voici la liste des broches par défaut des cartes de développement les plus courantes
SDA | SCL | SDA1 | SCL1 | |
Bus principal | Bus secondaire | |||
Uno* | A4 | A5 | ||
Ethernet | A4 | A5 | ||
Mega2560 | 20 | 21 | ||
Leonardo | 2 | 3 | ||
Due | 20 | 21 | SDA1 | SCL1 |
ESP8266 | D1 | D2 | ||
ESP32 DevkitC v4 | 21 | 22 | Utilisateur | Utilisateur |
ESP32 (anciennes générations) | IO21 | IO22 | Utilisateur | Utilisateur |
STM32 | PB7 ou PB9 | PB6 ou PB8 | PB11 | PB10 |
Raspberry Pi (toute génération) | 3 | 5 |
(*) Ne pas utiliser les broches repérées SDA et SCL sur l’Arduino Uno.
Présentation de la librairie Wire.h pour Arduino, ESP32 et ESP8266
Le bus i2c est pris en charge par la librairie Wire.h qui a également été portée sur ESP32 et ESP8266.
C’est une librairie standard qui ne nécessite aucune installation complémentaire. La version dédiée aux ESP32 et ESP8266 est installée en même temps que le SDK.
Pour utiliser le bus I2C dans un projet Arduino, il suffit déclarer la librairie wire en début de code.
#include
On initialise le bus i2c à l’aide de la méthode Wire.begin(adresse).
Sur Arduino, les broches ne sont pas spécifiées, la librairie utilise les broches par défaut pour la carte de développement ciblée. L’adresse correspond à l’adresse que l’on désire attribuer à l’équipement secondaire. On utilisera par exemple ce paramètre lorsqu’on développe un réseau I2C entre plusieurs Arduino. Nous verrons deux exemples juste après.
Wire.begin();
Les modules I2C du commerce disposent d’une librairie qui s’occupe de récupérer les données ce qui facilite grandement de travail de développement puisqu’on n’a pas à s’occuper du décodage des paquets envoyés.
Il est toutefois possible d’utiliser la librairie Wire.h pour développer notre propre protocole de communication entre deux (ou plus) Arduino (ou tout autre micro-contrôleurs d’ailleurs)
Pour faire simple, la librairie Wire.h dispose de 4 méthodes principales. Toutes les méthodes sont détaillées ici.
Wire.beginTransmission(adresse_i2c) permet de démarrer un envoi de données vers l’équipement dont l’adresse est passée en paramètre.
Wire.write(donnees_a_envoyer) permet d’envoyer une donnée vers l’équipement spécifié auparavant. Plusieurs formats de données sont supportés par la librairie
Wire.write(value) une valeur à envoyer sur un octet (byte)
Wire.write(string) une chaîne à envoyer sous forme de série d’octets (byte). La conversion d’une chaîne de caractère en byte est gérée par la librairie
Wire.write(data, length)
- data un tableau d’octets (bytes)
- length le nombre d’octets à transmettre
Wire.endTransmission() permet de fermer la communication avec l’équipement
Nous verrons d’autres méthodes utiles dans les exemples suivants
Limitations de la librairie Wire.h pour les cartes Arduino
Pour les cartes Arduino, la méthode Wire.begin() permet de spécifier manuellement l’adresse d’un équipement. Par contre, on ne pourra pas spécifier manuellement les broches SDA et SCL.
Wire.begin(0x09);
Limitations de la librairie Wire.h pour ESP32 et ESP8266
L’adaptation de la librairie Wire.h pour les cartes de développement ESP32 et ESP8266 ne permet pas d’attribuer une adresse à un équipement secondaire. On ne pourra donc pas créer un réseau I2C pour faire communiquer plusieurs ESP32 ou ESP8266 ensembles.
Par contre, on peut spécifier les broches SDA et SCL. Ici par exemple on attribue manuellement les broches 21 (SDA) et 22 (SCL) au bus I2C en appelant la méthode comme ceci Wire.begin(broche_sda,broche_scl).
Wire.begin(21,22);
En résumé
Arduino | ESP32 / ESP8266 | |
Attribuer une adresse à un équipement secondaire sur le réseau I2C | Oui | Non |
Créer un réseau I2C | Oui | Non |
Attribuer les broches SDA et SCL | Non | Oui |
Piloter et récupérer des données d’équipements I2C | Oui | Oui |
Scanner I2C compatible Arduino, ESP32 et ESP8266
La plupart du temps, on utilisera le bus I2C pour communiquer avec des capteurs prêt à l’emploi (breakout).
L’adresse I2C des modules les plus courant sont répertoriées dans cet article
A LIRE AUSSI :
Adresses I2C des capteurs et actionneurs les plus courants
Si vous ne trouvez pas l’adresse I2C de votre composant ou que vous rencontrez des problèmes de communication, voici le code source d’un scanner I2C compatible Arduino, ESP32 et ESP8266.
#include
#include
#define DISPLAY_ERROR false
#define LOOP_DELAY 10000
#define USER_PIN false
// Personnaliser les broches du bus I2C pour ESP8266 ou ESP32
// Customize I2C bus pins for ESP8266 or ESP32
const int PIN_SCL = D1;
const int PIN_SDA = D2;
String I2Ctest() {
byte error, address;
int nDevices;
String s;
s="Scanning...n";
nDevices = 0;
for(address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
s+="I2C device found at 0x";
if (address 0 ) {
if ( DISPLAY_ERROR ) {
s+="Unknow error at 0x";
if (address