Datalogger de température minimaliste et autonome (code Arduino + LM35)

par skywodd | | Langue : C++ | Licence : GPLv3

Description :

Datalogger de température minimaliste et autonome.

Code source :

Voir le code source brut | Télécharger datalogger_lm35.ino | Télécharger datalogger_lm35.ino.zip

/*
 * Datalogger de température minimaliste et autonome.
 */

#include <EEPROM.h>


/* Broche du capteur de température LM35DZ */
const byte TEMP_SENSOR_PIN = A5;

/* Broche pour l'activation du logging instantané */
const byte LOG_NOW_PIN = 2;

/* Constantes pour le mode lecture */
const String HELP_CMD = "HELP";
const String READ_CMD = "READ";
const String LOG_CMD = "LOG";
const String ERASE_CMD = "ZERO";
const unsigned long READ_CMD_TIMEOUT = 10000;

/* Constante pour le datalogging */
const unsigned long DELAY_BETWEEN_SAMPLE = 30000;


/* Buffer temporaire pour les données */
const unsigned int MAX_NB_SAMPLES = 256;
struct DataBuffer {
  unsigned int nb_samples;
  unsigned int samples[MAX_NB_SAMPLES];
};
DataBuffer data = { 0, { 0 } };


/** Fonction de conversion : valeur brute -> température */
float temperature(unsigned int value) {
  return value * 1.1 / 1023.0 * 100.0;
}


/** Terminal de commande */
void command() {
  
  /* Attends l'ordre de passage en mode lecture */
  Serial.setTimeout(READ_CMD_TIMEOUT);
  bool exit = false;
  while (!exit) {

    /* Lit la commande */
    Serial.print(F("CMD> "));
    String cmd = Serial.readStringUntil('\n');
    Serial.println(cmd);

    /* Interpréte la commande */
    if (cmd == HELP_CMD) {

      /* Menu aide */
      Serial.println(F("-- COMMAND LIST --"));
      Serial.println(F("HELP Display this help"));
      Serial.println(F("READ Read back data from memory"));
      Serial.println(F("LOG Starting logging data at last index"));
      Serial.println(F("ZERO Reset index and data values"));

    } else if (cmd == READ_CMD) {

      /* Affiche les données en mémoire */
      if (data.nb_samples) {
        Serial.println(F("Index; Data; Temperature"));
        for (unsigned int index = 0; index < data.nb_samples; ++index) {
          Serial.print(index);
          Serial.print(F("; "));
          Serial.print(data.samples[index]);
          Serial.print(F("; "));
          Serial.println(temperature(data.samples[index]), 2);
        }
      } else {
        Serial.println(F("No data in memory."));
      }

    } else if (cmd == LOG_CMD) { 

      /* Sortie du mode terminal */
      exit = true;

    } else if (cmd == ERASE_CMD) {  

      /* Vidage de la mémoire */
      Serial.print(F("ERASING ... "));
      data.nb_samples = 0;
      EEPROM.put(0, data);
      Serial.println(F("Memory erased."));        

    } else {
      
      /* Commande inconnue */
      Serial.println(F("ERROR (Bad command)"));
    }
  }
}

/** Fonction setup() */
void setup() {

  /* Initialise le port série */
  Serial.begin(115200);
  
  /* Référence analogique à 1.1 volts pour une meilleure précision */
  analogReference(INTERNAL);
  
  /* Load previous memory data */
  EEPROM.get(0, data);

  /* Lance le terminal de commande si la broche n'est pas activée */
  pinMode(LOG_NOW_PIN, INPUT_PULLUP);
  if (digitalRead(LOG_NOW_PIN) == HIGH) {
    command();
  }
  Serial.println(F("START LOGGING ..."));
}

/** Fonction loop() */
void loop() {
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();

  /* Mesure toutes les N millisecondes */
  if (currentMillis - previousMillis >= DELAY_BETWEEN_SAMPLE) {
    previousMillis = currentMillis;

    /* Arret en cas de fin de mémoire */
    if (data.nb_samples == MAX_NB_SAMPLES) {

      /* Empéche la surécriture des données */
      Serial.println(F("LOGGING STOPPED (Out of memory)"));
      for (;;);
    }

    /* Mesure la température */
    data.samples[data.nb_samples] = analogRead(TEMP_SENSOR_PIN);

    /* Debug */
    Serial.print(F("SAMPLE "));
    Serial.print(data.nb_samples);
    Serial.print(F(": "));
    Serial.print(data.samples[data.nb_samples]);
    Serial.print(F(" = "));
    Serial.println(temperature(data.samples[data.nb_samples]), 2);
    
    /* Sauvegarde */
    data.nb_samples += 1;
    EEPROM.put(0, data);
  }
  
  /* Active le mode commande si l'utilisateur passe le caractère '$' sur le port série */
  if (Serial.available() && Serial.read() == '$') {
    command();
    Serial.println(F("RESTART LOGGING ..."));
  } 
}