Ecriture sur SD impossible sans moniteur série

Bonjour à tous,

Comme beaucoup, je fais mes premières armes sur Arduino avec un DHT22 dont je veux écriture périodiquement les mesures sur une carte SD. Je possède le duo classique Arduino Uno et shield Datalogger d'Adafruit. Rien de bien compliqué vous allez me dire.

Bref, tout se passe bien quand la carte est connecté au PC : les mesures s'affichent dans le moniteur et "s'écrvient" dans un fichier "datalog.txt" sur la carte SD. Comme prévu.

Mais dans la configuration ou la carte est alimentée par une alimentation extérieure (12 V, 600 mA), plus rien. Aucun fichier n'est crée sur la SD qui reste vide. Cela fait des jours que je cherche, teste, écumant bouquins, forums et sites internet et je ne trouve pas grand chose...

Notamment, purger le code des éléments liés au Serial.print... Mais sans succès : Writing data to an SD card without the Serial Monitor - Project Guidance - Arduino Forum

Je me permet donc de vous solliciter pour jeter un coup d’œil à mon code (il est très détaillé... because j'apprends !)

// BIBLIOTHEQUE
#include <DHT_U.h> // Etablit un dialogue avec le DHT22
#include <RTClib.h> // Etablit un dialogue avec la RTC
#include <Wire.h> //Etablit un dialogue avec le protocole sur 2 fils TWI (appelé aussi I2C) : la RTC communique en I2C
#include <SPI.h>
#include <SD.h>

// DEFINITION DES CONSTANTES
#define DHTPIN 2 // Définition du pin de connection
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE) ; // dht(numéro de la pin, type de DHT)
RTC_DS1307 rtc;

// DECLARATION DES VARIABLES
String ChaineDonnees ; // Objet contenant les infos à écrire
int id = 0 ; // Compteur de mesure
const int chipSelect = 10 ;
File dataFile ;

///////////////////////////////////////////////////////////////////////////////////////////////////////
 
void setup()
{
  Serial.begin(9600);
  Serial.println("Welcome in the DHT22 tester!");
  Serial.print("Initializing SD card...");
  dht.begin();
  rtc.begin();// Vérification de la RTC
  
  if (!rtc.isrunning()) {
    rtc.adjust(DateTime(__DATE__,__TIME__)) ;
    return;
  }
  
  if (!SD.begin(chipSelect)) { // Vérification de la présence de la SD 
      Serial.println("Card failed, or not present"); // On arrete là
      return;
  }
  
  Serial.println("DHT, RTC and SD card initialized");

  dataFile = SD.open("datalog.csv", FILE_WRITE) ; // Vérification et parametrage du fichier
  
  if (dataFile) {
  dataFile.println("id|unixtime|date|time|temp|hr"); // Ecriture des entetes
  dataFile.close(); // Fermeture
  Serial.println("id|unixtime|date|time|temp|hr");
  }
  else
  {
    Serial.println("Erreur d'ouverture de la SD");
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void loop()

{ 
  float h = dht.readHumidity(); //on lit l'hygrometrie
  float t = dht.readTemperature(); //on lit la temperature en celsius (par defaut)
  
  DateTime now = rtc.now() ; // On fait un "top temps"

    ChaineDonnees =
    String(id)+"|"+
    String(now.unixtime(),DEC)+"|"+
    String(now.day(),DEC)+"/"+String(now.month(),DEC)+"/"+String(now.year(),DEC)+"|"+ // Construction de la date
    String(now.hour(),DEC)+":"+String(now.minute(),DEC)+":"+String(now.second(),DEC)+"|"+  // Construction de l'heure
    String(t)+"|"+String(h);

  dataFile = SD.open("datalog.csv", FILE_WRITE); // Ouverture du fichier en mode écriture
  
  if (dataFile) {
    dataFile.println(ChaineDonnees); // On y écrit les données
    dataFile.close(); // On le ferme
    Serial.println(ChaineDonnees); // print to the serial port too:
  }
    else
  {
    Serial.println("Erreur d'écriture de la SD");
  }
  
  id += 1 ;
  ChaineDonnees = "" ; 

delay (10000) ; 
}

Merci pour vos avis, là je sèche et commence un peu désespérer...

clarky56:
if (!SD.begin(chipSelect)) { // Vérification de la présence de la SD
Serial.println("Card failed, or not present"); // On arrete là
return;
}

En faisant return, tu n'arrêtes rien du tout ! tu quittes la fonction setup(), et donc la fonction loop() va être appelée en boucle - alors qu'il y a un problème avec la SD !
Pour arrêter un programme Arduino on fait :

while ( 1 );

Par ailleurs, après avoir ouverr le fichier ( par SD.open() ) dans le setup(), tu l'ouvres à nouveau à chaque fois que loop() est appelée ! Ca peut avoir des conséquences...

Salut merci pour ton message !

Eh bien, j'ai modifié le code en suivant notamment tes commentaires (voir ci après). Idem : si je l’exécute avec le câble USB et le moniteur série tout OK.

Dès que je passe en mode "alimentation indépendante" : plus rien sur la SD.

Ce qui est bizarre, c'est que la LED rouge émet 2 flash rapides (en plus du flash d'écriture de débug que j'ai rajouté...)

Pour l'ouverture puis fermeture du fichier à chaque écriture, j'ai repris ce qu'il y a dans le bouquin Arduino Application avancées. Il conseille cette méthode : ouverture, écriture et fermeture.

// BIBLIOTHEQUE
#include <DHT_U.h> // Etablit un dialogue avec le DHT22
#include <RTClib.h> // Etablit un dialogue avec la RTC
#include <Wire.h> //Etablit un dialogue avec le protocole sur 2 fils TWI (appelé aussi I2C) : la RTC communique en I2C
#include <SPI.h>
#include <SD.h>

// DEFINITION DES CONSTANTES
#define DHTPIN 2 // Définition du pin de connection
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE) ; // dht(numéro de la pin, type de DHT)
RTC_DS1307 rtc;

// DECLARATION DES VARIABLES
String ChaineDonnees ; // Objet contenant les infos à écrire
int id = 0 ; // Compteur de mesure
const byte chipSelect = 10 ;
File dataFile ;
const byte LEDEcriture = 9;

///////////////////////////////////////////////////////////////////////////////////////////////////////
 
void setup()
{
  Serial.begin(9600);
  Serial.println("Welcome in the DHT22 tester!");
  Serial.print("Initializing SD card...");
  pinMode(chipSelect, OUTPUT);
  pinMode(LEDEcriture, OUTPUT);
  digitalWrite(LEDEcriture, LOW);
  
  Wire.begin();
  dht.begin();
  rtc.begin();// Vérification de la RTC
  
  if (!rtc.isrunning()) { // Si la carte SD n'est pas configurer, prendre l'heure du PC
    rtc.adjust(DateTime(__DATE__,__TIME__)) ;
  }
  
  if (!SD.begin(chipSelect)) { // Vérification de la présence de la SD 
      Serial.println("Card failed, or not present"); // On arrete là
      while (1);
  }
  
  Serial.println("DHT, RTC and SD card initialized");

  dataFile = SD.open("datalog.csv", FILE_WRITE) ; // Vérification et parametrage du fichier
  
  if (dataFile) {
  dataFile.println("id|unixtime|date|time|temp|hr"); // Ecriture des entetes
  dataFile.close(); // Fermeture
  Serial.println("id|unixtime|date|time|temp|hr");
  }
  
  else
  {
    Serial.println("Erreur d'ouverture de la SD");
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

void loop()

{ 
  float h = dht.readHumidity(); //on lit l'hygrometrie
  float t = dht.readTemperature(); //on lit la temperature en celsius (par defaut)
  
  DateTime now = rtc.now() ; // On fait un "top temps"

    ChaineDonnees =
    String(id)+"|"+
    String(now.unixtime(),DEC)+"|"+
    String(now.day(),DEC)+"/"+String(now.month(),DEC)+"/"+String(now.year(),DEC)+"|"+ // Construction de la date
    String(now.hour(),DEC)+":"+String(now.minute(),DEC)+":"+String(now.second(),DEC)+"|"+  // Construction de l'heure
    String(t)+"|"+String(h);

  dataFile = SD.open("datalog.csv", FILE_WRITE); // Ouverture du fichier en mode écriture
  
  if (dataFile) {
    digitalWrite(LEDEcriture, HIGH);
    dataFile.println(ChaineDonnees); // On y écrit les données
    dataFile.close(); // On le ferme
    Serial.println(ChaineDonnees); // print to the serial port too:
    digitalWrite(LEDEcriture, LOW);
    }
    
    else {
    Serial.println("Erreur d'écriture de la SD");
    }
  
  id += 1 ;
  ChaineDonnees = "" ; 

delay (10000) ; 
}

tu n'as rien corrigé du tout en ce qui concerne l'ouverture du fichier : tu continues à l'ouvrir sans cesse sans jamais le refermer.

Il conseille cette méthode : ouverture, écriture et fermeture.

C'est un bon conseil, mais il faudra faire attention à une chose: il faut rouvrir le fichier de façon à ne pas repartir du début du fichier à chaque fois, sinon chaque écriture effacera la précédente !
regarde bien le mode d'emploi de la fonction SD.open().

Tu pourrais aussi te contenter d'ouvrir le fichier une et une seule fois dans le setup(). L'inconvénient est que si tu arrêtes l'Arduino, la dernière écriture pourrait manquer. Peut-être, peut être pas. Ca dépend si les écriture sur la carte SD son synchrones ou asynchrones.
Etudie à fond la bibliothèque SD.

Merci pour ton retour.

J'avais compris que dans le Setup, c'est le "Return" qui n'allait pas, j'ai donc modifié en conséquence :

  • j'initialise la SD,
  • j'ouvre [et créé le fichier "s'il est ouvert en écriture il sera créé automatiquement s'il n'existe pas"],
  • j'écris la ligne des entêtes du fichier
  • je referme le fichier
  if (!SD.begin(chipSelect)) { // Vérification de la présence de la SD
      Serial.println("Card failed, or not present"); // On arrete là
      while (1);
  }
 
  Serial.println("DHT, RTC and SD card initialized");

  dataFile = SD.open("datalog.csv", FILE_WRITE) ; // Vérification et parametrage du fichier
 
  if (dataFile) {
  dataFile.println("id|unixtime|date|time|temp|hr"); // Ecriture des entetes
  dataFile.close(); // Fermeture
  Serial.println("id|unixtime|date|time|temp|hr");
  }

Plus loin dans la loop, à chaque besoin d’écriture, je rouvre le même fichier, écrit et ferme. Du moins c'est comme ça que je le vois... :slight_smile:

  dataFile = SD.open("datalog.csv", FILE_WRITE); // Ouverture du fichier en mode écriture. 
 
  if (dataFile) {
    dataFile.println(ChaineDonnees); // On y écrit les données
    dataFile.close(); // On le ferme
    Serial.println(ChaineDonnees); // print to the serial port too:
    }

Le mode FILE_WRITE écrit systématiquement à la fin du fichier.

L'ouverture une seule fois est à priori peu recommandé

Bonsoir,

Étant à 2 doigts de littéralement craquer, je me suis posé la question : qu'est ce qui change entre une connexion par USB et par la jack ? L'alimentation, entre autre.

J'ai donc opté pour une alimentation 7V 300mA en lieu et place de la 12V et ça semble fonctionner : en tout cas, avec cette nouvelle alimentation, le fichier s'écrit. Plus de "double flash" de la LED du shield SD-RTC...

Bon, je ne crie pas victoire (test en cours) mais c'est encourageant. Merci d'ores et déjà à biggil pour son coup de main.

ps. C'est bizarre j'étais dans les clous des tension de service de la jack...

Bon eh bien testé sur un week-end en continu ça fonctionne.

C'était donc bien l'alimentation qui faisait dérailler le tout. La 12V ne collait pas, la 9V à 300 mA est OK.

Affaire classée donc, et bonne soirée à tous !