Vous êtes sur la page 1sur 12

2022

TP N° :02

Gérez plusieurs Arduino avec un bus


I2C

Module : Réseaux locaux industriels


Ecole nationale supérieure des énergies
renouvelables, de l'environnement et du
développement durable de BATNA
07/11/2022
Sommaire

Table des matières


Sommaire .................................................................................................................................... 1
TP2 : Gérez plusieurs Arduino avec un bus I2C ........................................................................ 3
1. Introduction ...................................................................................................................................... 3
2. Généralités sur le communication en I2C ......................................................................................... 3
3. Terminologie du bus I2C .................................................................................................................. 3
4. Principe de fonctionnement du protocole I2C .................................................................................. 4
5. Matériel utilisé dans ce TP ............................................................................................................... 4
6. Schéma de connexion du bus I2C entre cartes Arduino ................................................................... 5
7. Bibliothèque ( fonction ) vous permettant de communiquer avec des appareils I2C (Code de
configuration du bus I2C) ......................................................................................................................... 6
8. Code pour identifier les périphériques branchés sur le bus I2C ..................................................... 10
Références .............................................................................................................................................. 12

2 TP2 : Gérez plusieurs Arduino avec un bus I2C


TP2 : Gérez plusieurs Arduino avec un bus I2C

1. Introduction

L’I2C est un protocole de communication qui fut tout d’abord propriétaire (inventé par
Philips) et né de la nécessité d’interfacer de plus en plus de microcontrôleurs. En effet, à ce
moment là une voie série "classique" ne suffisait plus car elle ne pouvait relier que deux à deux
les microcontrôleurs. La particularité de cette liaison est qu’elle transporte son propre signal
d’horloge. Ainsi, la vitesse n’a pas besoin d’être connu d’avance. Les données sont transportées
en même temps que l’horloge grâce à deux fils : SDA (Data) et SCL (Clock). Comme pour
l’USB, la communication se fait sur un système de maître/esclave.[1]

Il peut être pratique, notamment dans des projets de domotique, de communiquer entre
plusieurs appareils. Une des techniques couramment utilisées est le protocole I2C (ou TWI). Le
protocole I2C est une méthode qui permet de connecter plusieurs cartes « Maîtres » et plusieurs
cartes « Esclaves » et de faire communiquer jusqu’à 128 appareils. Elle permet des connexions
asynchrones entre plusieurs composants pour partager des informations via un « bus commun
». Nous avions vu la communication via le port Série (dit UART) qui est utilisée pour envoyer
le code à l’Arduino par un ordinateur ou pour connecter deux appareils notamment en
Bluetooth.[4]

N.B. : Il est bon de noter que la communication I2C est prévue, au départ, pour de la
communication carte à carte. De ce fait, elle n’est pas adaptée pour la communication sur de
longues distances (>1m)[4]

2. Généralités sur le communication en I2C

• Le bus I2C permet de faire communiquer entre eux des composants électroniques très
divers grace à seulement trois fils : Un signal de donnée ( SDA ), un signal d’horloge ( SCL ),
et un signal de référence électrique ( Masse ).

• Les données sont transmises en série à 100Kbits/s en mode standard et jusqu’à 400Kbits/s
en mode rapide.
• chaque périphérique sur le bus I2C est adressable, avec une adresse unique pour chaque
périphérique du bus

• Le nombre maximal d’équipements est limité par le nombre d’adresses disponibles, 7


bits d’adressage et un bit R/W (lecture ou écriture), soit 128 périphériques, mais il dépend
également de la capacité (CB) du bus (dont dépend la vitesse maximale du bus). Il faut savoir
que des adresses sont réservées pour diffuser des messages en broadcast et que de
nombreuses adresses sont déjà attribuées par les fabricants ce qui limite grandement le
nombre d’équipements (une variante d’adressage sur 10 bits existe également). [5]

3. Terminologie du bus I2C

• Emetteur : le composant qui envoie des données sur le bus.


• Récepteur : le composant qui reçoit les données présentes sur le bus.

3 TP2 : Gérez plusieurs Arduino avec un bus I2C


• Maître : le composant qui initialise un transfert, génère le signal d’horloge et termine le
transfert. Un maître peut être soit récepteur soit émetteur.
• Esclave : le composant adressé par un maître. Un esclave peut être soit récepteur soit
émetteur.
• Multimaître : plus d’un maître peut tenter de commander le bus en même temps sans
en altérer le message.
• Arbitrage : procédure réalisée afin de s’assurer que si plus d’un maître essaie
simultanément de prendre la commande du bus, un seul sera autorisé à le faire.
• Synchronisation : procédure réalisée afin de synchroniser les signaux d’horloge
fournis par deux ou plusieurs maîtres.
• SDA : ligne des signaux de données (Serial DAta).
• SCL : ligne des signaux d’horloge (Serial CLock).[5]

4. Principe de fonctionnement du protocole I2C

Le bus I2C est un autre mécanisme de communication et d’interfaçage, où il utilise


seulement deux lignes (SDA et SCL) pour communiquer bidirectionnellement (half-duplex).

Les périphériques utilisant le protocole I2C ont une adresse unique et on communique avec
eux grâce à cette adresse. En outre, I2C permet un contrôle multi-maître.

Figure 1 : Exemple de transmission via le protocole I2C [1]

Avant de commencer la transmission, le bus doit être en repos avec SDA et SCL mis à 1 (ou
HIGH). Ensuite, SDA passe à 0 et SCL garde l’état 1, et après la transmission SDA revient à 1
et SCL garde l’état 1 [1]. Le protocole I2C est basé sur MSBFirst, où il transmet le premier bit
puis le valide en passant SCL à 0 et revient à 1 pour transmettre le bit suivant. A la fin, le maître
transmet un bit d’acquittement 1 et l’esclave répond avec 0 pour signaler la bonne transmission.

La transmission d’une adresse se fait comme la transmission d’une donnée, sauf elle est
codée sur 7 bits et le 8ème bit définit s’il s’agit d’une lecture ou d’une écriture. En outre, après
la transmission de la commande, le maître garde l’état 1 dans l’acquittement jusqu’à la réception
de la donnée de l’esclave en cas d’une lecture de donnée. Puis le remet à 0 pour continuer la
lecture ou à 1 pour mettre fin à la transmission [2].

5. Matériel utilisé dans ce TP

Afin de réaliser ce TP et pratiquer le protocole I2C, nous utilisons le matériel suivant :

• Ordinateur
4 TP2 : Gérez plusieurs Arduino avec un bus I2C
• Arduino UNO x2 ou plus

• Jumper câble M/M x3 fois le nombre de carte[4]

Figure 2 : Matériel utilisé pour pratiquer le protocole I2C[4]

6. Schéma de connexion du bus I2C entre cartes Arduino

Avec le protocole I2C, il est aussi possible de communiquer entre différents systèmes
(capteurs, écran LCD, Raspberry Pi, etc.). Un exemple intéressant est la communication entre
plusieurs cartes Arduino. Pour cela, il nous faut écrire au moins deux programmes, un pour la
carte « Maîtresse » (Master) et l’autre pour les cartes « Esclaves » (Slaves).

Une communication I2C est défini par un bus de deux fils (parfois appelé TWI, Two Wire
Interface) et une adresse. Les broches utilisées par la communication I2C sont généralement
fixé pour chaque appareil. L’une sur laquelle sont envoyées les données (SDA Serial Data
Line) et sur l’autre l’horloge de synchronisation (SLC Serial Clock Line).

Broches I2C/TWI:

• Uno, Ethernet A4 (SDA), A5 (SCL)

• Mega2560 20 (SDA), 21 (SCL)

• Leonardo 2 (SDA), 3 (SCL)

• Due 20 (SDA), 21 (SCL), SDA1, SCL1

Dans cet exemple nous utilisons une carte Arduino Uno, donc, les broches A4 et A5.

Afin que les deux cartes communiquent entre elles il faut les relier correctement (A4 avec
A4 et A5 avec A5) et ne pas oublier de relier les masses (GND) comme indiqué sur le schéma
suivant. [4]

5 TP2 : Gérez plusieurs Arduino avec un bus I2C


Attention : Si les broches A4 et A5 sont reliées aux broches d’une carte non alimentée, le
code se figera au moment de la transmission.

Figure 3 : Schéma général de branchement de trois cartes Arduino en série

Généralement, une carte va envoyer des informations (Writer) et une autre va les recevoir
(Reader).[4]

7. Bibliothèque ( fonction ) vous permettant de communiquer avec des appareils I2C


(Code de configuration du bus I2C)

La libraire Wire.h permet de les définir simplement la communication série sur le bus I2C.
Les fonctions sont similaires à la librairie Serial.

• begin()
o Description : Initialise la librairie Wire et se connecte au bus I2C en tant que maître ou
esclave. L’argument de la fonction peut être vide pour les appareils maître Cette instruction
ne doit normalement n’être appelée qu’une seule fois au début du programme.
o Syntaxe :
▪ Wire.begin()
▪ Wire.begin(adresse)
o Paramètres :
▪ addresse : l’adresse 7-bit esclave (optionnel); si non spécifiée, la connexion au
bus se fait en mode maître.
• read()

o Description : Lit un octet qui a été transmis d’un périphérique esclave à un maître après
un appel à requestFrom () ou a été transmis d’un maître à un esclave.
o Syntaxe :
▪ Wire.read ()
o Paramètres : Aucun
• write()
o Description : Cette fonction écrit le paramètre qu’on lui donne (le premier) sur le bus de
communication (permet d’envoyer des bytes). Elle est commune aux deux types de
périphériques .
▪ le maître écrit sur le bus ,fonction utilisée entre beginTransmission()
et endTransmission() .
▪ l’esclave écrit sur le bus mais après requête du maître, il ne peut pas écrire de son
propre chef.
6 TP2 : Gérez plusieurs Arduino avec un bus I2C
o Syntaxe :
▪ Wire.write(value)
▪ Wire.write(string)
▪ Wire.write(data, length)
o Paramètres :
▪ value : une valeur à envoyer en un seul octet .
▪ string : une chaîne à envoyer en tant que série d’octets.
▪ data : un tableau de données à envoyer en octets
▪ length : le nombre d’octets à transmettre
• requestFrom()
o Description : Fonction utilisée par le périphérique maître, elle sert à demander une
information à un esclave (gère la fonction de réception de requête). L’argument de cette
fonction est l’adresse de l’esclave à interroger.
o Syntaxe :
▪ Wire.requestFrom(address, quantity)
▪ Wire.requestFrom(address, quantity, stop)
o Paramètres :
• beginTransmission()
o Description : Cette fonction commence la transmission vers un esclave sur le bus de
communication. L’adresse de ce périphérique doit être passée en argument.
o Syntaxe :
▪ Wire.beginTransmission(adresse)
o Paramètres :
• endTransmission()
o Description : Termine une transmission à un périphérique esclave qui a été commencée
par beginTransmission () et transmet les octets qui ont été mis en file d’attente par write () .
o Syntaxe :
▪ Wire.endTransmission()
▪ Wire.endTransmission(stop)
o Paramètres :
• onRequest()
o Description : Enregistrer une fonction à appeler lorsqu’un maître demande des données
à ce périphérique esclave.
o Syntaxe : Wire.onRequest(handler)
o Paramètres :
• onReceive()

o Description : Enregistre une fonction à appeler lorsqu’un périphérique esclave reçoit


une transmission d’un maître.
o Syntaxe : Wire.onReceive(handler)
o Paramètres :

7 TP2 : Gérez plusieurs Arduino avec un bus I2C


Code de la carte « Maîtresse » [4]

#include <Wire.h>

# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12

#define PAYLOAD_SIZE 2

int n=0;

void setup()
{
Wire.begin();
Serial.begin(9600);

Serial.println(F("------------------I am the Master"));


delay(1000);

//Request value of n to slave


Wire.requestFrom(I2C_SLAVE1_ADDRESS, 1);
n = Wire.read();
Serial.print(F("recieved value : "));
Serial.println(n);

//Send value 12 to slave


Wire.beginTransmission(I2C_SLAVE1_ADDRESS);
Wire.write(12);
Serial.print(F("sending value : "));
Serial.println(12);
Wire.endTransmission();

Serial.print(" ");

//Request value of n to slave after change


Wire.requestFrom(I2C_SLAVE1_ADDRESS, 1);
n = Wire.read();
Serial.print(F(" new recieved value : "));
Serial.println(n);
}

void loop()
{
delay(100);
}
8 TP2 : Gérez plusieurs Arduino avec un bus I2C
Code de la carte « Esclave »[4]

#include <Wire.h>

# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et


ainsi de suite

#define PAYLOAD_SIZE 2

void setup()
{
Wire.begin(I2C_SLAVE_ADDRESS);
Serial.begin(9600);
Serial.println("--------------------I am Slave1");
delay(1000);
Wire.onRequest(requestEvents);
Wire.onReceive(receiveEvents);
}

void loop(){}

int n = 0;

void requestEvents()
{
Serial.println(F("---> recieved request"));
Serial.print(F("sending value : "));
Serial.println(n);
Wire.write(n);
}

void receiveEvents(int numBytes)


{
Serial.println(F("---> recieved events"));
n = Wire.read();
Serial.print(numBytes);
Serial.println(F("bytes recieved"));
Serial.print(F("recieved value : "));
Serial.println(n);
}

9 TP2 : Gérez plusieurs Arduino avec un bus I2C


Ouvrez le moniteur série des cartes esclaves avant le moniteur de la carte maître.
Dans le moniteur série de la carte « Maîtresse » :

Figure 4 : Moniteur série de la carte « Maîtresse »[4]

Dans le moniteur série de la carte « Esclave 1 »:

Figure 4 : Moniteur série de la carte « Esclave 1 » [4]

Nous pouvons voir que les deux cartes échangent des informations. Il est très facile d’étendre cet
exemple à plusieurs cartes Arduino (Leonardo, Mini, etc.) en adaptant le câblage et l’adresse du
composants dans le code « Esclave ».

8. Code pour identifier les périphériques branchés sur le bus I2C

Un bon test pour savoir si vos appareils communiquent bien entre eux est d’utiliser le code
ci-dessous (I2CScanner) qui retourne toutes les adresses des appareils branchés à la carte
Maîtresse. [4]
10 TP2 : Gérez plusieurs Arduino avec un bus I2C
#include <Wire.h>

void setup()
{
Wire.begin();
Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println(F("\nI2C Scanner"));
}

void loop()
{
byte error, address;
int nDevices;

Serial.println(F("Scanning..."));

nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();

if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");

nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
11 TP2 : Gérez plusieurs Arduino avec un bus I2C
}
if (nDevices == 0)
Serial.println(F("No I2C devices found\n"));
else
Serial.println(F("done\n"));

delay(5000); // wait 5 seconds for next scan


}

Références

[1] ] https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/744_la-
communication-avec-arduino/3426_generalites-sur-la-voie-serie/#3-10740_connexion-serie-entre-arduino-et

[2] Polycopié de Travaux Pratiques Module : Bus de communication et réseaux locaux industriels, Réalisé
par Mr. ABAINIA Kheireddine, Année universitaire 2019/2020
[3] https://www.aranacorp.com/fr/gerez-plusieurs-arduino-avec-un-bus-i2c/

[4] https://www.redohm.fr/2018/02/tutoriel-arduino-communication-i2c-1-maitre-2-esclaves/(14/11/2022)

12 TP2 : Gérez plusieurs Arduino avec un bus I2C

Vous aimerez peut-être aussi