Crash carte Arduino Uno

Bonjour,
Je rencontre un problème avec mon montage qui comprend une carte Arduino Uno R3, une matrice led 328, un module RTC, un écran OLED 12864, 2 boutons poussoir, un encodeur numérique un buzzer et un capteur ultrasons. Effectivement lorsque je met la partie de mon code concernant l'affichage de la mémoire EEPROM (ligne 257 à 261) et que je téléverse, tout se passe bien mais une fois le téléversement terminé, la carte Arduino crash totalement et plus rien ne fonctionne, sauf le buzzer qui se met à faire du bruit en continu alors que dans le code il n'a jamais été spécifié de s'allumer !
Si vous avez une idée du problème je suis preneur ce problème me bloque totalement...
Voici mon code :

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <MsTimer2.h>
#include <RTClib.h>
#include <LedControl.h>
#include <Encoder.h>
#include <EEPROM.h>

RTC_DS3231 RTC;
LedControl matrice = LedControl(8, 10, 9, 4);  // Pins DIN, CLK, CS, et nb matrices
Encoder monEncodeur(2, 3); // pins A et B de l'encodeur

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//======================================================================================================================================================================
const int pinLED = 13;
const int trigPin = 12;
const int echoPin = 11;
const int buzPin = 6;

int REVEIL = 0;
bool state = LOW;
int i = 0;

const int boutonEncodeurPin = 4;
int modeReglage = 0;
bool boutonPresse = false;

const int buttonPin = 5;
const int buttonMenu = 7;
bool button = false;
int modeMenu = 0;

int reveilHeure = 0;
int reveilMinute = 0;
bool reveilActive = false;

int dizaineHeure, uniteHeure, dizaineMinute, uniteMinute;

int ajustementHeure = 0;
int ajustementMinutes = 0;

bool format = false; // false 24h, true 12h

const int EEPROM_RECORD_SIZE = 2;
//======================================================================================================================================================================
void clignoterLED() {
  static bool etatLED = false; // Variable pour suivre l'état de la LED
  // Inverser l'état de la LED
  etatLED = !etatLED;
  // Mettre à jour l'état de la LED
  digitalWrite(pinLED, etatLED);
}
//======================================================================================================================================================================
void enregistrerDansEEPROM(unsigned int difference) {
  int adresseEEPROM = 0;  // Adresse de départ dans la mémoire EEPROM

  // Parcourez les enregistrements existants pour trouver une adresse non utilisée
  while (EEPROM.read(adresseEEPROM) != 255 && EEPROM.read(adresseEEPROM + 1) != 255) {
    adresseEEPROM += EEPROM_RECORD_SIZE;
    if (adresseEEPROM >= EEPROM.length()) {
      // Si la mémoire est pleine, retournez au début
      adresseEEPROM = 0;
    }
  }

  // Enregistrez la différence dans la mémoire EEPROM
  EEPROM.write(adresseEEPROM, difference >> 8);    // Octet de poids fort
  EEPROM.write(adresseEEPROM + 1, difference & 0xFF);  // Octet de poids faible
}
//======================================================================================================================================================================
void setup() {
  Serial.begin(9600);
  for(int i = 0;i<4;i++) matrice.shutdown(i, false);
  for(int i = 0;i<4;i++) matrice.setIntensity(i, 2);
  for(int i = 0;i<4;i++) matrice.clearDisplay(i);

  RTC.begin();

  pinMode(pinLED, OUTPUT);
  MsTimer2::set(1000, clignoterLED);
  MsTimer2::start();

  pinMode(buttonPin, INPUT);
  pinMode(buttonMenu, INPUT);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3D);

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(buzPin, OUTPUT);
}
//======================================================================================================================================================================
void loop(){
  unsigned long startTime = 0;
  unsigned long stopTime = 0;
  digitalWrite(buzPin, LOW);
  
  DateTime now = RTC.now();

  if (digitalRead(boutonEncodeurPin) == LOW) {
    boutonPresse = true;
    modeReglage++;
    delay(140);
  }
  if (boutonPresse) {
    int positionEncodeur = monEncodeur.read();
    if (modeReglage == 1) {
      ajustementHeure = positionEncodeur;
    } else if (modeReglage == 2){
      ajustementMinutes = positionEncodeur;
    } else if(modeReglage > 2){
      modeReglage = 0;
      boutonPresse = false;
    }
  }
  afficherHeure(now + TimeSpan(0, ajustementHeure, ajustementMinutes, 0));

  menu();

  while(REVEIL == 1 && reveilActive){
    if (startTime == 0) {
      startTime = millis();
    }
    float distance = mesureDistance();
    if(i == 45){state = !state;i = 0;}
    i++;
    digitalWrite(buzPin, state);
    if (distance <= 7.000 || millis() - startTime > 20000) {
      stopTime = millis();
      int dif = stopTime - startTime;
      enregistrerDansEEPROM(dif);
      reveilActive = false;
    }
  }
}
//======================================================================================================================================================================
void afficherHeure(DateTime currentTime) {
  if (format == false) {
    dizaineHeure = (currentTime.hour() / 10);
    uniteHeure = (currentTime.hour() % 10);
  } else {
    // 12h format
    int heure12 = currentTime.hour() % 12;
    dizaineHeure = (heure12 / 10);
    uniteHeure = (heure12 % 10);
  }
  dizaineMinute = (currentTime.minute() / 10);
  uniteMinute = (currentTime.minute() % 10);
  afficher(dizaineHeure, 3);
  afficher(uniteHeure, 2);
  afficher(dizaineMinute, 1);
  afficher(uniteMinute, 0);
}
//======================================================================================================================================================================
void menu(){
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  if(digitalRead(buttonMenu)==HIGH){
    modeMenu++;
    delay(140);
  }
  if(modeMenu > 3){
    modeMenu = 0;
  }
  if(modeMenu == 0){
    display.setCursor(5 , 20);
    display.println(">");
  } else if(modeMenu == 1){
    display.setCursor(5 , 30);
    display.println(">");
  } else if(modeMenu == 2){
    display.setCursor(5 , 40);
    display.println(">");
  } else if(modeMenu == 3){
    display.setCursor(5 , 50);
    display.println(">");
  }
  if(digitalRead(buttonPin)==HIGH){
    button = true;
    delay(140);
  }
  //=================================================
  if(button && modeMenu == 0){
    //option1
    while (true) {
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(0, 10);
      display.println("--Reveil--");
      display.setTextSize(1);
      if (digitalRead(boutonEncodeurPin) == LOW) {
        modeReglage++;
        delay(140);
      }
      int positionEncodeur = monEncodeur.read();
      if (modeReglage == 1) {
        if(!format){
          reveilHeure = constrain(positionEncodeur, 0, 23);
        } else {
          reveilHeure = constrain(positionEncodeur, 0, 12);
        }
      } else if (modeReglage == 2) {
        reveilMinute = constrain(positionEncodeur, 0, 59);
      } else if (modeReglage > 2) {
        modeReglage = 0;
      }
      // Afficher l'heure de réveil en cours de réglage
      display.setCursor(30, 30);
      display.print("Heure: ");
      display.print(reveilHeure);
      display.setCursor(30, 40);
      display.print("Minutes: ");
      display.print(reveilMinute);
      display.display();
      if (digitalRead(buttonPin) == HIGH) {
        button = false;
        delay(140);
        break;
      }
    }
  }
  //=================================================
  if(button && modeMenu == 1){
    //option2
    reveilActive = !reveilActive;
    button = false;
    delay(140);
  }
  if (reveilActive){
    display.drawLine(100, 1, 127, 1, SSD1306_WHITE);
    display.drawLine(103, 3, 124, 3, SSD1306_WHITE);
    display.drawLine(106, 5, 121, 5, SSD1306_WHITE);
    display.drawLine(109, 7, 118, 7, SSD1306_WHITE);
    display.drawLine(112, 9, 115, 9, SSD1306_WHITE);
    REVEIL = comparateur();
  }
  //=================================================
  if(button && modeMenu == 2){
    //option3
    format = !format;
    button = false;
    delay(140);
  }
  //=================================================
  if(button && modeMenu == 3){
    //option1
    while (true) {
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(5, 10);
      display.println("-Memoire-");
      display.setTextSize(1);
      display.setCursor(5, 20);
      /*for (int adresse = 0; adresse > 4; adresse++) {
        byte valeur = EEPROM.read(adresse);
        display.print("Temps : ");
        display.println(valeur);
      }*/
      display.display();
      if(digitalRead(buttonMenu)==HIGH){
        for (int adresse = 0; adresse < EEPROM.length(); adresse++) {
          EEPROM.write(adresse, 0xFF);
        }
      }
      if (digitalRead(buttonPin) == HIGH) {
        button = false;
        delay(140);
        break;
      }
    }
  }
  //=================================================
  display.setTextSize(2);
  display.setCursor(30, 0);
  display.println("MENU");
  display.setTextSize(1);
  display.setCursor(25 , 20);
  display.println("Reglage reveil");
  display.setCursor(25 , 30);
  display.println("Activer reveil");
  display.setCursor(25 , 40);
  if (!format){
    display.println("Format 24h");
  } else {
    display.println("Format 12h");
  }
  display.setCursor(25 , 50);
  display.println("Memoire");
  display.display();
}
//======================================================================================================================================================================
void afficher(int numero, int nMatrix){
  byte chiffres[10][8] = {
    {B01111110,B01000010,B01000010,B01000010,B01000010,B01000010,B01000010,B01111110}, // 0
    {B00001000,B00001000,B00001000,B00001000,B00001000,B00001000,B00001000,B00001000}, // 1
    {B01111110,B00000010,B00000010,B01111110,B01000000,B01000000,B01000000,B01111110}, // 2
    {B01111110,B00000010,B00000010,B00111110,B00000010,B00000010,B00000010,B01111110}, // 3
    {B01000010,B01000010,B01000010,B01111110,B00000010,B00000010,B00000010,B00000010}, // 4
    {B01111110,B01000000,B01000000,B01111110,B00000010,B00000010,B00000010,B01111110}, // 5
    {B01111110,B01000000,B01000000,B01111110,B01000010,B01000010,B01000010,B01111110}, // 6
    {B01111110,B00000010,B00000010,B00000010,B00000010,B00000010,B00000010,B00000010}, // 7
    {B01111110,B01000010,B01000010,B01111110,B01000010,B01000010,B01000010,B01111110}, // 8
    {B01111110,B01000010,B01000010,B01111110,B00000010,B00000010,B00000010,B01111110}  // 9
  };
  // Vérifier si le numéro est dans la plage de 0 à 9
  if (numero >= 0 && numero <= 9) {
    // Afficher le chiffre correspondant sur la matrice spécifiée
    for (int i = 0; i < 8; i++){
      matrice.setRow(nMatrix, i, chiffres[numero][i]);
    }
  }
}
//======================================================================================================================================================================
int comparateur(){
  int dizaineHeureR, uniteHeureR, dizaineMinuteR, uniteMinuteR;
  dizaineHeureR = (reveilHeure / 10);
  uniteHeureR = (reveilHeure % 10);
  dizaineMinuteR = (reveilMinute / 10);
  uniteMinuteR = (reveilMinute % 10);
  if (dizaineHeureR == dizaineHeure && uniteHeureR == uniteHeure && dizaineMinuteR == dizaineMinute && uniteMinuteR == uniteMinute){
    return 1;
  } else {
    return 0;
  }
}
//======================================================================================================================================================================
float mesureDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  return duration * 0.034 / 2;
}

Il y a deux sources de non-fonctionnement possibles :

  • le programme
  • le câblage ou une consommation excessive.

Qui fournit l'alimentation à ce petit monde ?
Où sont les renseignements sur ce petit monde ?
Où est le schéma de câblage ?

Comment crois-tu que quelqu'un puisse répondre sans ces renseignements.

Et si tu lisais ces conseils ?

As-tu fait fonctionner tous les modules un par un pour être sûr que tu ne faisais pas d'erreur, ou as-tu tout testé en une seule fois, pensant gagner du temps. Si tu as choisi cette deuxième solution, tu as perdu.

La bonne démarche est de faire les exemples des bibliothèques, mais sur un module à la fois.
Une fois que tout est positif, on assemble.

Pour le schéma, un schéma papier, stylo, règle (un schéma avec des traits droits est plus facile à comprendre) nous convient parfaitement, inutile de passer par des logiciels spécialisés.
Tu as bien une imprimante avec un scanner ?
Sinon tu as un téléphone pour prendre des photos.
Tu joins le schéma a l'aide de l'icône "flèche vers le haut".

Merci pour vos conseils, j'ai résolu le problème (même si mon montage reste fragile, à tout moment je met un Sérial.println("test"); au mauvais endroit et mon montage plante). Pour répondre rapidement aux questions, tout est alimenté par la carte arduino branché sur un pc portable via USB, et j'ai bien essayé tous les modules 1 par 1. Étant donné que tout fonctionne pour le moment, je ne vais pas vous déranger plus longtemps !
Merci encore pour votre réactivité et je prends note des bonnes pratiques à avoir lorsque l'on pose une questions sur un forum (première fois pour moi).
:slight_smile:

C'est très probablement dû à un problème d'alimentation, le Uno ne supportant pas tous les appels de courant cumulés de tous les périphériques.
Utilise une alim 5V pour certains d'entre eux (au hasard le buzzer, la matrice de leds et l'écran) ça délestera l'Arduino et tu n'auras plus de plantages.

Ce genre de symptôme me fait plutôt penser à une occupation mémoire limite. Ne pas oublier que la librairie Adafruit_SSD1306 crée un buffer en mémoire avec un écran 128x64 cela consomme 1k de RAM.
Pour gagner de la RAM, il faudrait mettre les chaines de caractères constantes en Flash ainsi que le tableau chiffres. Cela permettrait de gagner une bonne centaine d'octets je pense.

Ok ça marche merci pour le conseil !

Ok je prends note merci, je pensais avoir assez de place étant donné qu'au téléversement il me disais que j'occupait 60% de l'espace de stockage et 40% de la mémoire dynamique, donc j'ai mis de côté votre hypothèse mais finalement c'est peut-être ça.

Sur la UNO, 1k c'est 50% de la mémoire RAM.
La librairie U8g2 permet de gérer ce type d'écran avec un buffer de taille réduite mais en contre-partie le tracé est un peu plus lent.
Il y a même une version U8x8 qui permet de travailler en texte seul sans aucun buffer.

Edit: pour compléter ma réponse.
Le buffer est alloué dynamiquement au démarrage du programme donc l'occupation mémoire reportée par le compilateur n'en tient pas compte. Donc pour qu'un code fonctionne avec cette librairie et cet écran il faut que le compilateur retourne une consommation de la mémoire inférieure à 40% environ.

D'accord je comprend mieux maintenant, merci beaucoup pour vos informations !

OUI.
Ci dessous l'extrait du code de la méthode begin() de Adafruit_SSD1306 :

  if ((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))

Ce qui donne 1136 bytes.

Il reste donc 60% de 2048 bytes : 1228 bytes
Si l'on retire 1136 bytes il reste réellement 92 bytes pour la pile.
C'est faible ...

Ah oui ok, bon bah je vais peut-être changer de librairie alors si la u8g2lib consomme moins, merci :+1:t2:

Il faut regarder le Wiki car il y a une nombre très important de constructeurs qui dépendent du driver d'écran, du type d'interface, du type de buffer. Le Wiki présente une liste relativement bien organisée.