Conflit afficheur LCD(I2C) et lecteur carte SD(MOSI/MISO)

Bonjour,

Je suis désolé si je fais des erreurs ou si il manque des informations, c'est mon premier poste et mon premier programme arduino. :grin:

Je travaille sur un projet d'arrosage automatique en perso. La carte Arduino UNO est équipé d'un afficheur LCD (I2C) , une horloge RTC, des capteurs (pression, humidité, niveau d'eau) et de relais.
Le programme doit dans un premier temps arroser une serre la nuit en fonction de l'humidité du sol et du niveau d'eau. Puis si ça fonctionne, il prendra en compte la pression atmosphérique et la température pour faire de l'arrosage à l'extérieur de la serre. Pour économiser l'électricité, 2 relais coupent l'alimentation des capteurs et de l'afficheur quand ils ne sont pas utilisés.

Jusque là tout va bien. J'ai rajouté un lecteur de carte SD (pin 4; 11;12;13) pour enregistrer les données des capteurs et les événements (arrosage et réinitialisation de la carte). Sauf qu'il ne fonctionne pas correctement lorsque je l'associe à mon programme.

La fonction EcrireCarteSD(char* NomFichier, char* Texte) me renvoie des erreurs d'ouverture de fichier sur le port série. Le problème semble venir de la fonction Afficher(). Si je mets en commentaire les lcd.print affichant la valeur de variables (exemple lcd.print(SaveJour2);), alors les écritures sur la carte SD fonctionnent. Afficher du texte (exemple lcd.print("Dernier arrosage :");) ou l'heure avec RTC (exemple lcd.print(myRTC.minutes);) sur l'afficheur LCD ne semblent pas poser de problème.

J'ai essayé d'utiliser des pointeurs pour afficher les valeurs ça n'a pas fonctionné non plus.
Si c'était un conflit entre I2C et MOSI/MISO ou les librairies, pourquoi l'affichage du texte et des valeurs de l'horloge RTC fonctionnent?

Résultat : je ne peux pas utiliser sur la même carte Arduino l'afficheur LCD et le lecteur de carte SD. Hors j'aimerai que la carte SD fonctionne pour brancher la pompe et tester mon programme en condition réelle.

Si vous avez des exemples de programme utilisant un afficheur LCD I2C et un lecteur de carte SD, je suis preneur. :star_struck:

Merci 'avance pour votre aide. :grinning:

/*
Programme d'arrosage automatique
13/05/2023

Note importante : Heure à changer à chaque téléversement

*/

// ------------------------------------------------------------------ 
// -------------------------- DECLARATIONS -------------------------- 
// ------------------------------------------------------------------

//BIBLIOTHEQUES ET OBJETS 
  //Général
    #include <Wire.h>
    #include <math.h>
    #include "SPI.h"

  //Afficheur
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27, 20, 4);  // I2C address 0x27, 20 column and 4 rows
    //LiquidCrystal_I2C lcd(0x3F,20,4);

  //Capteur BMP388 (capteur pression)
    //Altitude is calculated based on temperature and sea level pressure.
    #include "DFRobot_BMP388.h"
    #include "DFRobot_BMP388_I2C.h"
    #include "bmp3_defs.h"
    DFRobot_BMP388_I2C bmp388;  //Create a bmp388 object to communicate with I2C.

  //DS1302 (horloge RTC)
    #include <virtuabotixRTC.h>
    virtuabotixRTC myRTC(6, 7, 8); // Creation of the Real Time Clock Object

  //Carte SD
    #include <SD.h>
    File monfichier;
    



//VARIABLE GLOBALE
  //Commande
    volatile byte EtatBouton = LOW;       //Bouton poussoir
      
  //Capteurs
    float seaLevel;               //Paramétrage capteur de pression
    float CptHumi1;               //Valeur reelle Capteur humidité 1
    float CptHumi2;               //Valeur reelle Capteur humidité 2
    float CptPression;            //Valeur reelle capteur pression
    float CptTemperature;         //Valeur reelle capteur température
    byte CptNiveau;               //Valeur etat niveau 0:niveau atteint 1:niveau découvert

  //Arrosage
    //Mémoriser dernier arrosage
      //int SaveAnnee1; byte SaveMois1; byte SaveJour1; byte SaveHeure1; byte SaveMin1;    //Date et heure Arrosage 1
      int SaveAnnee2; byte SaveMois2; byte SaveJour2; byte SaveHeure2; byte SaveMin2;    //Date et heure Arrosage 2
      //float SaveHumi1;
      float SaveHumi2; 

    //Gestion du temps
      int CptMin;                   //Compteur minute pour palier arrosage
      int DernierMesureMin;         //Sauvegarde de la dernière mesure (en minute)
      int ProchainArrosage = 0;	    //Heure du prochain arrosage (minute) pour les paliers dans la période d'arrosage

    //Consigne
      float PalierArrosage = 0;     //Palier humidité (%) dans la période d'arrosage, ce palier est calculé en fonction de la première humidité mesurée

    //Indicateur
      byte NbArrosage = 1;          //nombre d'arrosage effectué dans la période
      int CPTarrosage1 = 0;         //Compteur nombre d'arrosage Pompe 1
      float CPTHarrosage1 = 0;      //Compteur temps d'arrosage heure Pompe 1
      int CPTarrosage2 = 0;         //Compteur nombre d'arrosage Pompe 2
      float CPTHarrosage2 = 0;      //Compteur temps d'arrosage heure Pompe 2
      float VolumeEau = 0;          //Volume d'eau utilisé

  
//CONSTANTE GLOBALE  
  //Définition des pins
    const byte PIN_POMPE_1 = 0;               //Pin activer pompe 2
    const byte PIN_BP_AFFICHE = 2;            //Pin pour le bouton poussoir permettant l'affichage des infos
    const byte PIN_ALIM_CAPTEUR = 3;          //Pin alimantation capteurs : Alimentation capteur humidité et capteur niveau
    const byte PIN_CHIP_SELECT = 4;           //Carte SD
    const byte PIN_ALIM_AFFICHEUR = 5;        //Pin alimentation afficheur
    const byte PIN_CAPT_NIVEAU = 9;           //Pin detection niveau
    const byte PIN_POMPE_2 = 10;              //Pin activer pompe 1
    const byte PIN_CAPT_HUM_1 = A0;           //Entrée analogique pour acpteur humidité intérieur
    const byte PIN_CAPT_HUM_2 = A1;           //Entrée analogique pour acpteur humidité intérieur  
    const byte PIN_VOYANT_NIVEAU = A2;        //Pin activant le voyant alerte niveau insuffisant 
    const byte PIN_VOYANT_VIE = A3;           //Pin activant le voyant de vie

  
//PARAMETRES
  //Définition seuil 
    const float SEUIL_ARROSAGE_HUM_CRITIQUE = 20;         //Arrosage en dessous de 20% d'humidité,ne tient pas compte de la pression et l'heure (en %)
    const float SEUIL_HUM_FIN_ARROSAGE_CRITIQUE = 40;     //L'arrosage s'arrête lorsqu'il atteint ce seuil  
    const float SEUIL_ARROSAGE_PRESSION = 1013;           //Arrosage si pression supérieur à cette valeur en hPa  
    const byte SEUIL_HEURE_DEBUT_ARROSAGE = 2;            //Déclenche l'arrosage à cette heure (heure) (ici 2h du matin) (doit commencer après minuit)  
    const byte SEUIL_HEURE_FIN_ARROSAGE = 5;              //Déclenche l'arrosage à cette heure (heure) (ici 5h du matin)
    const float SEUIL_ARROSAGE_HUMIDITE = 50;             //Arrosage en dessous de 50% d'humidité en fonction du seuil de pression et de l'heure (en %)
    const float SEUIL_HUMIDITE_FIN_ARROSAGE = 90;         //L'arrosage s'arrête lorsqu'il atteint ce seuil
    const byte NB_ARROSAGE_MAX = 10;                      //Nombre d'arrosage entre le début et la fin de l'arrosage
    const float PAS_TEMPS_ARROSAGE = (SEUIL_HEURE_FIN_ARROSAGE - SEUIL_HEURE_DEBUT_ARROSAGE) * 60 / NB_ARROSAGE_MAX;   //Pas de temps arrosage (minute) 

  //Paramètres globaux
    const int PAS_MESURE = 1;                             //Déclenche une mesure et un traitement tout les pas de temps (en minute)
    const int TEMPO_MAX_ARROSAGE = 360;                   //Tempo durée maximum d'arrosage (seconde) sur chaque pas de mesure  
    const float DEBIT_POMPE = 550;                        //Débit de la pompe en L/h

  //Carte SD
    const char* FICHIER_ARROSAGE = "arrosage.txt";        //Nom du fichier pour l'enregitrment des données d'arrosage
    const char* FICHIER_DATA_CAPTEUR = "datalog.txt";     //Nom du fichier pour l'enregitrment des données des capteurs
    const char* FICHIER_EVENEMENT = "events.txt";         //Nom du fichier pour l'enregitrment du journal de bord

  //Affichage
    const int DUREE_AFFICHAGE = 5000;

  //Etalonnage
    const float NB_POINT_MIN= 0;         // Valeur en nombre de point pour 100% humidité
    const float NB_POINT_MAX = 500;      // Valeur en nombre de point pour 0% humidité (max 1024 point)
    const float A_HUMIDITE = -100/(NB_POINT_MAX-NB_POINT_MIN);
    const float B_HUMIDITE = 100;

  //Paramètre initialisation horloge RTC (mettre l'heure au moment du chargement du programme)
    const int INIT_RTC_MIN = 22;                       //Minute             
    const int INIT_RTC_HEURE = 20;                     //Heure 
    const int INIT_RTC_DAYWEEK = 1;                    //Jour de la semaine 
    const int INIT_RTC_DAYMONTH = 27;                  //Jour du mois 
    const int INIT_RTC_MONTH = 3;                      //Mois 
    const int INIT_RTC_YEAR = 2023;                    //Année

// ---------------------------------------------------------- 
// -------------------------- INIT -------------------------- 
// ----------------------------------------------------------
  
void setup() { // put your setup code here, to run once:   
    
  //Com avc moniteur série
    Serial.begin(9600);
    
    while (!Serial) {
      ; // wait for serial port to connect. Needed for native USB port only
    }

  Serial.println("");
  Serial.println("");
  Serial.println("RESET");    

  //Initialisation de l'afficheur 
    lcd.init(); 

  //Initialisation capteur de pression BMP388 
    bmp388.set_iic_addr(BMP3_I2C_ADDR_PRIM);
    while(bmp388.begin()){
      Serial.println("Capteur de pression Erreur Initialisation");
      delay(1000);
    }  
    /*You can use an accurate altitude to calibrate sea level air pressure.
    *And then use this calibrated sea level pressure as a reference to obtain the calibrated altitude.
    *In this case,525.0m is villes hervé YFFINIAC accurate altitude.
    */
    delay(100);
    seaLevel = bmp388.readSeaLevel(155.0);
    Serial.print("seaLevel : ");
    Serial.print(seaLevel);
    Serial.println(" Pa");

  //DS1302 (horloge RTC)
    // Heure de départ à changer à chaque téléversement
    // Set the current date, and time in the following format:
    // seconds, minutes, hours, day of the week, day of the month, month, year
    myRTC.setDS1302Time(00, INIT_RTC_MIN, INIT_RTC_HEURE, INIT_RTC_DAYWEEK, INIT_RTC_DAYMONTH, INIT_RTC_MONTH, INIT_RTC_YEAR);  

  //Initialisation carte SD
    Init_SDcard(); 

  //Définition des entrées/sorties
    pinMode(PIN_VOYANT_VIE,OUTPUT);
    pinMode(PIN_ALIM_CAPTEUR,OUTPUT); 
    pinMode(PIN_ALIM_AFFICHEUR,OUTPUT); 
    pinMode(PIN_VOYANT_NIVEAU,OUTPUT); 
    pinMode(PIN_POMPE_1,OUTPUT); 
    pinMode(PIN_POMPE_2,OUTPUT); 
    pinMode(PIN_BP_AFFICHE,INPUT_PULLUP);
    pinMode(PIN_CAPT_NIVEAU,INPUT);
    
  //Initialisation des variables et des sorties
    CptHumi1=0;         //Valeur reelle Capteur humidité 1
    CptHumi2=0;         //Valeur reelle Capteur humidité 2
    CptPression=0;      //Valeur reelle capteur pression
    CptTemperature=0;   //Valeur reelle capteur température
    //SaveAnnee1=90; SaveMois1=1; SaveJour1=1; SaveHeure1=0; SaveMin1=0;   //Date et heure
    SaveAnnee2=90; SaveMois2=1; SaveJour2=1; SaveHeure2=0; SaveMin2=0;   //Date et heure
    CptMin=0; DernierMesureMin=0;
    //Lecture niveau 
      digitalWrite(PIN_ALIM_CAPTEUR,HIGH);    //Alimentation capteur
      CptNiveau = digitalRead(PIN_CAPT_NIVEAU);
    digitalWrite(PIN_ALIM_CAPTEUR,LOW);
    digitalWrite(PIN_ALIM_AFFICHEUR,LOW);  
    digitalWrite(PIN_POMPE_1,LOW); 
    digitalWrite(PIN_POMPE_2,LOW);
    digitalWrite(PIN_VOYANT_NIVEAU,HIGH);   //eteindre voyant
    digitalWrite(PIN_VOYANT_VIE,HIGH);      //eteindre voyant

  //Définition d'une interruption  
    attachInterrupt(digitalPinToInterrupt(PIN_BP_AFFICHE), onEvent, CHANGE);

}

// ---------------------------------------------------------- 
// -------------------------- MAIN -------------------------- 
// ----------------------------------------------------------

void loop()  { // put your main code here, to run repeatedly:
 
 
// -------------------------- INITIALISATION --------------------------  
  //Alimentation
  digitalWrite(PIN_ALIM_CAPTEUR,LOW);
  digitalWrite(PIN_ALIM_AFFICHEUR,LOW);  
  //Horloge
  myRTC.updateTime(); // This allows for the update of variables for time or accessing the individual elements.

// -------------------------- COMPTEUR TEMPS --------------------------  
  CptMin = myRTC.minutes + myRTC.hours * 60;
  //Serial.print(DernierMesureMin); Serial.print("     "); Serial.println(CptMin);
  if (CptMin < DernierMesureMin) { DernierMesureMin = CptMin; }  //Cas début de chaque jour
  
  if (CptMin >= DernierMesureMin + PAS_MESURE) {

    //Gestion du pas de temps
    DernierMesureMin = CptMin;  //Sauvegarde du temps 
        
    // -------------------------- LECTURE + ENREGISTREMENT -------------------------- 
      LectureGenrale(); 
      EcritureDonneesSD();
    

  //Arroser en premier l'intérieur car plus génant si le detecteur de niveau bas est atteint

    if (CptNiveau == 0) {  //si niveau ok
    // -------------------------- SEUIL CRITIQUE -------------------------- 
      //Seuil critique d'arrosage
      if (CptHumi2 < SEUIL_ARROSAGE_HUM_CRITIQUE){
        //Arroser
        ArrosagePompe(CptHumi2,PIN_CAPT_HUM_2,PIN_POMPE_2,SEUIL_HUM_FIN_ARROSAGE_CRITIQUE);

      }

      /*      
      if (CptHumi1 < SEUIL_ARROSAGE_HUM_CRITIQUE){
        //Arroser
        ArrosagePompe(CptHumi1,PIN_CAPT_HUM_1,PIN_POMPE_1,SEUIL_HUM_FIN_ARROSAGE_CRITIQUE);
      }
      */
        
    }    
  } // Fin du pas de temps 

// -------------------------- TRAITEMENT ARROSAGE INTERIEUR -------------------------- 
  if (CptNiveau == 0) {  //si niveau ok
    if ((myRTC.hours >= SEUIL_HEURE_DEBUT_ARROSAGE)&&(myRTC.hours < SEUIL_HEURE_FIN_ARROSAGE)){   //si dans la période d'arrosage
      
      if ((ProchainArrosage<=myRTC.hours * 60 + myRTC.minutes)&&(NbArrosage > 1)){        //pour les arrosages suivants si heure d'arrosage inférieur à l'heure actuelle
        //Arroser
        ArrosagePompe(CptHumi2,PIN_CAPT_HUM_2,PIN_POMPE_2,PalierArrosage*NbArrosage);

        NbArrosage = NbArrosage + 1;
        ProchainArrosage = ProchainArrosage + PAS_TEMPS_ARROSAGE;     //Heure du prochain arrosage
      }
      
      if ((CptHumi2 < SEUIL_ARROSAGE_HUMIDITE)&&(NbArrosage == 1)){  //Condition particulière lors du première arrosage 
        PalierArrosage = (CptHumi2 - SEUIL_HUMIDITE_FIN_ARROSAGE) / NB_ARROSAGE_MAX;      //définir palier d'arrosage
        ProchainArrosage = myRTC.hours * 60 + myRTC.minutes;                          //initier l'heure de début d'arrosage pour les pas de temps arrosage                              
      
        //Arroser
        ArrosagePompe(CptHumi2,PIN_CAPT_HUM_2,PIN_POMPE_2,PalierArrosage);
           
        NbArrosage = 2;
        ProchainArrosage = ProchainArrosage + PAS_TEMPS_ARROSAGE;     //Heure du prochain arrosage
      } 
    }   
    else {
      NbArrosage = 1;
    }
      
   }


// -------------------------- TRAITEMENT ARROSAGE EXTERIEUR -------------------------- 
  /*    
    //Arrosage en fonction de l'heure et de la pression
    if ((myRTC.hours >= SEUIL_HEURE_DEBUT_ARROSAGE)&&(myRTC.hours < SEUIL_HEURE_FIN_ARROSAGE)){
      if ((CptHumi1 < SEUIL_ARROSAGE_HUMIDITE)&&(CptPression > SEUIL_ARROSAGE_PRESSION)){

        //Arroser
        ArrosagePompe(CptHumi1,PIN_CAPT_HUM_1,PIN_POMPE_1);
      }
    }
    */
  

// -------------------------- AFFICHAGE -------------------------- 
  // SECURITE : Voyant de vie
  if ((myRTC.hours >= SEUIL_HEURE_DEBUT_ARROSAGE)&&(myRTC.hours < SEUIL_HEURE_FIN_ARROSAGE)){   //Les voyants ne s'allument pas la nuit
    digitalWrite(PIN_VOYANT_VIE,HIGH);
    digitalWrite(PIN_VOYANT_NIVEAU,HIGH);   //Eteindre voyant 
  }
  else{         
    if (CptHumi1 < SEUIL_ARROSAGE_HUMIDITE){ 
      digitalWrite(PIN_VOYANT_VIE,LOW);   //Si inférieur au seuil reste allumé   
    }
    else {                              //Sinon clignotement long
      digitalWrite(PIN_VOYANT_VIE,LOW);
      delay(1000);
      digitalWrite(PIN_VOYANT_VIE,HIGH);
      delay(5000);
    }
    // SECURITE : Voyant de niveau  
    if (CptNiveau == 0) {   //Si capteur de niveau ok
      digitalWrite(PIN_VOYANT_NIVEAU,HIGH);   //Eteindre voyant  
    }
    else {
      digitalWrite(PIN_VOYANT_NIVEAU,LOW);    //Sinon Allumer voyant     
    }
  }

  //Afficheur LCD
  if (EtatBouton == 1){     //si BP appuyé
    VolumeEau = DEBIT_POMPE * (CPTHarrosage1 + CPTHarrosage2);  
    LectureGenrale();   
    Afficher();  
    EcritureDonneesSD();
  }   
  else {        //si BP non appuyé
    digitalWrite(PIN_ALIM_AFFICHEUR,LOW);  //garder alimentation afficheur à 0
  }
}

// --------------------------------------------------------------- 
// -------------------------- FONCTIONS -------------------------- 
// --------------------------------------------------------------- 

// -------------------------- INTERRUPTION -------------------------- 
//Interruption
void onEvent() {
  EtatBouton = digitalRead(PIN_BP_AFFICHE);    //Lecture bouton
}  

// -------------------------- LECTURE -------------------------- 
//Lecture de tous les capteurs
void LectureGenrale() {
  //Serial.println("Debut lecture ");
  digitalWrite(PIN_ALIM_CAPTEUR,HIGH);    //Alimentation capteur humidité
  delay(500);
  CptHumi1 = LectCptHumi(PIN_CAPT_HUM_1);   //Lecture + etalonnage
  CptHumi2 = LectCptHumi(PIN_CAPT_HUM_2);   //Lecture + etalonnage
  CptPression = bmp388.readPressure()/100;                    //Lecture + conversion hPa
  CptTemperature = bmp388.readTemperature();                  //Lecture
  CptNiveau = digitalRead(PIN_CAPT_NIVEAU);
  delay(500); 
  digitalWrite(PIN_ALIM_CAPTEUR,LOW);
  /*Serial.print("T° ");Serial.println(CptTemperature); 
  Serial.print("H1 conv ");Serial.println(CptHumi1); 
  Serial.print("H2 conv ");Serial.println(CptHumi2); 
  Serial.print("H1 lect ana ");Serial.println(analogRead(PIN_CAPT_HUM_1)); 
  Serial.print("H2 lect ana ");Serial.println(analogRead(PIN_CAPT_HUM_2));
  Serial.println("Fin lecture "); */
}

//Enregistrer date pour arrosage extérieur
void SaveDateInt(float Humi) {
  SaveAnnee2 = myRTC.year;
  SaveMois2 = myRTC.month;
  SaveJour2 = myRTC.dayofmonth;
  SaveHeure2 = myRTC.hours;
  SaveMin2 = myRTC.minutes; 
  SaveHumi2 = Humi; 
}
/*
//Enregistrer date pour arrosage extérieur
void SaveDateInt(float Humi) {
  SaveAnnee2 = myRTC.year;
  SaveMois2 = myRTC.month;
  SaveJour2 = myRTC.dayofmonth;
  SaveHeure2 = myRTC.hours;
  SaveMin2 = myRTC.minutes; 
  SaveHumi2 = Humi; 
}*/

//Convertion capteur humidité
float LectCptHumi(byte PinCptHum) {
  return A_HUMIDITE*analogRead(PinCptHum)+B_HUMIDITE;
}


// -------------------------- ACTION -------------------------- 
//Action arrosage
void ArrosagePompe(float CptH, byte PinCaptHum, byte PinPompe, byte SeuilArrosage) {
  float DebutArrosage = myRTC.hours*3600+myRTC.minutes*60+myRTC.seconds;  //Sauvegarde temps début arrosage (seconde)
  float Temps = DebutArrosage;                                            //Raffrechissement du temps d'arrosage (seconde)

  Serial.println("Debut arrosage"); 
  if (CptNiveau == 0) {   //Sécurié Si capteur de niveau ok
    if (PinPompe == PIN_POMPE_2){    
      //enregistrement carte SD
      EcritureArrosageSD("Pompe 2", "Debut arrosage",CPTarrosage2, CPTHarrosage2 );
    }   
    /*
    else if (PinPompe == PIN_POMPE_1){
      EcritureArrosageSD("Pompe 2", "Fin arrosage",CPTarrosage2, CPTHarrosage2 );      
    }*/      
    // Arrosage
    digitalWrite(PIN_ALIM_CAPTEUR,HIGH);    //Alimentation capteur humidité 
    while ((CptH < SeuilArrosage)&&(CptNiveau == 0)&&(TEMPO_MAX_ARROSAGE >= (Temps - DebutArrosage))){
      CptH = LectCptHumi(PinCaptHum);   //Lecture + etalonnage 
      CptNiveau = digitalRead(PIN_CAPT_NIVEAU);     //Lire niveau eau  
      digitalWrite(PinPompe,HIGH);        //Activer pompe
    
    //Rafréchissement du temps pour la tempo 
    myRTC.updateTime();
    Temps = myRTC.hours*3600+myRTC.minutes*60 + myRTC.seconds;
      
      //Serial.print("Humidite ");Serial.println(CptH);
      //Serial.print("DebutArrosage ");Serial.println(DebutArrosage);   
      //Serial.print("TEmps seconde ");Serial.println(myRTC.minutes*60 + myRTC.seconds);
      //Serial.print("Tempo ");Serial.println(myRTC.minutes*60 + myRTC.seconds - DebutArrosage);        
    }

    //Temps à la fin de l'arrosage
    myRTC.updateTime();
    Temps = myRTC.hours*3600+myRTC.minutes*60 + myRTC.seconds;

    //Couper alimentation capteur + éteindre pompe
    digitalWrite(PIN_ALIM_CAPTEUR,LOW);   
    digitalWrite(PinPompe,LOW); 

    
    if (PinPompe == PIN_POMPE_2){
      // Compteurs
      CPTarrosage2 = CPTarrosage2 + 1 ;
      CPTHarrosage2 = ((Temps - DebutArrosage)/3600) + CPTHarrosage2;

      //enregristrement date
      SaveDateInt(CptHumi2);
      //enregistrement carte SD
      EcritureArrosageSD("Pompe 2", "Fin arrosage",CPTarrosage2, CPTHarrosage2 );
  
      Serial.println("Pompe 2");
      Serial.print("temps ");Serial.println(Temps);      
      Serial.print("debut arrosage ");Serial.println(DebutArrosage);
      Serial.print("compteur temps arrosage ");Serial.println(CPTHarrosage2);  
    }
    /*
    else if (PinPompe == PIN_POMPE_1){
      // Compteurs
      CPTarrosage1 = CPTarrosage1 + 1 ;
      CPTHarrosage1 = ((Temps - DebutArrosage)/3600) + CPTHarrosage1; 

      //enregristrement date
      SaveDateExt(CptHumi1);
      EcritureArrosageSD(string NomPompe, string Commentaire, int NbArrosage, float DureeArrosage);
      
      Serial.println("Pompe 1");
      //Serial.print("compteur temps arrosage ");Serial.println(CPTHarrosage1); 
    }*/
    Serial.println("Fin arrosage ");
    //Serial.print("Tempo max ");Serial.println(TEMPO_MAX_ARROSAGE);        
  }
  else {    //Sinon 
    digitalWrite(PIN_VOYANT_NIVEAU,LOW);    //Allumer voyant niveau insuffisant

    if (PinPompe == PIN_POMPE_2){    
      //enregistrement carte SD
      EcritureArrosageSD("Pompe 2", "Manque eau",CPTarrosage2, CPTHarrosage2 );
    }   
    /*
    else if (PinPompe == PIN_POMPE_1){
      EcritureArrosageSD("Pompe 2", "Fin arrosage",CPTarrosage2, CPTHarrosage2 );      
    }*/  
    
  }
}

//Ecriture des données capteurs sur carte SD
void EcritureDonneesSD(){

  monfichier = SD.open(FICHIER_DATA_CAPTEUR, FILE_WRITE);

  Serial.println(FICHIER_DATA_CAPTEUR);

  if (monfichier) {
    
    myRTC.updateTime();  
   
    String DataWrite = "";
      DataWrite +=String(myRTC.dayofmonth);
      DataWrite += "/";
      DataWrite +=String(myRTC.month);
      DataWrite += "/";
      DataWrite +=String(myRTC.year);
      DataWrite += " ";
      DataWrite +=String(myRTC.hours);
      DataWrite += ":";
      DataWrite +=String(myRTC.minutes);
      DataWrite += ";";
      DataWrite +=String(CptHumi1);
      DataWrite += ";";
      DataWrite +=String(CptHumi2);
      DataWrite += ";";
      DataWrite +=String(CptPression);
      DataWrite += ";";    
      DataWrite +=String(CptTemperature);    

    monfichier.println(DataWrite);        
    Serial.println(DataWrite);
    Serial.println("Fin ecriture carte SD");
    monfichier.close(); 
    
  }
  // si probleme d'ouverture
  else { 
    Serial.print("error opening file : "); 
    Serial.println(FICHIER_DATA_CAPTEUR);
  }

}

//Ecriture des arrosage sur carte SD
void EcritureArrosageSD(String NomPompe, String Commentaire, int NbArrosage, float DureeArrosage){

  monfichier = SD.open(FICHIER_ARROSAGE, FILE_WRITE);

  if (monfichier) {

    myRTC.updateTime();  
   
    String DataWrite = "";
      DataWrite +=String(myRTC.dayofmonth);
      DataWrite += "/";
      DataWrite +=String(myRTC.month);
      DataWrite += "/";
      DataWrite +=String(myRTC.year);
      DataWrite += " ";
      DataWrite +=String(myRTC.hours);
      DataWrite += ":";
      DataWrite +=String(myRTC.minutes);
      DataWrite += ";";
      DataWrite += NomPompe;
      DataWrite += ";";    
      DataWrite += Commentaire;  
      DataWrite += ";";
      DataWrite +=String(NbArrosage);
      DataWrite += ";";
      DataWrite +=String(DureeArrosage);

    monfichier.println(DataWrite);        
    Serial.println("Fin ecriture carte SD");
    Serial.println(DataWrite);
    
    monfichier.close(); 
    //Serial.println("fichier ferme");
  }
  // si probleme d'ouverture
  else { 
    Serial.print("error opening file : "); 
    Serial.println(FICHIER_ARROSAGE);
  }

}

//Ecrire du texte sur carte SD
void EcrireCarteSD(char* NomFichier, char* Texte){
  
  monfichier = SD.open(NomFichier, FILE_WRITE);
  
  Serial.println(NomFichier);
  Serial.println(Texte);
  
  if (monfichier) {  
    
    myRTC.updateTime(); 
    
    String WriteSD = "";
      WriteSD +=String(myRTC.dayofmonth);
      WriteSD += "/";
      WriteSD +=String(myRTC.month);
      WriteSD += "/";
      WriteSD +=String(myRTC.year);
      WriteSD += " ";
      WriteSD +=String(myRTC.hours);
      WriteSD += ":";
      WriteSD +=String(myRTC.minutes); 
      WriteSD += ";"; 
      WriteSD += Texte;       
      
    monfichier.println(WriteSD);

    Serial.println(WriteSD);
    Serial.println("Fin ecriture carte SD"); 
    
    monfichier.close();  

  }  
  else { 
    Serial.print("error opening file : "); 
    Serial.println(NomFichier);
  }
  
}

//Affichage écran LCD
void Afficher() {

    //Alimenter afficheur   
    digitalWrite(PIN_ALIM_AFFICHEUR,HIGH);
    delay(1000); 
  
    //Initialisation de l'afficheur   
    lcd.init();     
    lcd.backlight();  //allumer le retro-eclairage
    lcd.display();    //allumer le cristaux liquide
    digitalWrite(PIN_VOYANT_VIE,HIGH);  //Eteindre voyant de vie
   
   digitalWrite(PIN_ALIM_CAPTEUR,HIGH);    //Alimentation capteur humidité

    //Ecran 1    
    lcd.clear();      //Nettoyer valeur affichée
    lcd.setCursor(0, 0); lcd.print(myRTC.dayofmonth); lcd.print("/"); lcd.print(myRTC.month); lcd.print("/"); lcd.print(myRTC.year); lcd.print("-"); lcd.print(myRTC.hours); lcd.print(":"); lcd.print(myRTC.minutes);
    lcd.setCursor(0, 1); lcd.print("Dernier arrosage :");
    lcd.setCursor(0, 2); lcd.print(SaveJour2); lcd.print("/"); lcd.print(SaveMois2); lcd.print("/"); lcd.print(SaveAnnee2); lcd.print("-"); lcd.print(SaveHeure2); lcd.print(":"); lcd.print(SaveMin2);   
    //lcd.setCursor(0, 3); lcd.print("Ext:"); lcd.print(SaveJour1); lcd.print("/"); lcd.print(SaveMois1); lcd.print("/"); lcd.print(SaveAnnee1); lcd.print("  "); lcd.print(SaveHeure1); lcd.print(":"); lcd.print(SaveMin1);
    delay(DUREE_AFFICHAGE);     //Durée d'affichage infos

/*
    //Ecran 2  
    lcd.clear();      //Nettoyer valeur affichée    
    lcd.setCursor(0, 0); lcd.print("Humidite 1 "); lcd.print(int(CptHumi1)); lcd.print("%");
    lcd.setCursor(0, 1); lcd.print("Humidite 2 = "); lcd.print(int(CptHumi2)); lcd.print("%");
    lcd.setCursor(0, 2); lcd.print("Pre atmo = "); lcd.print(int(CptPression)); lcd.print("hPa");
    lcd.setCursor(0, 3); lcd.print("Temperature = "); lcd.print(int(CptTemperature)); lcd.print("deg"); 
    delay(DUREE_AFFICHAGE);     //Durée d'affichage infos
  
    //Ecran 3  
    lcd.clear();      //Nettoyer valeur affichée    
    lcd.setCursor(0, 0); lcd.print(myRTC.dayofmonth); lcd.print("/"); lcd.print(myRTC.month); lcd.print("/"); lcd.print(myRTC.year); lcd.print("  "); lcd.print(myRTC.hours); lcd.print(":"); lcd.print(myRTC.minutes);
    if (CptNiveau == 1) {
      lcd.setCursor(0, 1); lcd.print("MANQUE EAU"); 
    }
    else {
      lcd.setCursor(0, 1); lcd.print("Niveau OK");     
    }
    //lcd.setCursor(0, 2); lcd.print("Total eau consomme"); 
    //lcd.setCursor(0, 3); lcd.print("= "); lcd.print(VolumeEau); lcd.print("L");  
    delay(DUREE_AFFICHAGE);     //Durée d'affichage infos

    //Ecran 4  
    lcd.clear();      //Nettoyer valeur affichée    
    lcd.setCursor(0, 0); lcd.print("Pompe interieur"); 
    lcd.setCursor(0, 1); lcd.print("Nb arrosage= "); lcd.print(CPTarrosage2); 
    lcd.setCursor(0, 2); lcd.print("Temps arro.= "); lcd.print(CPTHarrosage2); lcd.print("H");
    lcd.setCursor(0, 3);   
    delay(DUREE_AFFICHAGE);     //Durée d'affichage infos
*/
    lcd.clear();     //Nettoyer valeur affichée
   
    //Fin   
    EtatBouton = 0;
    lcd.noBacklight(); //eteindre le retro-eclairage
    lcd.noDisplay();   //eteindre le cristaux liquide  
    delay(500);      
    digitalWrite(PIN_ALIM_AFFICHEUR,LOW);
    EcrireCarteSD(FICHIER_EVENEMENT, "Lecture et Affichage");
}

// -------------------------- VOID SETUP -------------------------- 
//Tester écriture et lecture carte SD
void Init_SDcard(){ 
  Serial.println("Initializing SD card.");
  
  pinMode(SS, OUTPUT);
  while (!SD.begin(SPI_HALF_SPEED, PIN_CHIP_SELECT)) { Serial.println("initialization failed"); }

  // see if the card is present and can be initialized:
  if (!SD.begin(PIN_CHIP_SELECT)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }

  EcrireCarteSD(FICHIER_EVENEMENT, "Reset");  
  /*monfichier = SD.open(FICHIER_EVENEMENT, FILE_WRITE);
  
  if (monfichier) {  
    
    myRTC.updateTime(); 
    
    String WriteSD = "";
      WriteSD +=String(myRTC.dayofmonth);
      WriteSD += "/";
      WriteSD +=String(myRTC.month);
      WriteSD += "/";
      WriteSD +=String(myRTC.year);
      WriteSD += " ";
      WriteSD +=String(myRTC.hours);
      WriteSD += ":";
      WriteSD +=String(myRTC.minutes); 
      WriteSD += ";"; 
      WriteSD += "Reset";       
      
    monfichier.println(WriteSD);
    monfichier.close(); 
    Serial.println("fichier ferme");
    Serial.println("card initialized.");  

  }  
  else { 
    Serial.print("error opening file : "); 
    Serial.println(FICHIER_EVENEMENT);
  }

  */
}

Bonjour jeromer999

Ton programme est peut-être un peu "gros" pour un UNO:

Le croquis utilise 26922 octets (83%) de l'espace de stockage de programmes. Le maximum est de 32256 octets.
Les variables globales utilisent 1687 octets (82%) de mémoire dynamique, ce qui laisse 361 octets pour les variables locales. Le maximum est de 2048 octets.

Le lecteur SD n'a plus assez de mémoire pour écrire sur la carte.

Une fois que tu as mis ces lignes en commentaire, quels sont les pourcentages de mémoire utilisés?
Ceci a libéré de l'espace et le lecteur peut ainsi travailler.

Un UNO est un peu juste pour ton projet, passer sur un MEGA?

Cordialement
jpbbricole

Le minimum serait déjà de passer les strings constantes en FLASH :

Deuxièmement, on peut douter de l'utilité d'une SD, qui est un gouffre d'un point de vue mémoire, pour un tel projet.
A partir du moment où un LCD est présent, il est assez facile d'ajouter un clavier pour faire la saisie des heures d'arrosage et stocker celles-ci en EEPROM :

La SD si j'ai bien compris est prévu pour faire du log pas du stockage de configuration.

Les lignes pour l'affichage en commentaire, le croquis est à 83% de l'espace de stockage de programmes et 82% de mémoire dynamique. Si j'active les lignes pour l'afficheur, le croquis est à 85% de l'espace de stockage de programmes et 88% de mémoire dynamique.

Je pensais que si j'atteignais pas les 100% c'était bon.

L'arduino mega m'embête un peu car la carte va être dans un boitier dans une serre. Et si l'étanchéité n'est pas bonne, je suis bon pour racheter une carte.

ok je vais faire ça. Merci

Oui c'est ça. Les paramètres (heure d'arrosage, seuil d'humidité, ...) sont déjà stockés sur l'Arduino. La carte SD doit juste conserver les données relevées par les capteurs

Le compilateur ne retourne que l'utilisation mémoire des variables qui sont déclarées à la compilation. Mais il y a des librairies qui créent des variables lors de l'exécution du programme (par exemple les buffers pour les afficheurs). Et il faut quand même garder de la mémoire disponible pour les variables locales des fonctions et les valeurs qu'elles échanges.

Merci, j'ai gagné 10% de mémoire dynamique et mon afficheur et la carte SD fonctionnent. C'est bien un problème de mémoire.

Il restait donc 245 octets pour la pile et le tas. Dans certains cas cela ne suffit pas.
Merci pour le retour.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.