On a l’habitude d’utiliser l’I2C soit pour augmenter le nombre d’entrées sorties (MCP23017), soit pour communiquer avec un module (Ex : Afficheur LCD, mesure de la tension via un INA219).
Mais on peut aussi faire communiquer des Arduinos entre eux en I2C.
Une seule règle importante : Si vous avez 2 modèles avec des niveaux logiques différents (3.3V et 5V), passer par un transformateur de niveaux logiques.
Pour le reste, c’est assez simple, en voici un exemple :
Voici 2 Arduinos, le 1er (en haut) dispose de 2 boutons poussoirs et de 2 Led. L’appuie sur un bouton provoque l’allumage de la Led correspondante.
Mais en plus, cela prépare une donnée binaire (00,01,10,11 soit 0,1,2, ou 3) prête à être envoyée en I2C si on l’interroge.
Cet Arduino est donc le « slave », il écoute l’adresse 0x09 sur son port I2C et est prêt à fournir la valeur de la donnée si on la lui demande
Le deuxième Arduino (en dessous du 1er ) n’a aucun bouton mais il a les 2 même Led. Il interroge régulièrement l’autre Arduino via I2C (qui est à l’adresse 0x09) , analyse la donnée reçue et en déduit quels boutons sont appuyés. Pour visualiser qu’il a compris, il allume les Led correspondantes (c’est à dire que les mêmes Led doivent s’allumer en même temps sur les 2 Arduinos)
Vous remarquerez la présences de résistances :
- Pour les boutons poussoirs, il y a des Pull Up de 1 000 ohms
- Pour les Led, des résistances de 220 ohms
- Pour le port I2C, des Pull up de 4 700 ohms (si nous n’en n’avez pas, des 5 000 ohms vont très bien)
Remarques :
- L’I2C se connecte en fil à fil (SDA sur SDA et SCL sur SCL), on peut y ajouter d’autres modules ou Arduinos en I2C qui se connecteront en parallèle. Il ne peut y avoir qu’un seul « Master » mais jusque 127 « Slaves ».
- Il faut que les 2 Pi partagent la même masse. Ici, ils partagent aussi la même alimentation 5V mais ceci n’est pas obligatoire
Les 2 boutons poussoirs sont sur les Pin 6 et 7
Les 2 Led sur les pin 8 et 9
J’utilise toujours le jaune pour le SDA et le bleu pour le SCL.
Code du slave
Voici maintenant le code du « slave » (Le Arduino en haut, qui porte les boutons, prépare et fournis la donnée lorsqu’on l’interroge à l’adresse 0x09)
/******************************************/ /* I2C ENTRE 2 ARDUINO */ /* CODE SLAVE : 2 BOUTONS SUR D6 et D7 */ /* 2 LED SUR D8 ET D9 */ /* LES SCRIPT ENVOIE A L'ARDUINO EN 0x09 */ /* L'ETAT DES BOUTONS */ /* CE SCRIPT ALLUME LA LED CORRESPONDANT */ /* AUX BOUTONS ET PREPARE UNE DONNEES */ /* SELON LES BOUTONS QU'IL ENVOIE VIA I2C */ /******************************************/ #include #define GREEN_BUTTON 6 #define RED_BUTTON 7 #define GREEN_LED 8 #define RED_LED 9 #define I2C_DEST_ADDR 0x09 #define TIME_BETWEEN 100 byte old_red=0; byte old_green=0; byte current_red=0; byte current_green=0; void setup() { Wire.begin(); Serial.begin(9600); while(!Serial){ delay(1);}; delay(50); pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT); pinMode(GREEN_BUTTON, INPUT); pinMode(RED_BUTTON, INPUT); } void loop() { byte data=0; current_red=digitalRead(RED_BUTTON); current_green=digitalRead(GREEN_BUTTON); data=data+current_red; data=data+current_green * 2; if ((current_red!=old_red) or (current_green!=old_green)) { digitalWrite(RED_LED, current_red); digitalWrite(GREEN_LED, current_green); old_red=current_red; old_green=current_green; Serial.println(data); Wire.beginTransmission(I2C_DEST_ADDR); Wire.write(data); int err=Wire.endTransmission(); if (err!=0) { Serial.print("Erreur de transmission "); Serial.println(err); } } delay(TIME_BETWEEN); }
Code du master
Voici maintenant le code du « master » (Le Arduino en bas, il n’a pas de boutons, il interroge l’autre Arduino qui est à l’adresse 0x09 et en déduit quelles Led allumer.)
/*****************************************/ /* I2C ENTRE 2 ARDUINO */ /* CODE SLAVE : */ /* 2 LED SUR D8 ET D9 */ /* LES CRIPT EST EN I2C SUR 0x09 */ /* IL RECOIT UNE DONNEE ET ALLUME LES LED*/ /*****************************************/ #include #define I2C_MY_ADDR 0x09 #define GREEN_LED 8 #define RED_LED 9 byte old_red=0; byte old_green=0; byte current_red=0; byte current_green=0; byte data = 0; void setup() { pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT); Serial.begin(9600); while(!Serial){ delay(1);}; Wire.begin(I2C_MY_ADDR); Wire.setClock(10000); Wire.onReceive(receiveEvent); Serial.println("Démarrage i2c"); } void receiveEvent(int bytes) { data = Wire.read(); Serial.println(data); Wire.write(data); } void loop() { current_red=data % 2; current_green=(data - current_red ) / 2; if ((current_red!=old_red) or (current_green!=old_green)) { digitalWrite(RED_LED, current_red); digitalWrite(GREEN_LED, current_green); Serial1.write(data); old_red=current_red; old_green=current_green; Serial.println(data); } delay(100); }