Le bus I²C
Description
1. Les caractéristiques
Après un chapitre consacré au protocole DCC, en voici un autre consacré au protocole I²C. Étudier un protocole est toujours un peu rébarbatif. Cependant, une mise en pratique à la fin de ce chapitre va permettre de le rendre un peu plus attrayant. Cette description est nécessaire, car c’est le protocole de communication qui va être utilisé pour communiquer entre les Arduino.
Le bus I²C est un bus série initialement créé par Philips pour équiper ses appareils électroniques, tels que des téléviseurs, magnétoscopes ou machines à laver. Il a été régulièrement amélioré et sert dorénavant surtout pour des applications de domotique. Mais on peut aussi le trouver intégré sur les connectiques vidéo VGA, et même HDMI en tant que bus de contrôle. On le trouve également chez d’autres constructeurs sous les noms TWI (Two Wire Interface) ou TWSI (Two Wire Serial Interface).
Ses principales caractéristiques sont les suivantes :
-
Bus série synchrone bidirectionnel
-
Fonctionnement maître-esclave
-
Communication par deux fils, plus la masse
-
Signaux électriques en 5 V, ou en 3,3 V pour les plus récents
-
Vitesse standard de 100 kbit/s
-
Vitesses rapides de 400 kbit/s, 1 Mbit/s et 3,4 Mbits/s
-
Adressage des périphériques sur 7 ou 10 bits
Bien qu’il soit plutôt conçu pour rester à l’intérieur d’un appareil électronique, il est possible de faire parcourir des distances assez importantes à un signal I²C, ce qui permet de l’utiliser pour câbler le bus de communication entre les différents éléments d’un réseau de trains. Il faut évidemment prendre quelques précautions pour protéger les signaux des parasites : utiliser des câbles blindés, réduire la valeur des résistances de pull-up, limiter la vitesse du bus. Et pour effectuer des transmissions fiables sur de plus longues distances, il suffit d’utiliser des amplificateurs de bus.
Les Arduino disposent aussi d’un bus SPI, qui n’a pas été choisi pour plusieurs raisons :
-
Le bus SPI nécessite...
La bibliothèque
1. Quelques explications
Les cartes Arduino disposent nativement des signaux SDA et SCL, permettant de piloter des périphériques I²C. À noter que sur les Arduino Uno et Nano, ces signaux sont communs avec les broches A4 et A5, il faut donc faire un choix. Sur Arduino Leonardo et Mega, ils sont disponibles sur des broches séparées.
C’est la librairie Wire qui contient toutes les fonctions permettant l’accès au bus I²C. Il est possible de l’utiliser aussi bien en tant que maître qu’en tant qu’esclave. Sa documentation complète est disponible à l’adresse suivante : https://www.arduino.cc/en/Reference/Wire
La librairie se chargeant de tout, il n’est donc pas forcément nécessaire de connaître le détail du protocole, même s’il est toujours intéressant de bien comprendre son fonctionnement. Ceci dit, il peut être utile dans certains cas de recourir à un bus I²C géré par logiciel, soit pour gérer simultanément un bus I²C en tant que maître et l’autre en tant qu’esclave, soit pour libérer les entrées analogiques A4 et A5 sur les Arduino Uno et Nano.
2. Le côté maître
Wire.begin()
Initialise l’interface I²C en mode maître. Il n’y a rien d’autre à faire.
Wire.beginTransmission(address)
-
address : adresse du circuit esclave à contacter
Initie une transmission avec le circuit dont l’adresse est passée en paramètre. Cette fonction est utilisée en conjonction avec les fonctions Wire.write et Wire.end pour envoyer des données vers un circuit esclave.
Wire.write(value)
Wire.write(string)...
Conventions
1. Les connecteurs
Il n’existe pas de connecteur normalisé pour le bus I²C, et c’est un peu normal : ce bus n’a jamais été conçu pour aller au-delà du boîtier d’un appareil électronique. On peut néanmoins en trouver des implémentations sur plusieurs générations de connecteurs vidéo.
-
Péritel : SDA broche 12, SCL broche 10
-
VGA : SDA broche 12, SCL broche 15
-
HDMI : SDA broche 16, SCL broche 15
Si l’on se concentre sur les interfaces I²C pour Arduino, ce n’est guère mieux. Il existe de nombreuses variantes de câblage, que ce soit le type de connecteur ou l’ordre des signaux. Cependant, si l’on veut disposer de liaisons fiables, il est recommandé que les fils de données et d’horloge ne soient pas côte à côte, ainsi on peut éviter les perturbations par couplage capacitif. Donc, si l’on utilise un câble en nappe, on placera l’alimentation au milieu pour bien séparer SDA et SCL, et si l’on utilise un câble à paires torsadées (du câble Ethernet, par exemple), on mettra SDA et SCL sur des paires séparées.
Le bus I²C se contente de trois fils, mais un fil d’alimentation additionnel est le bienvenu dès qu’il s’agit de pouvoir alimenter un circuit externe. Un connecteur HE13 à quatre contacts est donc le minimum vital, c’est une connectique que l’on retrouve souvent sur les cartes d’extension pour Arduino, l’ordre des fils étant malheureusement très variable, ce qui nécessite une attention très particulière lorsque l’on connecte un nouveau périphérique I²C.
HE13-4 |
1 |
2 |
3 |
4 |
Signal I²C |
SDA |
+5V |
GND |
SCL |
Pour disposer simultanément de deux alimentations (5 V et 7,5 V), on peut passer à six fils, ce qui permet aussi de véhiculer éventuellement un signal d’interruption. Le connecteur HE13 n’étant très fiable, les circuits proposés dans le livre seront surtout équipés de connecteurs HE10. Ceux-ci sont dotés de deux rangées de connecteurs, ce qui permet de les sertir sur du câble en nappe : les numéros des pattes du connecteur...
Le testeur de bus
1. Le principe de l’écho
Lorsque l’on teste un réseau, il est toujours utile de savoir si un circuit répond pour diagnostiquer les problèmes. De la même façon que l’on teste la communication entre deux machines connectées par le protocole IP au moyen de la commande ping, il est possible de mettre au point un protocole de test entre périphériques I²C. Le principe reste toujours le même, il s’agit d’un écho : on envoie des données vers le périphérique interrogé et celui-ci les retourne. Il suffit d’effectuer une comparaison entre ce qui a été envoyé et ce qui a été reçu pour s’assurer de la fiabilité de la communication.
Deux commandes sont donc nécessaires pour faire fonctionner le circuit.
sendData : 0x22
Envoi des données depuis le circuit maître vers l’esclave. Le deuxième octet indique le nombre d’octets envoyés, il est suivi par les octets à envoyer.
recvData : 0x11
Réception des données renvoyées par l’esclave. Cette commande est suivie d’un seul octet qui indique le nombre d’octets que l’esclave doit renvoyer.
2. Le programme côté maître
Le code qui suit est extrait de la fonction I2CTest du programme AT-MULTI qui a été présenté dans le chapitre Les autres circuits. On commence par réserver deux blocs de mémoire pour stocker les données envoyées et les données reçues, ce qui permettra de faire la comparaison.
#define DATASIZE 4
byte writeData[DATASIZE];
byte readData[DATASIZE];
Il faut ensuite remplir ces quatre octets avec quelques données. L’appel à la fonction micros() permet de récupérer le nombre de microsecondes écoulées depuis le démarrage du processeur, ce qui permet de disposer de valeurs variables. La valeur lue est recopiée octet par octet dans le tableau writeData.
unsigned long micSec = micros()
byte i;
for(i=0; i<DATASIZE; i++)
{
writeData[i]=micSec&0xFF
micSec>>=8;
}...