/* Programme en préparation à la prochaine expérience.
   Ce démonstrateur permet de mettre en œuvre le capteur de température et d'humidité DHT11.
   >>>>>>> Penser à importer la librairie DHT11.h fournie dans le dossier dédié <BIBLIOTHEQUES>.
   Avant de tenter de communiquer les valeurs issues du capteur DHT11 ainsi que la tension
   du +Vcc de la carte Arduino, il importe de vérifier que les mesures sont effectives.
   Il sera alors envisageable de pratiquer la télémesure.
 
 BRANCHEMENTS à effectuer :
 --------------------------
  • Le +5V va sur VCC du HC-05.
  • GND va sur GND  du HC-05.
  • GND va sur EN  du HC-05.
  • D2 d'Arduino va sur TX du HC-05.
  • D3 d'Arduino va sur RX (1k,2k) du HC-05.
  • La sortie du module DHT11 est branchée sur D5.
  • Le +5Vcc de la carte Arduino va sur l'entrée analogique A0.

UTILISATION :  Téléverser le programme. Se contenter de lire les informations que génère 
=============  le démonstrateur sur le Moniteur de lIDE initialisé à 57600baud.

Compilateur v1.7.9.          PGM              RAM dynamique
                       5062 Octets (16%)    236 Octets (11%)  */

//------------------------ Constantes du programme --------------------------
#define Version "11/07/2025" // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//------------- Définition des broches d'entrées analogiques ----------------
#define Entree_Vmetre 14       // A0 pour mesurer la tension de l'accumulateur.

//---------------------- Déclarations pour le matériel ----------------------
#include <DHT11.h>
#define Broche_Com_DH11 5 // DATA branchée sur la broche binaire D5.
/* 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.

//------------------------- Variables du programme --------------------------
byte Temperature, Humidite; // Variables de service.
int Tension_lue;

//========================= Procédures de servitude ============================
/* >>> Lecture de la température et lu taux d'humidité mesurés par un capteur DHT11 <<<
  * Broche_DATA : Broche sur laquelle est câblée la sortie du capteur.
  * Temperature : Pointeur vers la variable stockant la température.
  * Humidite : Pointeur vers la variable stockant le taux d'humidité.
  * Retourne DHT11_SUCCESS si aucune erreur, DHT11_TIMEOUT_ERROR en cas de dépassement,
    ou DHT11_CHECKSUM_ERROR en cas d'erreur de checksum */

byte readDHT11(byte Broche_DATA, byte* Temperature, byte* Humidite) {
  byte Variable_DATA[5] = {0}, BIT_serie = 7, Index = 0;
  unsigned int timeout;
    // Variable_DATA[] : Tampon contenant les données du cpateur.
    // BIT_serie : 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 délai en dépassement.
  //----------------------------------------------------------------------------------  
  // 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(Broche_DATA);
  uint8_t port = digitalPinToPort(Broche_DATA);
  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 engendrant 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 40 bits de données du capteur.
  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) Variable_DATA[Index] |= (1 << BIT_serie); // "1"
    // Le tableau Variable_DATA[] est initialisé à "0" par défaut si le compteur de bits atteint zéro.
    if (BIT_serie-- == 0) { BIT_serie = 7; ++Index;}} // On passe à l'octet suivant.
  /* 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)   */
  *Humidite = Variable_DATA[0]; *Temperature = Variable_DATA[2];
  // >>> Vérifie la totalisation de contrôle. (Checksum) <<<
  if (Variable_DATA[4] != (Variable_DATA[0] + Variable_DATA[2])) return DHT11_CHECKSUM_ERROR;
  else return DHT11_SUCCESS;} // Pas d'erreur.

//=========================== Corps du programme ===============================

void setup() {
  Serial.begin(57600); Serial.println(); Serial.print(" P10 Test du capteur : ");
  Serial.println(Version); Serial.println();
  Serial.println(F(">>> Exemple d'utilisation du capteur DHT11 : <<<"));}

void loop() {
  Tension_lue = analogRead(Entree_Vmetre); // Mesure analogique [0 à 1023].
  Serial.println(); // Ci-dessous : 205 = 1023 / 5 donc CAN supposée 1023 pour 5V.
  Serial.print(F(" Tension Vcc : ")); Serial.print((Tension_lue / 205.0),1); Serial.println('V');
  //-----------------------------------------------------------------------------
  // >>> Lecture de la température et de l'humidité + gestion des erreurs <<<
  switch (readDHT11(Broche_Com_DH11, &Temperature, &Humidite)) {
     case DHT11_SUCCESS:          
       // Affichage du taux d'humidité puis de la température.
       Serial.print(F("    Humidite : "));
       Serial.print(int(Humidite)); Serial.println('%');
       Serial.print(F(" Temperature : "));
       Serial.print(int(Temperature)); Serial.print(char(176)); Serial.println('C');
       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 du case DHT11_SUCCESS:
  //-----------------------------------------------------------------------------    
  delay(2000);} // Une mesure toutes les deux secodes suffit.



