J'ai recours à vous pour un problème dont je n'arrive pas à trouver la solution. Je suis en train de construire un incubateur dont je règle la température par un fil chauffant et l'humidité par un brumisateur, chacun étant commandé par un triac. Je travaille avec Windows10.
J'ai mis au point le programme sur un Arduino uno R3 programmé avec l'IDE 1.6.10.
Comme capteur j'ai utilisé le classique DHT22 avec la librairie de LadyAda.
Tout fonctionnant à merveille, je suis passé au montage dans une boîte de commande. Pour gagner de la place, j'ai remplacé l'Arduino par une carte de développement de l'atmega8 mais qui marche sur tous les Atmega 28 pins.
Ici devrait venir l'image que j'ai prise, mais que j'ai été obligé de joindre en fichier joint.
Le µC se programme avec ICSP. Il est alimenté par ICSP ou par l'USB (qui ne comporte que les pins d'alimentation). L'interrupteur sert à couper l'alimentation USB. Il possède un quartz de 8 MHz, un bouton de Reset, une LED d'alimentation, une LED de Rx, une barrette de contact pour chaque Port et 2 * 3 connecteurs pour +5V et GND.
Lors des tests, tout fonctionne normalement, sauf le DHT22 . Impossible de mesurer la T° ou l'humidité.
J'ai d'abord cru à une erreur de câblage. J'ai vérifié celui-ci au moins 10 fois, en essayant de changer la Pin de mesure. J'ai testé la continuité des câbles. J'ai mesuré la résistance des pistes et des soudures de la carte. Finalement, sans rien changer au programme, j'ai refait un montage externe sur breadboard tantôt avec la carte de développement, tantôt avec l'Aduino. Le DHT22 n'est pas détecté avec la carte de développement mais il l'est avec l'Arduino ! C'est un mystère pour moi car le capteur, le câble, les pins, le µC et le programme sont les mêmes. la seule chose que je n'ai pas faite est de tester le DHT avec l'Atmega montés seuls sur la breadboard.
Quelqu'un aurait-il une idée pour m'aider à comprendre ce mystère ?
Bonjour Jean Marie, heureux de te lire de nouveau.
Quelle est ta fréquence système : 16 , 8 ou 1 MHz ?
Le DHT22 est un composant rapide et les fonctions digitalRead() sont des fonctions gastéropodes.
Plutôt que d'aller chercher la bibliothèque sur Ladaya récupère celle du playground. Elle utilise une version "adaptée" de digital ReadFast.
Mais malheureusement elle utilise toujours la fonction millis() pour faire des mesures de temps de "1" ou de "0".
Si cela ne fonctionne toujours pas j'ai quelque part (mais où ?) une version qui banni les fonctions arduino digitalRead et millis.
utilisation du registre PINx pour lire l'état d'une pin
utilisation du compteur de TIMEOUT des boucles while pour comparer le temps des "1"
Info
Un bit "0" est composé d'un élément binaire "0" suivi d'un élément binaire "1" de longueur inférieure à celle du "0".
Un bit "1" est composé d'un élément binaire "0" suivi d'un élément binaire "1" de longueur supérieure à celle du "0".
La longueur de l'élément binaire "0" est constante.
En sortie de boucle while il suffit de conserver la valeur du compteur de TIMEOUT puis de comparer les valeurs correspondant au "0" à celle correspondant au "1"--> la fonction millis() est en fait inutile.
Le temps passé dans une boucle while ne dépend que du système.
Avec digitalRead qui est très lent on ne fera pas beaucoup de tour de boucle et la mesure sera imprécise (encore plus si on utilise millis ).
Si on utilise le registre de pin PINx la lecture se limitera à la lecture d'un octet ce qui ira très vite, on parcourera plus de fois la boucle et la comparaison de temps de du "1" court et du "1" long sera plus précise.
Sauvé (ou presque) : j'ai retrouvé un répertoire dénommé arduino_foutoir et je me suis dit que ce devait être là.
Trois précisions :
1 ) bien qu'il s'agisse d'une classe avec un fichier h et un fichier cpp ce n'est pas une bibliothèque.
Les fichiers sont à recopier dans le répertoire de ton fichier ino. Ils peuvent être édités à partir de l'IDE arduino comme tous fichiers additionnels.
La pin sur laquelle est relié le DHT22 (AM2302) est "câblée en dur". Il y aura de l'adaptation à faire pour l'adapter à ton câblage.
C'est pour cela que ce n'est pas une bibliothèque : il faut modifier le fichier cpp en fonction de chaque réalisation.
En échange cela permet de mieux optimiser.
Ce n'est pas la version définitive (elle se cache super bien, je ne la retrouve plus).
Cette version intermédiaire n'utilise pas les variables de TIMEOUT mais compte le nombre de cycle horloge en monopolisant un timer. Dans le cas présent j'ai choisi le timer 2.
Dernier point : si tu veux faire une vraie bibliothèque pour passer une IO (référence Atmel bien sûr) dans une fonction ou une méthode voir :
PS : je n'ai pas vérifié que l'archive fonctionnait avant de poster le fichier, j'espère que c'est la bonne version.
Tu te souviens donc de moi ?
Je ne suis malheureusement guère plus avancé que dans le temps. Je dirais même que j'ai oublié pas mal.
Tu soulèves la question de la fréquence. L'arduino travaille en 16 MHz. La carte de développement est en 8 MHz. C'est donc la moitié de la fréquence. Cela pourrait-il être la cause ?
Pour régler la température, je lis la sonde toutes les 5 secondes. Si la T° lue est inférieure à la consigne, le chauffage est mis à "fort" (une seconde comporte 100 passages par zéro. Si "fort" constitue 20 % de la puissance maximale du fil chauffant, la pin du triac de T° est mise à HIGH pendant les 20 premiers passages par zéro et à LOW pendant les 80 passages suivants, avant de recommencer. Il y a donc un compteur de passage par zéro commandé par l'interruption 1. Ce compteur est remis à zéro au centième passage et le nombre de secondes est incrémenté. Après 5 secondes, une nouvelle lecture est faite et le cycle recommence.
Pour l'humidité, c'est plus simple. A chaque lecture (toutes les 5 secondes) le brouillard est envoyé ou coupé pendant 5 secondes par un triac si la mesure est plus basse ou plus haute que la consigne.
Je ne sais évidemment pas combien de temps prend la procédure de lecture de la Température / Humidité mais elle n'est pas longue et n'est appelée que toutes les 5 secondes alors que l'interruption est appelée tous les centièmes de seconde.
Ceci n'a malheureusement rien à voir avec ce que tu m'expliques sur la lecture des 0 et des 1. Demain, je vais essayer de dessouder le quartz de 8 MHz et le remplacer par un quartz de 16 MHz (si j'en ai en réserve). On verra bien. Si cela ne marche pas, il sera encore temps de réfléchir à la librairie.
En tout cas, merci bien de t'être penché sur mon problème. Je tiens le forum au courant de toute façon.
PS. Deux nouveaux messages de toi ont été postés. J'envoie celui-ci avant de les lire.
Ben oui à l'époque j'étais un grand débutant en micro-contrôleur.
Mais si je dois remplacer ma carte de développement par un arduino, je pourrais peut-être utiliser un Nano pour gagner de la place.
Qu'en pensez-vous ?
Ce serait plus simple en effet.
Pour savoir si c'est bien le problème que je subodore as tu testé les messages d'erreurs renvoyée par la bibliothèque ?
Les différentes bibliothèques sont presque toutes du coupé/collé (avec beaucoup de cinéma sur la licence opensourse et le respect des travaux des différents auteurs --> je me marre : bande de faux cul !).
Si tu as des "checksum error" c'est que c'est bien un problème de rapidité.
La bibliothèque version playground n'a maintenant presque plus d'erreur de somme de contrôle mais à 16 MHz.
A 8 MHz ce n'est pas assurément gagné d'avance.
Si tu as le temps essaye de lire l'état de la pin en utilisant les registres. En faisant ainsi on gagne un rapport 8 en vitesse de lecture.
Tu devrait pouvoir conserver ton quartz de 8 MHz et avoir un gain effectif de 4..
Le programme que j'utilise ne donne pas de message d'erreur. En fait, je ne sais pas du tout ce qui se passe dans la librairie que j'utilise. La procédure de lecture est ceci:
float Temperature()
{
float t = dht.readTemperature();
if (isnan(t)) {// if t Is Not a Number
return -99;
}
else {
return t;
}
}
Le seul message d'erreur est donc une réponse de -99.
Je ne suis pas certain non plus de ce que signifie "lire l'état de la pin en utilisant les registres". La pin utilisée pour lire le DHT est la pin D2 (Registre 0x09 ou 0x29). Veux-tu dire qu'on compte le nombre de boucle "while" pour que PinD passe de xxxxx0xx à xxxxx1xx ou vice-versa ?
C'est le revers de la médaille : une fonction digitalWrite/Read très facile d'emploi, qui fait tous les contrôles possibles pour détecter des erreurs utilisateur, qui transforme la numérotation Atmel (Gestion en PORT) en numérotation de 1 à n, malheureusement en utilisant PROGMEM, est forcément lente.
Et dans certains cas cela ne passe pas.
Veux-tu dire qu'on compte le nombre de boucle "while" pour que PinD passe de xxxxx0xx à xxxxx1xx ou vice-versa ?
Il faut distinguer la notion de bit (quantité d'information) de celle d'élément binaire 0 ou 1 qui pris isolément ne transporte aucune information.
On fait souvent la confusion car c'est souvent la même chose sauf dans des cas comme le DHT22.
Le DHT22 envoi des "bits" TOUJOURS sous la forme d'un couple élément binaire "0" (eb 0) suivi d'un élément binaire "1" (eb 1)
L'information est contenue dans la longueur des eb 0 et eb 1.
Le programme sait donc s'il doit recevoir un eb 0 ou un eb 1
Quand on sait que le prochain eb sera un eb 0 on entre dans une boucle while dont le critère de sortie est la détection d'un eb 1.
C'est là que la méthode de traitement est multiple :
Méthode des bibliothèques arduino
On récupère le temps avec millis en entrée et en sortie de boucle. Cela donne la durée de l'eb. On compare sa valeur avec la théorique pour prendre la décision 0 ou 1.
Le problème c'est que millis fait énormément de traitements inutiles pour cette application.
La conséquence est qu'il bouffe du temps normalement réservé à la boucle while. Si on ajoute le fait que comme digitalRead est lent on ne fera pas beaucoup de tours de boucle (moins de 10 dans le cas d'un bit 0) on arrive à prendre des fausses décisions d'où les Checksum Error.
Mon premier choix :
Le principe est peu différent mais nettement plus rapide --> utilisation du registre TCNTx d'un timer.
Il suffit juste d'écrire 0 dans un octet avant de lancer la boucle while et de lire ce même octet à la sortie de la boucle while.
Le deuxième choix (que je ne retrouve plus) :
L'utilisation d'un timer est inutile.
Il y a déjà une variable dans la boucle qui sert à ne pas bloquer le programme en cas de non réponse du DHT22.
Il suffit d'utiliser deux variables, une pour l'eb 0 et l'autre pour l'eb 1 et de les comparer.
Si la variable pour l'eb 1 à une valeur plus faible que celle de l'eb 0 le bit est égal à 0 dans le cas contraire le bit est un 1.
C'est déjà un peu plus clair, mais un peu seulement !
Il faudrait que je lise en détail la datasheet du DHT22 mais je suis un peu paresseux. J'ai d'abord essayé la librairie et comme cela a marché du premier coup, je n'ai pas approfondi la datasheet et je me suis contenté d'utiliser la librairie.
En fait, j'ai un autre problème que je vais exposer dans un nouveau topic.
[EDIT] Mon problème est résolu. En corrigeant une valeur, j'avais mis une virgule au lieu d'un point. Evidemment, cela bloquait à la compilation mais le message d'erreur ne m'aidait pas
(expected unqualified-id before numeric constant).