Probleme ecran Oled

Bonjour à tous,

Je me retrouve bloqué dans mon projet et je ne comprends pas pourquoi il ne fonctionne pas. Je m'explique : je veux, pour un projet, enregistrer une pression sur une carte SD avec un écran OLED. Le programme fonctionnait parfaitement avec un écran LCD I2C, j'ai simplement adapté le code pour un écran OLED. Cependant, mon problème est que depuis, je perds la communication avec l'écran.

J'ai déjà testé séparément la carte SD et l'écran, et les deux fonctionnent bien. Les câblages sont corrects, et j'ai vérifié les adresses I2C, elles remontent bien. Mais lorsque je les assemble, rien ne fonctionne. Je ne comprends pas d'où vient le problème. Ci-dessous, le code complet.

 #include <Wire.h>  // Inclusion de la bibliothèque Wire pour la communication I2C
#include <Adafruit_GFX.h>  // Inclusion de la bibliothèque Adafruit_GFX pour les graphiques (affichage sur OLED)
#include <Adafruit_SSD1306.h>  // Inclusion de la bibliothèque Adafruit_SSD1306 pour l'écran OLED SSD1306
#include <RTClib.h>  // Inclusion de la bibliothèque RTClib pour gérer le module RTC
#include <SD.h>  // Inclusion de la bibliothèque SD pour interagir avec la carte SD
#include "logo_cegelec.h"  // Inclusion du fichier contenant le logo Cegelec (si utilisé)

#define SCREEN_WIDTH 128  // Largeur de l'écran OLED (en pixels)
#define SCREEN_HEIGHT 64  // Hauteur de l'écran OLED (en pixels)
#define PRESSURE_SENSOR A0  // Pin du capteur de pression (sur la pin A0 de l'Arduino)
#define SD_CS 10  // Pin CS (Chip Select) de la carte SD (ici sur la pin 10)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);  // Création d'un objet display pour l'écran OLED sans pin RESET
RTC_DS1307 rtc;  // Création d'un objet rtc pour gérer l'horloge RTC

float V, P;  // Variables pour stocker la tension et la pression
File dataFile;  // Variable pour gérer le fichier sur la carte SD

void setup() {
  Serial.begin(9600);  // Initialisation de la communication série à 9600 bauds
  pinMode(PRESSURE_SENSOR, INPUT);  // Définition de la pin du capteur de pression comme entrée

  // Initialisation de l'écran OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Vérifie si l'écran OLED s'initialise correctement (adresse 0x3C)
    Serial.println(F("Échec de l'initialisation de l'écran OLED"));
    while (true);  // Arrête le programme en cas d'échec
  }

  // Initialisation du module RTC
  if (!rtc.begin()) {
    Serial.println("Échec de l'initialisation du RTC");
    while (true);  // Arrête le programme en cas d'échec
  }

  // Vérifier l'heure du RTC et la régler si nécessaire
  if (!rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  // Réglage de l'heure et de la date avec la date de compilation du programme
  }

  // Initialisation de la carte SD
  if (!SD.begin(SD_CS)) {  // Vérifie si la carte SD est bien initialisée
    Serial.println("Erreur d'initialisation de la carte SD !");
    while (true);  // Arrête le programme en cas d'échec
  }
  Serial.println("Carte SD initialisée");

  // Créer un fichier et écrire des données d'entête
  dataFile = SD.open("data.csv", FILE_WRITE);  // Ouvre (ou crée) un fichier CSV sur la carte SD en mode écriture
  if (dataFile) {
    dataFile.println("Date,Time,Tension (V),Pression (bar)");  // Ajoute des entêtes de colonnes
    dataFile.close();  // Ferme le fichier après l'écriture
  } else {
    Serial.println("Erreur d'ouverture du fichier !");
    while (true);  // Arrête le programme si l'ouverture du fichier échoue
  }

  // Initialisation de l'écran OLED pour l'affichage
  display.clearDisplay();  // Efface l'écran OLED
  display.setTextSize(1);  // Définit la taille du texte sur l'écran OLED
  display.setTextColor(SSD1306_WHITE);  // Définit la couleur du texte (blanc)
}

void loop() {
  DateTime now = rtc.now();  // Obtenez l'heure et la date actuelles du RTC

  // Lecture et conversion de la tension du capteur de pression
  V = analogRead(PRESSURE_SENSOR) * (4.5 - 0.05) / 1024.0 + 0.05;  // Lecture de la tension et conversion en volts
  P = max((V - 0.493) * 10.0 / 0.9, 0.0);  // Calcul de la pression en bar en fonction de la tension

  // Affichage de la date, de l'heure et de la pression sur l'écran OLED
  display.clearDisplay();  // Efface l'écran pour mettre à jour les données

  // Affichage de la date
  display.setTextSize(1);  // Définit la taille du texte
  display.setCursor(0, 0);  // Position du curseur à la première ligne
  display.print("Date: ");
  display.print(now.year(), DEC);
  display.print('/');
  display.print(now.month(), DEC);
  display.print('/');
  display.print(now.day(), DEC);

  // Affichage de l'heure
  display.setCursor(0, 10);  // Position du curseur à la deuxième ligne
  display.print("Time: ");
  display.print(now.hour(), DEC);
  display.print(':');
  display.print(now.minute(), DEC);
  display.print(':');
  display.print(now.second(), DEC);

  // Affichage de la pression
  display.setCursor(0, 30);  // Position du curseur à la troisième ligne
  display.print("Pression: ");
  display.print(P, 1);  // Affiche la pression avec une décimale
  display.print(" bar");

  display.display();  // Actualisation de l'affichage

  // Enregistrement des données dans la carte SD
  dataFile = SD.open("data.csv", FILE_WRITE);  // Ouvre le fichier en mode écriture
  if (dataFile) {
    // Enregistre la date, l'heure, la tension et la pression dans le fichier CSV
    dataFile.print(now.year(), DEC);
    dataFile.print('/');
    dataFile.print(now.month(), DEC);
    dataFile.print('/');
    dataFile.print(now.day(), DEC);
    dataFile.print(",");
    dataFile.print(now.hour(), DEC);
    dataFile.print(":");
    dataFile.print(now.minute(), DEC);
    dataFile.print(":");
    dataFile.print(now.second(), DEC);
    dataFile.print(",");
    dataFile.print(V, 3);  // Enregistrement de la tension avec 3 décimales
    dataFile.print(",");
    dataFile.print(P, 1);  // Enregistrement de la pression avec 1 décimale
    dataFile.println();    // Ajoute une nouvelle ligne après chaque enregistrement
    dataFile.close();      // Ferme le fichier après l'écriture
    Serial.println("Données enregistrées sur la carte SD");
  } else {
    Serial.println("Erreur lors de l'écriture sur la carte SD");
  }

  // Affichage sur le moniteur série
  Serial.print("Tension : ");
  Serial.print(V, 3);  // Affiche la tension avec 3 décimales
  Serial.println("V");

  Serial.print("Pression : ");
  Serial.print(P, 1);  // Affiche la pression avec 1 décimale
  Serial.println(" bar");
  Serial.println();

  delay(1000);  // Attendre 1 seconde avant de recommencer le loop
}

La librarie Adafruit_SSD1306 à besoin de stocker localement le contenu de l'image. Pour cela elle crée un buffer de la taille de l'écran, cela occupe 1024 octets (50% de la mémoire d'un ATmega328).
La librairie SD à besoin d'un buffer pour stocker un secteur de la carte SD. Cela occupe 512 octets.
Si on ajoute à cela les ressources mémoire nécessaires au fonctionnement des librairies et de ton programme, il ne doit pas rester grand chose pour faire tourner le programme.

Bonjour, merci pour la piste.

J’ai déjà vu des projets sur Internet avec des enregistreurs SD et un écran pour du relevé de température, et ils semblent fonctionner. Est-ce que ma mémoire est trop juste ? Est-ce que cela pourrait expliquer mes problèmes ?

Quand je charge le projet, il m’indique que j’ai encore de la place, enfin si c’est bien de ça qu’on parle :

Le croquis utilise 26 912 octets (87%) de l’espace de stockage de programmes. Le maximum est de 30 720 octets.
Les variables globales utilisent 1 517 octets (74%) de mémoire dynamique, ce qui laisse 531 octets pour les variables locales. Le maximum est de 2 048 octets.

A quoi il faut ajouter le buffer utilisé par la librairie Adafruit_SSD1306 qui est créé lorsqu'on appelle display.begin().
Tu devrais avoir un message "Échec de l'initialisation de l'écran OLED" dans la console au démarrage.

Oui, j'ai bien un échec de l'initialisation de l'écran OLED. Donc, si je comprends bien, j'ai un problème de mémoire, ce qui fait que mon projet ne fonctionnera jamais. J'ai vu qu'on pouvait utiliser une autre bibliothèque, la "SSD1306Ascii", mais du coup, il n'y aurait plus de logo, donc moins fun.

Exactement.

Une autre solution serait de partir sur un CPU avec un peu plus de mémoire.

Le but des modifications du projet était de compacter les composants dans la boîte de dérivation, et donc je trouve ça dommage de gagner de la place avec l'écran, mais de la reperdre avec un Arduino plus gros, surtout que je ne sais même pas lequel il me faut. En gros, en conclusion, c’est soit j’oublie le logo, je reprogramme et j’espère que ça marche, soit je m’oriente vers un ESP32 et je dois tout reconfigurer

Un CPU avec plus de mémoire ne veut pas dire une carte plus volumineuse.
Il y a des petites cartes avec des CPU récents.
Regarde par exemple la famille Xiao de SeeedStudio.
Il y a des cartes à base d'ESP32, de RP2040 ou nRF52840 tous supportés par l'IDE Arduino.
Et il n'est pas dit que cela nécessite de tout casser. De nombreuses librairies sont maintenant multi-plateformes.

Bonjour
il est possible d'afficher des logos sans bibliothèques encombrantes.

avec twioled et pixoled

codes exemples avec affichage de mon aigle en logo
j'ai aussi ajouté la possibilité d'afficher des textes en flash ce qui libére encore plus la mémoire !

c'est extrait de Music box il y a donc des trucs a virer !....

mais on peut s'en inspirer comme dans la fonction affichage()

// "TwiOled.h" minimal transfer lib using AVR TWI on AVR 328 17611
//dans pp  #include "TwiOled.h"  SetupTwiOled();
//#include <avr/io.h>

#define Adr 0x78  //(0x3C*2)
void SetupTwiOled() {
  TWSR = 1;  //0 400kHz 1-160k 2 40k
  TWBR = 0x0C; // bitrate
  TWCR = (1 << TWEN); // autres bits à 0
}

void  Start () {
  TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // start
  while (!(TWCR & (1 << TWINT))) {}
}

void  Stop () {
  TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // stop
  for (volatile int i = 0; i < 20; i++) ;
}

void  Write (byte ab) {  // addr8 ou data8
  TWDR = ab;
  TWCR = (1 << TWINT) | (1 << TWEN);
  while (!(TWCR & (1 << TWINT))) {}
  //  status= TWSR & 0xF8;  // Ack bit
}

byte TwReadAck () {
  TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
  while (!(TWCR & (1 << TWINT))) {}
  return (TWDR);
}
byte TwReadNack () {
  TWCR = (1 << TWINT) | (1 << TWEN);
  while (!(TWCR & (1 << TWINT))) {}
  return (TWDR);
}

//PixOled.h //  190317 11h  référence
// Gencar, text et dot
// NumOled pour OledPix fonctions  Dec9999 BigDec
// Ping.h pour fonctions raq et ball

//  dans pp #include "OledPix.h"   SetupOledPix();
//===============
#include <avr/pgmspace.h>

const uint8_t taNum[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, // space !
  0x03, 0x00, 0x03, 0x00, 0x70, 0x2e, 0x74, 0x0e, // " #
  0x2c, 0x52, 0xff, 0x34, 0x43, 0x33, 0x6c, 0x63, // $ %
  0x66, 0x59, 0x19, 0x26, 0x00, 0x04, 0x03, 0x00, // & '
  0x1c, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1c, // ( )
  0x2a, 0x1c, 0x1c, 0x2a, 0x08, 0x3e, 0x08, 0x08, // * +
  0x00, 0xa0, 0x60, 0x00, 0x08, 0x08, 0x08, 0x08, // , -
  0x00, 0x60, 0x60, 0x00, 0x03, 0x0c, 0x30, 0xc0, // . /

  0x3e, 0x41, 0x41, 0x3e, 0x04, 0x02, 0x7f, 0x00, // 0 1
  0x62, 0x51, 0x49, 0x46, 0x22, 0x41, 0x49, 0x36, // 2 3
  0x1c, 0x12, 0x79, 0x10, 0x2f, 0x49, 0x49, 0x31, // 4 5
  0x36, 0x49, 0x49, 0x31, 0x41, 0x31, 0x0d, 0x03, // 6 7
  0x36, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x3e, // 8 9
  0x00, 0x36, 0x36, 0x00, 0x00, 0xd6, 0x76, 0x00, // : ;
  0x08, 0x14, 0x22, 0x41, 0x24, 0x24, 0x24, 0x24, // < =
  0x41, 0x22, 0x14, 0x08, 0x02, 0xc1, 0xd9, 0x06
}; // > ?
const uint8_t taMaj[] PROGMEM = {
  0x32, 0x49, 0x71, 0x41, 0x3e, 0x7e, 0x11, 0x11, 0x11, 0x7e, // @ A
  0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e, 0x41, 0x41, 0x41, 0x22, // B C
  0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x41, 0x41, // D,E
  0x7f, 0x09, 0x09, 0x01, 0x01, // F
  0x3e, 0x41, 0x49, 0x49, 0x3a, 0x7f, 0x08, 0x08, 0x08, 0x7f, // G,H
  0x00, 0x00, 0x7f, 0x00, 0x00, 0x21, 0x41, 0x41, 0x41, 0x3f, // I,J
  0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40, // K,L
  0x7f, 0x02, 0x04, 0x02, 0x7f, 0x7f, 0x04, 0x08, 0x10, 0x7f, // M,N
  0x3e, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x11, 0x11, 0x11, 0x0e, // O,P
  0x3e, 0x41, 0x49, 0x51, 0x7e, 0x7f, 0x09, 0x11, 0x29, 0x46, // Q,R
  0x46, 0x49, 0x49, 0x49, 0x32, 0x01, 0x01, 0x7f, 0x01, 0x01, // S,T
  0x3f, 0x40, 0x40, 0x40, 0x3f, 0x07, 0x18, 0x60, 0x18, 0x07, // U,V
  0x1f, 0x60, 0x1e, 0x60, 0x1f, 0x63, 0x14, 0x08, 0x14, 0x63, // W,X
  0x07, 0x04, 0x78, 0x04, 0x07, 0x61, 0x51, 0x49, 0x45, 0x43, // Y,Z
  0x00, 0x7f, 0x41, 0x41, 0x00, 0x03, 0x06, 0x1c, 0x30, 0x60, /* [ \ */
  0x00, 0x41, 0x41, 0x7f, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ] ^
  0x80, 0x80, 0x80, 0x80, 0x80
}; // _

const uint8_t taMin [] PROGMEM = {
  0x00, 0x03, 0x06, 0x00, 0x20, 0x54, 0x54, 0x78, // ` a 0x38,0x44,0x44,0x7C,
  0x7f, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x28, // b c
  0x38, 0x44, 0x44, 0x7f, 0x38, 0x54, 0x54, 0x58, // d e
  0x00, 0xfe, 0x09, 0x08, 0x98, 0xa4, 0xa4, 0x78, // f g
  0x7f, 0x04, 0x04, 0x78, 0x00, 0x7d, 0x00, 0x00, // h i
  0x40, 0x80, 0x80, 0x7d, 0x7e, 0x10, 0x28, 0x44, // j k
  0x00, 0x3f, 0x40, 0x00, 0x7c, 0x08, 0x08, 0x7c, // l m
  0x7c, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x38, // n o
  0xfc, 0x24, 0x24, 0x18, 0x38, 0x44, 0x44, 0xf8, // p q
  0x7c, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x24, // r s
  0x04, 0x7f, 0x44, 0x04, 0x3c, 0x40, 0x40, 0x3c, // t u
  0x1c, 0x60, 0x60, 0x1c, 0x5c, 0x20, 0x20, 0x5c, // v w
  0x64, 0x18, 0x18, 0x64, 0x1c, 0x20, 0xA0, 0x7c, // x y
  0x64, 0x54, 0x4C, 0x44, 0x08, 0x08, 0x36, 0x41, // z {
  0x00, 0x00, 0xff, 0x00, 0x41, 0x36, 0x08, 0x08, // | }
  0x10, 0x20, 0x10, 0x20, 0xff, 0xff, 0xff, 0xff
}; // ~ del


const uint8_t eagle1[] PROGMEM = {0, 1, 3, 31, 126, 254, 254, 252, 252, 248, 248, 248, 240, 240, \
                                  224, 192, 0, 0, 0, 0, 0, 0, 128, 192, 192, 192, 128, 0, 0, 0, 0, 192, \
                                  224, 240, 240, 248, 248, 248, 252, 252, 254, 254, 126, 31, 3, 1, 0
                                 };
const uint8_t eagle2[] PROGMEM = {0, 0, 0, 0, 0, 0, 31, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
                                  143, 0, 128, 198, 227, 243, 255, 255, 255, 255, 255, 198, 128, 0, \
                                  143, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 0, 0, 0, 0, 0, 0
                                 };
const uint8_t eagle3[] PROGMEM = {4, 60, 248, 224, 192, 128, 128, 3, 7, 15, 63, 63, 127, 127, 127, 255, \
                                  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
                                  255, 255, 127, 127, 127, 63, 63, 15, 7, 3, 128, 128, 192, 224, 248, 60, 4
                                 };
const uint8_t eagle4[] PROGMEM = {0, 0, 1, 15, 31, 63, 127, 255, 252, 252, 248, 240, 112, 120, 124, 126, \
                                  127, 63, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 191, 63, 127, \
                                  126, 124, 120, 112, 240, 248, 252, 252, 255, 127, 63, 31, 15, 1, 0, 0
                                 };
const uint8_t eagle5[] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 15, 31, 31, 30, 124, 242, 143, 63, 31, 63, \
                                  63, 127, 63, 127, 63, 63, 31, 63, 143, 242, 124, 30, 31, 31, 15, 3, 3, 3
                                  , 0, 0, 0, 0, 0, 0, 0, 0
                                 };

// chaine OLED

const char ProgName[] PROGMEM = " *-*  MUSIC BOX  *-* ";
const char PasdeCarte[] PROGMEM = "Erreur carte absente !";
const char ErreurCarte[] PROGMEM = "Erreur lecture carte !";



extern char Titre_melody[17];
extern char Auteur_melody[17];
extern uint8_t tempo;
extern uint16_t nombre_notes;
//xxxxxxxxxxxxxxxxxxxxxx

// Initialisation et fonctions de base
void  Clear();
byte taInitOled[] = { 0xae, 0xd5, 0x80, 0xa8, 63, \
                      0xD3, 0x0, 0x40, 0x8d, 0x14, 0x20, 0x00, 0xa1, \
                      0xc8, 0xDA, 0x12, 0x81, 0xcf, 0xd9, 0xf1, 0xdb, \
                      0x40, 0xa4, 0xa6, 0x2e, 0xaf
                    };
void  WrStaData () {
  Start(); Write (Adr); Write(0x40);
}
void  SetupPixOled () {
  for (byte i = 0; i < sizeof (taInitOled); i++) {
    Start(); Write (Adr); Write(1);
    Write (taInitOled[i]); Stop();
    WrStaData(); Stop();
  }
  Clear();
}
void  WrStaCom () {
  Start(); Write (Adr); Write(0);
}
void  Cmd (byte cc) {
  WrStaCom (); Write (cc); Stop();
}
byte taIniTr[] = {Adr, 0, 0x21, 0x0, 0x7f, 0x22, 0x0, 0x7F};
void  IniTransfert () {
  for (byte i = 0; i < sizeof (taIniTr); i++) {
    WrStaCom ();
    Write (taIniTr[i]); Stop();
  }
}
byte saveLi, saveCol;
void  SetLine (int8_t cc) {
  saveLi = cc;
  cc--; if (cc < 0) {
    cc = 7;
  }
  WrStaCom (); Write (0x22);
  Write (cc); Write (7); Stop();
}
void  SetCol (byte cc) {
  WrStaCom (); Write (0x21);
  Write (cc); Write (127); Stop();
  saveCol = cc;
}
void  LiCol (byte li, byte co) {
  SetLine (li); SetCol (co);
  //  ptMap = (128*saveLi)+saveCol;
}
void  Clear() {  //nn<128x8=1024
  IniTransfert();
  WrStaData();
  for (int i = 0; i < 1024; i++) {
    Write (0);
  }
  Stop();
}
void  ClearBas() {
  LiCol (2, 0);
  WrStaData();
  for (int i = 0; i < 768; i++) {
    Write (0);
  }
  Stop();
}

void  Trait(byte col, int val) {
  LiCol (col, 75);
  WrStaData();
  for (int i = 0; i < 40; i++) {
    if (i < val) {
      Write (28);
    } else {
      Write (0);
    };
  }
  Stop();
}

#define  Sprite(tt) \
  WrStaData(); \
  for (byte i=0; i<sizeof tt; i++) { \
    Write (pgm_read_byte(&tt[i])); } Stop()
#define MySprite(tt) \
  WrStaData(); \
  for (byte i=0; i<sizeof tt; i++) { \
    Write (tt[i]); } Write(0); Stop();

//xxxxxxxxxxxxxxxxxxxxxxxxxx

void DoubleH () {
  Cmd (0xda);
  Cmd (0x02);
}
void SimpleH () {
  Cmd (0xda);
  Cmd (0x12);
}

void Car(char cc) {
  cc &= 0x7F;
  switch (cc / 32) {
    case 0:
      if (cc == 13) {
        SetLine(saveLi + 1);  // saut de ligne
        SetCol(0);
      }
      //else Error();
      break;
    case 1:  // codes 32-
      Start(); Write (Adr); Write (0x40);
      for (byte i = 0; i < 4; i++)
      {
        Write (pgm_read_byte(&taNum[((cc - 32) * 4) + i]));
      }
      Write (0); Stop();
      break;
    case 2:  // codes 64-
      Start(); Write (Adr); Write (0x40);
      for (byte i = 0; i < 5; i++)
      {
        Write (pgm_read_byte(&taMaj[((cc - 64) * 5) + i]));
      }
      Write (0); Stop();
      break;
    case 3:  //codes 96-
      Start(); Write (Adr); Write (0x40);
      for (byte i = 0; i < 4; i++)
      {
        Write (pgm_read_byte(&taMin[((cc - 96) * 4) + i]));
      }
      Write (0); Stop();
      break;
  }  // end switch
}

void Text(const char str[]) {
  for (byte i = 0; i < strlen(str); i++) {
    Car(str[i]);
  }
}



void TextFlash(const char * message) {
  while (pgm_read_byte(message)) {
    Car(pgm_read_byte(message++));
  }
}




//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//\prog: "OledGraPix.h" 170426
void Dot(byte xx, byte yy) { // yy 0-64 --> 0-7
  LiCol(yy / 8, xx);
  WrStaData (); Write (1 << yy % 8); Stop();
}
//ddot  2points superposés si (yy/8!=7)
// si =7 il faut agit sur le bit0 de la ligne suiv si !=7
void DDot(byte xx, byte yy) { // yy0-64 --> 0-7
  byte tmp = (1 << yy % 8);
  if (yy % 8 != 7) tmp += (1 << (yy % 8 + 1));
  LiCol(yy / 8, xx);
  WrStaData (); Write (tmp); Stop();
}

void Hline (byte yy) {
  for (byte i = 0; i < 128; i++) {
    Dot(i, yy);
  }
}
void Vline (byte xx) {
  for (byte i = 0; i < 8; i++) {
    LiCol (i, xx);
    WrStaData (); Write (0xFF); Stop();
  }
}
#define vLine Vline
#define hLine Hline
void afficheTitre ()
{
  LiCol (3, 24);
  for (byte i = 0; i < 15; i++) {
    Car(Titre_melody[i]);
  }
  LiCol (5, 24);
  for (byte i = 0; i < 15; i++) {
    Car(Auteur_melody[i]);
  }

  char snum[5];
  itoa(tempo, snum, 10);

  LiCol (7, 6); Text("Tempo : "); LiCol (7, 45); Text(snum);
  itoa(nombre_notes, snum, 10);
  LiCol (7, 70); Text("Notes : "); LiCol (7, 110); Text(snum);
}
void splash() {
  Clear();
  LiCol (0, 9); TextFlash(ProgName);
  Hline(12);
  LiCol(2, 29); TextFlash(Version);
  LiCol (3, 41); Sprite(eagle1);
  LiCol (4, 41); Sprite(eagle2);
  LiCol (5, 41); Sprite(eagle3);
  LiCol (6, 41); Sprite(eagle4);
  LiCol (7, 41); Sprite(eagle5);
  LiCol (7, 5); TextFlash(Copy);
  LiCol (7, 100); TextFlash(Annee);
  delay(500);
}

void erreurcarte () {
  ClearBas();
  LiCol (5, 5); TextFlash(PasdeCarte);
}