Plusieurs actions en meme temps

Bonjour, j'essaie temps bien que mal de faire un système de brassage d'eau en cas de température trop basse.
J'utilise un NANO, avec une sonde de température. Le relevé de la température est ok, et le relais se déclenche en dessous de 2°C.
C'est ce que je veux.
J'ai ensuite mis un encodeur rotatif, pour régler la température à laquelle la pompe doit démarrer.
Le code fonctionne, je peux gérer cette température en tournant l'encodeur.

Le problème, c'est qu'avec mon code, la tant que la boucle de température est en cours, l'encodeur fonction très mal. Si je ne test que l'encodeur, aucun souci. Que la température, aucun souci. Le problème est quand il y a les deux. J'ai pu lire que les boucles ne pouvaient s'exécuter que les unes après les autres.

Y a t'il un moyen de contourner le problème s'il vous plait ?

Voici mon montage et mon code: (sans le relais sur le montage):

#include "OneWire.h"
#include "DallasTemperature.h"
#include "Wire.h"
#include "LCD_I2C.h"
#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);                    
#define WATER_TEMP_PIN A0 
OneWire oneWire(WATER_TEMP_PIN); 
DallasTemperature sensors(&oneWire);
#define inputCLK 4
#define inputDT 5
 
float counter = 26; 
int currentStateCLK;
int previousStateCLK; 
String encdir ="";

void setup() 
{
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  lcd.begin (20,4);
  lcd.setBacklightPin(3,POSITIVE);
  pinMode (inputCLK,INPUT);
  pinMode (inputDT,INPUT);
  previousStateCLK = digitalRead(inputCLK);
}

void loop() 
{
    temperature();
    encoder();
}

void temperature()
{
  sensors.requestTemperatures();
    double dTempWater = sensors.getTempCByIndex(0);
    
    lcd.setCursor(0,0);
    lcd.setBacklight(HIGH);
    lcd.print("Temp. ext: ");
    lcd.print(dTempWater);
    lcd.print(" C");
    lcd.setCursor(0,1);
    
    if(dTempWater < counter)
    {
      digitalWrite(2, LOW);
      lcd.setCursor(4,2);
      lcd.print("Pompe: ON ");
    }
    else
    {
      digitalWrite(2, HIGH);
      lcd.setCursor(4,2);
      lcd.print("Pompe: OFF");
    }
}

void encoder()
{
  currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK){ 
       if (digitalRead(inputDT) != currentStateCLK) { 
       counter = counter-float(0.25);
       encdir ="CCW";
     } else {
       counter = counter+float(0.25);
       encdir ="CW";
     }
     
     Serial.print("Direction: ");
     Serial.print(encdir);
     Serial.print(" -- Value: ");
     Serial.println(counter);
     lcd.setCursor(0,1);
     lcd.print("Temp. decl: ");
     lcd.print(counter);
     lcd.print("C");
   } 
   previousStateCLK = currentStateCLK; 
}

Bonjour,
Il y a des librairies de gestion d'encodeurs qui fonctionnent sous interruption
Par exemple:
http://www.pjrc.com/teensy/td_libs_Encoder.html

votre code est trop synchrone, la fonction temperature() prend trop longtemps et vous ratez des ticks de l'encodeur.

prenez la bibliothèque encoder et connectez votre encodeur sur des pins d'interruption (2 et 3 pour la Nano - on dirait que c'est ce que vous avez). La valeur de l'encodeur sera maintenue par interruptions


EDIT: @fdufnews les grands esprits se rencontrent :slight_smile:

Merci pour cette info, je vais bien me pencher dessus, mais ca a l'air d'être exactement ce qu'il me faut.

Merci également, et oui, c'est éxactement le probleme. Donc votre solution a tous les deux m'a l'air la bonne. Je reviens demain vous dire ce qu'il en est. Encore merci

Ha si, j'ai quand meme un probleme en fait avec l'encodeur. Lorsqu'il fonctionne tout seul, si je veux incrémenter la temperature de +1 ou de -1, sur le moniteur, au lieu de faire +1, il fait +1+1 ou -1-1. L'action se déroule deux fois

c'est parce que votre encodeur envoie 2 ticks pour un cran, divisez la valeur lue par 2 (certains ont même 4 ticks par cran)

essayez ce code

#include <Encoder.h>  // https://www.pjrc.com/teensy/td_libs_Encoder.html
const byte encoderCLKPin = 2;    // encoder CLK
const byte encoderDTPin  = 3;    // encoder DT
Encoder encoder(encoderDTPin, encoderCLKPin);

long currentPosition = 0;

bool encoderChanged() {
  long newPosition = encoder.read() >> 1;   // 2 ticks par click => on divise par 2
  if (newPosition != currentPosition) {
    currentPosition = newPosition;
    return true;
  }
  return false;
}

void setup() {
  Serial.begin(115200); Serial.println();
  Serial.println(F("Prêt"));
}

void loop() {
  if (encoderChanged()) {
    Serial.println(currentPosition);
  }
}

en ouvrant le moniteur série à 115200 bauds

Merci encore. Je m'occupe de tout ça des demain matin. Hate d'éssayer.

"Petite parenthèse"
Je n'ai pas encore testé, mais je me pose une question, en lien avec ce projet. Enfin, c'est pour un autre projet, mais ça sera exactement la même chose. Je compte adapter ce système a mon fermenteur pour produire ma bière. Est ce qu'il est possible selon vous de fabriquer un densimètre avec une toute petite carte arduino pour mesurer le taux de sucre dans mon mout ? C'est surement un sujet que j'ouvrirais dans plusieurs semaines. Mais c'est déjà pour avoir une idée.

Fritzing :
Merci de générer le schéma electrique a partir du schéma de câblage.

Sur le schéma de câblage les numéros des entrées sorties ne figurent pas.
La référence de la carte ne figure pas.
Ces informations sont essentielles.
Les personnes qui t-on repondu ont du retrouver ces informations.

Ho oui désolé, un sérieux manque de pratique, mais je promets de faire mieux la prochaine fois.

Donc, c'est parfait, après des essais, tout fonctionne comme je le veux a quelques exceptions près.
L'incrémentation ce fait de 1 en 1, est-il possible de faire de 0.5 en 0.5?
Aussi, lorsque le relais ce déclenche, une baisse d'intensité de l'éclairage de l'écran se voit nettement. Avez-vous une idée du pourquoi ?
Merci d'avance.

vous pouvez conserver le compteur de 1 en 1 dans le code est faire une variable dérivée qui progresse que de la moitié de cette valeur. il faudra la déclarer comme type float ou double

je ne sais pas quel relai vous avez mais la bobine tire facilement entre 70 et 100mA lorsque vous déclenchez. Tout dépend donc de ce que le reste de la carte fourni

idéalement vous ne passez pas par l'arduino pour tout ce qui est alimentation des composants ayant besoin d'un courant significatif, vous les alimentez en direct.

Ok je vois parfaitement, je ne passerais donc pas par la carte pour alimenter le relais, l'encodeur et la sonde. J'alimenterais directement en 5V.

l'encodeur ne consomme quasiment rien, donc c'est OK pour celui là
pensez à joindre les GND de toutes les alimentations (en étoile c'est mieux)

c'est à dire en étoile ?

vous partez du GND de l'arduino et vous allez au GND de chaque module avec un fil différent, vous ne les chaînez pas les un derrière les autres

comme ça

pas comme ça

Ok super, c'est bien ce qu'il me semblait mais je voulais en etre sur. Merci pour toutes ces précieuses informations.

Cependant je ne comprends pas pour l'incrémentation de 0.5 en 0.5.

Voila mon code:

#include "OneWire.h"
#include "DallasTemperature.h"
#include "Wire.h"
#include "LCD_I2C.h"
#include "LiquidCrystal_I2C.h"
#include "Encoder.h"
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);                    
#define WATER_TEMP_PIN A0 
OneWire oneWire(WATER_TEMP_PIN); 
DallasTemperature sensors(&oneWire);
const byte encoderCLKPin = 2;    // encoder CLK
const byte encoderDTPin  = 3;    // encoder DT
Encoder encoder(encoderDTPin, encoderCLKPin);
 
float currentPosition = 0;

bool encoderChanged() {
  long newPosition = encoder.read() >> 2;   // 2 ticks par click => on divise par 2
  if (newPosition != currentPosition) {
    currentPosition = newPosition;
    return true;
  }
  return false;
}

void setup() 
{
  Serial.begin(115200); Serial.println();
  Serial.println(F("Prêt"));
  pinMode(4, OUTPUT);
  lcd.begin (20,4);
  lcd.setBacklightPin(3,POSITIVE);
  
}

void loop() 
{
    temperature();
    encoderbutton();
}

void temperature()
{
  sensors.requestTemperatures();
    double dTempWater = sensors.getTempCByIndex(0);
    
    lcd.setCursor(0,0);
    lcd.setBacklight(HIGH);
    lcd.print("Temp. ext: ");
    lcd.print(dTempWater);
    lcd.print(" C");
    lcd.setCursor(0,1);
     lcd.print("Temp. decl: ");
     lcd.print(currentPosition);
     lcd.print(" C");
    
    
    if(dTempWater < currentPosition)
    {
      digitalWrite(4, LOW);
      lcd.setCursor(0,2);
      lcd.print("Pompe: ON ");
    }
    else
    {
      digitalWrite(4, HIGH);
      lcd.setCursor(0,2);
      lcd.print("Pompe: OFF");
    }
}

void encoderbutton()
{
 if (encoderChanged()) {
    Serial.println(currentPosition);
    lcd.setCursor(0,1);
     lcd.print("Temp. decl: ");
     lcd.print(currentPosition);
     lcd.print(" C");
  }
}```

précisez ce que vous voulez faire pour 0.5 en 0.5 ?

(il suffit de diviser par deux la valeur de l'encodeur)

Bonjour J-M-L

Electriquement, c'est identique?
Dans le cas d'un bus comme i2C, c'est ainsi que ça se câble?

Cordialement
jpbbricole