J'ai une pt question au sujet de l'usage de "case/switch"

Bonjour la communauté,

Je suis tout nouveau .... Grâce à vos écris XDje me débrouille jusqu'ici très bien ...
Mais je cale avec les subtilités ou limites de l'usage de "case".

L'usage d'un simple case fonctionne parfaitement, maintenant, j'essaye de les imbriqués.
Le soucis, il semble qu'il rentre bien dans la sélection mais il break et reviens à l'attente de l'entrée principal.

Pour mieux comprendre :

int incomingByte; 
int incomingByted; 
int incomingBytec;
int incomingByteca;
int incomingBytecn;
void loop()
{
while (Serial.available() > 0)  {
    Serial.println("H or h For Help command");
    Serial.println("Ready !");
    incomingByte = Serial.read();
    switch (incomingByte) {
	case 'd':  
	case 'D':
		Serial.print("D Fonction selected");
		Serial.println(" - Select Channel Type ?");
		incomingByted = Serial.read();
		switch (incomingByted) { 
			case 'a':  
			case 'A':	
			Serial.print("Analogique type selected");
			Serial.println(" - Select Channel number");
			incomingByteca = Serial.read();
			switch (incomingByteca) {
				case '1':
						break;
		//		MaFonctionD(A1);			
				case '2':
						break;
		//		MaFonctionD(A2);			
				case '3':
						break;
		//		MaFonctionD(A3);			
				case '4':
						break;
		//		MaFonctionD(A4);			
				case '5':
						break;
		//		MaFonctionD(A5);			
				case '6':
						break;
		//		MaFonctionD(A6);			
				case '7':
						break;
		//		MaFonctionD(A7);			
				default:
				Serial.println("Error Please select analogique channel 1 to 7");
						break;
			}
			

		case 'n':  
		case 'N':	
			delay(100);
			Serial.print("Numerique Type selected");
			Serial.println(" - Select Channel number");
			incomingBytecn = Serial.read();
			switch (incomingBytecn) {
				case '1':
				MaFonctionD(30);			
				break;
				case '2':
				MaFonctionD(31);		
				break;			
				case '3':
		//		MaFonctionD(3);		
				break;		
				case '4':
		//			MaFonctionD(4);			
						break;
				case '5':
		//			MaFonctionD(5);
				break;		
				case '6':
		//	//			MaFonctionD(6);			
						break;
				case '7':
		//			MaFonctionD(7);
				break;		
				default:
				Serial.println("Error Please select Numeric channel 1 to 7");
				break;
		}	

		default:
			Serial.println(incomingByted);
			Serial.println("Error please select N fo Numeric or A for analogique");
										break;     
		}
	break;     
	
    case 'v':
	case 'V':
      Serial.println(incomingByte);
      Serial.println("Nano - 1.0");
      break;

    case 'o':
    case 'O':
      Serial.println(incomingByte);
      OKLED();
      break;

    case 'n':
    case 'N':
      Serial.println(incomingByte);
      NOOKLED();
      break;

 	case 'h':    
    case 'H':
      Serial.println(incomingByte);
      Serial.println("Internal Fonction:");	  
      Serial.println("H Help"); 
      Serial.println("V Version");
      Serial.println("O Led Vert OK On");
      Serial.println("N Led Rouge ON");
      Serial.println("D Fonction menu");
    break;
	default:
      Serial.println(incomingByte);
      Serial.print("Error:");
      Serial.println("Unreconize command");
      Serial.println("For all command please command H");
    break;
    }	
  }
}

Quand je presse O ou N pas de soucis, il s’exécute sans problème. Par contre quand je sélectionne D c'est comme si il passait incomingByted = Serial.read(); Il affiche donc le message d'erreur par défaut mais en plus il break et renvois vers le case supérieur ...

Serial.println("Error please select N fo Numeric or A for analogique");

D'ailleurs, je n'arrive jamais à switch (incomingByteca) ...

J'ai essayer en retirant les break des sous combinaisons sans résultat et si je retire tout les breaks pas mieux. ... J'ai tenter plusieurs combinaisons avec ou sans break, mais le résultat n'est pas celui espérer !

Un Arduineur pour peut être m'éclairer ?
Ou je devrait peut être mixé if dans un case ?

Merci pour votre aide,
Bonne journée,

  • En l'absence de break, l'exécution continue sur le case suivante
  • Un break sort du switch courant au niveau de la } fermante

Exemple 1:

a = 2;
switch( a )
{
case 1:
  Serial.println("a=1");
  break;
case 2:
  Serial.println("a=2");
  break;
case 3:
  Serial.println("a=3");
  break;
}
Serial.println("fin switch");

Affichera :

a=2
fin switch

En supprimant les breaks :

a = 2;
switch( a )
{
case 1:
  Serial.println("a=1");
case 2:
  Serial.println("a=2");
case 3:
  Serial.println("a=3");
}
Serial.println("fin switch");

Affichera :

a=2
a=3
fin switch

En cas d'imbrication

a=1;
b=1;
switch( a )
{
case 1:
  switch ( b )
  {
  case 1:
    Serial.println("a=1 et b=1");
    break; // break appartenant au switch (b ), fin du case b=1
  case 2:
    Serial.println("a=1 et b=2");
    break; // break appartenant au switch (b ), fin du case b=2
  }
  Serial.println("fin switch b dans a=1");
  break;   // break appartenant au switch (a), fin du case a=1

case 2:
  switch ( b )
  {
  case 1:
    Serial.println("a=2 et b=1");
    break; // break appartenant au switch (b ), fin du case b=1
  case 2:
    Serial.println("a=2 et b=2");
    break; // break appartenant au switch (b ), fin du case b=2
  }
  Serial.println("fin switch b dans a=2");
  break;   // break appartenant au switch (a), fin du case a=2
}
Serial.println("fin switch a");

Affichera

a=1 et b=1
fin switch b dans a=1
fin switch a

Dans ton code, dans les cas 'd' et 'D' du 1er switch(incomingByte), tu as un 2nd switch(incomingByteca), tu n'as pas de break après la fermeture de } du switch(incomingByteca)
Donc l'exécution continue sur le case 'n'/'N' du 1er switch.
Est-ce voulu ?

Quand je presse O ou N pas de soucis, il s’exécute sans problème. Par contre quand je sélectionne D c'est comme si il passait

incomingByted = Serial.read();

C'est peut être qu'il n'a pas encore reçu le caractère en question.
Il faudrait peut être mettre un while (!Serial.available()); avant de faire la lecture. ATTENTION quand même cette fonction est bloquante!!

Merci pour vos réponses réactive,

Etant dimanche, je me plonge sur vos solutions :slight_smile:
Concernant le break, oublier sur le case "D fonction", j'ai le même résultat avec et sans ... (viens d'essayer pour le pas dire de bêtises)

Donc, j'ai bien :
Quand j'appuis sur D, il semble rentrée dans le swtich car je vois :

		Serial.print("D Fonction selected");
		Serial.println(" - Select Channel Type ?");

Mais alors, il ne marque pas l'arrêt pour attendre le Serial.read(), il passe directement au default :

			Serial.println("Error please select N fo Numeric or A for analogique");

Quand j'appuis sur N, il exectue N du premier switch ...

   case 'n':
  case 'N':
     Serial.println(incomingByte);
      NOOKLED();
      break;

Ce qui me laisse pensez, qu'il passe le Serial.read() du Case "D fonction" exécute le "default" et le break dans le default renvois vers le switch principal incomingByte ... Sauf quand supprimant le break dans default, il se rend quand même au swtich principal sur incomingBute ... comprend plus rien...

J'ai cru lire sur internet qu'il était "utile" de ne pas mettre certain break dans le cadre de case imbriqué.

Concernant la réponse de Fdunews, merci et en effet, je vais regarder maintenant pour ajouter un while car je confirme qu'il n'attends pas de recevoir le second switch. Pour dé-bug, j'ai fait un print des valeurs et j’obtiens : -1

Je reviens ...
Bonne journée et merci pour vos réponses,

En effet, l'ajout du while à résolu le problème :slight_smile:
Cependant avec quelques effet toujours aussi "strange" il n'attends pas la seconde valeur ... va trop vite.
Du coup, j'ai ajouter des delay() et relancer le serial ... du coup il y a moyen de parser manuellement ou via script la commande.
A l'occurence, DN1 pour Fonction D mode numérique sur channel 1 (signifie pin N1).

int incomingByte; 
int incomingByted; 
int incomingBytec;
int incomingByteca;
int incomingBytecn;
void loop()
{

while (Serial.available() > 0)  {
    Serial.println("H or h For Help command");
    Serial.println("Ready !");
    incomingByte = Serial.read();
    switch (incomingByte) {
	case 'd':  
	case 'D':
        delay(1000);
        Serial.begin(9600);
		while (Serial.available() > 0)  {
		Serial.print("DHT Fonction selected");
		Serial.println(" -Select Channel Type");
		incomingByted = Serial.read();
		switch (incomingByted) { 
	
			case 'a':  
			case 'A':
			delay(3000);
            Serial.begin(9600);
			Serial.print("D Analogique Fonction selected");
			Serial.println(" - Select Channel number");
			while (Serial.available() > 0)  {
			incomingByteca = Serial.read();
			switch (incomingByteca) {
				case '1':
				MaFonctionD(A1);					
				break;
		
				case '2':
				MaFonctionDA2);						
				break;
	
				case '3':
				MaFonctionD(A3);				
				break;
			
				case '4':
				MaFonctionD(A4);					
				break;
		
				case '5':
				MaFonctionD(A5);				
				break;
			
				case '6':
				MaFonctionD(A6);					
				break;
		
				case '7':
				MaFonctionD(A7);			
				break;
			
				default:
				Serial.println("Error Please select analogique channel 1 to 7");
				break;
			}
			break;
			}
			break;
		
		case 'n':  
		case 'N':	
			delay(1000);
            Serial.begin(9600);
			Serial.print("D Numerique Fonction selected");
			Serial.println(" - Select Channel number");
			while (Serial.available() > 0)  {
			incomingBytecn = Serial.read();
			switch (incomingBytecn) {
				case '1':
				MaFonctionD(30);			
				break;
				case '2':
				MaFonctionD(31);		
				break;		
				case '3':
				MaFonctionD(3);		
				case '4':
				MaFonctionD(4);			
				break;
				case '5':
				MaFonctionD(5);
				break;
				case '6':
				MaFonctionD(6);			
				break;
				case '7':
				MaFonctionD(7);
				break;	
				default:
				Serial.println("Error Please select Numeric channel 1 to 7");
				break;
			}
		break;
		}
		break;
		
		default:
			Serial.println(incomingByted);
			Serial.println("Error please select N fo Numeric or A for analogique");
			break;

	}
	break;
	}
	break;        
	
    case 'v':
	case 'V':
      Serial.println(incomingByte);
      Serial.println("Nano - 1.0");
      break;

    case 'o':
    case 'O':
      Serial.println(incomingByte);
      OKLED();
      break;

    case 'n':
    case 'N':
      Serial.println(incomingByte);
      NOOKLED();
      break;

 	case 'h':    
    case 'H':
      Serial.println(incomingByte);
      Serial.println("Internal Fonction:");	  
      Serial.println("H Help"); 
      Serial.println("V Version");
      Serial.println("O Led Vert OK On");
      Serial.println("N Led Rouge ON");
      Serial.println("D Fonction menu");
    break;
	default:
      Serial.println(incomingByte);
      Serial.print("Error:");
      Serial.println("Unreconize command");
      Serial.println("For all command please command H");
    break;
    }	
  }
}

Peut être qu'il y a plus simple ou plus propre ...
Merci et bon dimanche,

il n'attends pas la seconde valeur ... va trop vite.

C'est normal la ligne suivante n'attends pas la saisie.

while (Serial.available() > 0)  {

Elle s'exécute s'il y a une entrée sinon elle sort. Je t'avais proposé de mettre

while (!Serial.available());

Cette ligne attend jusqu'au moment ou il y aura une saisie. C'est d'ailleurs l'inconvénient que j'avais signalé la ligne est bloquante. S'il n'y a pas d'entrée elle restera à attendre.
Si cela ne te gène pas tu laisses comme ça. Sinon il faut ajouter une variable liée au temps dans la condition du while.

Super,

merci en effet, il attends, mais c'est totalement ce que je cherche.

Bonne soirée,