Go Down

Topic: [AIDE] Capteur 18B20 (module) plusieurs actions (Read 4359 times) previous topic - next topic

dancex47

Bonjour à tous !

Premiers post pour premiers pas en programmation :-)
Donc merci de me lire avec mes mots n'ayant, pour l'instant, pas tout assimilé.

J'ai donc un projet simple : Arrosage automatique

Matériel :

1 x ARDUINO R3
1 x Module capteur 18B20  http://arduinosensors.nl/index.php?route=product/product&path=20&product_id=69
1 x Ecran LCD 16x2

Le VRAI projet :
         - Arroser une surface afin de la maintenir à 25°C

Le fonctionnement :
         - Enclenchement de l'arrosage lorsque <25°C et couper une fois atteinte.
         - Affichage sur LCD 16x2 en direct (température et action)

Mon souhait :
         - Lire en continue la température MÊME une fois l'arrosage enclenché (Relay; HIGH)


Maintenant voici mon problème  :

Suivant le code ci-joint et comme je ne sais pas mettre plusieurs actions (je débute) et ce sont des bouts de codes pompés sur le net et un peu de moi (quand même :-) ...)
Je ne sais pas faire en sorte que le relais s'enclenche à <25°C et EN MÊME TEMPS que la lecture du capteur continue (ainsi que les actions d'affichage sur le LCD) ceci afin qu'une fois les >25°C, le relais coupe.

Suivant mon code (qui est loin d'être propre, j'en conviens) TOUT s'arrête lorsque le relais est sur HIGH.
Donc plus de lecture, plus de continuité sur le LCD etc... (enfin je pense car pas encore branché LCD).

en définitive mes actions sont BLOQUANTES et il me faut donc des NON BLOQUANTES (c'est bien ca ?)

J'ai un lien sympa sur le sujet : Multitâches
Mais comment l'intégrer dans mon code, si toutefois c'est bien la solution...

Ma demande peut vous paraître simple mais pour un débutant, c'a l'est moins.

En vous remerciant pour votre aide.



Code: [Select]
#include <OneWire.h> // Inclusion de la librairie OneWire
#define DS18B20 0x28     // Adresse 1-Wire du DS18B20
#define BROCHE_ONEWIRE A0 // Broche utilisée pour le bus 1-Wire

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
 boolean unefois = false;
 boolean unefois1 = false;

OneWire ds(BROCHE_ONEWIRE); // Création de l'objet OneWire ds
//KY019 5V relay module
int relay = 7; // relay turns trigger signal - active high;

// Fonction récupérant la température depuis le DS18B20
// Retourne true si tout va bien, ou false en cas d'erreur
boolean getTemperature(float *temp) {
  byte data[9], addr[8];
  // data : Données lues depuis le scratchpad
  // addr : adresse du module 1-Wire détecté

  if (!ds.search(addr)) { // Recherche un module 1-Wire
    ds.reset_search();    // Réinitialise la recherche de module
    return false;         // Retourne une erreur
  }

  if (OneWire::crc8(addr, 7) != addr[7]) // Vérifie que l'adresse a été correctement reçue
    return false;                        // Si le message est corrompu on retourne une erreur

  if (addr[0] != DS18B20) // Vérifie qu'il s'agit bien d'un DS18B20
    return false;         // Si ce n'est pas le cas on retourne une erreur

  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20

  ds.write(0x44, 1);      // On lance une prise de mesure de température
  delay(800);             // Et on attend la fin de la mesure

  ds.reset();             // On reset le bus 1-Wire
  ds.select(addr);        // On sélectionne le DS18B20
  ds.write(0xBE);         // On envoie une demande de lecture du scratchpad

  for (byte i = 0; i < 9; i++) // On lit le scratchpad
    data[i] = ds.read();       // Et on stock les octets reçus

  // Calcul de la température en degré Celsius
  *temp = ((data[1] << 8) | data[0]) * 0.0625;

  // Pas d'erreur
  return true;
}

// setup()
void setup() {
  Serial.begin(9600); // Initialisation du port série
  lcd.begin(16, 2); //Taille LCD
  pinMode(12, OUTPUT); // LED VERTE
  pinMode(13, OUTPUT); // LED ROUGE
  pinMode(relay, OUTPUT); // Relais sortie
}

// loop()
void loop() {

  if(!unefois){
        //Affichage TEXTE (Nom du produit) une seule fois
    lcd.setCursor(0,0);
    lcd.print("  * X-Fresh *");
    lcd.setCursor(0,1);
    lcd.print(" Version : 1.0");
    delay(4000);
    lcd.clear();
    unefois = true;
  }
   
  if(!unefois1){
            //Affichage TEXTE (Démarrage) une seule fois
    lcd.setCursor(0,0);
    lcd.print("Bonjour !");
    lcd.setCursor(0,1);
    lcd.print("    Demarrage...");
    delay(1000);
    lcd.clear();
    unefois1 = true;
  }
 
  float temp;
 
  // Lit la température ambiante à ~1Hz
  if (getTemperature(&temp)) {

    // Affiche la température
    Serial.print("Temperature : ");
    Serial.print(temp);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }

 
 // Action au-dela de 25°C enclanche relais
  if (temp > 25) {

    lcd.setCursor(0,0);
    lcd.write("Arrosage actif");
    lcd.setCursor(0,1);
    lcd.print(temp); //Température mesurée réelle
    lcd.print(" C  [====]"); //Pompe enclenchée
    digitalWrite(12,LOW); //  VERTE ETEINTE
    digitalWrite(13,HIGH); //  ROUGE ALLUMEE
    digitalWrite(relay, HIGH); //  MOTEUR ALLUME
    delay(2000);


  }

  else {

    digitalWrite(relay, LOW); //  MOTEUR ETEINT
    digitalWrite(12, HIGH); // VERTE ALLUMEE
    digitalWrite(13, LOW); // ROUGE ETEINTE
    noTone(13);
  }
}
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

infobarquee

bonjour,
je ne pige pas trop
Quote
Le VRAI projet :
         - Arroser une surface afin de la maintenir à 25°C

Le fonctionnement :
         - Enclenchement de l'arrosage lorsque <25°C et couper une fois atteinte.
et dans ton code
Code: [Select]
if (temp > 25)

déjà au lieu de te faire chi.. avec des
Code: [Select]
if(!unefois)
*****
if(!unefois1)

si t veux afficher qu'une fois, tu mets le tout dans le setup
sans if(!unefois1) et if(!unefois)

après, tu peux mettre la fonction getTemperature dans un void à part
et faire l'affichage sur le lcd dedans

vire les delay aussi qui sont bloquant, pas besoin ou alors pour le ds18B20 un delay(500), ca lui suffira suivant la précision que tu désire

AUCUNE AIDE PAR MP

kamill

Bonjour,

La mesure de température se fait tout le temps. Il suffit que tu mettes aussi l'affichage de température dans le else final.
Tu peux enlever le delay(2000); La lecture de la température prend déjà un certain temps.

dancex47

Merci pour votre aide.

infobarquee : erreur de ma part, je voulais dire >25°C !
Ok pour l'astuce, je mets tous dans le setup.

kamill : Ok pour l'astuce de mettre dans le else final.
Par contre si je vire le delay(2000) le relais ne s'enclenche jamais, en gros mon programme ne fonctionne pas.
Pourquoi ?

Quoiqu'il en soit je fais les essais entre 12h et 14h et je reviens donner les résultats

Encore merci.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

kamill

#4
Sep 20, 2016, 10:15 am Last Edit: Sep 20, 2016, 11:44 am by kamill
Je ne sais pas si c'est la source du problème, mais dans ton programme tu testes si la valeur retournée par  if getTemperature() est valide
Code: [Select]
if (getTemperature(&temp)) {
ce qui est bien.

Par contre si la température est invalide, tu fais quand même ton traitement, il faudrait faire le traitement uniquement si la température est valide.

Il y a autre chose qui me parait bizarre, la led verte utilise la même pin (12) que le lcd.

dancex47

Je ne sais pas si c'est la source du problème, mais dans ton programme tu testes si la valeur retournée par  if getTemperature() est valide
Code: [Select]
if (getTemperature(&temp)) {
ce qui est bien.

Par contre si la température est invalide, tu fais quand même ton traitement, il faudrait faire le traitement uniquement si la température est valide.

Il y a autre chose qui me parait bizarre, la led verte utilise la même pin (12) que le lcd.
Je vais m'y pencher sérieusement en reprenant le code du début...
Effectivement la pin 12 (erreur de ma part) car j'ai modifié 10 fois le code en faisant des copier/coller...

Pour un débutant c'est assez compliqué.
Je prends d'ici et de là, j'essai d'assimiler les fonctions, un peu tout en même temps...

Je me sert de : Ce Site pour débuter...

Voyez que j'en suis au début !

Merci.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

dancex47

Bon j'ai éclairci le code, je met ici qu'à partir du void loop jusqu'à la fin :

Code: [Select]
void loop() {
  float temp;
  
  // Lit la température ambiante à ~1Hz
  if (getTemperature(&temp)) {

    // Affiche la température
    Serial.print("Temperature : ");
    Serial.print(temp);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }

  
 // Action au-dela de 25°C enclanche relais
  if (temp > 25) {

    lcd.setCursor(0,0);
    lcd.write("Arrosage actif");
    lcd.print(" C  [====]"); //Pompe enclenchée
    digitalWrite(8,LOW); //  VERTE ETEINTE
    digitalWrite(6,HIGH); //  ROUGE ALLUMEE
    digitalWrite(relay, HIGH); //  MOTEUR ALLUME

  }
  else {
    lcd.setCursor(0,0);
    lcd.write("Temperature");
    lcd.print(temp);
    lcd.print("        C "); //Pompe enclenchée
    digitalWrite(8,HIGH); //  VERTE ETEINTE
    digitalWrite(6,LOW); //  ROUGE ALLUMEE
    digitalWrite(relay, LOW); //  MOTEUR ALLUME
  }
  
}


Donc codé comme ca, résultat passé 25°C le relais ne fais que cliquer ON-OFF-ON-OFF-ON..........
Video : Clic Clac
Il clique à la même fréquence d'affichage de la température sur le moniteur série.

Donc si j'ajoute un delay genre (2000) il reste enclenché ce temps et ce coupe ensuite, pui se ré-enclenche si la température est toujours à + de 25° sinon non. (en gros j'allonge la fréquence de clignotement c'tout...)

Comment faire pour que le relais soit ON et le reste jusqu'à ce que la température descende en dessous de 25°C ?

Je sais que ca parait simple pour vous, moi j'apprends...

J'ai aussi du mal avec les void, je n'arrive pas à en créer, la base quoi.

Merci.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

kamill

#7
Sep 21, 2016, 11:21 am Last Edit: Sep 21, 2016, 11:40 am by kamill
Dans ton programme, il n'y a pas d'affichage de la température dans le cas ou l'arrosage est actif. Il faut l'afficher dans tous les cas pour analyser ce qui se passe
Il faut que tu gère une hystéresis car dans le cas ou tu es environ à 25° tu vas basculer en permanence des que tu auras une variation de température de 1 millionième de degré (j'exagère un peu).

dancex47

Super, merci beaucoup de ton aide.
Donc si j'ai bien compris, pour l'affichage en arrosage de la température dans le moniteur, je fais comme ceci :
Code: [Select]
void loop() {
  float temp;
 
  // Lit la température ambiante à ~1Hz
  if (getTemperature(&temp)) {

    // Affiche la température
    Serial.print("Temperature : ");
    Serial.print(temp);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }

 
 // Action au-dela de 25°C enclanche relais
  if (temp > 25) {

    lcd.setCursor(0,0);
    lcd.write("Arrosage actif");
    lcd.print(" C  [====]"); //Pompe enclenchée
    digitalWrite(8,LOW); //  VERTE ETEINTE
    digitalWrite(6,HIGH); //  ROUGE ALLUMEE
    digitalWrite(relay, HIGH); //  MOTEUR ALLUME
// Affiche la température
    Serial.print("Temperature : ");
    Serial.print(temp);
    Serial.write(176); // caractère °
    Serial.write('C');
    Serial.println();
  }
  else {
    lcd.setCursor(0,0);
    lcd.write("Temperature");
    lcd.print(temp);
    lcd.print("        C "); //Pompe enclenchée
    digitalWrite(8,HIGH); //  VERTE ALLUME
    digitalWrite(6,LOW); //  ROUGE ETEINTE
    digitalWrite(relay, LOW); //  MOTEUR ALLUME
  }
 
}


Par contre, pour l'hystéresis, je découvre le mot et avec une recherche rapide j'ai compris le principe.
Le plus long ca va être d'assimiler correctement et de coder... ce qui n'est pas gagné.

Mais quand tu parles d'une variation de température, tu veux dire que ce serai cette variation qui créée le clignotement du relais ? Car si c'était une variation de 25,00° à 24,99°C je comprendrais, mais la non.

Merci.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

kamill

Tu es sur que ton programme donne un affichage exploitable?
Affiches la température de manière similaire dans les 2 cas
Code: [Select]
 // Action au-dela de 25°C enclanche relais
 if (temp > 25) {
   lcd.setCursor(0, 0);
   lcd.write("Arrosage actif  ");
   lcd.setCursor(0, 1);
   lcd.print(temp); //Température mesurée réelle
   lcd.print(" C  [====]"); //Pompe enclenchée

   digitalWrite(8, LOW); //  VERTE ETEINTE
   digitalWrite(6, HIGH); //  ROUGE ALLUMEE
   digitalWrite(relay, HIGH); //  MOTEUR ALLUME
 }
 else {
   lcd.setCursor(0, 0);
   lcd.write("Arrosage inactif");
   lcd.setCursor(0, 1);
   lcd.print(temp); //Température mesurée réelle
   lcd.print(" C        "); //Pompe aretée

   digitalWrite(relay, LOW); //  MOTEUR ETEINT
   digitalWrite(8, HIGH); // VERTE ALLUMEE
   digitalWrite(6, LOW); // ROUGE ETEINTE
 }


Ensuite d'après ton programme si le relais bagotte c'est FORCEMENT pars ce que la température varie.
Ou alors tu utilises aussi la pin relais pour autre chose.

dancex47

#10
Sep 21, 2016, 02:34 pm Last Edit: Sep 21, 2016, 03:21 pm by dancex47
Et bien... pour l'affichage correct je ne sais pas, je n'ai pas encore branché l'écran.

Ce serai un autre problème une fois le clignotement réglé.
Et puis je l'ai remis pour répondre à
Dans ton programme, il n'y a pas d'affichage de la température dans le cas ou l'arrosage est actif. Il faut l'afficher dans tous les cas pour analyser ce qui se passe...
Donc je ne dois visiblement pas le mettre là ?
-> Tu parles de l'affichage sur le LCD ou le moniteur série ?

Pour le Relais, sur le code il n'y à que le pin 7 utilisé pour lui et physiquement sur la carte, si tu regardes la vidéo : IDEM uniquement le relais connecté dessus.

Petit à petit j'avance, doucement mais surement. Mais si toutefois quelqu'un peut tester le code sur une carte ? Honnêtement je vois pas pourquoi il clignote...

Afin de me rassurer, peux-tu me confirmer que lorsque l'ont ne mets pas de : delay(xxxx) il est censé resté ON ?

De la même manière si je met

digitalWrite(8, HIGH);


Elle dois rester HIGH ?

Merci.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

kamill

#11
Sep 21, 2016, 03:44 pm Last Edit: Sep 21, 2016, 04:41 pm by kamill
Je parles de l'affichage sur la moniteur série le lcd.
Oui les sorties doivent rester à l'état ou on les a commander.

Essaies avec un hysteresis de 0.5° comme ceci
Code: [Select]
float temp;

 // Lit la température ambiante à ~1Hz
 if (getTemperature(&temp)) {

   // Affiche la température
   Serial.print("Temperature : ");
   Serial.print(temp);
   Serial.write(176); // caractère °
   Serial.write('C');
   Serial.println();
 }
 // Action au-dela de 25°C enclanche relais
 const float consigne=25;
 const float hysteresis=0.5;

 lcd.setCursor(0, 1);
 lcd.print(temp); //Température mesurée réelle
 lcd.print(" C");
 
 if (temp >= consigne+hysteresis) {
   lcd.setCursor(0, 0);
   lcd.write("Arrosage actif  ");

   digitalWrite(8, LOW); //  VERTE ETEINTE
   digitalWrite(6, HIGH); //  ROUGE ALLUMEE
   digitalWrite(relay, HIGH); //  MOTEUR ALLUME
 }
 if (temp <= consigne+hysteresis) {
   lcd.setCursor(0, 0);
   lcd.write("Arrosage inactif");

   digitalWrite(relay, LOW); //  MOTEUR ETEINT
   digitalWrite(8, HIGH); // VERTE ALLUMEE
   digitalWrite(6, LOW); // ROUGE ETEINTE
 }

dancex47

Merci kamill.

J'ai donc remplacer ta partie de code et le problème reste le même.
La seule différence c'est qu'il déclenche à partir de 25,50°C au lieu de 25°C

J'ai aussi essayer de retirer le delay(800); dans la partie lecture du capteur et le relais clac a une fréquence de folie, je dirais 30 ou 40 fois à la seconde  :smiley-confuse:

Donc toujours le même problème, le relais ne reste pas HIGH.

J'ai donc remarqué, et ca confirme bien, qu'en définitive il réagi comme s'il était synchronisé à la commande de lecture du capteur  :o

Relais : LOW -> Lecture du capteur  si température >25 = Relais : HIGH....
               et ca recommence... tous ca en 30 - 40 fois à la seconde...

Alors une première idée me vient, une méthode brute j'en convient, mais je me dis qu'après tout si le résultat est celui désiré, pourquoi pas mettre un condensateur de lissage aux bornes du relais, pour compenser et enlever ce clicclac ?

Biensur j'aimerai trouver la vraie solution puisque visiblement ce n'est pas normal  :(

En te remerciant de m'aider une fois de plus.
"L'imagination est plus importante que le savoir."
                              *Albert Einstein*
Ceci est mon mot d'excuse lorsque je n'en connais pas assez !

kamill

C'est hallucinant ton histoire!
Essaie de changer la pin du relais

rjnc38

il me semble que l'hystérésis n'est pas bien utilisé
Code: [Select]
if (temp >= consigne+hysteresis) {
  ...
   digitalWrite(relay, HIGH); //  MOTEUR ALLUME
 }
 if (temp <= consigne+hysteresis) {
   ...
   digitalWrite(relay, LOW); //  MOTEUR ETEINT
   ...
 }

on a une mitraillette lorsque la mesure = consigne + hystérésis
il faudrait mettre
 if (temp <= consigne) { ...

Go Up