Problème d'écriture sur carte SD

Bonjour,

Néophyte en programmation et utilisation d'un ARDUINO, j'ai réalisé un montage pour monitorer et enregistrer sur carte SD la température dans un circuit de liquide.

J'ai utilisé :

  • une carte UNO R3
  • un shield datalogger avec horloge RTC
  • un shield LCD 16x2
  • une sonde DS18B20 version étanche.

Je souhaite afficher sur le LCD la date, l'heure et la température actuelle. En parallèle, je souhaite enregistrer sur carte SD, avec une fréquence paramétrable, un fichier dont le nom est la date du jour et qui contiendrait 3 données séparées par une virgule pour exploitation ultérieure avec un tableur. Ces données sont jj/mm/aaaa, HH:MN, température.

Le montage électrique fonctionne et je parviens à créer le fichier sur la SD.

Voici les 2 problèmes que ne parviens pas à résoudre :

  1. Malgré une horloge RTC à l'heure, une date correcte sur le LCD et dans le nom de fichier sur SD, la valeur dans le fichier est toujours 1792 pour l'année.(voir capture d'écran excel).

  2. Je ne parviens à enregistrer les données que pendant quelques minutes sans pour autant avoir d'erreur du programme ou quoi que ce soit d'anormal sur le moniteur série.

Voici mon code

Merci d'avance pour vos conseils.

Bonne journée.

// sonde température DS18B20 *******************************************************************

#include <LiquidCrystal.h>// librairie écran lcd
#include <SPI.h>// librairie SD
#include <SD.h>// librairie SD
#include <OneWire.h>// librairie Bus One Wire
#include <RTClib.h>// Librairie horloge RTC
#include <DallasTemperature.h> //Librairie du capteur température


// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;


//pin 10 pour la carte SD
const int chipSelect = 10;
//File dataFile;
File fichierSD;


LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
RTC_DS1307 rtc;
unsigned long previousMillis = 0;//variable delay sans arrêt du programme
 
const long interval = 5000;// variable delay sans arrêt du programme qui prevoit une lecture de x millisecondes par mesure
 
OneWire oneWire(2); //PIN digital de la sonde sur la pin 2 de l'arduino
DallasTemperature sensors(&oneWire); //Utilistion du bus Onewire pour les capteurs
DeviceAddress sensorDeviceAddress; //Vérifie la compatibilité des capteurs avec la librairie

void setup() {
 

Serial.begin(9600);
delay(3000); // wait for console opening
  rtc.begin();
// following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  
  lcd.begin(16, 2); // lcd activé
 sensors.begin(); //Sonde activée
  sensors.getAddress(sensorDeviceAddress, 0); //Adresse de la sonde à 0
  sensors.setResolution(sensorDeviceAddress, 12); //Résolution sonde 12 bits
 //init SD
 Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
 
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
 




  
}
void loop() {
  
//AFFICHAGE LCD
  DateTime now = rtc.now();
  
  // l'heure sur la premiêre ligne du LCD
  lcd.setCursor(0, 0);
  if (now.hour() < 10) {
    lcd.print("0");
  }
  lcd.print(now.hour());
  lcd.print(":");
  if (now.minute() < 10) {
    lcd.print("0");
  }
  lcd.print(now.minute());
  
  
  
  // la date sur la deuxième ligne du LCD
  lcd.setCursor(0, 1); 
  if (now.day() < 10) {
    lcd.print("0");
  }
  lcd.print(now.day()); 
  lcd.print("/");
  if (now.month() < 10) {
    lcd.print("0");
  } 
  lcd.print(now.month()); 
  lcd.print("/");
  if (now.year() < 10) {
    lcd.print("0");
  }
  lcd.print(now.year()); 
  // le texte Temp : du LCD
  lcd.setCursor(7, 0);
  lcd.print("T:");
  lcd.setCursor(15, 0);
  lcd.print("C");
    
  delay(1000);
  //lcd.clear();
  unsigned long currentMillis = millis();// inclure une variable de temps par rapport à millis()
 
  if (currentMillis - previousMillis >= interval) {
       previousMillis = currentMillis;
 
    sensors.requestTemperatures(); //Demande la température aux capteurs
    Serial.print("Température = ");
    Serial.print(sensors.getTempCByIndex(0)+0.7,1); //Information récupérée sur l'adresse 0 de la sonde
    Serial.println(" DEGRES ");
 lcd.setCursor(10, 0);
 lcd.print(sensors.getTempCByIndex(0)+0.7,1);

// enregistre sur SD si temp>à valeur

if (sensors.getTempCByIndex(0) > 5) {

//On nomme le fichier selon la date, donc toutes les donnees prises le meme jour dans un seul fichier==========
 char datafile[13]; //tableau de 13 espaces pour le nom
 int jour=now.day();
 int mois = now.month();
 int annee= now.year(); 
 sprintf(datafile,"%02d%02d%04d.csv",jour,mois,annee); // %d pour un int 
 datafile[13]='\0';//à mettre pour fermer convenablement le fichier
//Fin nommer fichier==================

//Ouverture du fichier==========================
 fichierSD = SD.open(datafile, FILE_WRITE);

 
 //inscription dans fichier sur carte SD
 if (now.day() < 10) {
    fichierSD.print("0");
  }
 fichierSD.print(now.day(), DEC);
 fichierSD.print("/");
 if (now.month() < 10) {
    fichierSD.print("0");
  }
 fichierSD.print(now.month(), DEC);
 fichierSD.print("/");
 fichierSD.print(now.year(), DEC);
 fichierSD.print(",");
 if (now.hour() < 10) {
    fichierSD.print("0");
  }
 fichierSD.print(now.hour(), DEC);
 fichierSD.print(":");
 if (now.minute() < 10) {
    fichierSD.print("0");
  }
 fichierSD.print(now.minute(), DEC);
 fichierSD.print(":");
 if (now.second() < 10) {
    fichierSD.print("0");
  }
 fichierSD.print(now.second(), DEC);
 fichierSD.print(",");
 fichierSD.println(sensors.getTempCByIndex(0)+0.7,0);
 Serial.print("enregistré");
 fichierSD.flush();

  }
}
}

vous avez certainement un petit problème: votre tableau datefile déborde (dimensionné à 13) : datefile[12] est donc le dernier element, datefile[13] fait deborder
[/code] datafile[13]='\0';//à mettre pour fermer convenablement le fichier
//Fin nommer fichier==================[/code]
Je pense que la ligne incriminée ne sert à rien, et je l'ai testé sur mon PC

sh-4.1$ gcc ty.c &&  cat ty.c && ./a.exe
#include <stdio.h>
#include <string.h>
int main() {
 char datafile[13];
 int jour = 1, mois = 10,annee = 2019;
 sprintf(datafile,"%02d%02d%04d.csv",jour,mois,annee); // %d pour un int
 printf("<%s> lg=%d\n", datafile, strlen(datafile));
 // on prepare une chaine pour le stockage : est plsu concis
 char chaineJour[13]; // 
 sprintf(chaineJour, "%02d/%02d/%04d", jour,mois,annee);
 printf("<%s> lg=%d\n",  chaineJour,  strlen(chaineJour));
}
<01102019.csv> lg=12
<01/10/2019> lg=10

Par ailleurs, vous ne devriez pas être trop rigoureux, au risque d'une erreur de comptage, en dimensionnant les tableaux de caracteres terminés par \0 : il vaut mieux perdre 3 ou 4 caracteres (sur 2K pour un arduino) que d'avoir des debordements de tableaux, fastidieux à detecter.
Edite:
ce debordement ne règle pas tous vos symptomes;
SD.open ouvre le fichier, et positionne l'écriture à la fin du fichier; si, au lieu de SD.flush, vous mettiiez SD.close() , vous n'ouvririez pas un fichier déjà ouvert, ce qui me semble une source de désordre (et SD.close() force le flush).

Merci pour votre réponse, j'ai modifié mon code en fonction et vous tiens au courant lorsque j'aurai fait les essais.