[RÉSOLU] Mega Projet Contrôleur de Température et d'Humidité

tenez étudiez un peu ce code que j'avais fait il y a quelques temps pour quelqu'un d'autre

comme composants il faut

  • 2 DS18820 sur la pin 9 (avec une résistance de 4.7KΩ entre 5V et pin 9)
  • 1 potentiomètre branché sur A0
  • 1 bouton câblé ainsi pin 8 --> entrée bouton ---> BOUTON --> sortie bouton --> GND que l'on mettra dans le code en INPUT PULLUP
  • 1 écran LCD connecté en I2C 16x2 ou 20x4

appuyez sur le bouton, faites varier le potentiomètre ou faites chauffer ou refroidir les DS18820 et vous verrez comment ça se comporte

// Gestion des DS18820
#include <OneWire.h>
#include <DallasTemperature.h>

const byte onewireBusPin = 9;        // pin 9 pour le bus 1 wire avec une résistance de 4.7KΩ entre 5V et pin 9
OneWire  oneWire(onewireBusPin);
DallasTemperature sensors(&oneWire);

const byte nbCapteurs = 2;
DeviceAddress  DS18820Address[nbCapteurs];
float temperatures[nbCapteurs];

const int resolution = 10; // en bits --> Max 12 bit, min 9 bit (9bit prends 95ms, 10bit 187ms, 11bit 375ms et 12bit 750ms)

// on va lire la température seulement de temps en temps
unsigned long   chronoTemperatures = 0;
const unsigned long periodeLecture = 250; // 250 est OK pour une résolutoin en 10 bits. au minimum attendre  (750 / (1 << (12 - resolution)));

// Gestion du LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// adresse LDC 0x27  16 caractères, 2 lignes
const byte nbColumns = 20;
const byte nbLines   = 2;
 LiquidCrystal_I2C lcd(0x27, nbColumns, nbLines);

// ou avec 4 lignes
//const byte nbColumns = 20;
//const byte nbLines   = 4;
//LiquidCrystal_I2C lcd( 0x3F, nbColumns, nbLines); // my LCD is at I2C address 0x3F, 20 cols, 4 rows

const byte symboleFlecheDroite = 126;
const byte symboleFlecheGauche = 127;
const byte symboleBlocBlanc = 255;
const byte symboleEgal = '=';



// La librairie de gestion des boutons
#include <OneButton.h>    // https://github.com/mathertel/OneButton

// le bouton pour les modes
const byte buttonPin = 8; // notre bouton est sur la pin 8
OneButton button(buttonPin, true); // true pour le mettre en INPUT_PULLUP

// les mode
enum : byte {eteint, manuel, automatique} mode = eteint;

// le potentiomètre
const byte pinConsigne = A0;
int tempConsigne = 0;


void afficheTemperature(int t, byte ligne, byte col)
{
  // on sait que la température est entre -55° et 125°, donc la longeur max de la chaîne 125°C = 5 caractères
  char affichage[9]; // 9 = 8 carcatère dédiés à la consigne + 1 '\0'

  char tmpBuffer[9];
  itoa(t, tmpBuffer, 10); // connvertir en chaîne, cf http://www.cplusplus.com/reference/cstdlib/itoa/?kw=itoa

  strcat(tmpBuffer, "\337C"); // \337 est le symbole '°'
  size_t l = strlen(tmpBuffer);
  memset(affichage, ' ', 8 - l); // on met des espaces à gauche
  strcpy(affichage + 8 - l, tmpBuffer);

  lcd.setCursor(col, ligne);
  lcd.print(affichage);
}


int lireEtAfficherTemperature()
{
  float t;
  for (int i = 0; i < nbCapteurs; i++) {
    t = sensors.getTempCByIndex(i);  // lire les T°. ici exemple de code avec des DS18820
    if (((int) t) != ((int) temperatures[i])) { // on n'affiche qu'en nombre entier vu la précision nécessaire
      afficheTemperature((int) t, 1, 8 * i);
    }
    temperatures[i] = t; // mais on stocke bien la bonne valeur
  }
}


void lireEtAfficherConsigne()
{
  int c;

  analogRead(pinConsigne); // double lecture pour stabiliser la mesure
  c = map(analogRead(pinConsigne), 0, 1023, -20, 100);
  if (c != tempConsigne) {
    tempConsigne = c;
    afficheTemperature(c, 0, 8);
  }
}


void afficherMode()
{
  // occupe 6 caractères de l'afficheur
  lcd.setCursor(0, 0);
  switch (mode) {
    case eteint:
      lcd.noBacklight();
      lcd.clear();
      lcd.print(F("Eteint"));
      digitalWrite(LED_BUILTIN, LOW);
      for (int i = 0; i < nbCapteurs; i++) temperatures[i] = -99; // valeur arbitraire en mode off
      tempConsigne = -99;
      break;

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

    case automatique:
      lcd.print(F(" Auto "));
      digitalWrite(LED_BUILTIN, HIGH);
      lcd.backlight();
      break;
  }
}

// La fonction de call back, appellée automatiquement quand on clique
void simpleclick()
{
  switch (mode) {
    case eteint:
      mode = manuel;
      sensors.requestTemperatures();  // on lance une demande de lecture qui sera prête plus tard
      chronoTemperatures = millis();
      // ***  ICI ALLUMER LA REGULATION DE COURANT ***

      break;

    case manuel:
      mode = automatique;
      sensors.requestTemperatures();  // on lance une demande de lecture qui sera prête plus tard
      chronoTemperatures = millis();
      // ***  ICI ALLUMER LA REGULATION DE COURANT ***

      break;

    case automatique:
      mode = eteint;
      // ***  ICI ETEINDRE LA REGULATION DE COURANT ***

      break;
  }
  afficherMode();
}



void regulation()
{
  static byte oldSymbole = 0;
  byte symbole;

  switch (mode) {
    case eteint:
      symbole = symboleBlocBlanc;
      break;
    case manuel:
    case automatique:
      if ((int) tempConsigne > (int) temperatures[1]) {
        symbole = symboleFlecheDroite;
      } else if ((int) tempConsigne == (int) temperatures[1]) {
        symbole = symboleEgal;
      } else {
        symbole = symboleFlecheGauche;
      }
      break;
  }

  // pour éviter de clignotter pour rien
  if (symbole != oldSymbole) {
    // occupe 1 caractère de l'afficheur
    lcd.setCursor(7, 0);
    lcd.write(symbole);
    oldSymbole = symbole;
  }

  // ************************************************************************************
  // ici piloter les alimentations pour contrôler la température comme vous le souhaitez
  // ************************************************************************************

  // A FAIRE


  // ************************************************************************************
}




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

  pinMode(pinConsigne, INPUT);

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

  // on initialise les capteurs de températures
  sensors.begin();
  for (byte i = 0; i < nbCapteurs; 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();

  // initialiser the LCD
  lcd.begin();
  lcd.noBacklight();

  // On attache la fonction simpleClick() comme callBack en cas de simple click
  button.attachClick(simpleclick);

  afficherMode();
}


void loop() {
  // On vérifie l'état des boutons, ce qui déclenche l'appel d'une des fonctions callBack si nécessaire
  button.tick();

  if (mode != eteint) {

    // est-ce le moment le lire les capteurs de température?
    if (millis() - chronoTemperatures >= periodeLecture) {
      lireEtAfficherTemperature();
      // on relance une requete pour la prochaine fois
      sensors.requestTemperatures();
      chronoTemperatures = millis();
    }

    lireEtAfficherConsigne();

    // ici on peut gérer la régulation, cette fonction est appelée souvent mais la température n'est lue que de temps en temps
    regulation();
  }

}