Shield data-logger enregistreur de données Arduino.

Réalisation détaillée de projets complets

Shield data-logger enregistreur de données Arduino.

Messagepar tiptop » Jeu 16 Oct 2014 14:37

Utilisation du shield data-logger enregistreur de données pour Arduino.
Dans cet exemple, nous allons réaliser une petite station météo qui enregistre sur carte SD la température, l'hygrométrie et la luminosité.

Image
Très peu de matériel suffit pour monter sa mini station météo.

Composants utilisés

Image.Image.Image
Photorésistance, capteur de température et humidité DHT11, sonde de température étanche DS18b20
Image.Image
Capteur de température Ds18B20, Shield Data logger

_________________________________________________________________________________________________

Principe de fonctionnement
Le shield d'enregistrement de données vient s'emboîter (sans soudures) sur la carte Arduino (Uno, Mega...). Il est fourni déjà assemblé et soudé, prêt à l'emploi.

Il rajoute à l'Arduino des fonctionnalités d'enregistrement sur carte mémoire SD amovible, que l'on peut relire dans un ordinateur ensuite, et une horloge en temps réel (RTC = Real Time Clock), grâce à une pile de sauvegarde qui conserve l'heure plusieurs années (5 à 7 ans) hors tension de l'Arduino.

Image
Carte UNO + Shield Data Logger

Utilisation
  • Mettre la pile lithium CR1220 dans son logement sur le shield (le pôle + en haut). Emboîter le shield sur la carte Arduino.
    Mettre une carte mémoire SD formatée dans le lecteur / enregistreur. Elle peut être formatée en FAT16 ou FAT 32 jusqu'à 32 Go.
Image

Excel (ou tout autre logiciel de statistiques) permet ensuite de d'analyser, retraiter et afficher vos données enregistrées.

Des pastilles de soudure sur une zone de 11 x 11 points permettent de prototyper directement sur la surface du circuit imprimé du shield.
Ici j'ai aussi rajouté un shield de prototypage avec sa petite breadboard bien pratique.
Image

Caractéristiques
  • Un régulateur intégré 3.3V alimente la carte SD et fournit par ailleurs une référence de tension précise.
  • Des leds témoins indiquent le bon fonctionnement.
  • 1 led d'alimentation (marquée Power) est allumée rouge si OK.
  • 2 LEDs sont disponibles pour l'utilisateur (marquées L1, L2).
  • La carte utilise l'adresse I2C sur 7 bits 0x68.
  • Un bouton reset est disponible.
  • 4 pins donnent accès au bus (5V, GND, SDA et SCL).
  • Des librairies servent à gérer le lecteur SD et l'horloge RTC.

Les sorties disponibles, en plus du brochage habituel de l'Arduino :
  • 3V est le régulateur de tension 3.3.V.
  • SQ est le signal carré (square) en sortie d'horloge.
  • WP Write Protect pour détecter si la carte SD est protégée en écriture.
  • CD Card Detect, si une carte mémoire est insérée (alors sur GND).
  • CS Chip Select (pour remplacer pin 10 en cas de conflit et accéder à la carte SD).
  • L1 et L2 les deux LEDS (avec 470Ohm déjà en série), qui s'allument sur HIGH.
___________________________________________________________________________________________________

Première partie : Utilisation de l'horloge en temps réel RTC.

La carte Arduino redémarre automatiquement son timer interne à chaque remise sous tension.

La fonction millis() chronomètre le temps écoulé depuis le dernier redémarrage, donc ce n'est pas un temps réel.
L'utilisation de l'horloge temps réel RTC du shield permet de conserver le temps exact écoulé, même hors tension.
Elle fonctionne avec une puce DS-1307.

Cette horloge est indispensable pour horodater des enregistrements par exemple. Il faut toujours placer une pile dans le logement, sinon le fonctionnement peut être erratique. Une fois la pile installée et l'heure réglée, on la laisse en place.

Le RTC est un dispositif I2C, il communique par seulement 2 fils, Analog4 et Analog5.

Téléchargez la librairie RTClib et l'installer dans le répertoire librairies (les 2 fichiers RTClib.cpp et RTClib.h, avec un sous-dossier examples).
Elle est disponible ici https://github.com/adafruit/RTClib

Les 3 exemples fournis :
* ds1307 met le module à l'heure à partir du PC et affiche date/heure/ temps écoulé
* datecalc fournit des exemples de calcul de dates (un an après, un jour après, une semaine après, etc...).
Il s'écoule 60*60*24 = 86400 secondes par jour, pour effectuer les calculs à partir de temps UNIX.
* softrtc réalise des calculs sur des dates.

______________________________________________________________________________________________________

Charger le premier programme d'exemple File / Example / RTClib / ds1307
Il est également disponible ici :
Code: Tout sélectionner
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//*****************************************************************
// Exemple d'utilisation du Shield Data Logger
// Réglage de l'horloge RTC
// tiptopboards.com 22 10 2014
//*****************************************************************
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

void setup () {
  Serial.begin(9600);
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();

  if (! rtc.isrunning()) {
    Serial.println("RTC ne fonctionne PAS!");
    // La ligne qui suit ajuste le RTC à la date et time du moment de compilation
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop () {
    DateTime now = rtc.now();
   
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
   
    Serial.print(" depuis miniut 01/01/1970 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("j");
   
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now.unixtime() + 7 * 86400L + 30);
   
    Serial.print(" maintenant + 7 jours + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
   
    Serial.println();
    delay(3000);   //Mise à jour toutes les 3 s
}


Dé-commenter la ligne RTC.adjust pour régler la date et l'heure sur le moment exact de compilation du programme dans le PC.
Image

Ce programme va afficher l'heure interne du shield :
Image
et faire quelques calculs de temps.

Les principales fonctions utiles :
now() permet de lire la date et l'heure actuelle,
unixtime fournit un timestamp qui chronomètre le nombre de secondes écoulées depuis le 1 janv 1970 (norme unix),

______________________________________________________________________________________________________

Le programme Datecalc fait des calculs sur les dates.
Image

Code: Tout sélectionner
// Simple date conversions and calculations

#include <Wire.h>
#include "RTClib.h"

void showDate(const char* txt, const DateTime& dt) {
    Serial.print(txt);
    Serial.print(' ');
    Serial.print(dt.year(), DEC);
    Serial.print('/');
    Serial.print(dt.month(), DEC);
    Serial.print('/');
    Serial.print(dt.day(), DEC);
    Serial.print(' ');
    Serial.print(dt.hour(), DEC);
    Serial.print(':');
    Serial.print(dt.minute(), DEC);
    Serial.print(':');
    Serial.print(dt.second(), DEC);
   
    Serial.print(" = ");
    Serial.print(dt.unixtime());
    Serial.print("s / ");
    Serial.print(dt.unixtime() / 86400L);
    Serial.print("d since 1970");
   
    Serial.println();
}

void setup () {
    Serial.begin(9600);
   
    DateTime dt0 (0, 1, 1, 0, 0, 0);
    showDate("dt0", dt0);

    DateTime dt1 (1, 1, 1, 0, 0, 0);
    showDate("dt1", dt1);

    DateTime dt2 (2009, 1, 1, 0, 0, 0);
    showDate("dt2", dt2);

    DateTime dt3 (2009, 1, 2, 0, 0, 0);
    showDate("dt3", dt3);

    DateTime dt4 (2009, 1, 27, 0, 0, 0);
    showDate("dt4", dt4);

    DateTime dt5 (2009, 2, 27, 0, 0, 0);
    showDate("dt5", dt5);

    DateTime dt6 (2009, 12, 27, 0, 0, 0);
    showDate("dt6", dt6);

    DateTime dt7 (dt6.unixtime() + 3600); // one hour later
    showDate("dt7", dt7);

    DateTime dt8 (dt6.unixtime() + 86400L); // one day later
    showDate("dt8", dt8);

    DateTime dt9 (dt6.unixtime() + 7 * 86400L); // one week later
    showDate("dt9", dt9);
}

void loop () {
}



______________________________________________________________________________________________

Deuxième partie : Utilisation de la carte SD

La carte amovible SD est une support de stockage de grande capacité.
Formatez la carte (sur un ordinateur) et insérez la dans le lecteur / enregistreur. Le chipselect est pin10.

Charger le programme File / Examples / SD/ CardInfo
et changer la ligne
Code: Tout sélectionner
const int chipSelect = 10;   

Image

Code: Tout sélectionner
/*
  SD card test
   
 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.
    
 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
       Pin 4 used here for consistency with other Arduino examples

 
 created  28 Mar 2011
 by Limor Fried
 modified 9 Apr 2012
 by Tom Igoe
 */
 // include the SD library:
#include <SD.h>

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

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 10;   

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("\nInitializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);     // change this to 53 on a mega


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
 
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

 
  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);
 
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
 
}

Ce programme affiche les fichiers déjà contenus sur la carte SD :

Image

______________________________________________________________________________________________

Troisième partie : réalisation d'une mini station météo


Dans cet exemple de datalogger, nous réalisons d'abord une petite station météorologique enregistrant la température de l'air, l'hygrométrie, et la luminosité.
On a vu comment utiliser l'horloge et la carte SD. Il ne reste plus qu'à rajouter des capteurs.

Le 5V de la carte ne doit pas être utilisé comme référence de tension pour un capteur (trop bruitée), se servir du 3.3V à relier à la pin AREF pour obtenir une meilleur précision.

Montage des capteurs sur le shield de prototypage

Image
Un capteur DHT-11 (température et humidité) une photorésistance, quelques fils et 2 résistances : c'est prêt

Branchement
  • Capteur 1 = Photorésistance (lumière) sur pin A0 analogique
  • Capteurs 2-3 = DHT11 humidité et température sur pin 5

Monter d'abord le proto-shield tout seul, pour tester les capteurs. On fera l'enregistrement ensuite.

Programme de test des capteurs

Code: Tout sélectionner
 
//**************************************************
// Exemple de petite station météo
// tiptopboards.com  17 10 2014
// demo_meteo
// Capteur 1 =   Photorésistance (lumière) sur A0
// Capteur 2-3 = DHT11 humidité            sur 5
//**************************************************
///Humidite avec le DHT11
const byte DHT11_PIN = 5;     //DHT11 sur pin5
byte temperature, humidity;   //dht11

/** Code d'erreur de la fonction readDHT11() */
enum {
  DHT11_SUCCESS, //!< Pas d'erreur
  DHT11_TIMEOUT_ERROR, //!< Temps d'attente dépassé
  DHT11_CHECKSUM_ERROR //!< Données reçues erronées
};

//Lumiere
int lumiere = 0;        // Mesure de lumière
int lumierePin = 0;     //Photorésistance sur A0 avec 1OK


//=========SETUP ==========
void setup() {
  Serial.begin(9600);  //Debugage
   Serial.println("Ma petite Station Meteo ");
}
 
 //=======LOOP ==============
void loop() {
  //lumiere
  lumiere = analogRead(lumierePin);
   Serial.println();  //ligne suivante
  Serial.print("Lumiere = ");
  Serial.print(lumiere);  //lecture de la photorésistance

  //humidite
   /* Lecture de la température et de l'humidité + gestion des erreurs */
  switch (readDHT11(DHT11_PIN, &temperature, &humidity)) {
  case DHT11_SUCCESS:
     
    /* Affichage de la température et du taux d'humidité */
    Serial.print("  Humidite = ");
    Serial.print((int) humidity);
    Serial.print("  Temperature = ");
    Serial.print((int) temperature);
    break;
 
  case DHT11_TIMEOUT_ERROR:
    Serial.println(F("Temps d'attente depasse !"));
    break;
 
  case DHT11_CHECKSUM_ERROR:
    Serial.println(F("Erreur de checksum !"));
    break;
  }
  delay(1000);  // mesurer chaque  seconde 1Hz
}

//========Fonction DHT11
/**
 * Lit la température et le taux d'humidité capté par un capteur DHT11
 *
 * @param pin Broche sur laquelle est câblé le capteur
 * @param temperature Pointeur vers la variable stockant la température
 * @param humidity Pointeur vers la variable stockant le taux d'humidité
 * @return DHT11_SUCCESS si aucune erreur, DHT11_TIMEOUT_ERROR en cas de timeout, ou DHT11_CHECKSUM_ERROR en cas d'erreur de checksum
 */
byte readDHT11(byte pin, byte* temperature, byte* humidity) {
 
  /* data[] -> buffer contenant les données du cpateur
   * counter -> compteur permettant de savoir quel bit est reçu (bitwise)
   * index -> compteur permettant de savoir quel octet est reçu (bitwise)
   * timeout -> compteur pour le timeout
   */
  byte data[5] = { 0 }, counter = 7, index = 0;
  unsigned int timeout;
 
  /* Conversion du numéro de broche Arduino en ports/masque binaire "bas niveau" */
  /* Utiliser les registres du microcontrôleur est bien plus rapide que digitalWrite() */
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *ddr = portModeRegister(port); // Registre MODE (INPUT / OUTPUT)
  volatile uint8_t *out = portOutputRegister(port); // Registre OUT (écriture)
  volatile uint8_t *in = portInputRegister(port); // Registre IN (lecture)
 
  /* Réveil du capteur */
  *ddr |= bit; // OUTPUT
  *out &= ~bit; // LOW
  delay(18); // Temps d'attente à LOW causant le réveil du capteur
  *out |= bit; // HIGH
  delayMicroseconds(40);
  *ddr &= ~bit; // INPUT
 
  /* Attente de la réponse du capteur */
  timeout = 0;
  while(!(*in & bit)) /* Attente d'un état LOW */
    if (++timeout == 10000)
      return DHT11_TIMEOUT_ERROR;
  timeout = 0;
  while(*in & bit) /* Attente d'un état HIGH */
    if (++timeout == 10000)
      return DHT11_TIMEOUT_ERROR;
 
  /* Lecture des données du capteur (40 bits) */
  for (byte i = 0; i < 40; ++i) {
 
    /* Attente d'un état LOW */
    timeout = 0;
    while(!(*in & bit))
      if (++timeout == 10000)
        return DHT11_TIMEOUT_ERROR;
 
    /* Mise en mémoire du temps courant */
    unsigned long t = micros();
 
    /* Attente d'un état HIGH */
    timeout = 0;
    while(*in & bit)
      if (++timeout == 10000)
        return DHT11_TIMEOUT_ERROR;
 
    /* Si le delta Temps est supérieur à 40µS c'est un "1", sinon c'est un "0" */
    if ((micros() - t) > 40)
      data[index] |= (1 << counter); // "1"
    // Le tableau data[] est initialisé à "0" par défaut <span class="wp-smiley wp-emoji wp-emoji-wink" title=";)">;)</span>
 
    /* Si le compteur de bits atteint zéro */
    if (counter-- == 0) {
      counter = 7; /* On passe à l'octet suivant */
      ++index;
    }
  }
 
  /* Format des données :
   * [0] = humidité en %
   * [1] = zéro
   * [2] = température en degrés Celsius
   * [3] = zéro
   * [4] = checksum (humidité + température)
   */
  *humidity = data[0];
  *temperature = data[2];
 
  /* Vérifie la checksum */
  if (data[4] != (data[0] + data[2]))
    return DHT11_CHECKSUM_ERROR; /* Erreur de checksum */
  else
    return DHT11_SUCCESS; /* Pas d'erreur */
}


Tout fonctionne correctement :
La résistance augmente quand la lumière diminue.
La température et l'hygrométrie augmentent si on souffle sur le capteur DHT11.

Image
_______________________________________________________________________________________________

Quatrième partie : Le data-logger météo complet

Programme d'enregistrement des capteurs sur la carte SD
Code: Tout sélectionner
//********************************************************
// Data logger qui enregistre des capteurs sur une carte SD
// la date, l'heure, la température, l'humidité et la lumière
//
//  demo_meteo_logger
//
//  tiptopboards.com  C. ROLLAND  22 10 2014
// adapté de https://github.com/adafruit/Light-and-Temp-logger/blob/master/lighttemplogger.pde
//
//********************************************************
#include <SD.h>      //Librairie SD
#include <Wire.h>    //Pour l'accès RTC
#include "RTClib.h"  //Librairie RTC pour Real Time Clock

// Intervalle d'acquisition de données, 1000ms = chaque seconde
#define LOG_INTERVAL  1000 // mills between entries (reduce to take more/faster data)

// Intervalle d'écriture sur disque SD
// Régler sur LOG_INTERVAL pour enregistrer à chaque mesure (plus sûr)
// Régler sur 10 x LOG_INTERVAL pour enregistrer une fois sur 10, plus rapide et économe en énergie
#define SYNC_INTERVAL 1000 // mills between calls to flush() - to write data to the card

uint32_t syncTime = 0; // time of last sync()

#define ECHO_TO_SERIAL   1 // 1 pour afficher sur le serial port
#define WAIT_TO_START    0 // Attente du  serial input dans le  setup()

// Les 2 LED témoins du shield datalogger
#define redLEDpin 2      //rouge
#define greenLEDpin 3    //vert

// Nos capteurs météo ici
// Capteur 1 =   Photorésistance (lumière) sur A0
// Capteur 2-3 = DHT11 humidité            sur 5
const byte DHT11_PIN = 5;     //Température et Humidite DHT11 sur pin5
byte temperature, humidity;   //dht11

/** Code d'erreur de la fonction readDHT11() */
enum {
  DHT11_SUCCESS, //!< Pas d'erreur
  DHT11_TIMEOUT_ERROR, //!< Temps d'attente dépassé
  DHT11_CHECKSUM_ERROR //!< Données reçues erronées
};

//Lumiere (photorésistance)
int lumiere = 0;        // Mesure de lumière
int lumierePin = 0;     //Photorésistance sur A0 avec 1OK

//  indicator pour measurer le bandgap
#define BANDGAPREF 14           

// On relie 3.3V sur ARef, tension précise qui sert de référence aux mesures analogiques
#define aref_voltage 3.3         
#define bandgap_voltage 1.1     

RTC_DS1307 RTC; // Objet  Real Time Clock

// Shield data-logger, SD = pin 10
const int chipSelect = 10;

// Le fichier d'enregistrement des mesures
File logfile;

// === gestion des erreurs
void error(char *str)
{
  Serial.print("erreur: ");
  Serial.println(str);

  // La LED rouge indique les erreurs
  digitalWrite(redLEDpin, HIGH);

  while(1);
}

// ==== Initialisation
void setup(void)
{
  Serial.begin(9600);   //Serial monitor pour le debugage
  Serial.println("Mon datalogger Meteo ");
  Serial.println();

  // LEDs témoin de débug
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);

#if WAIT_TO_START
  Serial.println("Taper une touche pour lancer le log");
  while (!Serial.available());
#endif //WAIT_TO_START

  // Initialiser la SD
  Serial.print("Initialiser la carte SD...");
  pinMode(10, OUTPUT);  //mêmesi on ne s'en sert pas

  // regarder si la carte SD est présente et initialisable
  if (!SD.begin(chipSelect)) {
    error("Carte SD echec ou absente");
  }
  Serial.println("carte initialisee");

  // Créer un nouveau fichier, on les numérote successivement
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // N'ouvrir un nouveau fichier que s il n'existe pas
      logfile = SD.open(filename, FILE_WRITE);
      break;  // quiter la boucle
    }
  }

  if (! logfile) {
    error("Nepeut pas creer le fichier");
  }

  Serial.print("Enregistrer dans : ");
  Serial.println(filename);

  // connection  RTC
  Wire.begin(); 
  if (!RTC.begin()) {
    logfile.println("RTC echec");
#if ECHO_TO_SERIAL
    Serial.println("RTC echec");
#endif  //ECHO_TO_SERIAL
  }

//Première ligne du fichier CSV pour excel
logfile.println("millis,stamp,dateheure,temperature,humidite,lumiere,vcc");   
#if ECHO_TO_SERIAL
  Serial.println("millis, stamp, dateheure, temperature, humidite, lumiere, vcc");   
#endif //ECHO_TO_SERIAL

  // Pourfixer aref sur autre chose que 5V
  analogReference(EXTERNAL);
}

// ======= Boucle de mesures
void loop(void)
{
  DateTime now;  //Instant actuel de mesure

  // Delai de scan entre mesures
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));

  digitalWrite(greenLEDpin, HIGH);  //LED témoin Vert

  // Enregistrer les millisecondes écoulées depuis le départ
  uint32_t m = millis();
  logfile.print(m);           // millisecondes depuis le départ
  logfile.print(", ");   
#if ECHO_TO_SERIAL
  Serial.print(m);         
  Serial.print(", "); 
#endif

  // Mesurer le time RTC
  now = RTC.now();
  logfile.print(now.unixtime()); // secondes depuis 01/01/1970
  logfile.print(", ");
  logfile.print('"');
  logfile.print(now.year(), DEC);  //année
  logfile.print("/");
  logfile.print(now.month(), DEC);  //mois
  logfile.print("/");
  logfile.print(now.day(), DEC);   //jour
  logfile.print(" ");
  logfile.print(now.hour(), DEC);  //heure
  logfile.print(":");
  logfile.print(now.minute(), DEC);  //minutes
  logfile.print(":");
  logfile.print(now.second(), DEC);  //secondes
  logfile.print('"');
#if ECHO_TO_SERIAL
  Serial.print(now.unixtime()); // secondes depuis 01/01/1970
  Serial.print(", ");
  Serial.print('"');
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
  Serial.print('"');
#endif //ECHO_TO_SERIAL

 //=== Lecture de nos capteurs meteo
  lumiere = analogRead(lumierePin);    //Lumiere
  //Serial.println();  //ligne suivante
  Serial.print(", ");
  Serial.print(lumiere);  //lecture de la photorésistance

  //Humidite et temperature
  // Lecture de la température et de l'humidité + gestion des erreurs
  switch (readDHT11(DHT11_PIN, &temperature, &humidity)) {
  case DHT11_SUCCESS:
     
    // Affichage de la température et du taux d'humidité de l'air
    Serial.print(", ");
    Serial.print((int) humidity);
    Serial.print(", ");
    Serial.print((int) temperature);
    break;
 
  case DHT11_TIMEOUT_ERROR:
    Serial.println(F("Temps d'attente depasse !"));
    break;
 
  case DHT11_CHECKSUM_ERROR:
    Serial.println(F("Erreur de checksum !"));
    break;
  }  //Fin de lecture des capteurs
 
   // === Stocker ces mesures en fichier de log
  logfile.print(", ");   
  logfile.print((int) temperature);
  logfile.print(", ");   
  logfile.print((int) humidity);
  logfile.print(", ");   
  logfile.print(lumiere);


  //Enregistrer aussi le Vcc estimé en mesurant le 1.1V interne
  analogRead(BANDGAPREF);
  delay(10);
  int refReading = analogRead(BANDGAPREF);
  float supplyvoltage = (bandgap_voltage * 1024) / refReading;

  logfile.print(", ");   //Fichier
  logfile.print(supplyvoltage);
#if ECHO_TO_SERIAL
  Serial.print(", ");     //Ecran
  Serial.print(supplyvoltage);
#endif // ECHO_TO_SERIAL

  logfile.println();
#if ECHO_TO_SERIAL
  Serial.println();
#endif // ECHO_TO_SERIAL

  digitalWrite(greenLEDpin, LOW);  //Eteindre en fin de mesure



  //Puis on écrit sur le disque, ne pas synchroniser trop souvent, requiert 2048 bytes of I/O to SD card
  //cequi consomme du temps et de la puissance
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();

  // Clignoter la LED rouge pour montrer qu'on sauvegarde les data sur la carte SD + update FAT
  digitalWrite(redLEDpin, HIGH);
  logfile.flush();
  digitalWrite(redLEDpin, LOW);

}

//========Fonction DHT11
/**
 * Lit la température et le taux d'humidité capté par un capteur DHT11
 *
 * @param pin Broche sur laquelle est câblé le capteur
 * @param temperature Pointeur vers la variable stockant la température
 * @param humidity Pointeur vers la variable stockant le taux d'humidité
 * @return DHT11_SUCCESS si aucune erreur, DHT11_TIMEOUT_ERROR en cas de timeout, ou DHT11_CHECKSUM_ERROR en cas d'erreur de checksum
 */
byte readDHT11(byte pin, byte* temperature, byte* humidity) {
 
  /* data[] -> buffer contenant les données du cpateur
   * counter -> compteur permettant de savoir quel bit est reçu (bitwise)
   * index -> compteur permettant de savoir quel octet est reçu (bitwise)
   * timeout -> compteur pour le timeout
   */
  byte data[5] = { 0 }, counter = 7, index = 0;
  unsigned int timeout;
 
  /* Conversion du numéro de broche Arduino en ports/masque binaire "bas niveau" */
  /* Utiliser les registres du microcontrôleur est bien plus rapide que digitalWrite() */
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *ddr = portModeRegister(port); // Registre MODE (INPUT / OUTPUT)
  volatile uint8_t *out = portOutputRegister(port); // Registre OUT (écriture)
  volatile uint8_t *in = portInputRegister(port); // Registre IN (lecture)
 
  /* Réveil du capteur */
  *ddr |= bit; // OUTPUT
  *out &= ~bit; // LOW
  delay(18); // Temps d'attente à LOW causant le réveil du capteur
  *out |= bit; // HIGH
  delayMicroseconds(40);
  *ddr &= ~bit; // INPUT
 
  /* Attente de la réponse du capteur */
  timeout = 0;
  while(!(*in & bit)) /* Attente d'un état LOW */
    if (++timeout == 10000)
      return DHT11_TIMEOUT_ERROR;
  timeout = 0;
  while(*in & bit) /* Attente d'un état HIGH */
    if (++timeout == 10000)
      return DHT11_TIMEOUT_ERROR;
 
  /* Lecture des données du capteur (40 bits) */
  for (byte i = 0; i < 40; ++i) {
 
    /* Attente d'un état LOW */
    timeout = 0;
    while(!(*in & bit))
      if (++timeout == 10000)
        return DHT11_TIMEOUT_ERROR;
 
    /* Mise en mémoire du temps courant */
    unsigned long t = micros();
 
    /* Attente d'un état HIGH */
    timeout = 0;
    while(*in & bit)
      if (++timeout == 10000)
        return DHT11_TIMEOUT_ERROR;
 
    /* Si le delta Temps est supérieur à 40µS c'est un "1", sinon c'est un "0" */
    if ((micros() - t) > 40)
      data[index] |= (1 << counter); // "1"
    // Le tableau data[] est initialisé à "0" par défaut <span class="wp-smiley wp-emoji wp-emoji-wink" title=";)">;)</span>
 
    /* Si le compteur de bits atteint zéro */
    if (counter-- == 0) {
      counter = 7; /* On passe à l'octet suivant */
      ++index;
    }
  }
 
  /* Format des données :
   * [0] = humidité en %
   * [1] = zéro
   * [2] = température en degrés Celsius
   * [3] = zéro
   * [4] = checksum (humidité + température)
   */
  *humidity = data[0];
  *temperature = data[2];
 
  /* Vérifie la checksum */
  if (data[4] != (data[0] + data[2]))
    return DHT11_CHECKSUM_ERROR; /* Erreur de checksum */
  else
    return DHT11_SUCCESS; /* Pas d'erreur */
}


On vérifie que tout se passe bien :
Image

Le fichier sur la carte SD est en format CSV (valeurs délimitées par des virgules).
On l'ouvre sur Excel, on répartit les valeurs en colonnes séparées (avec le menu Données / Convertir /Délimité / Virgule / Suivant / Terminer).
Image

Si besoin, remplacer les points décimaux par des virgules décimales.

Les données peuvent alors être affichées en graphiques, statistiques...
Image
_______________________________________________________________________________________________

Références
Sur le site Adafruit http://learn.adafruit.com/adafruit-data ... me-clock-1 (en anglais)
Notre tutoriel en français en est largement inspiré.

Télécharger les librairies officielles SD et RTC :
https://learn.adafruit.com/adafruit-dat ... /downloads
tiptopboards - admin
Avatar de l’utilisateur
tiptop
Administrateur du site
 
Messages: 88
Inscription: Mar 13 Aoû 2013 20:38
Localisation: 38

Retourner vers Projets complets

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité