ATMEGA-328P et DHT22

Bonjour,

je suis en train de monté mon petit système météo/domotique, avec les composants suivants:

Capteur : DHT22, Photorésistance
Transmission : NRF24L01+
Alimentation : Batterie Li-ion
Divers : SWITCH 4 position

J’ai une première version avec un Arduino Pro Mini, qui fonctionne parfaitement bien. Aussi bien avec une version 5V que 3.3V.

Afin d’augmenté la durée de vie de la batterie, j’essaye de faire une version avec un ATMEGA-328P avec un quartz à 8MHZ, mais impossible de lire les valeurs du DHT22. La Photorésistance et le NRF24L01 fonctionnent eux correctement.

N’ayant pas de liaison série pour débugé, je suis un peu bloqué…

Je vous ai joint le schéma, si quelqu’un a une piste, c’est volontiers.

Merci et bonne journée

jettez un œil ici et aussi ce fil de discussion

Pas la peine d'aller chercher des explications en anglais, le sujet a été abordé plusieurs fois ici.

Je me suis intéressé a ce circuit et la raison du non fonctionnement est simple : le DHT22 est un circuit rapide, les fonctions arduino sont lentes et cet antagonisme provoque des erreurs de lecture.

La bibliothèque Adafruit est une des plus mauvaises que je connaisse. Celle de Rob Tllaert la meilleure de celles qui utilisent les fonctions arduino.

Rob à banni les fonctions digitalRead(), c'est ce qu'il fallait faire. Mais il continue d'utiliser millis() ce qui est une annerie.

J'ai une version qui n'utilise que les registres pour la rapidité et qui ne fait plus de mesure de temps avec millis(). A la place j'utilise tout simplement la variable auxiliaire qui sert à se protéger d'un "TimeOut" pour décider si l'élément binaire reçu est un 1 ou un 0.

Je ne peux pas la joindre actuellement (je suis sur une tablette) mais je poste dans la journée avec la datasheet du produit (ça aide à comprendre les choix).

PS : pour reduire encore la consommation il est possible de changer un fuse pour activer un diviseur d'horloge par 8.
Il est plus que probable qu'un certain nombre de fonctions arduino basées sur le temps ne donneront plus les résultats escomptés, mais on programmait déjà les avr avant la publication de l'IDE Wiring/Arduino donc les moyens de correction existent.

gberthoud:
... J'ai une première version avec un Arduino Pro Mini, qui fonctionne parfaitement bien. Aussi bien avec une version 5V que 3.3V.

Afin d'augmenté la durée de vie de la batterie, j'essaye de faire une version avec un ATMEGA-328P avec un quartz à 8MHZ, mais impossible de lire les valeurs du DHT22. ...

Je ne comprends pas : un Pro Mini à 3.3 V a une horloge à 8 MHz. Si le DHT22 fonctionne dans ce cas, alors pourquoi ne fonctionne-t-il pas avec un "ATMEGA-328P avec un quartz à 8MHZ", ce qui est la même configuration ?

Par ailleurs, j'ai eu ce problème de non fonctionnement du DHT22 avec un Pro Mini à 3.3 V et donc 8 MHz : un coup cela fonctionnait, le coup suivant : non. Le jour où j'ai pris sérieusement en considération qu'entre deux interrogations de ce composant, il fallait laisser 1.5 secondes, le problème a été purement et simplement résolu.

J'ai fait cet essai avec seulement le Pro Mini et le DHT22 et en jouant seulement sur ce paramètre. Le résultat a été évident. En de-ça de 1.2 secondes (pour celui que je possède), il fonctionnait un coup sur deux. remontant au-dessus de cette valeur, il fonctionnait normalement.

Cordialement.

Pierre

ChPr:
Le jour où j'ai pris sérieusement en considération qu'entre deux interrogations de ce composant, il fallait laisser 1.5 secondes, le problème a été purement et simplement résolu.

La spécification du capteur dit que l'interrogation doit se faire au maximum toutes les 2 secondes.

fdufnews:
La spécification du capteur dit que l'interrogation doit se faire au maximum toutes les 2 secondes.

Tu as raison et tu as tort, diantre, fichtre ! :wink:

Sur certaines docs, c'est une seconde, sur d'autres, deux secondes.

Et dans ma tête, j'avais mémorisé 1.5 secondes. En fait, dans mon programme, j'ai mis 1.5 secondes car le mien (après tests) fonctionnait jusqu'à 1.2 secondes : j'ai pris une petite marge.

Dans les faits, si on n'a pas de contrainte de temps, autant mettre deux secondes, voire plus.

NOTA : outre cet essai, j'en ai fait un autre. Dans mon application, pour économiser du courant, je coupe l'alimentation de tous mes capteurs lorsque je ne m'en sers pas. J'ai donc reproduit le test précédent pour observer quel temps il fallait après la remise sous tension : pratiquement les mêmes valeurs.

Cordialement.

Pierre.

En attendant que je retrouve mes fichiers je joins la datasheet qui m’est apparu être la plus sérieuse.

Dans toutes les bibliothèques qui me pose problème c’est la gestion du temps Tgo (voir page 6).

Une antique datasheet indiquait Tgo = 30 µs : temps fixe.

Toute les bibliothèques que j’ai pu lire sont restées bloquées sur cette “croyance” et réalisent un temps d’attente FIXE de 30 µs.
Or vous pouvez constater par vous même que 30 µs c’est le temps moyen mais que Tgo peut varier de 2µs à 200 µs.
Cela fonctionne très généralement parce que les temps de l’acknoledge sont de 80 µs et peuvent absorber des petites variations mais si une fois un lot de fabrication donne un Tgo de 100 µs il n’y aura rien à dire le produit sera dans sa spec, c’est la bibliothèque qui ne fonctionnera plus mais bien sûr on accusera le produit…
J’ai remplacé ce délai fixe de 30 µs par une boucle while qui s’adapte exactement au temps réel du DHT.

AM2302.pdf (570 KB)

Mon “truc”.

  1. Ce n’est pas une bibliothèque au sens Arduino.
    C’est une classe avec un fichier h et un fichier cpp qui se placent dans le même répertoire que e fichier ino

  2. Tel que c’est actuellement on ne peu gérer qu’un seul DH22 → c’était mon besoin et je ne me sentais pas investi de faire une bibliothèque universelle pour la Terre entière.

Cela peut se modifier : il suffit d’intégrer dans le constructeur la conversion (nommage Arduino/ nommage Atmel) comme Rob l’a fait dans ses dernières versions.
Il faut bien voir que le micro ne connais que le nommage Atmel et l’IDE que le nommage Arduino.

  1. J’ai utilisé une classe un peu sans réfléchir. Depuis que j’ai trouvé ça :

void set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
*port |= mask;
}

#define set_bits_macro(port,mask) ((port) |= (mask))

int main (void)
{
set_bits_func_correct (&PORTB, 0x55);
set_bits_macro (PORTB, 0xf0);
return (0);
}

sur le site d’Atmel http://www.atmel.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_port_pass.html
je me dis qu’une fonction aurait été plus adaptée qu’une classe exactement comme digitalWrite et digitalRead ne sont pas des objets mais des fonctions.

Prise de ligne :
Voir mon message précédent

Discrimination des 1 longs et des 1 courts :
Préalable : il faut distinguer la notion de “bit” de celle d’élément binaire.
Le mot “bit” a changé officiellement de signification depuis longtemps mais les mauvaises habitudes perdurent.
1 bit est une quantité d’information. Tout de suite un exemple : sur la liaison série en plus de l’octet à transmettre il faut ajouter un “bit” de start, un “bit” de stop, une parité etc.
Donc on transmet au minimum 10 “signaux” pour seulement 8 qui contiennent une information.
Dit autrement on transmet 10 éléments binaires (eb) pour seulement 8 bits d’information.
Je suis d’accord qu’il eû été préférable de ne pas modifier la signification du mot bit et de créer un nouveau nom mais si conne*ie il y a eu elle est le fait des Etats Unis.

Revenons au DHT22 :

  • un bit 0 est constitué d’un eb 0 de 50µs suivi d’un eb 1 de 26 µs.
  • un bit 1 est constitué d’un eb 0 de 50µs suivi d’un eb 1 de 70 µs
    Soit durée_eb 1 = durée_eb0 +/- 50% → avec un tel écart il n’y a pas besoin de faire des mesures à 4 µs prés.

Il est totalement inutile de mesurer ces temps il suffit de compter le nombre de fois que les boucles while de détection du 0 et du 1 ont tourné et de comparer.
D’après les essais que j’avais fait avec les fonctions digitalRead() la boucle 1 court n’était parcourue que 5 à 6 fois sachant que l’utilisation de millis() pour mesurer la longueur du zéro (qui est constant donc mesure inutile mais bon la bibliothèque était comme ça) bouffait une partie du temps du 1 court.

D’où les très nombreuses erreurs CHECKSUM.

Je n’ai pas fait de tests à 8MHz et à fortiori à 1 MHz mais je suis assez confiant cela devrait fonctionner à 1 MHz (quartz 8MHz diviseur par 8) ou 2MHz (quartz 16 MHz et diviseur par 8)

Clairement j’ai eu une approche d’électronicien pas très bon programmeur alors que les bibliothèques existantes ont eu une approche de programmeur pas très bon électronicien.

test_am2302.zip (4.54 KB)