5. Dataloggers Autonomes

5.1. Note

Il existe d’autres logger dont au moins deux, tout à fait remarquables, constituent des alternatives à ce qui va suivre

Le choix de développer un autre type de datalogger est motivé par des considérations pédagogiques. Alog fait le choix d’utiliser des borniers et une carte embarquée spécifique alors que nous préférons développer un instrument fonctionnel à partir d’une breadbord ce qui permet de travailler en salle de TP avec des étudiants puis proposer une carte PCB pour l’instrument final — les étudiants adorent souder ! —. Nous souhaitons utiliser du «tout arduino» ou équivalent pour des raisons de cout et de facilité d’achalandement et parceque les étudiants peuvent prendre rapidement la main. Le CavePearl project est plus proche de notre objectif mais le code final en C++ et bien trop élaboré pour des étudiants de L3 en géosciences et le choix d’un arduino mini pro avec une connection RX/TX pour les communications série rend l’appropriation par les étudiants moins évidente.

L’idée qui soutend les loggers qui suivent est donc qu’ils doivent être facile de construction, de programmation et d’emploi quitte à ce que leur autonomie sur le terrain ne soit «que» de quelques mois ce qui est suffisant quand on ne travaille pas en Terre Adélie et qu’on demande aux étudiants d’aller relever les données de façon régulière :=)).

Enfin des loggers et pas un logger car la gestion du temps et de l’échantillonnage dépend du capteur. Par exemple pour une mini station météo qui mesure la tempérture, l’humidité et la pression on choisira un logger avec une mesure à pas de temps constant. Pour un pluviomètre par contre le pas de temps constant n’apporte rien voire (cf la discussion sur la station météo). Dans ce cas autant donc mettre le logger en sommeil profond en attente d’un signal de pluie qui le réveille.

5.2. Cahier des charges

  • Facile d’emploi: c’est important pour que des étudiants / collègues puissent prendre en main le système et le réparer ou le modifier en fonction de leur besoins. Nous avons choisi de prendre un Arduino donc, et dans la liste des systèmes disponibles pour ce V1, le choix s’est porté sur un Nano. Le Nano a l’avantage d’être petit, facile d’emploi (quasi équivalent à l’Uno). Qui plus est le Nano fonctionne en 5V ce qui évite l’utilisation de MOSFET et autres relais pour alimenter les capteurs.

  • Autonomie de plusieurs mois sur batteries alcalines, faciles à trouver partout dans le monde. En modifiant légèrement un Nano on peut arriver à une consommation en veille profonde ~0.1 mA ce qui permet de le faire tourner plusieurs mois sur des piles alcalines

  • Pas trop volumineux. Nano + piles + capteurs

  • Un logger par type de mesure ou par capteur. Cela permet de limiter la complexité du système d’une part, de limiter les pertes de données d’autre part (si un logger plante, les autres continuent de tourner). Enfin cela simpifie le schéma et limite l’encombrement !

5.3. Le Logger stricto sensu:

  • Un arduino Nano dont on a enlevé la led on/Off et le régulateur de voltage afin de faire tomber sa consommation à moins de ~0.1 mA en mode sommeil.

  • lecteur de carte mico-SD. Ici nous faisons le choix de l’uPesy. Outre que ce lecteur est fabriqué en France, il a une consommation ridicule en mode sommeil, de l’ordre du micro A, ce qui le rend parfait pour un logger autonome.

  • une horloge RTC: là nous avons deux choix la DS1307 ou la DS3231.

    • DS1307:

      • Avantage: elle consomme très peu avec sa batterie ~0.1 mA.

      • Inconvénients: elle dérive un peu (10mn par an environ il faut donc la resynchroniser une fois de temps en temps), et rend difficile l’usage du port I2C pour des capteurs.

    • DS3281.

      • Avantage: réveil et précision (1mn par an). Cette horloge RTC est plus précise sur la durée que la DS13107 (https://tutoduino.fr/tutoriels/derive-du-rtc-ds1307-ds3231/), elle permet en outre de déclencher une alarme qui réveille le micro-contrôleur.

      • Désavantage: elle consomme plus, ~0.4 mA, en la modifiant comme indiqué ailleurs.

5.4. Exemples de Logger à réveil (horloge RTC DS1307)

config

L’intérêt de ce logger c’est sa faible consommation et sa simplicité. On gagne au moins 0.2 mA par rapport au logger avec DS3231 (voire plus bas) soit un gain de l’ordre de 40 à 50% d’autonomie. Stricto sensu, Le DS1307 n’a pas d’horloge à proprement parler mais on peut en fabriquer une avec son port SQW. En effet ce port quand il est activé permet d’envoyer un signal de fréquence donné au port digital. En prenant une fréquence de 1Hz et en activant le pin2 en INPUT_PULLUP on peut fabriquer une horloge somme toute assez précise. On attache ensuite un interrupteur au port 2 qui lance une fonction de comptage à chaque passage haut-bas de l’oscillateur. Le signal de l’horloge étant propre il n’y a pas de comptage multiple (cf la discussion sur le DS3231 dans le vademecum). De cette façon, toutes les secondes, un compteur s’incrémente et il suffit d’inclure un test dans la boucle void() pour décider quand on arrête de dormir.

Après comparaison il semble que des successions de sommeil de 1 seconde ne conduisent pas à une augmentation de consommation significative par rapport à une longue durée de sommeil. Autre avantage, on évite les bidouilles exigées par le DS3231 pour économiser l’énergie (désouder le chargeur, la led et couper l’alimentation VCC du DS3231 pour l’obliger à vivre sur la batterie).

Enfin le désavantage, car il y en a un tout de même, est lié à la dérive de la DS1307 qui est de l’ordre de 10mn par an. Il faut donc penser à mettre l’horloge à jour une fois de temps en temps pour limiter cette dérive.

/*
* Nano Logger
*
* Lecteur de carte Upesy
* Horloge RTC DS1307
*
* port SQW utilisé comme réveil à la fréquence de 1hz avec une fonction de comptage
* port OFF du lecteur utilisé pour éteindre le lecteur de carte SD
*
* Dernier test le 19/08/2024
*
* F. Métivier
* CC BY-SA 4.0
*/
#include "LowPower.h"

/*
* Horloge RTC
*/
#include "Wire.h"
#include <RTClib.h>
#define ADRESSE_I2C_RTC 0x68 // adresse I2C de l'horloge RTC
RTC_DS1307 rtc;

const int pullupPin = 2; // pin de récupération du signal à 1Hz
const int DT=10; // interval entre les interruptions en s
volatile int jedors = 0; // comptage

/*
* Carte SD
*/
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10; // CS pin du lecteur SD sur Nano
const int SDOFFPIN = 3; // pin de sommeil du lecteur

Sd2Card card;
SdVolume volume;
SdFile root;

void setup()
{
Serial.begin(57600); // pour affichage dans le moniteur série
delay(10);

Wire.begin();
Wire.beginTransmission(ADRESSE_I2C_RTC);
rtc.begin();
rtc.writeSqwPinMode(DS1307_SquareWave1HZ);
DateTime now = rtc.now();
Wire.endTransmission();

pinMode(pullupPin,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pullupPin),jeCompte,FALLING);

pinMode(SDOFFPIN,OUTPUT);
digitalWrite(SDOFFPIN,HIGH);
delay(1000);

if (!SD.begin(chipSelect)){
    Serial.println("Problème avec le lecteur SD");
}
else {
    Serial.println("Lecteur SD ok");
}

char buff[] = "démarrage hh:mm:ss DDD, DD MM YYYY";
Serial.println(now.toString(buff));
delay(100);

}

void loop()
{

    LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
    if (jedors % DT == 0) {

        // arrêt des interruptions
        detachInterrupt(digitalPinToInterrupt(pullupPin));

        // démarrage série
        Serial.begin(57600);
        delay(100);

        // récupération de la date
        Wire.begin();
        Wire.beginTransmission(ADRESSE_I2C_RTC);
        DateTime now = rtc.now();
        Wire.endTransmission();

        Serial.print(now.year());
        Serial.print(F(","));
        Serial.print(now.month());
        Serial.print(F(","));
        Serial.print(now.day());
        Serial.print(F(","));
        Serial.print(now.hour());
        Serial.print(F(","));
        Serial.print(now.minute());
        Serial.print(F(","));
        Serial.print(now.second());
        Serial.print("\n");

        // réveil lecteur SD
        digitalWrite(SDOFFPIN,HIGH);
        delay(100);
        // écriture carte
        if (SD.begin(chipSelect)){
        File dataFile = SD.open("DATALOG.TXT", FILE_WRITE);

        if (dataFile) {
        // if the file is available, write to it:
            dataFile.print(now.year());
            dataFile.print(F(","));
            dataFile.print(now.month());
            dataFile.print(F(","));
            dataFile.print(now.day());
            dataFile.print(F(","));
            dataFile.print(now.hour());
            dataFile.print(F(","));
            dataFile.print(now.minute());
            dataFile.print(F(","));
            dataFile.print(now.second());
            dataFile.print("\n");
            dataFile.close();
        } else {
        Serial.println("Pas de fichier ?");
        }
        } else {
        Serial.println("Pas de carte ?");
        }

        delay(10);
        //mise en sommeil lecteur SD
        digitalWrite(SDOFFPIN,LOW);

        // arrêt Série
        Serial.end();
        // redémarrage interruptions
        attachInterrupt(digitalPinToInterrupt(pullupPin),jeCompte,FALLING);
    }

} //end void

void jeCompte(){
jedors++;
}

5.4.1. Alternative avec une horloge RTC DS3231

Autre configuration avec une RTC 3231

config

cf la section arduino du vademecum un exemple simple de cycles sommeil/réveil sans comptage double (un problème récurrent des pullup).

L’horloge RTC3231 consomme 0.4 mA une fois les modifications suivantes effectuées:

  • arrêt du chargeur,

  • desoudage (destruction plutôt) de la LED de puissance,

  • deconnexion du pin d’alimentation 5V ce qui oblige l’horloge à fonctionner sur sa batterie CR.

j’ai testé le logger avec un capteur BME 680 qui mesure la température, l’humidité, la pression et un contenu en gaz (pas très utile celui-là car on ne sait pas très bien de quels gaz il s’agit). En moyenne sur cet exemple la consommation est de l’ordre de 0.5 mA. l’autonomie approximative pour des piles alcaline sera alors (comptée en mois de 30 jours)

  • Batterie AAA (1000 mAh): 2.5 mois

  • Batterie AA (2500 mAh): 6.3 mois

5.5. Code Arduino pour un logger à réveil périodique

  • Capteur météo DHT11 qui fournit la température, et l’humidité

  • horloge RTC 1307

  • lecteur de carte SD uPesy

  • Mesure toutes les 10mn

  • Consommation ~0.2 - 0.3 mA

  • Autonomie sur 3 batteries AAA (1000 mAh): entre 4.5 et 7 mois

/*
* Nano Logger
*
* RTC 1307
* SD uPesy
* DHT 11
*
* Testé le 05/07
* Pour gagner un peu de temps et d'énergie enlever toutes les sorties série
*
* F. Métivier
* CC BY-SA 4.0
*/
#include "LowPower.h"

#include "Wire.h"
#include <RTClib.h>
#define ADRESSE_I2C_RTC 0x68 // Adresse I2C de l'horloge RTC
RTC_DS1307 rtc;

const int pullupPin = 2;
const int DT=600;
volatile int jedors = 0;

/*
* Carte SD
*/
#include <SPI.h>
#include <SD.h>

const int chipSelect = 10; // CS pin de la carte SD sur Nano
const int SDOFFPIN = 3;

Sd2Card card;
SdVolume volume;
SdFile root;

#include "DHT.h"

#define DHTPIN 4
#define DHTTYPE DHT11

DHT dht(DHTPIN,DHTTYPE);

void setup()
{
Serial.begin(57600); // pour affichage dans le moniteur série
delay(10);

Wire.begin();
Wire.beginTransmission(ADRESSE_I2C_RTC);
rtc.begin();
rtc.writeSqwPinMode(DS1307_SquareWave1HZ);
DateTime now = rtc.now();
Wire.endTransmission();

pinMode(pullupPin,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pullupPin),jeCompte,FALLING);

pinMode(SDOFFPIN,OUTPUT);
digitalWrite(SDOFFPIN,HIGH);
delay(1000);


if (!SD.begin(chipSelect)){
    Serial.println("problème avec le lecteur SD");
}
char buff[] = "démarrage hh:mm:ss DDD, DD MM YYYY";
Serial.println(now.toString(buff));
delay(100);

digitalWrite(SDOFFPIN,LOW);

}

void loop()
{

    LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
    if (jedors % DT == 0) {
        // arrêt des interruption
        detachInterrupt(digitalPinToInterrupt(pullupPin));

        // démarrage série
        Serial.begin(57600);
        delay(100);

        // récupération de la date
        Wire.begin();
        Wire.beginTransmission(ADRESSE_I2C_RTC);
        DateTime now = rtc.now();
        // donné pour exemple mais À ÉVITER
        String sentence = String(now.year())+";"+String(now.month())+";"+String(now.day())+";"+String(now.hour()) + ";" + String(now.minute())+ ";" + String(now.second()) + ";";
        Wire.endTransmission();
        delay(100);

        // démarrage capteur DHT11
        dht.begin();
        delay(100);
        sentence += String(dht.readTemperature()) + ";" + String(dht.readHumidity()) ;

        Serial.println(sentence);

        // réveil lecteur SD
        digitalWrite(SDOFFPIN,HIGH);
        delay(10);
        // écriture carte
        if (SD.begin(chipSelect)){
        File dataFile = SD.open("DATALOG.TXT", FILE_WRITE);

        if (dataFile) {
        // if the file is available, write to it:
        dataFile.print(sentence+"\n");
        dataFile.close();
        } else {
        Serial.println("Pas de fichier ?");
        }
        } else {
        Serial.println("Pas de carte ?");
        }

        delay(10);
        //mise en sommeil lecteur SD
        digitalWrite(SDOFFPIN,LOW);

        // arrêt série
        Serial.end();
        // redémarrage interruptions
        attachInterrupt(digitalPinToInterrupt(pullupPin),jeCompte,FALLING);
    }

} //end void

void jeCompte(){
jedors++;
}

5.6. Références

Dernière modification le 2024-11-08