Problème pour brancher 7 sondes DS18B20 sur le même bus

Il manquait effectivement une accolade. Je parviens désormais à téléverser.

Je ne comprends pas le sens de la “phrase” : digitalWrite( pinBuzzer, digitalRead(pinBuzzer) == HIGH ? LOW : HIGH); Je peux difficilement réfléchir au problème qui se pose actuellement.

Lorsque je téléverse,

 if (not modeSilence && alarmesEnCours != AUCUNE_ALARME) {

    // une alarme au moins est en cours et on n'est pas en mode silence
    // digitalWrite(pinBuzzer, HIGH);
    static uint32_t chrono = 0;
    if (millis() - chrono >= 1000) {
      digitalWrite( pinBuzzer, digitalRead(pinBuzzer) == HIGH ? LOW : HIGH);
      chrono = millis();
    }
    else
    {
      digitalWrite(pinBuzzer, LOW);
    }
  }
  }

Le buzzer ne fonctionne plus, il fait des tic, tic, tic toutes les secondes. je me suis dit que si la fonction demandait 1 seconde de silence, il n’y avait pas de temps buzzer défini.

J’ai essayé de réintégrer la “phrase” - digitalWrite(pinBuzzer, HIGH); - là où elle fonctionnait avant mais c’est un petit bourdonnement très léger que le buzzer produit alors.

Peut-être que la solution se trouve dans la “phrase” digitalWrite( pinBuzzer, digitalRead(pinBuzzer) == HIGH ? LOW : HIGH); que j’ai essayé de manipuler à tâtons ???

Le else n'est pas placé au bon endroit. Il correspond au premier if, il coupe le buzzer si en mode silence ou qu'il n'y a pas d'alarme

 if (not modeSilence && alarmesEnCours != AUCUNE_ALARME) {

     // une alarme au moins est en cours et on n'est pas en mode silence
     // digitalWrite(pinBuzzer, HIGH);
     static uint32_t chrono = 0;
     if (millis() - chrono >= 1000) {
       digitalWrite( pinBuzzer, digitalRead(pinBuzzer) == HIGH ? LOW : HIGH);
       chrono = millis();
     }
   }    else   {
       digitalWrite(pinBuzzer, LOW);
   }
}

le Second argument de digitalWrite indique l'état de la sortie.
digitalRead(pinBuzzer) == HIGH ? LOW : HIGH cette partie retourne LOW si digitalRead(pinBuzzer) est HIGH et sinon retourne HIGH

Super, tout fonctionne désormais comme je le souhaitais.

Merci fdufnews, pour cette explication sur les arguments, (pour vous ça doit paraitre limpide ces suites d’arguments qui pour moi sont complexes) merci pour le placement de l’accolade.

Merci JML pour ce programme que je vais progressivement m’approprier.

En début de conversation, Claudius me demandait :

J’ai pensé qu’il parlait de l’alimentation générale de la UNO .

J’ai pensé que le mode parasite était péjoratif.

J’en ai déduit qu’il valait mieux avoir une alimentation externe à la carte pour éviter les parasites que les sondes pouvaient subir si la carte était alimentée directement.

C’était une erreur de schéma, dans la réalité, les résistances de la Gate du transistor ont bien les valeurs que vous m’avez données et qui m’ont été recommandées par 68tjs.

Merci pour tous vos conseils.

pour expliciter un peu plus, la notation avec le ? et les : s'appelle l'opérateur ternaire.

ça s'écrit comme cela

condition ? statement1 : statement2 ;

et ça se lit ainsi :

si la condition est vraie, alors évalue et retourne la valeur de statement1 sinon évalue et retourne la valeur de statement2

donc quand je fais

digitalRead(pinBuzzer) == HIGH ? LOW : HIGH

la condition c'est digitalRead(pinBuzzer) == HIGH, c'est à dire si pinBuzzer est HIGH

donc si on traduit ça se lit ainsi :

si pinBuzzer est HIGH alors retourne LOW sinon retourne HIGH

➜ en injectant cela comme second paramètre de digitalWrite, ça permet d'inverser l'état de la pin.

Je commence à comprendre cette subtilité du langage de programmation.

Le paragraphe suivant m’interroge aussi parce qu’il est similaire mais ne comprend pas de “digitalRead” dans sa formulation.

  boutonSilence.poll();
  if (boutonSilence.onPress()) {
    modeSilence = not modeSilence;
    digitalWrite(pinLedSilence, modeSilence ? HIGH : LOW); 			
    if (modeSilence) debutModeSilence = millis();
is();

Peut-on traduire ce paragraphe par :

si le bouton silence est pressé.

Et si le mode silence n’est pas le mode silence

la broche de sortie ledSilence, (si le mode silence est activé)… est inversée ???

Une autre énigme toute différente m’interroge, je reçois des notifications par mail lorsque les autres membres du forum interviennent dans cette discussion mais je n’en reçois jamais lorsque c’est JML qui intervient.

Parce que c’est JML…:woozy_face:

je suis discret de nature, je n'aime pas déranger :)

alors le code c'est

  if (boutonSilence.onPress()) {
    modeSilence = not modeSilence;
    digitalWrite(pinLedSilence, modeSilence ? HIGH : LOW); 			

donc on dit

Si le bouton silence vient d'être appuyé alors on inverse la valeur du mode silence (on alterne en appuyant sur ce bouton entrée dans le mode silence et arrêt du mode silence) puis on utilise ce nouveau modeSilence comme condition pour l'état de la pinLedSilence
c'est l'opérateur ternaire qui dit
si on est on mode silence (la condition) alors on met la pin à HIGH, sinon c'est à LOW.

C’est trés honorable de votre part…

“Mais en même temps”, comme dirait Manu l’homme aux discrètes lunettes noires, on voit beaucoup de pizza au plat du jour ces temps ci :smiling_face_with_sunglasses:.

Discrétion et efficacité :+1:

Bonjour, je reviens vers vous pour essayer de comprendre tous les termes du programme élaboré par JMLs

j’ai essayé d’annoter la première partie mais j’ai besoin de corrections et de complément d’information.

Je vous place ces annotations dans le code mais elles sont peu lisibles, y a-t-il un moyen d’annoter le code de manière plus accessible ?

#include <Wire.h>        //j'inclue la bib. Wire.h……….      à quoi sert-elle ????????
#include <hd44780.h>                          // j'inclue hd44780 pour gérer le LCD   
#include <hd44780ioClass/hd44780_I2Cexp.h>    // j'inclue l'extension hd44780 pour gérer le LCD
#include <Toggle.h>                           // j'inclue Toggle pour gérer le bouton

#include <OneWire.h>      // j'incluse OneWir pour gérer le bus en (7)
#include <DallasTemperature.h>    // j'incluse Dallas pour gérer les sondes

const uint8_t nbCols = 20;      // indique qu'il y a 20 colonnes du LCD,      pourquoi const uint8-t ………???
const uint8_t nbRows = 4;     // indique qu'il y a 4 lignes du LCD
hd44780_I2Cexp lcd;     // indique que c'est hd 44780 qui gère le LCD

const byte pinLedHP = 11;     // OK On peut changer cette valeur.
const byte pinLedPC = 12;       // OK On peut changer cette valeur.
const byte pinLedECS = 13;      // OK On peut changer cette valeur.
const byte pinBuzzer = 9;       // OK On peut changer cette valeur.
const byte pinBoutonSilence = 3;    // OK On peut changer cette valeur.
const byte pinLedSilence = 2;     // OK On peut changer cette valeur.

Toggle boutonSilence(pinBoutonSilence); // indique que Toggle gère le bouton silence en (3)

const byte pinBus = 7;      // indique que le bus des sondes est en 7… On peut changer cette valeur.
OneWire busOneWire(pinBus);     // indique que OneWire gère le bus (7)
DallasTemperature capteurs(&busOneWire);  // indique que Dallas gère les sondes et le bus avec OneWire
const uint8_t resolution = 12;    // indique la précision des sondes au 10 ème de ° pour le 12 bits. On peut changer cette valeur.. pourquoi const uint8_t???

uint32_t derniereLecture = 0; // indique que l'on remet le compteur à 0       pourquoi long-temps n'a pas été déclaré comme préconisé dans le tuto d'eskimon ???

struct Capteur {        // On explique la structure de ce qui est écrit plus bas     est-ce cela ???
  const char * nom;     // le nom               est-ce cela ???
  DeviceAddress adresse;      // l'adresse              est-ce cela ???
  float derniereTemperature;    // demande de prendre les températures        est-ce cela ???
  bool besoinAffichage;     // prend régulièrement les résultats pour pouvoir les afficher    est-ce cela ???
};

// Pour wokwi on a ces adresses   // j'ai remplacé par les miennes    0.0 affichage au dixième de degré est-ce cela ???   pourquoi spécifier "true "???
Capteur lesCapteurs[] = {
  {"EHP", {0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x7E}, 0.0, true}, // 0 - Eau Haut Poêle
  {"EBP", {0x28, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xDE}, 0.0, true}, // 1 - Eau Bas Poêle
  {"HCP", {0x28, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xBE}, 0.0, true}, // 2 - Haut Cuve Poêle
  {"BCP", {0x28, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x87}, 0.0, true}, // 3 - Bas Cuve Poêle
  {"PC ",  {0x28, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xE7}, 0.0, true}, // 4 - PC
  {"ECS", {0x28, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x47}, 0.0, true}, // 5 - ECS
};

J'ai un écran LCD piloté en I2C. J'ai donc besoin de la bibliothèque Wire pour gérer le I2C et j'ai décidé d'utiliser la bibliothèque hd44780 et plus spécifiquement la classe qui gère l'écran I2C qui est dans hd44780_I2Cexp.h


ces commentaires ne sont pas top

On définit ici de constantes ou des variables avec le bon type.

La constante nbCols est le nombre de colonne, nbRows le nombre de lignes de mon écran qui va s'appeler lcd.

Ces valeurs sont nécessaire dans le code plus tard pour définir le lcd (appel à begin) ou calculer où positionner nos écritures.

Comme le nombre de colonnes et lignes ne sera jamais modifié, on peut le dire au compilateur en utilsant le mot clé const.


ces commentaires sont peu intéressants...

expliquez plutôt à quoi ça sert

// Broche pour l'indicateur de dépassement de seuil pour Eau Haut Poêle.  
// câblage = pin 11 ---- Resistance 220Ω --- Anode [LED] Cathode ---- GND. 
const byte pinLedHP = 11;

// Broche pour l'indicateur de dépassement de seuil pour .....  
// câblage = pin 12 ---- Resistance 220Ω ---Anode [LED] Cathode ---- GND. 
const byte pinLedPC = 12;    // cette valeur dépend donc du câblage
...


C'est la création d'une variable nommée boutonSilence, du type Toggle, qui est initialisée en utilisant le N° de la broche pinBoutonSilence


Vous pourriez expliquer que la sonde fonctionne avec une précision réglable, entre 9, 10, 11 et 12 qui correspondent à la résolution de mesure de la température, exprimée en bits. La résolution définit la précision et le nombre de décimales que la sonde peut fournir.
La valeur 9 signifie que la sonde mesure avec une résolution de 9 bits, ce qui correspond à des incréments de 0,5 °C. La valeur 10 correspond à une résolution de 10 bits, soit des incréments de 0,25 °C. La valeur 11 correspond à 11 bits, soit des incréments de 0,125 °C. La valeur 12 correspond à 12 bits, ce qui donne la résolution maximale de la sonde, avec des incréments de 0,0625 °C.

Plus la résolution est élevée, plus la mesure est précise, mais le temps de conversion de la température augmente également. Pour 12 bits, le temps de conversion est d’environ 750 ms, tandis que pour 9 bits il est d’environ 93,75 ms.

pourquoi const uint8_t???

const parce qu'on la fixe une fois pour toute dans notre programme. elle ne changera pas donc on le dit au compilateur et le type uint8_t vient de l'usage que l'on veut en faire. Si vous regardez l'interface de la classe, on voit

que la fonction prend un paramètre de type uint8_t (c'est à dire un octet), donc c'est naturel de prendre ce type pour notre constante.


Concernant

Pour représenter facilement nos différents capteurs, on définit un nouveau type par le biais d'une structure.
On va mettre dans la structure tout ce qui a trait à un capteur dans notre code et donc après analyse des besoins, on voit qu'on a besoin :

  • d'un nom pour afficher sur le LCD. ce nom ne changera pas, donc on prend un pointeur sur un texte fixe (const char *) comme type de données.
  • l'adresse du module
  • la dernière valeur lue lors des demandes successives (ça permet de conserver la t° et de voir à combien on était sans attendre qu'une conversion soit terminée)
  • un drapeau vrai ou faux qui va dire si cette valeur a changé depuis la dernière fois afin d'optimiser l'affichage (on n'a pas besoin de récrire une valeur qui n'a pas changée)

on utilise ensuite ce nouveau type de données pour décrire nos capteurs

Capteur lesCapteurs[] = {
  {"EHP", {0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x7E}, 0.0, true}, // 0 - Eau Haut Poêle
  {"EBP", {0x28, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xDE}, 0.0, true}, // 1 - Eau Bas Poêle
  {"HCP", {0x28, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xBE}, 0.0, true}, // 2 - Haut Cuve Poêle
  {"BCP", {0x28, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x87}, 0.0, true}, // 3 - Bas Cuve Poêle
  {"PC ",  {0x28, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xE7}, 0.0, true}, // 4 - PC
  {"ECS", {0x28, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x47}, 0.0, true}, // 5 - ECS
};

sur la première ligne par exemple, on dit que l'on a un capteur dont le petit nom sera EHP, on donne ensuite son adresse, on dit que la dernière T° lue était 0 (pourquoi pas) et que l'on a besoin de faire un affichage (pour que lors du premier passage l'écran affiche quelque chose même si c'est 0°)


Vos explications me sont très utiles.

Dans mes premiers programme, avec “LiquidCristal.h”, il me semble qu’il fallait installer “OneWire.h” pour le I2C qui ne fonctionnait pas avec Wire.

… Mais dans ce cas, à quoi sert OneWire ? j’ai téléversé le programme en supprimant “OneWire.h” et tout semble fonctionner normalement, cela me questionne, OneWire est-il indispensable si le programme fonctonne avec Wire ?

Je règle la résolution à 12bits car, sur mon LCD comme sur wowi, sur 9 bits, les températures sont données au 5/10ème. par exemple elles passent de 22 à 22,5 sans plus de détail.

J’ai réalisé des essais sur wokwi, en faisant évoluer la températures du curseur sensiblement avec les flèches du clavier de l’ordinateur.

en sélectonnant 10 bits, j’ai un peu plus de précisions, les températures passent de 22 à 22,3 puis 22,5 puis 22,7 puis 24 sans les températures intermédiaires.

sur 11 bits, j’obtiens toutes les décimales mais on s’aperçois qu’l y a un décalage entre la température affichée au curseur et la température affichée sur le LCD

Avec 12 bits, on a la précision la meilleur bien qu’imparfaite. Je ne sais pas si la simulation de wokwi reflète la réalité.

encore merci pour vos conseils très précis.

Je n'utilise pas LiquidCristal.h parce qu'il y a plusieurs bibliothèques qui portent ce nom là et donc on ne sait jamais laquelle c'est et elles sont moins performantes que la bibliothèque hd44780

Si ça compile c'est que soit ce n'est pas utilisé, soit c'est ajouté pour vous par la bibliothèque

Faut pas tout mélanger.
Wire : librairie pour la gestion des périphérique I2C
OneWire: librairie pour la gestion des périphériques One Wire (comme le 18B20, par exemple)

La librairie DallasTemperature gère l'inclusion de OneWire.

Bonjour,

la doc du capteur donne une précision de+/-0,5°. Est ce que les décimales sont vraiment nécessaires?

https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf

Merci pour cette précision.

Effectivement, je n’ai pas suffisamment distingué Wire et OneWire.

Voilà une question pertinente. Effectivement, sur mon banc d’essai, j’ai 6 sondes espacées de 10cm. et qui donnent pratiquement chacune une température différente avec une variation d’un degré entre la température la plus haute et la température la plus basse.

Cependant, dans mon projet, j’ai besoin de savoir si une température est stable, est entrain de monter ou entrain de descendre et d’estimer à quelle vitesse cette température évolue. Pour analyser rapidement cette tendance, j’ai effectivement besoin d’avoir une précision au dixième de degré pour certaines sondes. Cette précision n’est pas nécessaire pour d’autres sondes.

La doc du composant dit

±0.5°C Accuracy from -10°C to +85°C

L’accuracy (exactitude) indique à quel point la valeur mesurée par le capteur se rapproche de la vraie température réelle. Pour le DS18B20, ±0,5 °C entre -10 °C et +85 °C signifie que la température affichée peut différer de la température réelle de plus ou moins 0,5 °C.

La précision décrit la reproductibilité des mesures : si vous mesurez plusieurs fois la même température, une mesure précise donnera toujours des valeurs très proches les unes des autres, même si elles sont toutes légèrement décalées par rapport à la vraie température.

Un capteur peut être précis mais pas exact (mesures cohérentes mais systématiquement décalées) ou exact mais pas précis (en moyenne proche de la vraie valeur, mais avec beaucoup de fluctuation).

En pratique, la précision réelle, c’est-à-dire la variation entre mesures répétées à température stable, est de l’ordre de ±0,1 à ±0,2 °C, mais cela dépend beaucoup de l’alimentation, du câblage et de l’environnement thermique. Les datasheets ne donnent pas de chiffre officiel pour la précision, seulement pour l'exactitude.

➜ quand vous dites "précision au dixième de degré pour certaines sondes" est-ce bien de la précision dont vous voulez parler ?

Ce n'est peut-être pas le bon capteur que vous avez choisi... un TMP117 sera plus précis et plus exact.

Bien sur que les décimales sont nécessaires, elles sont sans rapport avec la précision. chaque bit ajouté multiplie la résolution par 2. C'est un principe bien connu en programmation de conserver la résolution maximum avant les calculs qui peuvent être faits sur une variable

Comme dit précédemment, pour le DS18B20, l’exactitude est de ±0,5 °C entre -10 °C et +85 °C. La précision réelle n’est pas spécifiée officiellement, mais elle est souvent de l’ordre de ±0,1 à ±0,2 °C selon l’alimentation, le câblage et l’environnement.

La résolution (9 à 12 bits) détermine uniquement le pas de mesure affiché. A 12 bits le capteur peut afficher des incréments de 0,0625 °C, mais cela ne signifie pas que la mesure est réellement exacte à ±0,0625 °C ➜ l’exactitude reste ±0,5 °C entre -10 °C et +85 °C et la précision réelle dépend des caractéristiques internes du capteur et des conditions environnementales. Changer la résolution permet juste d’avoir une valeur plus lisse, de réduire le temps de conversion ou d’économiser de l’énergie, mais cela n’améliore ni l’exactitude ni la précision de la mesure.

Dit autrement, même si le capteur affiche un pas de 0,0625 °C à 12 bits, la variation réelle entre mesures répétées peut atteindre ±0,1 à ±0,2 °C à cause de la précision limitée. Cela signifie que les différences affichées plus fines que cette précision n’ont pas de valeur réelle : elles ne reflètent pas forcément de variation réelle de température mais seulement le bruit de mesure. Le pas fin ne rend pas la mesure plus exacte, il ne fait qu’afficher une résolution numérique plus élevée sans gain réel sur la fiabilité.

Je pense que pour le DS18B20, le réglage optimal se situe à 10 bits. Cela donne un pas de 0,25 °C, ce qui est proche de la précision réelle du capteur (±0,1 à ±0,2 °C).

Augmenter à 12 bits n’apporte pas de gain réel, et descendre à 9 bits (0,5 °C) peut être trop grossier pour suivre correctement les variations.

➜ 10 bits est un compromis entre résolution utile, temps de conversion et fiabilité de la mesure.