Probléme pour lire une valeur d'une sonde DS18B20 (Résolu)

Bonjour à tous,

je possède une carte mega2560

je viens vers vous car je rencontre un problème pour lire la valeur d’une sonde thermique.

Le premier problème est qu'il m' est impossble de tester les lignes de codes déjà présentes sur le même sujet, cela me dit que le téléversement est impossible sur une carte mega malgré que j'ai installé les bibliothèques ?

Et du coup j'ai essayé simplement avec une linéarisation et cela fonctionne enfin j'ai un retour sauf que j'ai une valeur de 98-97 sachant que 0v=-55 et 5v = 125 degres
:confused:

voici le code

void setup()

{

 Serial.begin(9600);

}

void loop() 

{

 int valeur=analogRead(A0);//lit en A0

 int t=map(valeur,0,1023,0,5000);// linearisation

 int valeurSonde=map(t,0,5000,-50,125); // je reprends linearisation

 Serial.print("Valeur lue : ");

 Serial.println(valeurSonde); //je lit valeur sonde
 delay(1250);
}

Merci de votre aide !

salut ,

remplacez :

int t=map(valeur,0,1023,0,5000);// linearisation

  int valeurSonde=map(t,0,5000,-50,125); // je reprends linearisation

par :

Serial.print("Valeur brute : ");
Serial.println (valeur);

 int valeurSonde=map(valeur,0,1023,-55,125);

ca dit quoi ?

PS : le code que vous avez mis est complet ?

si oui , consultez les exemples fournis avec la bilbiotheque , il manque la moitié du code , l ' initialisation et tout le toutim ...

Et du coup j'ai essayé simplement avec une linéarisation et cela fonctionne enfin j'ai un retour sauf que j'ai une valeur de 98-97 sachant que 0v=-55 et 5v = 125 degres

Ça veut dire quoi ?
Tu parle de la communication avec le DSB20 qui est un composant numérique et d'une linéarisation.

Je ne comprend pas bien.

PS: tu as intérêt à mettre vite fait le code entre balise code ==> voir les messages épinglés.
Et d'indenter le code avant de le copier (Ctrl T dans l'IDE)

Le DS18B20 ne se lit pas sur une broche analogique.
Il faut le raccorder à une broche GPIO, avec une résistance ... trouve de la doc sur ce composant.
De plus il existe une (ou plusieurs) bibliothèques permettant de gérer facilement ce composant. Cherche dans les bibliothèques proposées par l'IDE Arduino.

Bonsoir
merci à tous de votre aide j’ai tout repris et cela fonctionne !

j’essaye de suivre de cours notamment sur open classe room et le forum avec les tutos mais je suis vraiment débutant…

par exemple, maintenant je voudrais faire un truc simple allumé une led si la température est sup à 30 et une autre éteinte, pour ensuite remplacer les leds par des relais
Mais même cela ne fonctionne pas… les leds restent allumées tout le temps.
J’ai essayé de changer de place de configuration mais rien ne change

#include <OneWire.h>
OneWire  ds(10);  // entré 10
  int Temperature;
  int Seuil;
  int led1;
  int led2; 

  
void setup(void) 
{
   
  Serial.begin(9600); // pour avoir texte
}

void loop(void)
{ 
led1 = 2;
   led2 = 7;
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
 
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;


  if ( !ds.search(addr)) {
    
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      
      type_s = 1;
      break;
    case 0x28:
      
    case 0x22:
      
      type_s = 0;
      break;
    default:
      
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

 ;
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(" ");
  }

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0+0.75;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
 delay(1500);
 


if(celsius>=30) digitalWrite(led1,HIGH);

if(celsius<(30)) digitalWrite(led2,LOW);
}

Et si par hasard quelqu’un serait disponible pour perdre un peu de temps avec moi pour m’expliquer ce que je fais qu’il ne faut pas faire cela serait top !
Merci et dsl

Y'a plein d'inits ( pinmade() ... ) que tu devrais mettre dans setup() plutôt que dans loop() pour ne les faire qu'une fois.
Apparement (vu ton code) il y a deux thermomètres, réglés différemment (une histoire de résolution).
C'est bien ton cas ... ou c'est du copier-coller sans comprendre ?

OK à la fin tu obtiens une température (enfin ici un des deux températures)
Tout ce code, qui déclenche la lecture et convertit en °C, tu devrais le mettre dans une fonction.
Tu pourrais penser faire

float lire_temperature ();

mais ça ce n'est pas une bonne fonction car comment détecter une erreur ?
Un bonne fonction c'est

int llre_temperature ( float & temperature);

Tu passes en argument un référence sur un float, qui sera renseigné s'il n'y a pas eu d'erreur. L'entier renvoyé par la fonction est un code d'erreur - ou OK, qu'on choisit en général à 0. Par ex. si ta fonction n'a pas trouvé le capteur, elle renvoie -1. pour une autre erreur, c'est -2 ...

Donc, bon, tu as enfin ta température. Il est temps d'agir.
1 - il faut introduire une hystérésis, c-à-d une limite haute et une limite basse. Pourquoi ? Parce que si ta température oscille exactement autour de 30, tu vas allumer/éteindre la LED à toute vitesse.
Donc, tu fais

si T > Limite haute
  allumer
else if T > limite_basse
  éteindre

Tu peux prendre 29 et 31 °C comme limites, par ex.

Enfin, tu n'a pas mis de temporisation.
Enfin si, il y en a une dans le dialogue avec la sonde, mais ce n'est pas maîtrisé.
Tu dois te demander tout les combien de temps tu veux faire une mesure
à mon avis 1 fois /seconde c'est déjà beaucoup

J’ai écrit ça dans un autre post :

Setup et loop sont deux fonctions => voir ce qu’est une fonction en C/Cpp

Les noms setup et loop n’ont pas été choisis au hasard.
Setup : c’est pour les configurations. Cette fonction ne s’exécute qu’une seule fois au lancement du programme.
Loop : c’est de loop qu’on lance le programme. Loop est placée (par l’ide) dans une boucle dont elle ne peut pas sortir.
Elle s’exécute en boucle d’où son nom.

Et là je vois que la déclaration des sorties (fonction pin mode) est dans la loop.
Ne serait-elle pas mieux dans setup ?
Ça n’empêche pas de fonctionner mais cela allège le programme : inutile de refaire la déclatation à chaque tour de loop

D’autre part évite définitivement le Serial.begin(9600) passe à un débit plus élevé comme 115200 et même plus.
Mine de rien faire des sorties moniteur à 9600 bauds ralenti le programme.
Là aussi cela n’empêche pas de fonctionner mais c’est un peu idiot.

Dans une réponse précédente (#2) j’ai écrit :

Et d’indenter le code avant de le copier (Ctrl T dans l’IDE)

L’indentation c’est fait pour aider, pas pour embêter.

Si tu indentes régulièrement il te sera plus facile de détecter des erreurs et le code sera plus facile à comprendre pour les autres.

C’est très bien de faire des sorties moniteur pour surveiller la valeur de certaines variables .
Mais quand je vois cette ligne de code (a plusieurs endroits et surtout isolée, donc ce n’est pas pour faire un saut de ligne) :

Serial.println();

je ne pense pas qu’elle t’aide beaucoup.

Je ne regarde pas les détails du code ce n’est pas mon truc mais avant de dire que l’allumage des dels ne marche pas est tu certain que la valeur de température que tu as déterminé est la bonne ?

Si tu traite les problèmes un par un tu y arrivera plus facilement et plus vite que si tu veux faire tout en même temps.
Tu peux très bien faire :

  • un programme rien que pour “interoger” un DS18B20
    et à coté
  • un programme qui allume les dels en fonction de la valeur que tu as mis dans deux variables. Pour vérifier ces lignes de code tu n’as pas besoin de DS18B20.

Et quand tout fonctionne tu assemble.

68tjs:
Mine de rien faire des sorties moniteur à 9600 bauds ralenti le programme.

? je ne vois pas pourquoi ?
Si les octets sont émis sous interruption, le coût dépend du nombre d'octets à émettre, pas de la vitesse à laquelle l'UART les sérialise.
Sauf si le nombre d'octets en attente atteint la capacité du tampon, là bien sûr ça coince et le programme émetteur doit attendre.

Prends un analyseur logique et quand il y a plusieurs messages assez longs les uns derrière les autres a un moment ça coince. C'est une constatation d'électronicien qui voit que cela sature quelque part.
L'organisation de la liaison série avec les avr c'est un mix entre des tampons logiciels et des circuits de pure électronique, je n'irai pas plus loin dans le détail. Tout ce que je peux dire c'est que j'avais constaté un comportement bizare, d'où l'analyseur logique, et que ce comportement a disparu avec le passage à un débit plus élevé.

Cela ne se produit pas avec des messages courts mais autant prendre les bonnes habitudes dès le départ..

hello
meme longueur de texte à transmettre mais à deux vitesses différentes

unsigned long deb = 0;
unsigned long fin = 0;
void setup() {
  Serial.begin(2000000);//   512µ
  //Serial.begin(300);  //  766808µ
  deb = micros();
  Serial.print("ceci est un test de vitesse de transmission serie avec le moniteur 300/2000000 bauds  = ");
  fin = micros();
  Serial.print((fin - deb));
}

void loop() {}

Bonjour à tous et merci de votre aide !

J’ai essayé de comprendre ce que vous dites avant de l’appliquer…

Tout d’abord, j’ai bien mis les informations dans setup comme vous me l’avez dit

Non, pour l’instant je n’ai qu’une sonde, malgré que j’ai essayé de comprendre le code
je n’ai même pas vu qu’il y avait une deuxième sonde… et ne le vois toujours pas :o

La fonction serait ?

in lireTemperature (float celsius)

if(celsius > 10)
{
Serie.println("sonde ok") ;
}
else if (celsius<=10)
{
Serie.println("Probleme sonde !") ;

Ok pour l’hystérésis

Ok pour la tempo je l’ai modifié pour avoir une mesure toutes les 10 minutes

Je penser que cela ne servait que pour le forum ctrl + T… c’est génial cela range tout bien, je l’utiliserais tout le temps ! :slight_smile:

Pour la valeur de température, elle semble correcte, je retrouve les mêmes valeurs avec un autre thermomètre

Je vais reprendre les exercices pour faire des tableaux avec les leds ect et faire comme vous me dites toute assembler après !

Et dire que ce n’est que le début et je galère déjà :roll_eyes:

Et dire que ce n'est que le début et je galère déjà :roll_eyes:

Il faut voir les choses du bon coté : c'est au début qu'on galère le plus.

oui c’est sur ^^

Alors en utilisant le premier code j’arrive à allumé et eteindre les leds suivant une seul consigne de temp

#include <OneWire.h>
OneWire  ds(10);  // entré 10
int Temperature;
int led1;
int led2;
int limiteHaute = 32;
int limiteBasse = 29;
int pinLed1 = 2;
int pinLed2 = 7;
void setup(void)
{
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);

  Serial.begin(115200); // pour avoir texte augmenter a 115 200
}

void loop(void)
{



  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;


  if ( !ds.search(addr)) {

    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  for ( i = 0; i < 8; i++) {
    Serial.write(' ');

  }

  if (OneWire::crc8(addr, 7) != addr[7]) {

    return;
  }


  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:

      type_s = 1;
      break;
    case 0x28:

    case 0x22:

      type_s = 0;
      break;
    default:

      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  ;
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();

  }

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0 + 0.75;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");


  if (celsius > limiteHaute) 
  {
    digitalWrite(pinLed1, LOW); //led1 éteinte
    digitalWrite(pinLed2, HIGH); //led2 allumée
    Serial.println("trop chaud");
  }
  if (celsius < limiteBasse) 
  {
    digitalWrite(pinLed1, LOW); //Led1 allumée
    digitalWrite(pinLed2, LOW); //led2 éteinte
    Serial.println("");
    Serial.println("en chauffe");
    Serial.print("La limite basse est de ");
    Serial.print(limiteBasse );
    Serial.print(" Celsius");
  }
  delay(2500); //petite attente
}

par contre j’ai trouvé un nouveau code pour lire les sondes qu’y est beaucoup plus lisible que le premier, par contre il m’est impossible d’utiliser les leds j’ai cette erreur:

 no match for 'operator<' (operand types are 'DallasTemperature' and 'int')

Est ce à cause que j’utilise une information provenant de la bibliothèque Dallas et qu’il faudrait que je la convertisse ?
Comme pour passer d’un real à un int 16 ? ou est ce autre chose ?
voici le code

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS_1 2 // je dis ou lire la sonde pin 2
#define ONE_WIRE_BUS_2 4// pareil pour la deuxieme pin 4

OneWire oneWire_in(ONE_WIRE_BUS_1); // j'indexe dans la biblio?
OneWire oneWire_out(ONE_WIRE_BUS_2);

DallasTemperature sonde1(&oneWire_in);// je nome l'indexe
DallasTemperature sonde2(&oneWire_out);//pareil

// je declare mes variables
int Temperature;
int limiteHaute = 32;
int limiteBasse = 29;
int pinLed1 = 2;
int pinLed2 = 7;

void setup(void)//unique et intervient une fois
{
  Serial.begin(115200);
  Serial.println("Test avec deux sondes avec retour sur led");
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  sonde1.begin();//lancement
  sonde2.begin();//lancement sonde
}

void loop(void)
{
  Serial.println("Recherche de temperature...");

  sonde1.requestTemperatures();// interrogation
  sonde2.requestTemperatures();// interrogation
  delay(1500);

  Serial.print("sonde1: ");
  Serial.println(sonde1.getTempCByIndex(0));//recuperation de la temp
  delay(1500);

  Serial.print("sonde2: ");
  Serial.println(sonde2.getTempCByIndex(0));
  delay(5000);// tous les combiens de temps on scrute

  //allumage de la led pour sonde 1

  if (sonde1 > limiteHaute)
  {
    digitalWrite(pinLed1, LOW); //led1 éteinte
    digitalWrite(pinLed2, HIGH); //led2 allumée
    Serial.println("trop chaud");
  }
  if (sonde1 < limiteBasse) //test si bouton levé
  {
    digitalWrite(pinLed1, LOW); //Led1 allumée
    digitalWrite(pinLed2, LOW); //led2 éteinte
    Serial.println("");
    Serial.println("en chauffe");
    Serial.print("La limite basse est de ");
    Serial.print(limiteBasse );
    Serial.print(" Celsius");
  }

merci :slight_smile:

Essaie de mettre ça : sonde2.getTempCByIndex(0) à la place de sonde2 dans ta comparaison à limiteHaute :wink:

Pareil pour sonde1.getTempCByIndex(0) et limiteBasse.

Cela fonctionne merci :slight_smile:

j'ai remplacé les leds par des relais tout fonctionne impec !

Maintenant reste plus qu’a trouver comment faire fonctionner mon module RTC !

Merci à tous et surement à très bien tôt dans un autre post x)