Menu Rotary: variables ou tableau?

Bonjour
J’ai réussi à faire un menu super simple, et sous forme de fonction, qui réponde (presque) à mon besoin.
Il s’agit de régler un chronomètre à faisceau laser.
A terme, les valeurs seront, je pense, stockées dans l’Eeprom.
En attendant, il y a un paradoxe: ce menu permet de régler le contraste et la luminosité de l’afficheur, mais… en différé! On règle la luminosité, mais onn voit pas c’qu’on fait! Bah bravo

Etant donné que je lis partout qu’il faut éviter les variables globales et de les modifier dans des fonctions et tout ça, dois-je utiliser un tableau?

En effet, les variables que ce menu modifie devraient l’être DANS la fonction et non pas après le RETURN…

Si vous avez compris le souci et que vous avez un avis, j’en suis preneur.

Merci

int PinCLK = 4;
int PinDT = 5;
int PinSW = 0;
static long encoderpos;   
int PinCLKLast = LOW;
int n = LOW;

void setup() { 
  pinMode (PinCLK,INPUT);
  pinMode (PinDT,INPUT);
  pinMode (PinSW,INPUT);
  Serial.begin (9600);


  //test de la fonction
    Serial.println (RoMenu("Contraste", 50, 0, 100, 5, "Minimum", "Maximum")); 
    delay(1000);
    Serial.println (RoMenu("Beep son", 1,0, 1, 1, "Sans", "Avec"));
    delay(1000);
    Serial.println (RoMenu("Nombre de tours",1,0,999,1,"Infini","999 Maxi"));
    delay(1000);
} 



void loop() {
}



int RoMenu(String Titre, int encoderpos, int Vmin, int Vmax, int Vinc, String TxtMin, String TxtMax) { 
  //paramètres; (Titre, Valeur initiale, Valeur Minimale, Valeur Maximale, Valeur d'incrementation, Mot de remplacement pour la valeur min, Mot de remplacement pour la valeur max)
  
  Serial.println(Titre); //affiche le titre
  
  //afficher la valeur indiquée sous la bonne forme   
     if (encoderpos<=Vmin) {Serial.println(TxtMin);}
     else if (encoderpos>=Vmax) {Serial.println(TxtMax);}
     else {Serial.println(encoderpos);}
  encoderpos=encoderpos-Vinc; //rétablit la vraie valeur au démarrage
  
  
  
   while ((digitalRead(PinSW))) {      // tant qu'on n'appuie pas sur le bouton
 
 
   n = digitalRead(PinCLK); //lit la valeur
   
   if ((PinCLKLast == LOW) && (n == HIGH)) {  
 
     
     if (digitalRead(PinDT) == LOW) {   //si sens antihoraire
       encoderpos=encoderpos-Vinc;      //décrémenter
       delay(100);
     } 
     else {                             //sens horaire
       encoderpos=encoderpos+Vinc;      //incrémenter
       delay(100);
     }
     
     encoderpos = constrain (encoderpos,Vmin,Vmax);   //rétablit la valeur mini ou maxi de la variable si elle a dépassé les limites données par l'utilisateur
     
     //comparer la valeur à cells fournies et adapter l'affichage
     if (encoderpos<=Vmin) {Serial.println(TxtMin);}
     else if (encoderpos>=Vmax) {Serial.println(TxtMax);}
     else {Serial.println(encoderpos);}
     //delay(100);
   } 
   PinCLKLast = n;
 }
 Serial.println("FIN");
 
 return encoderpos;
}
int PinCLKLast = LOW;
int n = LOW;

Il faudrait pas des byte au lieu de int ?

Si, clairement. mais ça, je l'ai compris que ce matin ^^
En attendant ça marche, mais tu as entièrement raison.
Je n'ai pas encore très bien assimilé les différents types de variables, je regarde ça en mangeant mon sandwich ^^
Merci pour ta contribution

... donc il y a un problème ou pas ??

le problème c'est de savoir comment modifier en temps réel les variables dans RoMenu ...

Lorsque j'appelle ma fonction, puis-je mettre en paramètre une variable ?
Je fais un essai à la maison en espérant trouver sans embêter tout le monde

J’ai fait un pti bout de code pour me faire comprendre.

Dans ce code, j’ai une variable x, on pourrait en avoir des tas à modifier par la même fonction. Est-il donc possible de faire ce que je tente et qui me marche pas, mais d’une manière propre et efficace?

byte x=0;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
Serial.println("la variable x vaut");
Serial.println (x);
fonction(x);
delay(1000);
Serial.println("et maintenant");
Serial.println (x);
}

void loop() {
  // put your main code here, to run repeatedly:

}

byte fonction(byte variable) {
  variable++;
}

Tu déclares x en variable globale : pas besoin de la passer en argument, elle est connue de toutes tes fonctions (setup, loop et les autres). Si tu veux utiliser des variables locales, par exemple locales à la loop, et les utiliser et les modifier dans une fonction, il faut les passer en argument et en pointeur.

Exemple :

void test(int *pj) /* test attend l'adresse d'un entier... */
{
    *pj=2;          /* ... pour le modifier. */
    return;
}

int main(void)
{
    int i=3;
    test(&i);       /* On passe l'adresse de i en paramètre. */
    /* Ici, i vaut 2. */
    return 0;
}

Trouvé ici.

Voir aussi (même lien) :

Exemple - Passage de paramètre par référence en C++
void test(int &i) // i est une référence du paramètre.
{
    i = 2;    // Modifie le paramètre passé en référence.
    return;
}

int main(void)
{
    int i=3;
    test(i);
    // Après l'appel de test, i vaut 2.
    // L'opérateur & n'est pas nécessaire pour appeler
    // test.
    return 0;
}

C'est ce que j'utilise les rares fois où je ne veux pas utiliser des variables globales.

Merci, j'y vois plus clair.
Les pointeurs je m'y intéresse que depuis hier soir, ça tombe nickel.
Dans ton exemple *pj, si je modifie *pj, en réalité je modifier la variable x quand j'appelle ma fonction?

Par exemple
fonction(x);

Ma fonction:
fonction(*pj){
modifier *pj;}

Et là, c'est x qui est modifié?

Si c'est ça, je pouvais pas trouver tout seul

Merci!
Le petit & est magique, c'est certainement l'explication la plus rationnelle ^^ hihi
Non sans blague ça marche
Code d'exemple:

byte x=0;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
Serial.println("la variable x vaut");
Serial.println (x);

pinMode (13,OUTPUT); //pin 13 est une sortie, y mettre une led

}

void loop() {
  // put your main code here, to run repeatedly:
fonction(x);
delay(100);
Serial.println("et maintenant");
Serial.println (x);
analogWrite (13,x); //applique x au pin 13
}

byte fonction(byte &variable) { //le petit & magique
  variable++;
}

Coool ! :slight_smile:

Bon, du coup je commence à mettre en application, mais reste un sushi:
Si la variable désignée évolue bien en temps réel, elle n'est cependant pas appliquée.
Si je modifie le contraste, il faut bien appliquer la variable au pin, idem pour la lumière, mais ce n'est pas le cas pour la variable NombredeTours par exemple qui, elle, ne s'applique pas à un pin, mais à un For
Le but est bien une application directe, alors, comment faire?

Même si le sushi (ouais je continue avec cette vanne, étant en manque d’idées) premier est résolu, je crois qu’à force de bricoler des variables, je commence à avoir des conflits.

J’ai un message d’erreur
invalid initialization of reference of type ‘int&’ from expression of type ‘byte {aka unsigned char}’

//définition des broches

//broches du rotary encoder
int PinCLK = 4;
int PinDT = 5;
int PinSW = 0;
//broches des leds
int PinLedG = 13;  //led verte
int PinLedB = 12;  //led bleue
int PinLedR = 11;  //led rouge
//broche buzzer
int PinBeep = 10;  //buzzer

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//création de variables

//variable du programme de chrono
int VNbTours = 0; // contient le nombre de tours //0=infini puis de 1 à 999

//variables propres à la fonction RoMenu
static long encoderpos;   
byte PinCLKLast = LOW;
byte n = LOW;

//variable du buzzer
byte VBuzz = 1;  //0= muet 1=son activé

//variables du LCD
byte VLCDCon = 120; //par défaut le contraste est à 120/255
byte VLCDLum = 220; //par défaut la luminosité est à 220

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() { 
  pinMode (PinCLK,INPUT);
  pinMode (PinDT,INPUT);
  pinMode (PinSW,INPUT);
  Serial.begin (9600);

  // test du buzzer
  Serial.println("Buzzer on");
  VBuzz=1;
  FBuzzer();
  delay(1000);
  Serial.println("Buzzer off");
  VBuzz=0;
  FBuzzer();
  delay(1000);
  
  //test de la fonction RoMenu
    Serial.println (RoMenu("Contraste", 50, 0, 100, 5, "Minimum", "Maximum", VLCDCon)); 
    delay(1000);
    Serial.println (RoMenu("Beep son", 1,0, 1, 1, "Sans", "Avec", Vbuzz));
    delay(1000);
    Serial.println (RoMenu("Nombre de tours",1,0,999,1,"Infini","999 Maxi", VNbTours ));
    delay(1000);
} 



void loop() {
}


//FONCTION ROMENU COMMENCE ICI///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int RoMenu(String Titre, int encoderpos, int Vmin, int Vmax, int Vinc, String TxtMin, String TxtMax, int &encorderpos) { 
  //paramètres; (Titre, Valeur initiale, Valeur Minimale, Valeur Maximale, Valeur d'incrementation, Mot de remplacement pour la valeur min, Mot de remplacement pour la valeur max, Nom de la variable)
  
  Serial.println(Titre); //affiche le titre
  
  //afficher la valeur indiquée sous la bonne forme   
     if (encoderpos<=Vmin) {Serial.println(TxtMin);}
     else if (encoderpos>=Vmax) {Serial.println(TxtMax);}
     else {Serial.println(encoderpos);}
  encoderpos=encoderpos-Vinc; //rétablit la vraie valeur au démarrage
  
  
  
   while ((digitalRead(PinSW))) {      // tant qu'on n'appuie pas sur le bouton
 
 
   n = digitalRead(PinCLK); //lit la valeur
   
   if ((PinCLKLast == LOW) && (n == HIGH)) {  
 
     
     if (digitalRead(PinDT) == LOW) {   //si sens antihoraire
       encoderpos=encoderpos-Vinc;      //décrémenter
       delay(100);
     } 
     else {                             //sens horaire
       encoderpos=encoderpos+Vinc;      //incrémenter
       delay(100);
     }
     
     encoderpos = constrain (encoderpos,Vmin,Vmax);   //rétablit la valeur mini ou maxi de la variable si elle a dépassé les limites données par l'utilisateur
     
     //comparer la valeur à cells fournies et adapter l'affichage
     if (encoderpos<=Vmin) {Serial.println(TxtMin);}
     else if (encoderpos>=Vmax) {Serial.println(TxtMax);}
     else {Serial.println(encoderpos);}
     //delay(100);
   } 
   PinCLKLast = n;
 }
 Serial.println("FIN");
 
 //return encoderpos;
}



//FONCTION BUZZER//////////////////////////////////////////////////////
void FBuzzer() {
//fait sonner ou pas le buzzer
for (int i = 0; i<2; i++) {  //for (x = 0; x <= 255; x ++)
  analogWrite (PinBuzz, (255*VBuzz); //sonne si VBuzz=1, silence si =0
  delay(200);
  analogWrite (PinBuzz, 0);
  delay(200); }

//FONCTION LedFlash///////////////////////////////////////////////////
void FLedFlash(int Led) {  //int Led récupère la couleur de la led à allumer
  //pour appeler cette fonction   FLedFlash(G) allume la led verte// indiquer R, G, ou B

  //tout éteindre
  digitalWrite(PinLedR,LOW);  //led R off
  digitalWrite(PinLedG,LOW);  //led G off
  digitalWrite(PinLedB,LOW);  //led B off
  //allume la led définie par int Led
  switch (Led) {
  case R:
    digitalWrite(PinLedR,HIGH);// rouge
    break;
  case G:
    digitalWrite(PinLedG,HIGH);// verte
    break;
  case B:
    digitalWrite(PinLedB,HIGH);// bleue
}
}

A mon avis, il n’aime pas que je passe d’un byte à un int comme ça sans prévenir…

Je pense que c'est bien là ton erreur : tu passes des arguments à la fonction qui sont de types différents de ceux qui sont déclarés dans la fonction
Vbuzz est un byte et il attend un int.

wep, c'est certain
Les types de variables, ca me perturbe ^^
je potasse ça un peu et je cherche une solution
(je vais essayer en mettant tout en int, voir si ça marche mieux)

Non réfléchis plutôt à ton besoin (voir ce message qui a une problématique similaire et auquel tu contribues :slight_smile: )
Si tes valeurs sont positives et ne dépassent jamais 255, prends des byte, sinon des int.
De manière générale, vérifie que les paramètres dans l’appel des fonctions et dans les déclarations de ces fonctions sont de même type.

En parcourant ton code, j’ai l’impression qu’il manque une accolade fermante à la fin de cette fonction FBuzzer :

//FONCTION BUZZER//////////////////////////////////////////////////////
void FBuzzer() {
//fait sonner ou pas le buzzer
for (int i = 0; i<2; i++) {  //for (x = 0; x <= 255; x ++)
  analogWrite (PinBuzz, (255*VBuzz); //sonne si VBuzz=1, silence si =0
  delay(200);
  analogWrite (PinBuzz, 0);
  delay(200); }

//FONCTION LedFlash///////////////////////////////////////////////////

Dans l’IDE, fais CTRL T ça montre les indentations et ça permet de bien voir s’il manque quelque chose.

Oui bien vu, c'était truffé de fautes.
Par contre, maintenant que ça marche, j'ai voulu mettre tout ça sur mon LCD et fusionner les codes, mais j'ai cramé le LCD semble-t-il, il était brulant derrière et seul un quart de l'affichage s'affiche ...
C'est reparti pour des semaines de patience, j'en ai commandé un ou deux...

RIP