Tous les tutoriels

4 · Écrans & bus

Écrire sur un écran OLED

Avancé25 min

Objectif

Afficher du texte sur un SSD1306 128×64 via le bus I²C.

Pourquoi c'est utile

L'I²C ne demande que deux fils pour piloter des dizaines de périphériques.

Étapes

  1. 01Glissez le composant OLED 128×64 (I2C) sur le canevas.
  2. 02Câblez SDA sur A4 et SCL sur A5 — l'écran répond à l'adresse 0x3C.
  3. 03Chargez le sketch de départ : il embarque un mini pilote SSD1306 sur <Wire.h>.
  4. 04Lancez, puis modifiez les appels oledText() pour écrire votre message.

Code de départ

// OLED Hello — SSD1306 128x64 over I2C (SDA = A4, SCL = A5).
// The cloud toolchain ships only <Wire.h>, so this sketch includes a tiny
// built-in SSD1306 driver: no external libraries needed.

#include <Wire.h>

#define OLED_ADDR 0x3C

static const uint8_t FONT5X7[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
  0x14, 0x7f, 0x14, 0x7f, 0x14, 0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62,
  0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,
  0x00, 0x41, 0x22, 0x1c, 0x00, 0x2a, 0x1c, 0x7f, 0x1c, 0x2a, 0x08, 0x08, 0x3e, 0x08, 0x08,
  0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00,
  0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00, 0x42, 0x7f, 0x40, 0x00,
  0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4d, 0x33, 0x18, 0x14, 0x12, 0x7f, 0x10,
  0x27, 0x45, 0x45, 0x45, 0x39, 0x3c, 0x4a, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07,
  0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x00, 0x14, 0x00, 0x00,
  0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14,
  0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3e, 0x41, 0x5d, 0x59, 0x4e,
  0x7c, 0x12, 0x11, 0x12, 0x7c, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e, 0x41, 0x41, 0x41, 0x22,
  0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09, 0x09, 0x09, 0x01,
  0x3e, 0x41, 0x41, 0x51, 0x73, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f, 0x41, 0x00,
  0x20, 0x40, 0x41, 0x3f, 0x01, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40,
  0x7f, 0x02, 0x1c, 0x02, 0x7f, 0x7f, 0x04, 0x08, 0x10, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e,
  0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51, 0x21, 0x5e, 0x7f, 0x09, 0x19, 0x29, 0x46,
  0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7f, 0x01, 0x03, 0x3f, 0x40, 0x40, 0x40, 0x3f,
  0x1f, 0x20, 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x38, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14, 0x63,
  0x03, 0x04, 0x78, 0x04, 0x03, 0x61, 0x59, 0x49, 0x4d, 0x43, 0x00, 0x7f, 0x41, 0x41, 0x41,
  0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7f, 0x04, 0x02, 0x01, 0x02, 0x04,
  0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40,
  0x7f, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7f,
  0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7e, 0x09, 0x02, 0x18, 0xa4, 0xa4, 0x9c, 0x78,
  0x7f, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7d, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3d, 0x00,
  0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7f, 0x40, 0x00, 0x7c, 0x04, 0x78, 0x04, 0x78,
  0x7c, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xfc, 0x18, 0x24, 0x24, 0x18,
  0x18, 0x24, 0x24, 0x18, 0xfc, 0x7c, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24,
  0x04, 0x04, 0x3f, 0x44, 0x24, 0x3c, 0x40, 0x40, 0x20, 0x7c, 0x1c, 0x20, 0x40, 0x20, 0x1c,
  0x3c, 0x40, 0x30, 0x40, 0x3c, 0x44, 0x28, 0x10, 0x28, 0x44, 0x4c, 0x90, 0x90, 0x90, 0x7c,
  0x44, 0x64, 0x54, 0x4c, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00,
  0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02
};

void oledCmd(uint8_t c) {
  Wire.beginTransmission(OLED_ADDR);
  Wire.write(0x00);
  Wire.write(c);
  Wire.endTransmission();
}

void oledInit() {
  Wire.begin();
  const uint8_t init[] = {
    0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40,
    0x8D, 0x14, 0x20, 0x00, 0xA1, 0xC8, 0xDA, 0x12,
    0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6, 0xAF
  };
  for (uint8_t i = 0; i < sizeof(init); i++) oledCmd(init[i]);
}

void oledWindow(uint8_t col, uint8_t page, uint8_t width) {
  oledCmd(0x21); oledCmd(col); oledCmd(col + width - 1);
  oledCmd(0x22); oledCmd(page); oledCmd(page);
}

void oledClear() {
  oledCmd(0x21); oledCmd(0); oledCmd(127);
  oledCmd(0x22); oledCmd(0); oledCmd(7);
  for (uint16_t i = 0; i < 1024; i += 16) {
    Wire.beginTransmission(OLED_ADDR);
    Wire.write(0x40);
    for (uint8_t j = 0; j < 16; j++) Wire.write(0x00);
    Wire.endTransmission();
  }
}

// Prints text at a character cell. scale = 1 (5x7) or 2 (10x14).
void oledText(uint8_t col, uint8_t page, const char *text, uint8_t scale) {
  for (uint8_t row = 0; row < scale; row++) {
    uint8_t x = col;
    oledWindow(col, page + row, 128 - col);
    Wire.beginTransmission(OLED_ADDR);
    Wire.write(0x40);
    uint8_t sent = 0;
    for (const char *p = text; *p && x < 128; p++) {
      for (uint8_t i = 0; i < 6; i++) {
        uint8_t bits = (i < 5 && *p >= 32) ? pgm_read_byte(&FONT5X7[(*p - 32) * 5 + i]) : 0x00;
        uint8_t slice = 0;
        for (uint8_t b = 0; b < 8; b++) {
          uint8_t src = (row * 8 + b) / scale;
          if (src < 8 && (bits >> src) & 1) slice |= (1 << b);
        }
        for (uint8_t s = 0; s < scale && x < 128; s++) {
          Wire.write(slice);
          x++;
          if (++sent >= 16) { Wire.endTransmission(); Wire.beginTransmission(OLED_ADDR); Wire.write(0x40); sent = 0; }
        }
      }
    }
    Wire.endTransmission();
  }
}

int counter = 0;

void setup() {
  Serial.begin(9600);
  oledInit();
  oledClear();
  oledText(4, 0, "Circuitly", 2);
  oledText(4, 3, "SSD1306 over I2C", 1);
  Serial.println("OLED ready");
}

void loop() {
  char line[24];
  snprintf(line, sizeof(line), "uptime: %lu s", millis() / 1000);
  oledText(4, 5, line, 1);
  snprintf(line, sizeof(line), "frames: %d   ", counter++);
  oledText(4, 6, line, 1);
  delay(500);
}

Ce tutoriel se réalise dans le simulateur Circuitly : le montage et le code sont vérifiés automatiquement à chaque étape.

Tutoriels suivants