Arduino Nano emballement programme

Bonjour,

Je suis débutant en programmation et j'ai réalisé un programme pour faire un thermostat comportant 2 conditions : la température du local et la différence avec l'extérieur. Des ventilateurs se déclencheront lorsque la température intérieure dépassera un certain seuil (25°C) et que la température extérieure sera inférieure à celle du local (3°C).

Pour l'utilisation finale le délais entre 2 prises de température sera de 5 minutes.

J'ai ajouté une fonction test actionnée avec un bouton qui tourne sur un cycle d'une seconde afin de contrôler le bon fonctionnement lors de la mise en place.

Le programme fonctionne parfaitement sur un ESP32 mais sur un Nano il s'emballe au bout d'environ 45s. Je l'ai testé sur 2 cartes différentes et j'ai le même problème.

Quelqu'un a-t-il une idée ?

Merci

Voici le code :

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

#define ONE_WIRE_BUS_1 2
#define ONE_WIRE_BUS_2 5

OneWire oneWire_in(ONE_WIRE_BUS_1);
OneWire oneWire_out(ONE_WIRE_BUS_2);

DallasTemperature interieur(&oneWire_in);
DallasTemperature exterieur(&oneWire_out);

const int temp_lim = 25;  // Température maximum intérieur
const int ecart = 3;      // Ecart mini pour déclenchement

// const int delais_minutes = 1 ; // Délais entre chaque mesure en minutes
// const int delais = delais_minutes * 60 * 1000 ; // Conversion en ms

const int delais = 15000;
const int delais_test = 1000;

const int led = 13;
const int relais = 11;
const int test = A5;

int T0 = 0;


void setup(void) {

  Serial.begin(9600);
  delay(1500);

  Serial.println("----------------------------");
  Serial.println("Démarrage");
  Serial.println("----------------------------");

  interieur.begin();
  exterieur.begin();

  pinMode(relais, OUTPUT);

  // pinMode(14, OUTPUT); // ESP32
  // pinMode(15, OUTPUT); // ESP32
  pinMode(led, OUTPUT);  // NANO

  pinMode(test, INPUT_PULLUP);

  comp_temp();
}


void loop(void) {

  unsigned long T1 = millis();
  test_val = analogRead(test);

  if (test_val > 800 && T1 - T0 >= delais) {  // Fonctionnement normal

    Serial.println("Mode normal");

    comp_temp();

    T0 = T1;
  }

  if (test_val < 500) {  // Mode test

    while (test_val < 200) {

      Serial.println("Mode test");

      comp_temp();

      test_val = analogRead(test);

      delay(delais_test);  // délais test
    }

    T0 = millis() + delais + 100;
  }
}

void comp_temp() {

  interieur.requestTemperatures();
  exterieur.requestTemperatures();

  float T_int = interieur.getTempCByIndex(0);
  float T_ext = exterieur.getTempCByIndex(0);
  float ecart_calc = T_int - T_ext;


  Serial.print("Intérieur: ");
  Serial.print(T_int);
  Serial.print(" \xC2\xB0");
  Serial.println("C");

  Serial.print("Extérieur: ");
  Serial.print(T_ext);
  Serial.print(" \xC2\xB0");
  Serial.println("C");

  Serial.print("Ecart: ");
  Serial.print(ecart_calc);
  Serial.print(" \xC2\xB0");
  Serial.println("C");
  Serial.println("----------------------------");


  if (T_int > temp_lim && ecart_calc > ecart) {

    // digitalWrite(15, LOW ); // ESP32
    // digitalWrite(14, HIGH); // ESP32
    digitalWrite(led, HIGH);  // NANO

    digitalWrite(relais, LOW);

  }

  else {
    // digitalWrite(15, HIGH); // ESP32
    // digitalWrite(14, LOW); // ESP32
    digitalWrite(led, LOW);  // NANO

    digitalWrite(relais, HIGH);
  }
}

Ça veut dire quoi "il s' emballe" ?
Tu as peut-être un problème d' hystérésis. Lorsqu'un veut programmer une température de consigne, la température se met à osciller autour de cette valeur. C'est l' hystérésis.

Oui :wink:

Tu as int T0 = 0; or T0 traite des millis() qui doivent être des unsigned long.
Changes:
int T0 = 0;
en
unsigned long T0 = 0;

Avant de corriger, tu peux voir le problème en ajoutant un print ici:

		comp_temp();

		T0 = T1;
		Serial.println(T0);
	}

Tu verra l'évolution de T0

Cordialement
jpbbricole

Merci pour vos réponses rapides, ça fonctionne !

Je me permets de poser une seconde question, mon problème est peut-être du même ordre.

Lorsque je définis un délais au delà d'environ 50 000 ms ça ne fonctionne pas (ni directement ni avec le petit calcul delais_minutes), il faut que le rentre directement dans le programme.

Faut-il attribuer un autre type de variable également ?

Oui, du moment que tu traites des millis(), c'est des unsigned long.

delay(50000), c'est possible car 50000 est un entier court (16 bits) qui est transformé en long
delay(70000) ne fonctionne pas car 70000 est considéré comme un entier 16 bit qui est équivalent à environ 5000. Si on veut dépasser les 65535, il faut indiquer qu'il s'agir d'un entier long en rajoutant L ou l derrière:
delay(70000L) fonctionnera.

Par défaut quand on donne une valeur sans rien précisé, c'est un entier 16 bis.

Merci @jpbbricole pour les infos.

@vileroi, merci pour vos explications. Je viens de regarder un petit tableau récapitulatif sur les variables, c'est plus clair.

J'ai ajouté hier soir une condition à mon programme pour éviter un bug lors de la remise à 0 du compteur de l'Arduino au bout de 50 jours, je pensais me retrouver avec un résultat négatif à la soustraction des millis.

Mais si je comprends bien ce n'est pas nécessaire avec une variable de type unsigned long. Il va seulement y avoir un relevé de températures dans un intervalle plus court que celui défini, c'est bien ça ?

Un unsigned (long ou pas) ne donnera jamais un résultat négatif

Même pas Quand on fait T1 - T0 on calcule un intervalle et le passage à 0 n'a pas d'importance.

Si le dernier événement était à T0=12345ms 100ms plus tard on est à T1=12445ms. La différence fait bien 100ms.

L'unsigned long le plus grand est 4294967295. Si le dernier événement est à 4294967205, 100ms après, on est passé à 10ms (il y a eu le passage par zéro) et T1-T0 fait 10-4294967205 ce qui devrait faire -4294967195 et comme on calcule avec des entiers positifs on aura 100. Cela fonctionne toujours.

C'est pour cela que dans une de mes bibliothèques, comme les intervalles que je mesure sont inférieurs à 1000ms, je peux me permettre d'avoir tous les temps dans des variables 16 bits ce qui se calcule plus vite et prend moins d'octets.