Leçon 7 / 8
Leçon 07 · Arduino

Bibliothèques — I2C, SPI

Pourquoi des protocoles de communication ?

Un Arduino dispose d'un nombre limité de broches. Si tu veux connecter plusieurs composants — un écran, un capteur de pression, une carte SD — utiliser une broche par signal devient vite impossible. Les protocoles de communication I2C et SPI résolvent ce problème : ils permettent de faire communiquer plusieurs périphériques sur un même bus partagé, avec seulement 2 à 4 fils.

Ces protocoles sont gérés nativement par le matériel de l'Arduino (registres UART, TWI, SPI). Des bibliothèques dédiées abstrait leur complexité pour que tu te concentres sur l'essentiel : envoyer et recevoir des données.

I2C : deux fils pour tout un bus

L'I2C (Inter-Integrated Circuit, prononcé « I carré C ») n'utilise que deux lignes :

  • SDA (Serial Data) — données bidirectionnelles
  • SCL (Serial Clock) — horloge générée par le maître

Sur un Arduino Uno/Nano, SDA est sur la broche A4 et SCL sur A5. Sur un Arduino Mega, ce sont les broches 20 (SDA) et 21 (SCL).

Le bus I2C fonctionne en mode maître/esclave : l'Arduino est le maître, les capteurs et écrans sont les esclaves. Chaque esclave possède une adresse 7 bits unique (entre 0x08 et 0x77), ce qui permet jusqu'à 112 périphériques sur un même bus. Des résistances de tirage (pull-up) de 4,7 kΩ sont nécessaires sur SDA et SCL — elles sont souvent intégrées sur les modules breakout.

La bibliothèque standard pour I2C est Wire.h, incluse dans l'IDE Arduino sans installation.

💡

La vitesse standard I2C est de 100 kHz (mode standard) ou 400 kHz (mode rapide). C'est suffisant pour des capteurs et des petits écrans, mais trop lent pour des transferts de données importants comme une carte SD — c'est là que SPI prend le relai.

Scanner I2C : trouver les adresses de tes périphériques

Avant d'utiliser un composant I2C, il faut connaître son adresse. Elle est parfois indiquée dans la datasheet, mais un scanner I2C la détecte automatiquement en quelques secondes. Téléverse ce sketch, ouvre le moniteur série à 9600 bauds :

scanner_i2c.ino — Détecter les adresses I2C
// Scanner I2C — détecte tous les périphériques connectés au bus
#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("Scan I2C en cours...");

  int count = 0;
  for (byte addr = 8; addr < 120; addr++) {
    Wire.beginTransmission(addr);
    byte error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("Périphérique trouvé à l'adresse 0x");
      if (addr < 16) Serial.print("0");
      Serial.println(addr, HEX);
      count++;
    }
  }

  if (count == 0) {
    Serial.println("Aucun périphérique I2C détecté.");
  } else {
    Serial.print(count);
    Serial.println(" périphérique(s) trouvé(s).");
  }
}

void loop() {}

Écran LCD I2C avec LiquidCrystal_I2C

Les écrans LCD 16x2 classiques nécessitent 6 à 10 broches. Avec un module adaptateur I2C (souvent à base de PCF8574), on réduit à 2 fils (SDA + SCL). L'adresse par défaut est généralement 0x27 ou 0x3F selon le module — utilise le scanner pour confirmer.

Installe la bibliothèque LiquidCrystal I2C (par Frank de Brabander) via le gestionnaire de bibliothèques.

lcd_i2c.ino — Afficher du texte sur un écran LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// LiquidCrystal_I2C(adresse, colonnes, lignes)
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
  lcd.init();          // initialise le LCD
  lcd.backlight();    // allume le rétroéclairage

  lcd.setCursor(0, 0);   // colonne 0, ligne 0
  lcd.print("MonMiniLab");

  lcd.setCursor(0, 1);   // colonne 0, ligne 1
  lcd.print("I2C ready !");
}

void loop() {
  // Exemple : afficher un compteur
  static int compteur = 0;
  lcd.setCursor(10, 1);
  lcd.print(compteur++);
  delay(1000);
}

Capteur BMP280 (pression et température) via I2C

Le BMP280 est un capteur de pression atmosphérique et de température très populaire. Il communique en I2C (adresse 0x76 ou 0x77 selon le câblage de la broche SDO) ou en SPI. Pour l'utiliser, installe la bibliothèque Adafruit BMP280 (qui dépend aussi d'Adafruit Unified Sensor).

bmp280_i2c.ino — Lire pression et température
#include <Wire.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp;  // objet capteur

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

  if (!bmp.begin(0x76)) {  // 0x77 si SDO connecté à 3.3V
    Serial.println("BMP280 non détecté ! Vérifiez le câblage.");
    while (1);
  }
  Serial.println("BMP280 OK");
}

void loop() {
  float temperature = bmp.readTemperature();  // en °C
  float pression    = bmp.readPressure() / 100.0F;  // en hPa
  float altitude    = bmp.readAltitude(1013.25);   // en mètres (pression mer = 1013.25 hPa)

  Serial.print("Temp : "); Serial.print(temperature); Serial.println(" °C");
  Serial.print("Pression : "); Serial.print(pression); Serial.println(" hPa");
  Serial.print("Altitude : "); Serial.print(altitude); Serial.println(" m");
  Serial.println("---");

  delay(2000);
}

SPI : plus rapide, mais plus de fils

Le SPI (Serial Peripheral Interface) utilise quatre lignes :

  • MOSI (Master Out Slave In) — données du maître vers l'esclave
  • MISO (Master In Slave Out) — données de l'esclave vers le maître
  • SCK (Serial Clock) — horloge générée par le maître
  • SS / CS (Slave Select / Chip Select) — sélectionne le périphérique actif (une broche par esclave)

Sur Arduino Uno, les broches SPI hardware sont : MOSI = 11, MISO = 12, SCK = 13. La broche SS est libre, mais 10 est la convention. SPI peut atteindre plusieurs mégabits par seconde — bien plus rapide qu'I2C, idéal pour des afficheurs TFT ou des cartes SD.

⚠️

Si tu utilises plusieurs périphériques SPI, chacun a besoin de sa propre broche SS. Tu dois mettre les autres SS à HIGH (désactivés) avant de communiquer avec un périphérique. La bibliothèque SPI.h est incluse par défaut dans l'IDE Arduino.

Carte SD via SPI avec SD.h

Les modules carte SD communiquent en SPI. La bibliothèque SD.h est intégrée à l'IDE et simplifie la lecture et l'écriture de fichiers. Branchement standard : MOSI/MISO/SCK sur les broches hardware, et CS (Chip Select) sur la broche de ton choix (ici broche 4).

carte_sd.ino — Lire et écrire des fichiers sur carte SD
#include <SPI.h>
#include <SD.h>

const int CS_PIN = 4;   // broche Chip Select de la carte SD

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

  if (!SD.begin(CS_PIN)) {
    Serial.println("Echec initialisation carte SD !");
    while (1);
  }
  Serial.println("Carte SD OK");

  // --- Écriture dans un fichier ---
  File fichier = SD.open("data.txt", FILE_WRITE);
  if (fichier) {
    fichier.println("Temperature : 23.5 C");
    fichier.println("Pression : 1012.3 hPa");
    fichier.close();
    Serial.println("Données écrites.");
  }

  // --- Lecture du fichier ---
  fichier = SD.open("data.txt");
  if (fichier) {
    Serial.println("Contenu de data.txt :");
    while (fichier.available()) {
      Serial.write(fichier.read());
    }
    fichier.close();
  }
}

void loop() {}

Installer des bibliothèques Arduino

Il existe deux méthodes pour ajouter une bibliothèque à l'IDE Arduino :

  • Gestionnaire de bibliothèques (recommandé) — Menu Outils → Gérer les bibliothèques… (raccourci Ctrl+Maj+I). Recherche le nom de la bibliothèque, clique sur Installer. Les dépendances sont installées automatiquement.
  • Depuis un fichier .zip — si la bibliothèque n'est pas dans le registre officiel, télécharge le .zip depuis GitHub, puis menu Croquis → Inclure une bibliothèque → Ajouter la bibliothèque .ZIP….

Les bibliothèques installées sont stockées dans le dossier Documents/Arduino/libraries/ sur Windows et macOS. Une fois installées, elles apparaissent dans Croquis → Inclure une bibliothèque et sont accessibles par #include.

// À retenir
  • I2C = 2 fils (SDA + SCL), adresses 7 bits, jusqu'à 112 périphériques sur un même bus — bibliothèque Wire.h.
  • Le scanner I2C est indispensable pour identifier les adresses des composants inconnus.
  • LCD I2C : bibliothèque LiquidCrystal_I2C, init avec lcd.init() et lcd.backlight().
  • BMP280 via I2C : bibliothèque Adafruit BMP280 — readTemperature(), readPressure(), readAltitude().
  • SPI = 4 fils (MOSI, MISO, SCK, SS), rapide, adapté aux cartes SD et afficheurs TFT.
  • Carte SD : bibliothèque SD.h intégrée — SD.begin(CS), SD.open(), fichier.println().
  • Installer une bibliothèque : gestionnaire (Ctrl+Maj+I) ou menu fichier .ZIP.