Comment fait-on pour faire deux actions en même temps ?

Bonjour !

Je souhaiterai savoir comment peut-on faire pour effectuer deux actions simultanées sur un arduino.

En gros, j'aimerai pouvoir contrôler l'affichage de la première ligne d'un écran LCD (16 colonnes 2 lignes connecté en I2C) avec deux boutons poussoir. Et je souhaiterai que la deuxième ligne affiche une variable qui s'actualise continuellement sans affecter le reste de l'écran.

Le code que j'ai mis ci dessous me permet de faire chauffer une résistance contrôlée par un relais 12v (activé avec un bouton) et en même temps afficher la température (avec une sonde) sur un écran LCD.
L'écran sert également de menu (pour faire varier le délai entre l'activation du relais et sa désactivation).

Donc, dans le cas présent, je souhaiterai (au moment où on active le relais) faire afficher le message "Heating..." sur la première ligne de l'écran ET en même temps, sur la deuxième ligne, la température en temps réel.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_MAX31855.h>

int thermoDO = 7;
int thermoCS = 6;
int thermoCLK = 5;

Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);
  
LiquidCrystal_I2C lcd(0x27,16,2);

int pinButton = 2;
int pinTempButton = 4;
int relayPin = 3;
int t = 1000;

   double c = thermocouple.readCelsius();

void tempDisp (){
  
  lcd.setCursor(0,1);
  lcd.print("Temp:");
  lcd.setCursor(6,1);
  lcd.print(c);
  lcd.setCursor(12,1);
  lcd.print("C");
}


void setup() {
  
  Serial.begin(9600);
  Serial.println("MAX31855 test");

  pinMode(pinButton, INPUT);
  pinMode(relayPin, OUTPUT);
  pinMode(pinTempButton, INPUT);

  lcd.init();
  lcd.backlight();
  lcd.home();

  lcd.setCursor(0,0);
  lcd.print("Press to heat up");
  lcd.setCursor(0,1);
  lcd.print("Delay:");
  lcd.setCursor(7,1);
  lcd.print(t);
  lcd.setCursor(13,1);
  lcd.print("ms");
}

void loop() {

   Serial.print("Internal Temp = ");
   Serial.println(thermocouple.readInternal());

   double c = thermocouple.readCelsius();
   if (isnan(c)) {
     Serial.println("ERROR");
   } else {
     Serial.print("C = ");
     Serial.println(c);
   }
   
   delay(1000);
  
  boolean buttonState = digitalRead(pinButton);
  boolean TempButtonState = digitalRead(pinTempButton);

  if (TempButtonState==HIGH){

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Delay:");
    lcd.setCursor(7,0);
    lcd.print(t);
    lcd.setCursor(13,0);
    lcd.print("ms");

    lcd.setCursor(0,1);
    lcd.print("Press to change");

    if (TempButtonState==HIGH);{

      t = t+1000;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Delay:");
      lcd.setCursor(7,0);
      lcd.print(t);
      lcd.setCursor(13,0);
      lcd.print("ms");
      tempDisp();

      if (t >= 10000){

        t = 0;
      }
    }
  }

  if (buttonState==HIGH)
  {
  lcd.clear();
  tempDisp();
  lcd.setCursor(3,0);
  lcd.print("Heating...");
  digitalWrite(relayPin, HIGH);
  delay(t);
  digitalWrite(relayPin, LOW);
  lcd.clear();
  lcd.setCursor(1,0);
  lcd.print("Heating done !");
  tempDisp();
  }

}

Je ne sais pas si j'ai été très clair mais je vous remercie d'avance pour votre aide :wink: !

Je vais te répondre sans éplucher ton code, pour te laisser le soin de le modifier toi-même. La manière de faire tourner plusieurs tâches en parallèle a déjà été expliquée et illustrée de nombreuses fois sur le forum : tu peux chercher avec la loupe en haut à droite de la page web.

Imagine que tu es dans une cuisine et tu fais cuire un oeuf dur et un oeuf à la coque : 3 minutes pour l'un et 10 minutes pour l'autre. En même temps, tu regardes la télé : ça fait 3 tâches en parallèle.

Au début tu regardes ta montre : midi. Tu sais qu'à midi 3, tu devras couper le feu sous un oeuf et à midi 10 couper le feu sous l'autre. En attendant tu peux regarder la télé, mais il faut quand même surveiller la montre régulièrement pour ne pas faire chauffer trop longtemps.

Ici, c'est le même principe : tu crées un chrono par tâche et tu gères les actions en fonction de la valeur du chrono. Si tu as une action périodique, mettons toutes les secondes (1000 millisecondes), lorsque le chrono de cette action dépasse 1000, tu remets le chrono à 0 et tu exécutes ton action.

Ça se fait ainsi :
Déclarer la variable qui suit le temps et celle qui contient la période

unsigned long chrono1 = 0;
unsigned long duree1 = 1000ul;

Initialiser le chrono, dans le setup a priori :

chrono1 = millis();

millis() est la fonction qui te donne le temps écoulé en millisecondes depuis le lancement de ton programme
Puis dans la loop, surveiller le chrono :

if (millis()-chrono1 > duree1) {
  chrono1 = millis();
  action1();
}

Si tu as une autre action périodique, tu crées un chrono2, une duree2, et une fonction action2().

Certains mettent la surveillance du chrono dans l'action. Dans ce cas, la loop appelle l'action

action1();

et la fonction est conçue ainsi (par exemple) :

void action1() {
if (millis()-chrono1<duree1) return;
chrono1 = millis();
...
autres instructions
}

A toi de jouer... :slight_smile:

1 Like

Salut,
J'ai regardé ton code et j'ai vu qu'il y a pas mal de problèmes.
Concentre toi sur la dernière partie de ton code ( if (buttonState==HIGH).... )en essayant de comprendre ce que lesept essaye de te expliquer et appliquer cette technique à ton code.
Oublie

delay(t);

car c'est le cœur de ton problème.
Quand tu appuis sur buttonState tu dois lancer une action que se terminera quand ton temps t sera écoulé.
Cette action affichera ta température sur ton LCD et pourquoi pas le temps restant.
A la fin de cette action tu mettra ton PinRealy sur LOW et afficher ton message de fin.