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.