Communication en I2C entre 2 Arduinos

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)

 

arduino_led_i2c

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);
}

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.