Contrôleur de T° avec sauvegarde en SD

Bonsoir
Ce post s’adresse à JML car je souhaite reprendre une partie de son code Contrôleur de T°, Humidité avec pilotage manuel ou automatique publié en 2017
il est indiqué le nombre de capteur = 1

// Le nombre de capteurs de t° DS18820 sur le bus oneWire
const byte nbCapteursDS18820 = 1;
const int resolution = 10; // en bits --> Max 12 bit, min 9 bit (9bit prends 95ms, 10bit 187ms, 11bit 375ms et 12bit 750ms)
const unsigned long periodeTemperature = 250; // 250ms est OK pour une résolutoin en 10 bits. au minimum attendre (750 / (1 << (12 - resolution)));
const float tempTropChaudDelta = 2; // déclenchement chauffage si T° sous la consigne, arrêt au dela de la consigne + tempTropChaudDelta
const int minTemp = -30, maxTemp = 100;

Je souhaite utiliser deux capteurs pour piloter séparément deux électrovannes
Merci de vos conseils pour le code

le code gère déjà plusieurs capteurs et maintient les valeurs lues dans le tableau temperaturesDS18820, donc il n'y a rien d'autre à faire que de mettre 2 dans la constante et de brancher le second DS18820

la fonction void regulation() est appelée automatique à chaque tour de loop et comme documenté vous avez tous les éléments disponibles pour votre algo

Comme le code gère 4 pins en sorties

  4  = pin relai Chauffage (génération de chaud)
  5  = pin relai Humidificateur
  6  = pin relai Ventilateur (PWM utilsé pour le pilotage de cette pin)
  7  = pin relai Climatiseur (génération de froid)

à vous de décider celles que vous utilisez vraiment pour l'électrovanne 1 et l'électrovanne 2

Bonsoir

Merci, je vais essayer de désactiver tout ce que je n’ai pas besoin pour mon projet qui est d’utiliser simplement deux sondes de T° pour piloter deux électrovannes, ajuster des T° de consignes, et archiver les données pour voir l’évolution en fonction des heures et des jours
Si je rencontre des difficultés je me permettrai de vous demander conseils

Bonsoir
Je reviens sur mon projet, après avoir essayer de supprimer ce qui me paraissait inutile à mes besoins, J’ai un code défaut qui apparait sur le Void Loop
Merci de votre aide pour comprendre ce qui ne va pas
Pour votre info, je souhaite aussi utiliser ma deuxième sonde en remplacement de la sonde d’humidité, et ainsi avoir l’affichage de deux températures et de deux consignes



/*
   ********************************************************
     AUTEUR J-M-L pour forum Arduino
     http://forum.arduino.cc/index.php?topic=559714.0
     Pour Arduino UNO ou Arduino MEGA (MEGA NECESSAIRE POUR LA FONCTION CARTE DS)
     Code libre de droits, mention de l'origine appréciée
     Librairies propriété de leurs auteurs respectifs
     Sans garantie aucune de bon fonctionnement :)
   ********************************************************

   PINS UTILISEES
   --------------
  0,1 = Rx,Tx - port Série pour communication USB
  2   = laissée libre si besoin d'interruption
  3  = pour le bus 1 wire avec une résistance de 4.7KΩ entre 5V et pin 3
  4  = pin relai Chauffage (génération de chaud)
  5  = pin relai Humidificateur
  6  = pin relai Ventilateur (PWM utilsé pour le pilotage de cette pin)
  7  = pin relai Climatiseur (génération de froid)
  8  = pin bouton MODE
  9  = pin bouton Chauffage
  10 = pin bouton Humidificateur
  11 = pin bouton Ventilateur
  12 = pin bouton Climatiseur
  13 = LED_BUILTIN affichage de l'état du système (éteinte quand système éteint)

  48 = pin d'une LED (avec sa résistance de limitation de courant) qui sera allumée pendant le LOG
  50 = SD MISO  pour la communication SPI (avec la carte SD)
  51 = SD MOSI  pour la communication SPI (avec la carte SD)
  52 = SD SCK   pour la communication SPI (avec la carte SD)
  53 = SD CS    pour la communication SPI (avec la carte SD)

  A0 = pin pour le potentiomètre de Consigne
  A1
  A2
  A3
  SDA, SCL = I2C communication (UNO = A4 (SDA) + A5 (SCL) / MEGA = 20 (SDA) + 21 (SCL))

  COMPOSANTS UTILISES
  -------------------
  5 boutons momentannés
  un LCD 2 lignes 16 caractères
  une horloge DS3231
  un DS18820 avec la résistance de 4.7KΩ qui va bien pour la température (le code gère plusieurs DS18820)
  un Si7021 en I2C pour une l'humidité (et une autre mesure de t°). (préféré au DHT22 car plus rapide)
  un "te291 level shifter" = adaptateur de tension I2C car le Si7021 ne  fonctionne qu'en 3.3V
  un potentiomètre à glissière ou rotatif

  LIBRAIRIES UTILISEES
  --------------------
  LiquidCrystal_I2C                   https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
  RTClib                              https://github.com/adafruit/RTClib
  SparkFun_Si7021_Breakout_Library    https://github.com/sparkfun/Si7021_Breakout (read and fix with https://github.com/sparkfun/Si7021_Breakout/issues/14)
  OneButton                           https://github.com/mathertel/OneButton
  DallasTemperature                   https://github.com/milesburton/Arduino-Temperature-Control-Library
  SDFat                               https://github.com/greiman/SdFat
  OneWire                             dernière version maintenue par Paul Stoffregen https://github.com/PaulStoffregen/OneWire
  EEPROM                              en standard dans l'IDE


  CABLAGE
  -------
  boutons en INPUT_PULLUP donc 1 côté vers la pin Arduino, un côté vers GND
  RTC en I2C sous 5V (SDA, SCL, 5V, GND)
  LCD en I2C sous 5V (SDA, SCL, 5V, GND)
  Si7021 en I2C sous 3.3 V donc alimentation en 3.3V et usage du te291 level shifter pour transformer SDA et SCL de 5V en 3.3V
  Potentiomètre en câblage standard (Vcc 5V, GND et broche mesure vers Pin Arduino)

  Carte SD en SPI, utilise les pins standard de la carte MEGA
    Vcc sous 5V, GND à GND
    SD MISO <---> Arduino MEGA 50
    SD MOSI <---> Arduino MEGA 51
    SD SCK  <---> Arduino MEGA 52
    SD CS   <---> Arduino MEGA 53

  Pin 48 <---> ANODE LED <---> RESISTANCE 200Ω (adaptée à votre LED) <---> GND  (led d'activité carte SD)

*/

// **********************************************************
// les définitions
// **********************************************************
enum : byte {automatique, manuel, param, eteint } mode = automatique; // pour le mode de fonctionnement
enum commandeAppareil : byte {MARCHE = LOW, ARRET = HIGH, INCONNUE = 0xFF}; // pour la commande des relais, relai éteint sur HIGH (inverser sinon les valeurs)

// Les PINS pour la commande des RELAIS
const byte onewireBusPin = 3;    // pin 4 pour le bus 1 wire avec une résistance de 4.7KΩ entre 5V et pin 4

const byte pinChauffage = 4;
const byte pinHumidificateur = 5;
//const byte pinVentilateur = 6;
//const byte pinClimatiseur = 7;

// Les PINS pour les boutons
const byte buttonModePin = 8;
const byte boutonChauffagePin = 9;
const byte boutonHumidificateurPin = 10;
//const byte boutonVentilateurPin = 11;
//const byte boutonClimatiseurPin = 12;

// La PIN pour le potentiomètre de consigne
const byte pinConsigne = A0;

// les éléments  d'affichage
const byte xClock = 0, yClock = 0;
const byte xMode = 0, yMode = 1;
const byte xVConsigne = 6, yVConsigne = 0;
const byte xTConsigne = 7, yTConsigne = 0;
const byte xRelais = 2, yRelais = 1;
const byte xHum = 12, yHum = 1;
const byte xHConsigne = 12, yHConsigne = 0;
const byte xTemp = 7, yTemp = 1;


// adresse LDC 0x27 16 caractères, 2 lignes
const byte adresseI2CLCD = 0x27;
const byte nbCol = 16;
const byte nbLignes  = 2;

// Le nombre de capteurs de t° DS18820 sur le bus oneWire
const byte nbCapteursDS18820 = 2;
const int resolution = 10; // en bits --> Max 12 bit, min 9 bit (9bit prends 95ms, 10bit 187ms, 11bit 375ms et 12bit 750ms)
const unsigned long periodeTemperature = 250; // 250ms est OK pour une résolutoin en 10 bits. au minimum attendre (750 / (1 << (12 - resolution)));
const float tempTropChaudDelta = 2; // déclenchement chauffage si T° sous la consigne, arrêt au dela de la consigne + tempTropChaudDelta
const int minTemp = -30, maxTemp = 100;

/*
  // gestion du SI7021 humidité (et T°)
  const byte resolutionSI7021 = 0; // valeur par défaut 0 -> RH=12 bits, T° = 14 bits. dans [0..3] (cf page 25 de https://cdn.sparkfun.com/assets/learn_tutorials/4/6/7/Si7021Datasheet.pdf)
  const unsigned long periodeHumidite = 1000ul; // période de mise à jour de la lecture
  const int minHum = 0, maxHum = 100;
  const float deltaTropHumide = 2; // gestion hysteresis
*/
// Gestion de la carte SD et du LOG
const uint8_t chipSelect = SS; // On utilise la pin par défaut pour la carte SD
const uint8_t SDActivePin = 48; // On passe cette PIN à HIGH pendant qu'on écrit sur la carte SD
const uint32_t LOG_INTERVAL_MS = 5000; // (5 * 60 * 1000UL); // 5 minutes (attention de bien mettre le UL pour ne pas faire les calculs en int mais bien en unsigned long)
const char * extensionFichierLog = ".LOG"; // L'extension utilisée pour tous nos fichiers (format .XXX -> un point et 3 caracteres max)

// **********************************************************
// Gestion EEPROM
// **********************************************************
#include <EEPROM.h>

const uint32_t motClef = 0xBEEFDEAD;
const uint16_t adresseMotClef = 0x00;

// __attribute__ ((packed)) permet de forcer la conservation de l'ordre des champs
// c'est utile pour éviter que le compilateur mette le bazar quand on en rajoute au fil du temps
struct __attribute__ ((packed)) _paramS {
  int16_t tempConsigne;
  int16_t humConsigne;
  // int16_t ventConsigne;
  // byte   vitesseVentilateur; // PWM pour le ventilateur
} lesParametres;

const uint16_t adresseDesParametres = adresseMotClef + sizeof(motClef);



// **********************************************************
// Gestion du LCD
// **********************************************************
#include <LiquidCrystal_I2C.h> // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library


LiquidCrystal_I2C lcd( adresseI2CLCD, nbCol, nbLignes);

// les caractères fréquents
const char * degree = "\337"; // °
const char space = ' '; // espace
const char colon = ':'; // symbole pour séparer les heures des minutes (on peut aussi mettre 'h')
const char zero = '0';

const char symboleChauffageOn       = 'C';
//const char symboleVentilateurOn     = 'V';
const char symboleHumidificateurOn  = 'H';
//const char symboleClimatiseurOn     = 'F';

// caractères spéciaux pour la force du ventilateur
/*uint8_t ventilateurF_s[][8] = {
  {0b00000, 0b00000, 0b00000, 0b00000, 0b10001, 0b10001, 0b01010, 0b00100},
  {0b00000, 0b00000, 0b00000, 0b00000, 0b10101, 0b10001, 0b01010, 0b00100},
  {0b00000, 0b00000, 0b00000, 0b00100, 0b10101, 0b10001, 0b01010, 0b00100},
  {0b00000, 0b00000, 0b00100, 0b00100, 0b10101, 0b10001, 0b01010, 0b00100},
  {0b00000, 0b00100, 0b00100, 0b00100, 0b10101, 0b10001, 0b01010, 0b00100},
  {0b00100, 0b00100, 0b00100, 0b00100, 0b10101, 0b10001, 0b01010, 0b00100}
  };

*/
// **********************************************************
// LES RELAIS DES APPAREILS DE CONTROLE DE L'ENVIRONNEMENT
// **********************************************************

boolean chauffageOn  = false;
boolean humidificateurOn  = false;
//boolean ventilateurOn  = false;
//boolean climatiseurOn = false;


void chauffage(commandeAppareil c)
{
  if ((chauffageOn ? MARCHE : ARRET) != c) { // si on change d'état
    chauffageOn  = (c == MARCHE);
    digitalWrite(pinChauffage, c);
    lcd.setCursor(xRelais, yRelais);
    lcd.write(chauffageOn ? symboleChauffageOn : space);
  }
}

void humidificateur(commandeAppareil c)
{
  if ((humidificateurOn ? MARCHE : ARRET) != c) { // si on change d'état
    humidificateurOn  = (c == MARCHE);
    digitalWrite(pinHumidificateur, c);
    lcd.setCursor(xRelais + 1, yRelais);
    lcd.write(humidificateurOn ? symboleHumidificateurOn : space);
  }
}

/*void ventilateur(commandeAppareil c)
  {
  if ((ventilateurOn ? MARCHE : ARRET) != c) { // si on change d'état
    ventilateurOn  = (c == MARCHE);
    if (ventilateurOn) analogWrite(pinVentilateur, lesParametres.vitesseVentilateur); // PWM
    else digitalWrite(pinVentilateur, LOW);
    lcd.setCursor(xRelais + 2, yRelais);
    lcd.write(ventilateurOn ? symboleVentilateurOn : space);
  }
  }

  void climatiseur(commandeAppareil c)
  {
  if ((climatiseurOn ? MARCHE : ARRET) != c) { // si on change d'état
    climatiseurOn  = (c == MARCHE);
    digitalWrite(pinClimatiseur, c);
    lcd.setCursor(xRelais + 3, yRelais);
    lcd.write(climatiseurOn ? symboleClimatiseurOn : space);
  }
  }
*/
void eteindreTousLesSystemes()
{
  // ici éteindre tous les relais
  chauffage(ARRET);
  humidificateur(ARRET);
  // ventilateur(ARRET);
  // climatiseur(ARRET);
}

// force l'affichage des symboles
void afficheEtatSystemes()
{
  lcd.setCursor(xRelais, yRelais);
  lcd.write(chauffageOn ? symboleChauffageOn : space);
  lcd.write(humidificateurOn ? symboleHumidificateurOn : space);
  // lcd.write(ventilateurOn ? symboleVentilateurOn : space);
  // lcd.write(climatiseurOn ? symboleClimatiseurOn : space);
}


// **********************************************************
// le potentiomètre sert à modifier les consignes
// **********************************************************


void displayConsigne(boolean forceDisplay = false)
{
  int16_t c;

  if (forceDisplay) {
    lcd.setCursor(xVConsigne, yVConsigne);
    //   lcd.write(lesParametres.ventConsigne);
    //    lcdTemperature(lesParametres.tempConsigne, xTConsigne, yTConsigne);
    //    lcdHumidite(lesParametres.humConsigne, xHConsigne, yHConsigne);
  }
  /*
    // Les consignes T° et H ne sont modifiables qu'en mode param
    if (mode == param) {
      analogRead(pinConsigne); // double lecture pour stabiliser la mesure (au cas où d'autres lectures proches existeraient)
      if ((digitalRead(boutonChauffagePin) == LOW) || (digitalRead(boutonClimatiseurPin) == LOW) ) {     // il faut appuyer sur le bouton de Chauffage ou clim pour modifier la consigne T°
        c = map(analogRead(pinConsigne), 0, 1023, minTemp, maxTemp);
        if (c != lesParametres.tempConsigne) {
          lesParametres.tempConsigne = c;
          lcdTemperature(c, xTConsigne, yTConsigne);
        }
      } else if (digitalRead(boutonHumidificateurPin) == LOW) {      // il faut appuyer sur le bouton de l'humidificateur pour modifier la consigne Humidité
        c = map(analogRead(pinConsigne), 0, 1023, minHum, maxHum);
        if (c != lesParametres.humConsigne) {
          lesParametres.humConsigne = c;
          lcdHumidite(c, xHConsigne, yHConsigne);
        }
      }
    }
  */
  /*  // la vitesse du ventilateur est modifiable tout le temps (mais ne sera sauvegardée que si modifiée en mode Param)
    if (digitalRead(boutonVentilateurPin) == LOW) {      // il faut appuyer sur le bouton du ventilateur pour modifier la force du ventilo
      byte vv = map(c = analogRead(pinConsigne), 0, 1023, 0, 255);
      if (vv != lesParametres.vitesseVentilateur) {
        lesParametres.vitesseVentilateur = vv;
        lesParametres.ventConsigne = constrain(c / 171, 0, 5);
        lcd.setCursor(xVConsigne, yVConsigne);
        lcd.write(lesParametres.ventConsigne);
        if (ventilateurOn) analogWrite(pinVentilateur, lesParametres.vitesseVentilateur); // met à jour le PWM
      }
    }
    }
  */

  // **********************************************************
  // L'HORLOGE RTC
  // **********************************************************
#include "RTClib.h" // https://github.com/adafruit/RTClib (import adafruit RTCLib library)
  RTC_DS3231 rtc;


  void lcdPrint2Digits(uint8_t n, const char padding = space)
  {
    if (n < 10) lcd.print(padding);
    lcd.print(n);
  }

  void displayTime(boolean forceUpdate = false)
  {
    const unsigned long updatePeriod = 1000ul; // UL = unsigned long
    static unsigned long t0 = 0;
    static byte _h = 0, _m = 0;
    byte h, m;
    DateTime now;

    if (mode == eteint) return;

    if (forceUpdate) {
      now = rtc.now();
      _h = h = now.hour();
      _m = m = now.minute();
      lcd.setCursor(xClock, yClock);
      lcdPrint2Digits(h); lcd.write(colon);
      lcdPrint2Digits(m, zero);
      t0 = millis();
    } else if ((millis() - t0 >= updatePeriod) || (t0 == 0)) {
      now = rtc.now();
      h = now.hour();
      m = now.minute();
      if (_h != h) {
        lcd.setCursor(xClock, yClock); lcdPrint2Digits(_h = h);
      }
      if (_m != m) {
        lcd.setCursor(xClock + 3, yClock); lcdPrint2Digits(_m = m, zero);
      }
      t0 += updatePeriod;
    }
  }


  // **********************************************************
  // Gestion des DS18820 (dans ce code on n'affiche que le dernier)
  // **********************************************************

#include <OneWire.h>
#include <DallasTemperature.h>    // https://github.com/milesburton/Arduino-Temperature-Control-Library

  OneWire oneWire(onewireBusPin);
  DallasTemperature sensors(&oneWire);
  DeviceAddress DS18820Address[nbCapteursDS18820];
  float temperaturesDS18820[nbCapteursDS18820];
  unsigned long  chronoTemperatures = 0;

  void lcdTemperature(int t, byte x, byte y)
  {
    // on sait que la température est entre -55° et 125°, donc la longeur max de la chaîne 125° = 4 caractères
    char affichage[5]; // 4 carcatères + 1 pour le '\0'
    char tmpBuffer[5];
    // on s'assure de tenir sur 3 digits
    if (t < -99) t = -99;
    else if (t > 999) t = 999;
    itoa(t, tmpBuffer, 10); // connvertir en chaîne, cf http://www.cplusplus.com/reference/cstdlib/itoa/?kw=itoa

    strcat(tmpBuffer, degree); // ajoute le symbole '°'
    memset(affichage, space, sizeof(affichage)); // on replit d'espaces
    strcpy(affichage + sizeof(affichage) - strlen(tmpBuffer) - 1, tmpBuffer); // on cadre à droite
    lcd.setCursor(x, y);
    lcd.print(affichage);
  }

  void displayTemperature(boolean forceDisplay = false)
  {
    if (forceDisplay) {
      while (millis() - chronoTemperatures < periodeTemperature); // on attend que les t° soient prêtes
    }

    // est-ce le moment le lire les capteurs de température?
    if (millis() - chronoTemperatures >= periodeTemperature) {
      float t;
      for (int i = 0; i < nbCapteursDS18820; i++) {
        t = sensors.getTempCByIndex(i); // lire les T°
        // On n'affiche que la valeur du dernier capteur
        if ((i == nbCapteursDS18820 - 1) && ((((int) t) != ((int) temperaturesDS18820[i])) || forceDisplay)) {
          lcdTemperature((int) t, xTemp, yTemp);
        }
        temperaturesDS18820[i] = t; // mais on stocke bien la bonne valeur
      }
      // on relance une requete pour la prochaine fois
      sensors.requestTemperatures();
      chronoTemperatures = millis();
    }
  }

  // **********************************************************
  // Température et humidité du Si7021
  // **********************************************************
#include "SparkFun_Si7021_Breakout_Library.h" // https://github.com/sparkfun/Si7021_Breakout

  float temperatureSi7021;
  float humiditeSi7021;

  // instance de gestion du SI7021 temp & humidité
  Weather SI7021;
  unsigned long  chronoHumidite = 0;

  void lcdHumidite(int h, byte x, byte y)
  {
    // on sait que l'humidité est entre 0% et 100%, donc la longeur max de la chaîne 100% = 4 caractères
    char affichage[5]; // 4 carcatères + 1 pour le '\0'
    char tmpBuffer[5];
    // on s'assure de tenir sur 3 digits
    if (h < 0) h = 0;
    else if (h > 999) h = 999; // ne devrait jamais arriver car 100 est le max
    itoa(h, tmpBuffer, 10); // connvertir en chaîne, cf http://www.cplusplus.com/reference/cstdlib/itoa/?kw=itoa

    strcat(tmpBuffer, "%"); // ajoute le symbole '%'
    memset(affichage, space, sizeof(affichage)); // on replit d'espaces
    strcpy(affichage + sizeof(affichage) - strlen(tmpBuffer) - 1, tmpBuffer); // on cadre à droite
    lcd.setCursor(x, y);
    lcd.print(affichage);
  }

  void displayHumidite(boolean forceDisplay = false)
  {
    if (forceDisplay) {
      while (millis() - chronoHumidite < periodeHumidite);
    }

    // est-ce le moment le lire les capteurs de température?
    if (millis() - chronoHumidite >= periodeHumidite) {
      float h = SI7021.getRH(); // déclenche aussi la lecture de la T°
      temperatureSi7021 = SI7021.readTemp(); // °C. la T° est mesurée avec chaque demande d'humidité donc plus rapide que de faire getTemp()
      if ((((int) h) != ((int) humiditeSi7021)) || forceDisplay) {
        lcdHumidite((int) h, xHum, yHum);
      }
      humiditeSi7021 = h;
    }
  }



  // **********************************************************
  // Gestion CARTE SD
  // **********************************************************
  // La carte SD
  // utilise les pins standard de la carte MEGA (50, 51, 52 et 53)

#include <SPI.h>
#include "SdFat.h"

  // SD card chip select pin.
#include <SPI.h>
#include "SdFat.h"

  // gestion du File system
  SdFat sd;


  char * nomDuFichierLog()
  {
    // on crée un fichier par mois
    static char _nomDuFichierLog[13]; //  "AAAAMM.LOG"

    DateTime now = rtc.now();
    // Convertir les données en chaines http://www.cplusplus.com/reference/cstdlib/itoa/
    itoa (now.year(), _nomDuFichierLog, 10); // initialise les 4 premiers caractères

    if (now.month() < 10) { // on met un zéro
      _nomDuFichierLog[4] = '0';
      _nomDuFichierLog[5] = '0' + now.month();
    } else {
      _nomDuFichierLog[4] = '1';
      _nomDuFichierLog[5] = '0' + now.month() - 10;
    }

    _nomDuFichierLog[6] = '\0';
    strcat(_nomDuFichierLog, extensionFichierLog);
    return _nomDuFichierLog;
  }

  void logToutesDonnees()
  {
    // ************************************************************************************
    // ici sauvegardez les données comme vous le souhaitez
    // ************************************************************************************
    //    éléments disponibles:
    //    temperaturesDS18820[]       => tableau des T° lues sur les DS18820. On en a nbCapteursDS18820 (ce sont des float)
    //    temperatureSi7021           => la T° lue sur le Si7021 (float)
    //    humiditeSi7021              => l'humidité relative lue sur le Si7021 (float)
    //    lesParametres.tempConsigne  => la température telle que fournie par l'utilisateur
    //    tempTropChaudDelta          => une constante du programme
    //    humiditeMin                 => une constante du programme (seuil min d'humidité)
    //    humiditeMax                 => une constante du programme (seuil max d'humidité)
    //    chauffageOn                 => vrai si allumé
    //    humidificateurOn            => vrai si allumé
    //    ventilateurOn               => vrai si allumé
    //    climatiseurOn               => vrai si allumé
    //    mode                        ==> une valeur de l'enum {automatique, manuel, param, eteint}
    // ************************************************************************************

    const char * tabulation = "\t";
    const char * virgule = ", ";
    static unsigned long derniereSauvegarde = 0;

    if (millis() - derniereSauvegarde < LOG_INTERVAL_MS) return;

    SdFile fichier;

    if (fichier.open(nomDuFichierLog(), O_CREAT | O_WRITE | O_AT_END)) {
      DateTime now = rtc.now();

      // On ALLUME la LED d'incation d'activité SD
      digitalWrite(SDActivePin, HIGH);

      // On log le temps unix (nombre de secondes sur 32-bit depuis le 1/1/1970)
      fichier.print(now.unixtime());
      fichier.print(tabulation);

      // On log la date
      fichier.print(now.year());
      fichier.print('/');
      if (now.month() < 10) fichier.write('0');
      fichier.print(now.month());
      fichier.print('/');
      if (now.day() < 10) fichier.write('0');
      fichier.print(now.day());

      // On log l'heure
      fichier.print(tabulation);
      if (now.hour() < 10) fichier.write('0');
      fichier.print(now.hour());
      fichier.print(':');
      if (now.minute() < 10) fichier.write('0');
      fichier.print(now.minute());
      fichier.print(':');
      if (now.second() < 10) fichier.write('0');
      fichier.print(now.second());

      // on log les T° des DS18820
      if (nbCapteursDS18820 > 0) {
        fichier.print(tabulation);
        fichier.print(F("DS18820={"));
        for (int i = 0; i < nbCapteursDS18820; i++) {
          fichier.print(temperaturesDS18820[i], 1); // 1 chiffres après la virgule ensuite c'est  pas vraiment significatif
          if (i != nbCapteursDS18820 - 1) fichier.print(virgule);
        }
        fichier.print(F("}"));
      }

      // on log la T° et Humidité du Si7021
      fichier.print(tabulation);
      fichier.print(F("Si7021={"));
      fichier.print(temperatureSi7021, 1); // 1 chiffres après la virgule ensuite c'est  pas vraiment significatif

      // on log l'humidité du Si7021
      fichier.print(virgule);
      fichier.print(humiditeSi7021, 1); // 1 chiffres après la virgule ensuite c'est  pas vraiment significatif
      fichier.print(F("}"));

      // On log les consignes
      fichier.print(tabulation);
      fichier.print(F("Consignes={"));
      fichier.print(lesParametres.tempConsigne);
      fichier.print(virgule);
      fichier.print(lesParametres.humConsigne);
      fichier.print(virgule);
      fichier.print(lesParametres.ventConsigne);
      fichier.print(virgule);
      fichier.print(lesParametres.vitesseVentilateur);
      fichier.print(F("}"));

      // On log les etats

      fichier.print(tabulation);
      fichier.print(F("Etats={"));
      fichier.print(chauffageOn ? '1' : '0');
      fichier.print(virgule);
      fichier.print(humidificateurOn ? '1' : '0');
      fichier.print(virgule);
      fichier.print(ventilateurOn ? '1' : '0');
      fichier.print(virgule);
      fichier.print(climatiseurOn ? '1' : '0');
      fichier.print(F("}"));

      // on log le mode
      fichier.print(tabulation);
      fichier.print(F("Mode={"));
      switch (mode) {
        case automatique:
          fichier.print(F("AUTO"));
          break;

        case manuel:
          fichier.print(F("MAN"));
          break;

        case param:
          fichier.print(F("PARAM"));
          break;

        case eteint:
          fichier.print(F("ETEINT"));
          break;
      }
      fichier.print(F("}"));

      fichier.println();

      // on ferme le fichier
      if (!fichier.close()) {
        Serial.println(F("Probleme Fermeture Fichier"));
      }
      digitalWrite(SDActivePin, LOW); // On éteint la LED d'incation d'activité SD
    } else {
      // if the file didn't open, print an error:
      Serial.println(F("Probleme carte SD"));
    }
    derniereSauvegarde = millis();
  }



  // **********************************************************
  // Les Boutons
  // **********************************************************

#include <OneButton.h>  // https://github.com/mathertel/OneButton
  OneButton buttonMode(buttonModePin, true); // true pour le mettre en INPUT_PULLUP
  OneButton boutonChauffage(boutonChauffagePin, true); // true pour le mettre en INPUT_PULLUP
  OneButton boutonHumidificateur(boutonHumidificateurPin, true); // true pour le mettre en INPUT_PULLUP
  OneButton boutonVentilateur(boutonVentilateurPin, true); // true pour le mettre en INPUT_PULLUP
  OneButton boutonClimatiseur(boutonClimatiseurPin, true); // true pour le mettre en INPUT_PULLUP

  void tickBoutons()
  {
    buttonMode.tick();
    if (mode == manuel) {
      boutonChauffage.tick();
      boutonHumidificateur.tick();
      boutonVentilateur.tick();
      boutonClimatiseur.tick();
    }
  }


  void displayMode()
  {

    lcd.setCursor(xMode, yMode);
    switch (mode) {
      case automatique:
        lcd.print(F("A"));
        digitalWrite(LED_BUILTIN, HIGH);
        lcd.backlight();
        displayConsigne(true);
        afficheEtatSystemes();
        break;

      case manuel:
        lcd.print(F("M"));
        digitalWrite(LED_BUILTIN, HIGH);
        lcd.backlight();
        afficheEtatSystemes();

        // efface les valeurs de consignes
        lcd.setCursor(xTConsigne, yTConsigne);
        for (byte i = 0; i < 4; i++) lcd.print(space);
        lcd.setCursor(xHConsigne, yHConsigne);
        for (byte i = 0; i < 4; i++) lcd.print(space);
        break;

      case param:
        lcd.print(F("P"));
        digitalWrite(LED_BUILTIN, HIGH);
        lcd.backlight();
        displayConsigne(true);
        afficheEtatSystemes();
        break;

      case eteint:
        lcd.noBacklight();
        lcd.clear();
        digitalWrite(LED_BUILTIN, LOW);
        break;
    }
  }


  // Les fonctions de call back, appellées  quand on clique sur un des boutons

  void doubleClickMode()
  {
    eteindreTousLesSystemes(); // quand on change de mode on éteint les systèmes mais le logging reste actif
    mode = eteint;
    displayMode();
  }

  void clickMode()
  {

    switch (mode) {
      case automatique:
        eteindreTousLesSystemes(); // quand on change de mode on éteint les systèmes
        mode = manuel;
        break;

      case manuel:
        mode = param;
        break;

      case param:
        {
          // on sauvegarde les paramètres en EEPROM s'ils ont été modifiés
          _paramS temp;
          if (memcmp(&temp, &lesParametres, sizeof(_paramS)) != 0) { // http://www.cplusplus.com/reference/cstring/memcmp/
            EEPROM.put(adresseDesParametres, lesParametres);
          }
          eteindreTousLesSystemes(); // quand on change de mode on éteint les systèmes
          mode = automatique;
        }
        break;

      case eteint:
        mode = automatique;
        forceDisplay();
        break;
    }

    displayMode();
  }


  void clickChauffage()
  {
    // on ne veut pas allumer en même temps le chauffage et le climatiseur
    if (!chauffageOn && climatiseurOn) {
      climatiseur(ARRET);
    }
    chauffage(chauffageOn ? ARRET : MARCHE);
  }

  void clickHumidificateur()
  {
    humidificateur(humidificateurOn ? ARRET : MARCHE);
  }

  void clickVentilateur()
  {
    ventilateur(ventilateurOn ? ARRET : MARCHE);
  }

  void clickClimatiseur()
  {
    // on ne veut pas allumer en même temps le chauffage et le climatiseur
    if (chauffageOn && !climatiseurOn) {
      chauffage(ARRET);
    }
    climatiseur(climatiseurOn ? ARRET : MARCHE);
  }

  // **********************************************************
  // utilitaires
  // **********************************************************

  void forceDisplay()
  {
    displayTime(true);
    displayConsigne(true);
    displayTemperature(true);
    displayHumidite(true);
    displayMode();
  }


  // **********************************************************

  void regulation()
  {
    if (mode == eteint) return;

    // ************************************************************************************
    // ici piloter les relais pour contrôler l'environnement comme vous le souhaitez
    // ************************************************************************************
    //  éléments disponibles pour l'algo
    //  temperaturesDS18820[] => tableau des T° lues sur les DS18820. On en a nbCapteursDS18820 (float)
    //  temperatureSi7021     => la T° lue sur le Si7021 (float)
    //  humiditeSi7021        => l'humidité relative lue sur le Si7021 (float)
    //  lesParametres.tempConsigne          => la température telle que fournie par l'utilisateur
    //  tempTropChaudDelta    => une constante du programme
    //  humiditeMin           => une constante du programme (seuil min d'humidité)
    //  humiditeMax           => une constante du programme (seuil max d'humidité)
    //  chauffageOn           => vrai si allumé
    //  humidificateurOn      => vrai si allumé
    //  ventilateurOn         => vrai si allumé
    //  climatiseurOn         => vrai si allumé
    // ************************************************************************************
    // fonctions dispos pour l'algo (commande est soit MARCHE OU ARRET)
    // ventilateur(commande);
    // humidificateur(commande);
    // chauffage(commande);
    // ************************************************************************************
    // A VOUS DE JOUER
    // LE CODE CI DESSOUS EST VRAIMENT BASIQUE ET A TITRE D'EXEMPLE UNIQUEMENT
    // ************************************************************************************

    if (mode == automatique) {
      commandeAppareil c = INCONNUE, h = INCONNUE, f = INCONNUE; // v = INCONNUE si vous voulez utiliser aussi le ventilo

      if (temperaturesDS18820[0] < lesParametres.tempConsigne) {
        // il fait trop froid, on lance le chauffage
        c = MARCHE; // c pour chaud
        f = ARRET;  // f pour froid
      } else if (temperaturesDS18820[0] > (lesParametres.tempConsigne + tempTropChaudDelta)) {
        // il fait trop chaud, on lance la clim
        c = ARRET;
        f = MARCHE;
      } else {
        // entre les deux on arrête tout
        c = ARRET;
        f = ARRET;
      }

      // On gère l'humidité
      if (humiditeSi7021 <= lesParametres.humConsigne) {
        h = MARCHE;
      }
      else if (humiditeSi7021 >= lesParametres.humConsigne + deltaTropHumide )  {
        h = ARRET;
      }

      if (f != INCONNUE) climatiseur(f);
      if (c != INCONNUE) chauffage(c);
      if (h != INCONNUE) humidificateur(h);

      // la ventilation tourne dès qu'un appareil est en marche
      if (climatiseurOn || humidificateurOn || chauffageOn) ventilateur(MARCHE);
      else ventilateur(ARRET);

    }
  }

  // **********************************************************
  void etablirValeursParDefaut()
  {
    uint32_t lectureMotClef;
    EEPROM.get(adresseMotClef, lectureMotClef);
    if (lectureMotClef == motClef) {
      // la mémoire a déjà été initialisée, on peut charger les paramètres
      EEPROM.get(adresseDesParametres, lesParametres);
    } else {
      // la mémoire n'avait pas encore été initialisée
      lesParametres.tempConsigne = 20;
      lesParametres.humConsigne = 50;
      lesParametres.ventConsigne = 2; // entre 0 (ventilateur vitess min) et 5 PWM ventilateur à 0xFF)
      lesParametres.vitesseVentilateur = lesParametres.ventConsigne * 51;
      EEPROM.put(adresseDesParametres, lesParametres);
      EEPROM.put(adresseMotClef, motClef);
    }
 

  // **********************************************************

  void setup() {
    Serial.begin(115200);

    pinMode(pinConsigne, INPUT);
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);

    // LES RELAIS
    pinMode(pinVentilateur, OUTPUT);
    digitalWrite(pinVentilateur, ARRET);

    pinMode(pinHumidificateur, OUTPUT);
    digitalWrite(pinHumidificateur, ARRET);

    pinMode(pinChauffage, OUTPUT);
    digitalWrite(pinChauffage, ARRET);

    pinMode(pinClimatiseur, OUTPUT);
    digitalWrite(pinClimatiseur, ARRET);

    // L'INDICATEUR DE CARTE SD
    pinMode(SDActivePin, OUTPUT);
    digitalWrite(SDActivePin, LOW);

    // on définit les consignes en lisant l'EEPROM
    etablirValeursParDefaut();

    // initialiser the LCD
    lcd.begin();
    lcd.backlight();
    // et créer nos caractères
    for (byte i = 0; i <= 5; i++) lcd.createChar(i, ventilateurF_s[i]);

    // initialiser l'horloge
    if (! rtc.begin()) {
      Serial.print(F("RTC introuvable!"));
      while (1); // can't go further
    }
    // si l'horloge n'est pas à jour, décommenter, compiler et uploader. puis commenter et recharger à nouveau le code
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));


    // on initialise les capteurs de températures
    sensors.begin();
    for (byte i = 0; i < nbCapteursDS18820; i++) {
      sensors.getAddress(DS18820Address[i], i);
      sensors.setResolution(DS18820Address[i], resolution);
    }
    sensors.setWaitForConversion(false); // on travaillera en asynchrone, on n'attend pas les lectures
    sensors.requestTemperatures(); // on lance une demande de lecture qui sera prête plus tard
    chronoTemperatures = millis();
    /*
      // on initialise le capteur d'humidité
      SI7021.begin();
      SI7021.changeResolution(resolutionSI7021); // c'est normalement la valeur par défaut RH=12 bits, T° = 14 bits

      // on attend un peu l'initialisation de tous les capteurs
      delay(100);
    */
    // état initial tout éteint
    eteindreTousLesSystemes();

    // On affiche tout
    forceDisplay();

    // Initialise a la plus haute vitesse possible sous 50MHz
    // Essayez une vitesse plus basse si vous avez des "SPI errors"
    if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
      sd.initErrorHalt();
    }

    // On attache une fonction comme callBack en cas de click
    buttonMode.attachClick(clickMode);
    buttonMode.attachDoubleClick(doubleClickMode);
    boutonChauffage.attachClick(clickChauffage);
    boutonHumidificateur.attachClick(clickHumidificateur);
    boutonVentilateur.attachClick(clickVentilateur);
    boutonClimatiseur.attachClick(clickClimatiseur);

  }
}

  void loop() {

    displayTime();  // on vérifie s'il faut mettre à jour l'heure
    tickBoutons(); // test des boutons - certains capateurs sont lents, pour la réactivité

    displayTemperature();  // on vérifie si on peut mettre à jour les T°
    tickBoutons(); // test des boutons - certains capateurs sont lents, pour la réactivité

    displayConsigne();  // on vérifie s'il faut mettre à jour les consignes
    tickBoutons(); // test des boutons - certains capateurs sont lents, pour la réactivité

    displayHumidite();  // on vérifie s'il faut mettre à jour l'humidité
    tickBoutons(); // test des boutons - certains capateurs sont lents, pour la réactivité

    regulation();  // on déclenche une étapde de régulation

    tickBoutons(); // test des boutons - certains capateurs sont lents, pour la réactivité
    logToutesDonnees(); // on écrit (si le moment est venu) dans notre fichier de logs
  }

Bonsoir
Je suis reparti de zéro, en reprenant votre code sans sauvegarde en SD
J’ai bien modifié le nombre de capteur mais je ne vois pas la valeur du deuxième capteur de T°
Je ne souhaite pas utiliser l’humidité et voudrait la remplacer par la valeur du deuxième capteur de T°
Merci de votre aide et conseil pour comprendre

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.