switch case anidados (Solucionado)

¿Anidar por anidar? No lo entiendo. Se anida si con ello resuelves el problema que tratas de solucionar. No se trata de "estoy aburrido, voy a anidar".

Plantearé la pregunta de otra manera. ¿Qué es lo que quieres que se tenga que teclear para que se apague o encienda un LED determinado? Porque en lo que dices que no te funciona parece que estás teniendo en cuenta que hay que apretar '#' para que encienda o apague el LED y en que usas el waitForKey() no esperas a que se pulse el '#', sino que basta con pulsar letra y número.

Soy novato, pero se que se puede hacer de mil maneras, pero si lees el post desde el principio te vas dar cuenta, uso led para aprender a usar switch anidados con entradas de teclado, ignoranteabsoluto me explico cómo hacerlo con servos.

¿Te funcionó lo de los servos?

No me has explicado aún cómo se ha de comportar el programa ni porqué en uno parece que hay que pulsar 'A1#' mientras que en el otro sólo hay que teclear 'A1' para que actúe sobre el LED.

El de los led imagínate que tenés 4 líneas de nueve lámparas cada una, querés prender la lámpara número seis de la línea A y la Tres de la línea C

Adrian_E:
El de los led imagínate que tenés 4 líneas de nueve lámparas cada una, querés prender la lámpara número seis de la línea A y la Tresˊ de la línea C

¿Qué habría que teclear para ello? ¿'A6C3' o 'A6#C3#'?

Si presionas A y luego 3

Pues no. Porque si fuera así, ¿para qué estás poniendo el case ‘#’ :? Con los servos el ‘#’ servía para saber cuando terminabas de teclear los grados y una forma de “confirmar” pero ahora dices que no, que basta con letra y número.

No es cuestión de hacer COPY+PASTE y ya está. Es más bien COPY+COMPRENDER para encontrar una posible solución a tu problema en particular.

Aquí te dejo unas modificaciones para que funcionen las combinaciones A1, A2, B1 y B2 (ya que sólo has definido 4 LEDs).

#include <Keypad.h>


int led_1 =8;
int led_2 =9;
int led_3=11;
int led_4 =12;

const byte Filas = 4; //KeyPad de 4 filas
const byte Cols = 4; //y 4 columnas
byte Pins_Filas[] = {33,35,37,39}; //Pines Arduino para las filas.
byte Pins_Cols[] = {41,43,45,47}; // Pines Arduino para las columnas.

char cadena[17];
char Teclas [Filas][Cols] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
Keypad Teclado = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols);

enum estado_t{
  ESPARANDO_LETRA,
  ESPERANDO_LED
};
estado_t estado = ESPARANDO_LETRA;
char letra;
char led;


void setup() {
 Serial.begin(9600);
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(led_3, OUTPUT);
pinMode(led_4, OUTPUT);

}
void loop() {
 
  char pulsacion = Teclado.getKey();
   
  switch (pulsacion) {
      case 'A'...'B':
        letra = pulsacion;
        estado = ESPERANDO_LED;
        break;
      case '1':
        if (estado == ESPERANDO_LED) { // Sólo si ya tenemos la letra (estamos esperando el número del LED)
          switch (letra) {
            case 'A':
              digitalWrite(led_1,!digitalRead(led_1));
              break;
            case 'B':
              digitalWrite(led_2,!digitalRead(led_2));
              break;
          }
        }
        estado = ESPERANDO_LETRA;
        break;
      case '2':
        if (estado == ESPERANDO_LED) { // Sólo si ya tenemos la letra (estamos esperando el número del LED)
          switch (letra) {
            case 'A':
              digitalWrite(led_3,!digitalRead(led_3));
              break;
            case 'B':
              digitalWrite(led_4,!digitalRead(led_4));
              break;
          }
        }
        estado = ESPERANDO_LETRA;
        break;
      default:
        estado = ESPARANDO_LETRA;
        break;
  }
}

Aunque yo, personalmente, no lo haría con tanto switch, sino más bien con un array bidimensional donde guardar los pines a los que tengo conectados los LEDs a controlar. Y utilizar la letra y el número para saber la “fila” y “columna” de la posición del array que tiene el valor del pin deseado.

Nota: el código no lo he probado, ni tan siquiera sé si compila.

compila, pero me pasa lo mismo que el mio, lee las pulsaciones, pero no hace nada, el que yo hice por haber usado waitforkey() lo malo es que hasta que no eligo el led a enceder se frena el codigo.

#include <Keypad.h>


int led_1 =8;
int led_2 =9;
int led_3=11;
int led_4 =12;

const byte Filas = 4; //KeyPad de 4 filas
const byte Cols = 4; //y 4 columnas
byte Pins_Filas[] = {33,35,37,39}; //Pines Arduino para las filas.
byte Pins_Cols[] = {41,43,45,47}; // Pines Arduino para las columnas.

int tiempo = 250;
unsigned long inicia=0;

char cadena[17]; 
char Teclas [Filas][Cols] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
Keypad Teclado = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols);

char leds;
char pulsacion;


void setup() {
 Serial.begin(9600);
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(led_3, OUTPUT);
pinMode(led_4, OUTPUT);
pinMode(6, OUTPUT);
}
void loop() {
  
  pulsacion = Teclado.getKey();
  
  if(millis() - inicia>=tiempo){
      inicia = millis();
      digitalWrite(6, !digitalRead(6));
  }
  
  switch (pulsacion) {
     leds = Teclado.waitForKey();
      case 'A' :
                       switch (leds) 
               {
          
         case '1':
              digitalWrite(led_1, !digitalRead(led_1));
              break;
         case '2':
              digitalWrite(led_2, !digitalRead(led_2));
              break;
              }
              break;
           
      case 'B' :
              leds = Teclado.getKey();}   
        
        switch (leds){
                
        case '3':
              digitalWrite(led_3, !digitalRead(led_3));
              break;
          case '4':
              digitalWrite(led_4, !digitalRead(led_4));
              break;
               }
              break;

       }   
  
  }

No entiendo lo que tratas de decir. Dices que compila y te pasa lo mismo que con el tuyo. Pero pones un código que no es el que yo te he puesto. ¿Estás diciendo que lo que yo te he puesto, tal cual, no funciona? ¿Y a la vez estás poniendo un nuevo código hecho por ti que tampoco funciona? ¿O lo que has probado es el código que acabas de poner y no el mío?

Me estoy volviendo loco. No sé que es lo que has probado y qué no. ¿Has probado lo último que he puesto (sin modificaciones por tu parte) y no te ha funcionado?

por eso te muestro el que me funciona a medias, que lo malo que tiene es que selecciono Opcion 'A' pero por usar el waitforkey() hasta que no selecciono el led a encender se detiene todos, el tuyo compila pero no hace nada.

Efectivamente. No funciona. El fallo está en que si no se pulsan las teclas esperadas el default: "reinicia" la máquina de estados y por el default: se me está colando el caso de no haber ninguna tecla pulsada. Para corregirlo basta con poner un primer case.

  switch (pulsacion) {
      case NO_KEY :
          break;

NO_KEY es una constante de la librería que está definida con el valor 0, que es el valor que retorna si no hay ninguna tecla pulsada.

Y por lo que veo, en el que puse de los servos he cometido el mismo error. Así que tal como está no ha de funcionar, le falta el mismo case.

Siento tanto quebradero de cabeza. Eso me pasa por no haber probado el código, pero es que no tengo teclado de ese tipo y lo he tenido que depurar con un Arduino Uno un par de cables y un pulsador. :frowning:

ok lo voy a probar

Funciona perfectamente, gracias, me sirve de mucho ya que yo aprendí mucho por sólo preguntar sobre switch anidados :slight_smile:

Adrian_E has visto que dejé de responder porque la verdad este ha sido tu consulta mas errática.

Debes volver a leer lo que escribes y seguir el hilo de lo que se te responde.
Admiro la paciencia de IgnoranteAbsoluto pero coincido en que es como que te hablan y sigues en lo tuyo.

Finalmente has resuelto el problema pero lo que veo es que estas saltando pasos y no estas siguiendo un libro y aprendiendo C y Arduino en el proceso que es justamente tu gran dolor de cabeza.

ok, no, no estoy aprendiendo C, lo que pasa es que tuve ir a la fuente de arduino, porque me parecía que se me escapaba algo, ya que en la referencia de arduino, switch...case - Arduino Reference y que es muy pobre en su explicacion, y no habla de anidar,y mas tomando en cuenta que ingnoranteabsoluto, me parece a mi pero se mueve mucho por C++, entonces busque en foros de programación específicos de C, C++, entonces decidi primero ver como realmente se anida, y la solucion de problemas, lo que ignoranteabsoluto, me despejo muchas dudas, arrancando por esta sentencia que no la tenia

case NO_KEY :
          break;

y la forma de que debo usar para trabajar con las entrada de teclado en switch, por eso cambie de servo al usar leds, para que se entienda que lo quería entender como se anida y me parecio que el uso de led era menos complicado para explicarme.

Pero yo te lo digo con la mejor intención.
Además sabes que vengo viendo tu evolución y de ahi mi comentario.

No hay como un libro para aprender. Incluso lo que estas haciendo porque proyectos con teclados matriciales son parte de la enseñanza.

no lo tome a mal a tu comentario, trate de explicar porque tuve que ller sobre c++, el libro que tengo Arduino Curso practico de formación de Oscar Torrente Artero, pero de teclado de matriz nada, solo una referencia a keypads, despues lo de la web, que mucho de lo que hay confunde mas de lo que aclara, me refiero por ejemplo al uso del switch-case.