Compréhension du DHT11

Bonjour,

je dispose du 37 sensor Kit V2.0 de chez Elegoo aisni que d’un arduino Uno Atmega328P.

J’ai fais le branchement du DHT11 :

comme ce ci :

J’utilise la librairie SimpleDHT fournis sur le CD de Elegoo (Fournis avec la boîte 37 Sensor Kit V2.0).
La premiére fois j’ai réussi a faire fonctionner le module DHT11, et afficher une temperature et l’hygrométrie.

Aujourd’hui j’essaye a nouveau d’utiliser ce module dans les mêmes conditions sans succés.
Je fini par comprendre qu’il ya une erreur de communication, je fais donc un zoom sur la partie communication du DHT11.

Le cablage correspond toujours a la photo ci-dessus, sauf que je code volontairement le programme pour comprendre ce qu’il se passe.Je me suis donc documenté sur le DHT11.
Mon code :

const int dht = 5;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("***************************************************************");
  Serial.println("Attente - possible état instable - ne pas envoyer d'instruction - minimum 1s");
  delay(2000);    // Attente - possible état instable - ne pas envoyer d'instruction
  
  demande_de_donnees();
  
  reponse_mcu();

  delay(10000);  // Fin du programme de test, on peux debrancher 
}

void demande_de_donnees()
{
  Serial.println("Demande de données, passage état bas 20 millisecondes et état haut.");
  pinMode(dht, OUTPUT);
  digitalWrite(dht, LOW);
  delay(20);              // Etat bas minimum de 18 millisecondes
  digitalWrite(dht, HIGH);  
}

void reponse_mcu()
{
  Serial.println("Réponse du MCU :");
  pinMode(dht, INPUT);
  delayMicroseconds(30);        // @see https://github.com/winlinvip/SimpleDHT/issues/4

  // Observer une réponse basse de 80 microsecondes et haute de 80 microsecondes
  // LOW -> 0
  // HIGH -> 1
  // On choisi d'afficher 4 valeurs toutes les 40 microsecondes 
  for(int i = 0; i < 4; i++)
  {
    Serial.print(digitalRead(dht));
    delayMicroseconds(40);
  }
}

Bizarrement, le MCU me répond toujours par un état Haut alors qu’il devrait répondre :
Etat bas pendant 80 microsecondes et ensuite etat haut pendant 80 microsecondes.


Je me demande donc si il est possible que le MCU soit dégradé voir HS.

Sur le schéma de cablage en réalite, le fil vert arrive sur la broche 5.

Salut Frère Koala

Pourquoi refaire ce qui existe déjà ? Il existe des bibliothèques pour faire tout ça pour toi.

Salut frère Koala,

parce que la librairie m'affiche un code erreur qui ne m'explique pas le problème, je me suis donc dit que pour comprendre ce qui n'allait, je pouvais décomposer les phases d'acquisition des données.
ce qui m'a permis de comprendre que le(s) librairie(s) echoue tous au niveau du réveil du DHT11, qui ne renvoie pas un état bas pendant 80microsecondes.

:wink:

C'est étonnant, cette bibli a pignon sur rue depuis pas mal de temps, ça se saurait si elle était buguée. Il y en a d'autres au besoin.

Peux-tu copier / coller l'ensemble du message d'erreur que tu obtiens ?

lol, je ne remet pas en cause la bibli, je me demande si il est possible que mon MCU soit fatigué voir défectueux.

La bibli ne me permet pas de savoir ou est le problème de communication entre l'arduino et le MCU, hors c'est quelque lignes que j'ai codé permette juste de voir si il est possible d'activer le MCU. Et je m'aperçoit juste que mon MCU (DHT11) ne répond pas.

Je me demandai si il était possible que le MCU puisse rendre l'âme comme ça. Si il y avait une autre maniére de tester le 1-wire pour être sûr qu'il soit bien défecteux.

Bonsoir

je n'ai pas détaiilé à fond le code de test mais je fais une première remarque :
les serial.println() (qui plus est avec un débit lent de 9600bauds) perturbent le timing,
(A 9600 bauds la transmission d'un seul octet ,avec ses bits de start et stop, prend environ 1 ms)

un petit analyseur logique à 10€ et son soft permettraient de voir en détail ce qui se passe sur la ligne data.

Je viens d'augmenter le baud a 2 000 000, et ajouté un timer en micros() et effectivement , il y a bien un décalage dans le temps et du coup fausse, mes essais.

Je vais regarder l'analyseur.

Merci

C'est étonnant, cette bibli a pignon sur rue depuis pas mal de temps, ça se saurait si elle était buguée. Il y en a d'autres au besoin.

Buguée non elle ne l'était pas mais de très mauvaise qualité certes OUI.
Elle donnait des énormes quantités de "CHECKSUM ERROR".

Comme je ne cesse de le répéter il ne faut pas lire les DHT avec la fonction digitalRead() qui est trop lente (plus de 60 cycles horloge) pour les signaux à surveiller --> d'où tous ces "CHECKSUM ERROR" qui sont la conséquence d'une mauvaise discrimination entre les 1 et les 0.

D'un autre coté on peut se dire que si le concepteur du produit à introduit une somme de contrôle c'est bien qu'il savait que la lecture de l'état de la sortie de son produit était un point critique.

Le premier à avoir publié une bibliothèque qui abandonnait l'utilisation de digitalRead() au profit de la lecture des registres est Rob Tillaart (1).
On peut encore améliorer en supprimant l'utilisation de la fonction millis(), qui induit une perte de temps inutile. Il suffit d'utiliser 2 compteurs de boucle, un pour la boucle de discrimination des 1, l'autre pour la boucle de discrimination des 0 et de voir si le premier est supérieur ou inférieur au second mais il veut pas il préfère continuer à faire de la métrologie.

2 ou 3 ans après Adafruit à fini par s'inspirer du travail de Rob, mais autant prendre l'original que la copie et utiliser la bibliothèque de Rob Tillart qui se trouve sur Github.

(1) Dans le constructeur de la classe il utilise (en sens inverse) les macro qui servent à passer de la dénomination Atmel (Port et indice dans le PORT) à la dénomination Arduino

Après installation de la libDHT et chargement de l'exemple DHT11_Test :
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0

Donc vous êtes d'accord si je suppose que le MCU est défaillant.
Si vous deviez diagnostiquer le problème.

Il ne faut accuser le matériel trop vite, l'interface entre la chaise et le clavier est redoutable et quelque soit le niveau de l'opérateur.

Question :
Le circuit intégré DHTxx utilise des collecteurs (ou drain) ouvert: il faut impérativement ajouter une résistance entre la sortie du DHT et le Vcc pour que le montage fonctionne .
Dans la plus part des "modules" cette résistance est déjà câblée.
Qu'en est-il du tient ?
Si elle n'est pas câblée ( ou si elle est mal soudée) c'est impossible que le module fonctionne.

Qu'elle tension mesure tu entre la masse et la sortie quand le DHT est alimenté mais non relié au microcontrôleur ?
Qu'elle est la longueur de connexion au microcontrôleur ? N'y t-il pas de faux contact dans la liaison des masses DHT/Arduino ?

Je n'ai pas la datasheet du DHT11 mais celle du bien meilleur DHT22 (ou AM2302). Il y est indiqué qu'avec une résistance extérieure de 5k ohms, sous 5V la longueur max est de 30m mais que sous 3,3 V elle n'est plus que d'un mètre.
Sous quelle tension le DHT est-il alimenté ?

Je le dis toujours “90% des problèmes sont entre la chaise et le clavier”, mais il ne faut pas oublier les 10% pour le coup.

A l’ohmmètre je relève une résistance de 9,88kohms.
Elle est intégrée sur le circuit entre 5V et Data.
Entre la broche 5V et la résistance, le circuit sonne.
Entre la broche Data et la résistance, le circuit sonne.

Entre le 5V et le GND, je mesure 4,84V. (DHT non relié a l’arduino uno)
Entre le 5V et le GND, je mesure 4,83V. (DHT relié a l’arduino uno)
Le GND a été pris sur la breadboard et sur un autre emplacement GND de la carte arduino, donc pour moi pas de problème de masse.

Entre l’arduino et DHT11, la connexion est fil plein de 14cm sur une breadboard.

Datasheet DHT11

L’arduino est en USB, et alimente le DHT11 en 5V.

Librairie

Sketch :

//
//    FILE: dht11_test.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.01
// PURPOSE: DHT library test sketch for DHT11 && Arduino
//     URL:
//
// Released to the public domain
//

#include <dht.h>

dht DHT;

#define DHT11_PIN 5

void setup()
{
  Serial.begin(115200);
  Serial.println("DHT TEST PROGRAM ");
  Serial.print("LIBRARY VERSION: ");
  Serial.println(DHT_LIB_VERSION);
  Serial.println();
  Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)");
}

void loop()
{
  // READ DATA
  Serial.print("DHT11, \t");
  int chk = DHT.read11(DHT11_PIN);
  switch (chk)
  {
    case DHTLIB_OK:  
		Serial.print("OK,\t"); 
		break;
    case DHTLIB_ERROR_CHECKSUM: 
		Serial.print("Checksum error,\t"); 
		break;
    case DHTLIB_ERROR_TIMEOUT: 
		Serial.print("Time out error,\t"); 
		break;
    case DHTLIB_ERROR_CONNECT:
        Serial.print("Connect error,\t");
        break;
    case DHTLIB_ERROR_ACK_L:
        Serial.print("Ack Low error,\t");
        break;
    case DHTLIB_ERROR_ACK_H:
        Serial.print("Ack High error,\t");
        break;
    default: 
		Serial.print("Unknown error,\t"); 
		break;
  }
  // DISPLAY DATA
  Serial.print(DHT.humidity, 1);
  Serial.print(",\t");
  Serial.println(DHT.temperature, 1);

  delay(2000);
}
//
// END OF FILE
//

DHT TEST PROGRAM
LIBRARY VERSION: 0.1.29

Type, status, Humidity (%), Temperature (C)
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0
DHT11, Connect error, 0.0, 0.0

En décortiquant la lib de Rob Tillaart, on trouve ça :

    uint16_t loopCount = DHTLIB_TIMEOUT * 2;  // 200uSec max
    // while(digitalRead(pin) == HIGH)
    while ((*PIR & bit) != LOW )
    {
        if (--loopCount == 0) 
        {
          return DHTLIB_ERROR_CONNECT;
        }
    }

L'erreur que tu obtiens vient de ces instructions : si l'opération PIR & bit ne vient pas à 0 pendant un certain temps, il renvoie le code d'erreur.

pin est bien sûr le numéro de la pin data du capteur. Les autres variables PIR et bit sont définies un peu plus haut :

    // replace digitalRead() with Direct Port Reads.
    // reduces footprint ~100 bytes => portability issue?
    // direct port read is about 3x faster
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *PIR = portInputRegister(port);

Là, on rentre un peu profond dans l'AVR.

digitalPinToMask est une macro définie par:

#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )

Elle renvoie un byte dont tous les bits sont à 0 sauf celui de la pin dans le registre du port. Les autres sont définies ici :

  • digitalPinToPort : The digitalPinToPort() is a macro that returns the port of a specified pin.
  • portInputRegister : The portInputRegister() is a macro that returns an input port register of the specified port.
    C'est pas simple... Chez toi, pin vaut 5, donc bit doit valoir 0b0010000. Mais pour le reste, je cale un peu. Peut-être des spéléologues de l'Arduino pourront-ils aller plus loin...

En tout état de cause, ton code est celui de l'exemple DHT11 de la bibliothèque, donc il devrait fonctionner. Du coup, je te conseillerais d'aller faire un tour chez EucAlyptusExpress pour t'acheter un DHT22...

juste par acquis de conscience parce que je me suis arraché les cheveux pendant 15 bonnes minutes récemment avant de m'apercevoir que j'avais connecté (pas mis les lunettes...) mon fil sur A5 au lieu de D5... et donc que rien ne marchait...

Je peste contre moi même et je change pour D5 et là toujours rien... Je finis par vérifier mon fil et... il était cassé (pas de continuité)...

--> vérifiez juste vos fils et branchements par acquis de conscience