mémoriser un état dans une variable et non relire une sortie

Bonjour,
Comment donc s'affranchir de l'état d'une sortie pour utiliser une mémoire d'état afin de la reprendre pour l'usage d'une condition. La réponse est une variable de toute évidence , mais encore faut-il savoir correctement écrire le code.
Dans le premier code partiel suivant, aucun problème, la condition avec digitalWrite fonctionne.
A cours de sortie dans mon projet assez élaboré, je souhaite en récupérer une ou deux en simplifiant mon code où vous l'aurez compris, j'utilise 2 sorties juste pour une simple relecture mémoire.
il vaudrait mieux que ma fonction mémoire message en attente lecture " Memo " soit intégrée dans une variable uniquement. Et la reprendre ensuite dans ma condition.
Mes tentatives de déclaration restent infructueuses et ma condition du second code donne un résultat comme si Memo reste constamment à 1.

premier code

int DTMF = A2            // présence code DTMF

int Top = 4;            //  Commande départ enregistrement

int Memo = 8;            // sortie confirmation présence message en attente lecture restant activée a l'état 1 en fin de séquence enregistrement 
             

void setup ();
{

pinMode(DTMF,INPUT);
pinMode(Top,INPUT);
pinMode(Memo,OUTPUT);
}
void loop()
{
if((digitalRead (Top)==1)&&(digitalRead(DTMF) ==0)&&(digitalRead(Memo)==0)) {

  digitalWrite(10,LOW);                  // pin 10 reliée à la pin Reset de la carte Nano pour un reset total  
}
                                         // la condition étant,si absence message et code DTMF au départ enregistrement, Reset complet.

Second code

int DTMF = A2            // présence code DTMF

int Top = 4;            //  Commande départ enregistrement

int Memo = false;             /*déclaration variable confirmation présence message en attente lecture en remplacement de la relecture d'un état de sortie.                        
                               ici à l'état 0 au départ , ensuite passant à 1 dans le code complet initial en temps voulu */

void setup ();
{
pinMode(DTMF,INPUT);
pinMode(Top,INPUT);

}
void loop()
{
if(((Top)==1)&&(DTMF ==0)&&(Memo)==0)) {                   // code où la variable Memo pose problème 

  digitalWrite(10,LOW);                  // pin 10 reliée à la pin Reset de la carte Nano pour un reset total  
}
                                         // la condition étant,si absence message et code DTMF au départ enregistrement, Reset complet.

Je ne comprends pas toute ton histoire,
mais si tu dois en permanence tester une entrée, il ne sert à rien de la mettre dans une variable, il faut appeler digitalRead() à chaque fois que tu veux mesurer la valeur de cette entrée.

Bonjour,

Comme biggil je ne comprend pas trop ce que tu veux faire.
En tout cas le deuxième programme est complètement faux (non seulement pour Memo)

if(((Top)==1)&&(DTMF ==0)&&(Memo)==0)) {

Comme Top vaut 4 Top==1 est toujours faux, idem pour les variables suivantes.

Pour éviter (tout au moins minimiser) cela il faut être plus rigoureux dans le nommage de tes variables (qui sont en fait des constantes)
Par exemple:

// définition des pins
const byte pinDTMF = A2            // présence code DTMF
const byte pinTop = 4;            //  Commande départ enregistrement
const byte pinMemo = 8;            // sortie confirmation présence message en attente lecture restant activée a l'état 1 en fin de séquence enregistrement

Heureux de vous retrouver Biggil et Kamill , et merci pour vos bons conseils.

Pour être plus concret, le meilleur exemple où ça me pose problème est le résultat d'un compteur d'impulsions.
Mon compteur fonctionne et dès la 5eme impulsion, bascule une sortie à l'état haut pour la relire ensuite par digitalread lorsque j'ai besoin de connaître son état dans mes conditions de reset.
Donc , j'utilise cette sortie uniquement en mémoire, sans connection externe aucune.
Du style:

if(BoutonB_plus.vientDEtreEnfonce())
{compteur++;
if(compteur>=5) { digitalWrite(MEMO,HIGH);  

 // je mémorise le résultat compteur en cours de programme en modifiant l'état d'une sortie.
 //ayant besoin ou pas de cette information plus tard dans une condition multiple, j'utilise digitalRead.

 // afin de libérer une pin n'ayant pour fonction Que mémoriser un état,
 // créer une variable Memo qui mémorise un état,et écrire dans la condition,quelquechose du type: 

  if ((RST == HIGH) &&(AN== HIGH) && (Memo==HIGH)) { .........// action

             // où Memo est une variable non affectée à une Pin de sortie const byte pinMemo = 8;  par exemple

Ce que je souhaite est d'éviter une présence physique sur une pin de l'état Memo. Juste conserver une mémoire en interne, libérant ainsi une pin de sortie pour un autre usage.

Si un programme tourne et que l'on fait un reset, c'est le MEME programme qui redémarre. Si il y a besoin de faire un reset, c'est sans doute le programme qui est mal ficelé. Il vaut donc mieux reprendre la structure du programme, et le problème de la mémorisation se résout avec une variable.

Mais j'avoue aussi que je ne vois pas de cas où faire un reset aurait un intérêt. Sauf avec un programme qui se plante, mais ce ne doit pas être un but.

J'ai toujours trouvé drôle de faire un reset avec une broche physique alors que l'on peut le faire logiciellement.

vangel:
Mon compteur ... bascule une sortie à l'état haut pour la relire ensuite

Alors après un intense décorticage de tes messages, je finis par imaginer que tu veux te servir d'un I/O digitale comme d'une EEPROM : pour que sa valeur résiste au RESET ?

Pour reprendre ce qu'évoque Vileroi, c'est une solution que j'ai choisi pour stopper mon programme, du moins la succession de boucles, puisque la première dépend d'un appui bouton, sans lequel tout s'arrête bel et bien.
A chaque tentative d'introduire un Break, l'ide me refusait la compilation.
Quant à faire le reset par le logiciel, je suis preneur.
Comme vu je ne sais plus où, void(*softreset)(void)=0; , est ce à quoi tu fais allusion ?

Bigill, reset précédemment cité, est un exemple parmi d'autres. Et pour l'instant je ne cherche pas encore à conserver de mémoire au delà d'un reset,. Mon code actuel comprend plusieurs conditions différentes, dont celles où je veuille conserver un état en mémoire réutilisable entre elles, elles ne passent pas par un reset, mais une succession d'instructions mettant fin à ma séquence, sauf conservation de cet état mémoire par maintien d'une sortie à 1 ou 0 suivant le besoin. Lorsque je sollicite le reset, c'est donc que je n'ai pas besoin de connaître cet état mémoire ultérieurement.

j'ai donc des conditions sans reset, et d'autres avec Reset.
Le tout fonctionne actuellement avec des digitalread de sorties ou entrées, dont 2 sorties crées pour mémorisé un état.
En fait, vraisemblablement devrais-je user d'une variable mémoire. laquelle m'est essentielle dans mes conditions, exceptée l'unique où j'ai opté pour un reset.
Comme Vileroi l'a constaté, et en bon débutant, je bloque inutilement des sorties à des fins qui peuvent se faire de manière différente. c'est ce que je cherche à résoudre. Substituer des variables à mes trois sorties, dont l'une est la commande du reset , l'autre la mémoire de la présence ou non d'un message en attente lecture, la dernière étant le résultat d'un compteur..

Pour reprendre ce qu'évoque Vileroi, c'est une solution que j'ai choisi pour stopper mon programme, du moins la succession de boucles, puisque la première dépend d'un appui bouton, sans lequel tout s'arrête bel et bien.
A chaque tentative d'introduire un Break, l'ide me refusait la compilation.

Je reste persuadé qu'une écriture propre permet de ne pas avoir besoin de reset pour fonctionner. Break pour moi est vraiment une exception. J'ai du l'utiliser une fois par paresse, mais cela ne bonne pas un code bien structuré.
Il faudrait voir cela sur une exemple simple genre organigramme.

Comme vu je ne sais plus où, void(*softreset)(void)=0; , est ce à quoi tu fais allusion ?

Non, c'est à la discussion
https://forum.arduino.cc/?topic=686679
Il faut par contre connaitre la carte avec laquelle le faire, vu que cela dépend du système.

Maintenant pour conserver une variable entre deux cessions, il est possible d'utiliser l'EEprom. Elle est faite pour ça. Je l'utilise pour mon éclairage de la cuisine: si je viens d'allumer la lumière, et si avant c'était du blanc fixe, je passe en couleurs et inversement.

Peut-être une piste concernant mon problème.
Suite à la lecture d'articles sur les variables pêchés sur le net, une variable utilisée dans une fonction void ne pourrai qu'être lue et non ré_écrite, donc modifiée, comme dans le void ou le loop. c'est mon cas puisque que j'use de la fonction void séquence déclarée avant le setup et le loop.
D'où le bon fonctionnement avec digitalread, puisque relecture des pin sorties affectées. Et dysfonctionnement avec
celui de variables . d'ailleurs, lorsque j'écris le code et que l'IDE le reconnais, il me le rappelle bien "read only".
En réponse à Bigill , la mémoire eeprom ne semble pas résoudre ma problématique ici, ne faisant appel à relire l’état mémoire que tant que la session est active.
Me reste peut-être donc à choisir,soit modifier mon code pour gérer dans le loop les modifications de variables et conditions, non dans une séquence gérée par le loop, soit conserver mes digitalread actuels.
A moins d'une autre idée avec la façon de traiter mes variables.

Suite à la lecture d'articles sur les variables pêchés sur le net, une variable utilisée dans une fonction void ne pourrai qu'être lue et non ré_écrite, donc modifiée, comme dans le void ou le loop. c'est mon cas puisque que j'use de la fonction void séquence déclarée avant le setup et le loop.

c'est du grand n'importe quoi. soit vous n'avez pas compris l'article, soit l'article est nul...

Les variables n'ont pas besoin de correspondre à des pins...

si vous voulez une variable qui resiste au reboot = il faut la lire dans le setup depuis l'EEPROM et l'écrire en EEPROM au moment où l'arduino s'éteint (en supposant que le code n'est pas écrit avec les pieds et qu'il ne plante pas sauvagement)

si vous voulez juste des variables qui sont disponibles entre différentes fonctions, utilisez des variables globales

sinon les variables locales aux fonctions, non statiques, ont une portée (visible uniquement dans la fonction) et durée de vie limitée à la celle de la fonction.

Enfin, une fonction peut mettre à jour une variable connue que dans une autre fonction si on lui donne un pointeur ou une référence sur cette fonction.

En fait ce qui serait bien c'est d'avoir un code le plus petit possible ayant le problème évoqué. Si le code est trop long, je ne le lirai pas et sans doute d'autres non plus. Mais si il est très court, c'est possible de voir. Poster le code complet est risqué.

Vileroi, tout à fait d'accord, j'ai tendance à ne pas simplifier les choses à force de détails diffus.
Et parallèlement à ta réponse, ai pensé dès ce matin, reprendre à zéro ma problématique.
Donc ,voici un code simple où j'ai remplacé fictivement une sortie par une variable globale.

Lorsque ma condition contient varMemo == LOW , elle ne s'exécute pas
Lorsque ma condition contient varMemo == HIGH , elle s'exécute.

Pourtant, au départ varMemo est bien déclaré LOW

 const int sw1 = 2;
 const int sw2 =3;

 int varMemo = LOW;           // variable mémoire fictive en lieu et place de relecture d'une sortie 

void setup() {
  
  pinMode(sw1,INPUT_PULLUP);
  pinMode(sw2,INPUT_PULLUP);
  pinMode(6,OUTPUT); 
}
void loop() {

if(( digitalRead(sw1)== LOW)&&(digitalRead(sw2)==LOW)&&(digitalRead (varMemo) == LOW ))
{digitalWrite(6,HIGH);
}
}

C'est la 3ème fois que je relis ces échanges et je n'ai toujours pas compris le besoin.
Il me semble que tu confonds allègrement les entrées/sorties physiques et les variables.
Je ne comprends pas pourquoi tu t'acharnes à vouloir utiliser des I/O au lieu de variables?

Si tu expliquais clairement le besoin, et non la solution boiteuse que tu as trouvée, je pense que l'on arriverait plus vite au but.

Donc ,voici un code simple où j'ai remplacé fictivement une sortie par une variable globale.

Il faut aussi dire ce que tu attends du code et ce que tu obtiens. Pour moi le code se compile et fait ce qu'il y est écrit. Mais ce n'est pas forcément ce que tu voulais.
Si les inters sont passants, ne serait-ce qu'un court instant, la sortie 6 est à 1 et y restera. Si un des inter est ouvert, la sortie 6 est à 0 et restera à 0 jusqu'à ce que les deux inters soient fermés. C'est ce que je lis. Est-ce le fonctionnement souhaité?

Lorsque ma condition contient varMemo == LOW , elle ne s'exécute pas
Lorsque ma condition contient varMemo == HIGH , elle s'exécute.

Comme cela vous a été dit plusieurs fois déjà, les pins ne servent pas de case mémoire

Vous n'êtes pas sous excel non plus, l'affectation d'une variable est ponctuel. si vous dites:
int x = formuleDeCalcul();
alors x prend cette valeur et la conserve, même si plus tard ce qui sert dans formuleDeCalcul() a évolué.

Donc définissez une variable de type boolean (bool) qui va mémoriser la condition que vous souhaitez retenir.

bool appuiBouton = false;
const byte pinBouton = 2;

void setup() {
  pinMode(pinBouton, INPUT_PULLUP);
}

void loop() {
  appuiBouton = (digitalRead(pinBouton) == LOW); // appuiBouton prend la valeur true si pinBouton est LOW, false si HIGH
  // ici vous pouvez faire autre chose
  // même si la pin 2 change de valeur, appuiBouton ne change pas jusqu'à la fin de la loop
  ...

}

On est d'accord J-M-L, c'est ce que je cherche à éviter et comprendre à composer.
je sens qu'on parle de la même chose tous, sans se comprendre exactement.
Mon problème est la façon de traiter les variables, comme le dit fdufnews, l'usage des I/O est mal approprié.
Ce dont je ne doute pas.
Je répète,le but de ma recherche,remplacer l'état d'une sortie par une variable afin de libérer entre autre, des broches de la carte, et d'apprendre à écrire un code correct.
Mon besoin final du projet en cours: Corriger un code qui Fonctionne avec des sorties ayant fonction mémoire ( c'est totalement Moche, j'en conviens!) Ma session enregistrement d'un répondeur se termine par une ligne digitalWrite(Memo,HIGH); pour mémoriser la présence d'un message en attente lecture ultérieure. Hormis, mémoriser, je n'ai pas besoin de câbler cette sortie.
Je relis cette sortie lors de différentes conditions de coupure de communication suivant l'évolution de mon code, pour savoir si je dois remettre tout à zéro, ou début de code, en l'absence ou pas de message enregistré.
Et également, en cas de présence message, modifier la sortie pour une future prise en compte, ou le maintien en l'état si déjà modifiée. Je précise, tout cela fonctionne, sauf qu'avec maîtrise de variables , ce serait un niveau au dessus.
Et donc, souhaite ré-écrire un code avec et non sans, je m'embrouille sans aucun doute avec les I/O.
Mon esprit logique a ses limites!
L'exemple de J-M-L avec appui bouton s'en approche, sans doute en accord avec mon précédent post.
En réalité, c'est une action de ligne de code qui fera se modifier la variable true ou false.

  // exemple en fin de séquence enregistrement:

}
else if (etape == 12 && delai>= 5000)
{
digitalWrite(Relais,LOW);
digitalWrite(Rec,LOW);
digitalWrite(Start,LOW);
digitalWrite(Memo,HIGH);               // ma façon actuelle de mémoriser la présence message
etape=0;
}

Style de code que je voudrais obtenir:
il me manque , je pense, la manière de déclarer préalablement correctement cette variable.

// exemple en fin de séquence enregistrement:

}
else if (etape == 12 && delai>= 5000)
{
digitalWrite(Relais,LOW);
digitalWrite(Rec,LOW);
digitalWrite(Start,LOW);
Memo = true;    // remplacer la sortie A1 nommée Memo par une variable et ne plus utiliser de sortie
etape=0;
}

vangel:
Vileroi, tout à fait d'accord, j'ai tendance à ne pas simplifier les choses à force de détails diffus.
Et parallèlement à ta réponse, ai pensé dès ce matin, reprendre à zéro ma problématique.
Donc ,voici un code simple où j'ai remplacé fictivement une sortie par une variable globale.

Lorsque ma condition contient varMemo == LOW , elle ne s'exécute pas
Lorsque ma condition contient varMemo == HIGH , elle s'exécute.

Pourtant, au départ varMemo est bien déclaré LOW

 const int sw1 = 2;

const int sw2 =3;

int varMemo = LOW;          // variable mémoire fictive en lieu et place de relecture d'une sortie

void setup() {
 
  pinMode(sw1,INPUT_PULLUP);
  pinMode(sw2,INPUT_PULLUP);
  pinMode(6,OUTPUT);
}
void loop() {

if(( digitalRead(sw1)== LOW)&&(digitalRead(sw2)==LOW)&&(digitalRead (varMemo) == LOW ))
{digitalWrite(6,HIGH);
}
}

Moi je pense que ton erreur est ici :

if(( digitalRead(sw1)== LOW)&&(digitalRead(sw2)==LOW)&&([color=red][b]digitalRead [/b]([/color]varMemo) == LOW ))

pour lire une variable, il n'y a rien besoin de rajouter avant... si tu emploies digitalRead(), c'est pour lire une broche de l'arduino. Du coup là ce qui se passe dans ton code, c'est que comme ta variable "varMemo" contient la valeur LOW, donc 0, tu fais "digitalRead(0)==LOW" soit tu teste si la broche 0 est à 0.

Pour ce que tu veux faire, il suffit tout simplement de faire

if(( digitalRead(sw1)== LOW)&&(digitalRead(sw2)==LOW)&&(varMemo == LOW ))
{digitalWrite(6,HIGH);
}

mais pour le coup, si ta variable ne contient que HIGH ou LOW, par besoin d'employer un int qui prend 8 octets en mémoire, il vaut mieux employer un bool, qui est précisément prévu pour ça

Ma session enregistrement d'un répondeur se termine par une ligne digitalWrite(Memo,HIGH); pour mémoriser la présence d'un message en attente lecture ultérieure. Hormis, mémoriser, je n'ai pas besoin de câbler cette sortie.

et bien déclarez une variable (en lieu et place de Memo)byte etatRepondeur;et partout où dans le code vous avez digitalWrite(Memo,HIGH);vous mettez à la place etatRepondeur=HIGH;

puis partout où dans le code vous avez digitalWrite(Memo,LOW);vous mettez à la place etatRepondeur=LOW;
Enfin partout où dans le code vous avez digitalRead(Memo);vous mettez juste etatRepondeur à la place.

et le tour est joué.

(et vous virez le pinMode(Memo, output); du setup et la déclaration de Memo)

La réponse de J-M-L a croisé ma dernière réponse à bricofoy.

J'en déduis que vous avez tous les deux bien cerné la question.
bricofoy m'ayant mis sur la voie de l'usage correct d' une variable dans le cas précis de l'exemple cité.
J-M-L m'ayant mis sur la voie avec une application plus cernée sur mon projet actuel.

Merci encore à vous deux et tous les acteurs de ce sujet.

super :slight_smile:

je suppose qu'il y avait une LED attachée à cette pin qui montrait à l'utilisateur s'il y avait des messages en attente.