[arduino uno]Probléme Loop qui ne se termine pas et reprend a zéro

Bonjour,

Je viens vers vous, car je ne trouve pas de solution à mon soucis, j'ai un arduino uno (clone chinois) qui a l'air de plutôt bien fonctionner cependant, lors ce que je lance mon programme la loop effectue correctement les actions, mais à un moment s'arrête sans avoir terminé le code à exécuter et revient au début.

Je pense utile de vous préciser que j'utilise l'arduino avec une carte 8relais, un écran lcd brancher en I2c et un rtc, l'arduino est alimenté en 5v (chargeur téléphone) via les pins de la carte et le relais à lui aussi son alimentation pour la partie puissance je n'ai donc pas de parasite de ce côté là, pour ce qui est du câblage tout est blindé et le blindage relié à une masse (d'un seul coter)

Pour la partie hardware tout me semble être fonctionnel et au top, tout ça fait tourner un lave-vaisselle, j'ai deux lave vaisselle qui ont ce montage et tout deux ont le soucis de revenir au début de la loop après ''washTheDishes();" des fois cela fonctionne mais c'est rare et dans ce cas c'est à une autre étape comme à la fin du "rinçage" que la loop va reprendre a zéro.

niveau software voici mon code:

mon code ayant 26000charactere je l'ai mis sur mon Drive voici le lien: https://drive.google.com/file/d/1EmE0VSzxK46Y85g0oeZlquyzBFIS-5y2/view?usp=sharing

Si cela n'est pas correcte dite le moi je chercherai une meilleur façon de vous faire parvenir mon code merci

Je ne l'ai pas encore très bien rangé, il y a des commentaires un peu partout ^^

Merci d'avance aux personnes qui me permettront de résoudre ce soucis

Tu as 2 alim séparées : toutes les masses sont bien reliées ?

lesept:
Tu as 2 alim séparées : toutes les masses sont bien reliées ?

oui tout les masses sont bien relié, souder et par dessus de la gaine thermorétractable pour être sur que ce ne bouge pas dans le temps

Edit: après vérification les masses entre la carte relais et l'arduino ne sont pas relié.

Je vais faire un essai sans alimenter les relais, afin de voir si ce n'est pas un problème d'alimentation, puisque quand la pompe de cyclage (monophasé avec condensateur permanent) ce stop mon arduino reboot.

j'ai penser a la chute de tension que pouvait entrainer les divers élément du lave vaisselle mais j'ai remarqué en marche si je débranche la prise, je peux rebranché (2/3secondes après) et l'arduino ne s'étant pas éteint, tout reprend comme si de rien n'était.

j'essaye de vous donner un maximum d'indication pour être le plus claire possible et trouver une solution

Bonjour

Si tu utilises une platine de relais telle que ci-dessous (c'est-à-dire avec opto coupleurs) les masses de l'arduino et de la platine ne doivent SURTOUT PAS être reliées

bricoleau:
Bonjour

Si tu utilises une platine de relais telle que ci-dessous (c'est-à-dire avec opto coupleurs) les masses de l'arduino et de la platine ne doivent SURTOUT PAS être reliées

après avoir vérifié la 1er fois j'avais relié les masses mais, ça ne fonctionnait pas, je l'ai avais donc déconnecté et ça fonctionne, donc ce n'est pas un soucis de masse.

Donc ça serait un problème de code ?

J'ai regardé rapidement ton code, il est complexe. Tu peux l'optimiser un peu :

    if (pm) {
      lcd.print(F(" PM "));
    }
    else {
      lcd.print(F(" AM "));
    }

pourrait devenir
lcd.print((pm)? F(" PM "):F(" AM "));mais c'est du détail.

Tu devrais mettre les gros blocs de codes de la loop dans des fonctions, par exemple le bloc :

 while ((digitalRead(goButton))) {
   ....
     }

de sorte que ta loop ne serait qu'une suite d'appels de fonctions :

void loop() {
  fonction1();
  fonction2();
      ...
}

Ensuite, tu commentes tous ces appels de fonction et tu testes en les décommentant un par un jusqu'à ce que l'erreur se reproduise. Tu auras déjà une idée de ce qui pose problème. Une fois la fonction identifiée, même chose : tu testes petit à petit...

lesept:
Donc ça serait un problème de code ?
...

oui mon code n'est pas encore très bien optimisé

Par contre, j'ai essayé plusieurs fois en alimentant (seulement) l'arduino par usb avec un pc et tout ce déroule au top le seul petit truc qui bug c'est qu'il ne reste pas sur "vaisselle propre !!!" à la fin de ma loop.

Donc je ne sais pas si je dois éloigner la partie code pour chercher le problème au niveau de l'alimentation

Après un test dans les conditions normal (arduino et relais alimenter chacun par sont alimentation) avec un cycle de 5mn(10seconde pour la vidange et le remplissage, 1mn pour le lavage, pré rinçage et rinçage) tout fonctionne nickel.

Je me demande donc si l'arduino serait pas un peu tête en l'air a cause de la chaleur(quoi que des fois sans raison à température ambiante je lance le programme, il effectue la vidange et s'arrête, des fois il va jusqu'a prendre de leau s'arrêt et la pluspar du temps il a lave sans soucis mais apres le lavage ce stop) l'inox qui est à 5cm de l'arduino monte a 70°c je vais donc essayer d'isolé l'arduino de cette chaleur.

j'attend votre avis pour s'avoir si c'est probable

Merci

lesept:
Tu devrais mettre les gros blocs de codes de la loop dans des fonctions

C'est pas précisément ce qu'il a fait?

  delay(1000);
  fillItUp();                      //remplissage d'eau
  delay(1000);
  cycleLavage = millis();
  delay(1000);
  washTheDishes();                 //on fait la vaisselle
  delay(1000);
  drainItOut();                    //on vidange l'eau
  delay(1000);
  fillItUp();                      //remplissage d'eau
  delay(1000);
  preRinse();                      //on fait le pré rincage
  delay(1000);
  drainItOut();                    //on vidange l'eau
  delay(1000);
  fillItUp();                      //remplissage d'eau
  delay(1000);
  finalRinse();                    //on fait le rincage final
  delay(1000);
  drainItOut();                    //on vidange l'eau
  delay(1000);

Pour ma part je m'y serais pris autrement:
Pour commencer j'aurais fait un timer à la seconde par ex basé sur ton RTC.

Sur la bse de ce timer, j'aurais fait des switch(étape) case: séparés, mais partageant la variable (étape).

Un pour le programme principal et un autre pour l'affichage et eventuellement un troisième pour les messages de déboguage sur la liaison série.
En faisant attention de ne pas avoir de code bloquant.

Ca a l'avantage de clarifier le programme.

En + tu peux faire les moyennes sur les lectures brutes et normaliser la valeur après la moyenne.

RIN67630:
Pour ma part je m'y serais pris autrement:
Pour commencer j'aurais fait un timer à la seconde par ex basé sur ton RTC.

Sur la bse de ce timer, j'aurais fait des switch(étape) case: séparés, mais partageant la variable (étape).

Un pour le programme principal et un autre pour l'affichage et eventuellement un troisième pour les messages de déboguage sur la liaison série.
En faisant attention de ne pas avoir de code bloquant.

Ca a l'avantage de clarifier le programme.

En + tu peux faire les moyennes sur les lectures brutes et normaliser la valeur après la moyenne.

le timer je vois, cependant les switch je ne suis pas sûr de comprendre comment faire cela et pareil pour avoir plusieurs programmes qui tournent en même temps j'ai déjà regardé quelque tutoriel, mais je ne vois pas trop comment faire

Je ne suis pas du genre à me dire ça fonctionne je touche plus a rien, je cherche justement a amélioré mon code petit à petit, dans la limite de ce que je sais faire, j'apprends de plus en plus donc j'arriverais bien un jour à un code plus propre.

Par contre que pense tu du fait que mon arduino ne termine pas la loop et revienne au tout debut?

merci pour l'aide

parrazite:
Par contre que pense tu du fait que mon arduino ne termine pas la loop et revienne au tout debut?

Tu connais un chir qui fait des operations par telephone? :wink:

Ton code est volumineux et pas bien structuré. Si tu le laisses comme ça il faut inclure un débogage serieux sur la console.

En fait tu n'as pas besoin de plusieurs programmes tournant en même temps. Le truc est d'écrire du code non bloquant. Tu ecris ton programme comme un jeu de monopoly a plusieurs joueurs.

Tu fais au début la partie qui doit être rapide (pas grand'chose) et les exceptions de sécurité, ensuite un scheduler qui va lancer tes switch exactement chaque seconde. Dans les switch, tu n'attends jamais! *
Quand c'est pas fini, tu passes ton tour. Comme au monopoly, quand tu es en prison.
Quand une étape est finie tu changes d'étape.
Le switch du programme principal (et éventuellement une action opérateur) sont les seuls à pouvoir modifier la variable étape qui est partagée par les switch display et serial qui sont passifs et ne servent qu'à informer.

Comme tu passes -et repasses- dans tes switch chaque seconde les timers sont très simples a réaliser, tu prends une variable et tu l'incrémentes. Et hop!

  • quelques delay() de quelques millisecondes sont permis, si ca évite une étape...

Pour illustrer ce que propose RIN67630, il y a un tuto sur le forum anglais.

RIN67630:
Tu connais un chir qui fait des operations par telephone? :wink:

Euuu mamadou par télépathie il le fait Ahah

RIN67630:
Ton code est volumineux et pas bien structuré........

Je vais donc chercher à le faire de la méthode que vous me dites, je vais vraiment m'aventuré dans quelque chose que je ne maitrise pas, en espérant que je ne galère pas trop.

Cependant, je ne comprend pas trop le fait de faire un code non bloquant, ça contrôle un lave vaisselle il doit faire étape par étape et chaque étape doit être faite, par conséquent il y a des "while" qui attend une certaine température pour ouvrir la trappe de la lessive, mais ce n'est pas un choix pour le code de faire les étapes dans les étapes dans l'ordre, à moins que j'ai mal compris et que par exemple: le programme et au lavage, il check si la température de l'eau est à 50°c si ce n'est pas le cas il continue et check autres choses puis plus tard (quelques ms) contrôle de nouveau si la température et a 50°c et si c'est le cas il peut ouvrir la trappe de lessive.

Il faudrait que je visualise mieux ce que mon code doit effectuer, comment le faire et le rendre le plus fiable possible :confused:

en tout cas merci pour vos indication c'est vraiment top

parrazite:
Cependant, je ne comprend pas trop le fait de faire un code non bloquant, ça contrôle un lave vaisselle il doit faire étape par étape et chaque étape doit être faite, par conséquent il y a des "while" qui attend une certaine température pour ouvrir la trappe de la lessive, mais ce n'est pas un choix pour le code de faire les étapes dans les étapes dans l'ordre, à moins que j'ai mal compris et que par exemple: le programme et au lavage, il check si la température de l'eau est à 50°c si ce n'est pas le cas il continue et check autres choses puis plus tard (quelques ms) contrôle de nouveau si la température et a 50°c et si c'est le cas il peut ouvrir la trappe de lessive.

Pas tout a fait.
Quand tu es dans cette étape, tu mesures la temperature de l'eau et si c'est pas assez chaud, tu ne fais rien et passes ton tour. (*) Une seconde plus tard, tu te retrouves au même point et tu remesures. Quand c'est assez chaud, tu ouvres le trappe et passe à l'étape suivante en incrémentant la variable étape...

  • en fait tu finis ainsi le switch du programme principal pour passer au switch du display etc..

Une autre solution serait de faire une machine à états ; il y a des bibli bien faites sur Arduino qui rendent la tâche très simple.

lesept:
Une autre solution serait de faire une machine à états ; il y a des bibli bien faites sur Arduino qui rendent la tâche très simple.

Ce n'est pas une autre solution. C'est un autre nom pour la même solution.
La seule différence c'est l'idée de ne pas tout faire dans le même selecteur d'état, mais de séparer automatisme, affichage et debogage en trois machines à états synchronisés.
Ca simplifie bigrement le codage.

RIN67630:
Ce n'est pas une autre solution. C'est un autre nom pour la même solution.
La seule différence c'est l'idée de ne pas tout faire dans le même selecteur d'état, mais de séparer automatisme, affichage et debogage en trois machines à états synchronisés.
Ca simplifie bigrement le codage.

Vue mon faible niveau de codage j'ai un peu de mal à comprendre comment cela fonctionne et comment implanté tout ce que j'ai, Par contre, j'ai regardé les exemples donnés par lesept et surtout les exemples donnés dans la bibliothèque fsm et je pense avoir un peu mieux compris la façon de tourné mon code grâce a cet exemple:

// This example shows how two finite state machines can be used to simulate
// multitasking on an arduino. Two LED's are turned on and off at irregular
// intervals; the finite state machines take care of the transitions.

#include "Fsm.h"

#define LED1_PIN 10
#define LED2_PIN 11

void on_led1_on_enter() {
    Serial.println("on_led1_on_enter");
    digitalWrite(LED1_PIN, HIGH);
}

void on_led1_off_enter() {
    Serial.println("on_led1_off_enter");
    digitalWrite(LED1_PIN, LOW);
}

void on_led2_on_enter() {
    Serial.println("on_led2_on_enter");
    digitalWrite(LED2_PIN, HIGH);
}

void on_led2_off_enter() {
    Serial.println("on_led2_off_enter");
    digitalWrite(LED2_PIN, LOW);
}

State state_led1_on(&on_led1_on_enter, NULL, NULL);
State state_led1_off(&on_led1_off_enter, NULL, NULL);

State state_led2_on(&on_led2_on_enter, NULL, NULL);
State state_led2_off(&on_led2_off_enter, NULL, NULL);

Fsm fsm_led1(&state_led1_off);
Fsm fsm_led2(&state_led2_off);

void setup() {
    Serial.begin(9600);

    pinMode(LED1_PIN, OUTPUT);
    pinMode(LED2_PIN, OUTPUT);

    fsm_led1.add_timed_transition(&state_led1_off, &state_led1_on, 1000, NULL);
    fsm_led1.add_timed_transition(&state_led1_on, &state_led1_off, 3000, NULL);
    fsm_led2.add_timed_transition(&state_led2_off, &state_led2_on, 1000, NULL);
    fsm_led2.add_timed_transition(&state_led2_on, &state_led2_off, 2000, NULL);
}


void loop() {
    fsm_led1.run_machine();
    fsm_led2.run_machine();
    delay(200);
}

c'est comme cela que devrait fonctionner mon code si je comprends bien ?

Oui, pour bien y arriver, surtout si tu débutes, le plus simple est de faire un schéma pour définir les états et les actions liées. Par exemple :

Un automate fini est une construction mathématique abstraite, susceptible d'être dans un nombre fini d'états, mais étant un moment donné dans un seul état à la fois ; l'état dans lequel il se trouve alors est appelé l'« état courant ». Le passage d'un état à un autre est activé par un événement ou une condition ; ce passage est appelé une « transition ». Un automate particulier est défini par l'ensemble de ses états et l'ensemble de ses transitions. (Wikipedia)

Il faut bien définir sur ce schéma les transitions et les conditions associées, ainsi que les actions éventuelles à faire en entrée et en sortie de chaque état : c'est les fonctions du genre

void on_led1_on_enter() {
void on_led1_off_enter() {

Ensuite tu déclares les états

State state_led1_on(&on_led1_on_enter, NULL, NULL);
State state_led1_off(&on_led1_off_enter, NULL, NULL);

et les machines :

Fsm fsm_led1(&state_led1_off);
Fsm fsm_led2(&state_led2_off);

Dans le setup, tu définis les transitions "timées"

fsm_led1.add_timed_transition(&state_led1_off, &state_led1_on, 1000, NULL);
fsm_led1.add_timed_transition(&state_led1_on, &state_led1_off, 3000, NULL);

et la loop ne fait que lancer les machines : le déroulement se fait tout seul.
fsm_led1.run_machine();C'est magique...

Le seul truc à travailler un peu dans ton cas : si tu as des transitions qui dépendent d'un capteur (température par exemple), il faut voir comment les mettre en oeuvre (moi je n'ai fait que des transitions timées pour l'instant). Ça doit se faire avec des interruptions...

lesept:
Oui, pour bien y arriver, surtout si tu débutes, le plus simple est de faire un schéma pour définir les états et les actions liées(...)

D'accord, c'est beaucoup plus claire et je pense que mon code sera beaucoup moins volumineux, plus compréhensible et plus facile a debugé du coup :slight_smile:

par contre j'utilise toujours la loop pour afficher date et heure, les différents boutons ?

Mais je pense avoir bien compris le principe, un grand merci pour votre aide