Obtener cifra de dos dígitos de un teclado matricial


#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
// Definir constantes
byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
 
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
 
 int randomNumber;

 const byte ROWS = 4; // Cuatro filas.
 const byte COLS = 4; // Cuatro columnas.
 char keys[ROWS][COLS] = {
         {'1','4','7','*'},
         {'2','5','8','0'},
         {'3','6','9','#'},
         {'A','B','C','D'}
         };
 byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
 byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.
 
 Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
 byte ledPin = 13; 
 
 boolean blink = false;
 
 void setup(){
   Serial.begin(9600);
   pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
   digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A0));
  randomNumber = random(1, 100);
  // Activamos el objeto display asociado a la pantalla OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  // Limpiar buffer
  display.clearDisplay();
 
  // Tamaño del texto
  display.setTextSize(5);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println(randomNumber);
 
  // Enviar a pantalla
  display.display();
 
 }
 
 void loop(){

   char key = keypad.getKey();      // Captura una tecla del teclado.
   if (key) Serial.println(key);    // La muestra en el Monitor Serial

 }
 

Esta parte la tengo bien, lo único que lo que tengo que conseguir es que se compare el número aleatorio generado que me aparece en la pantalla, con un número que yo mande a través del teclado matricial, no se como convertir esas dos cifras sueltas en un número de dos dígitos.

Para que se comparen deberemos dar a un botón, por lo que podrá ser un número de 1,2 o 3 cifras, en el caso de introducir un número inferior la pantalla nos deberá indicar que estamos buscando un número mayor, y si introducimos un número mayor deberá indicarnos lo contrario.

Deberemos repetir este proceso hasta que demos con el número generado al azar y volvamos a empezar desde 0

Matemáticas de nivel 2º de primaria (esto no es una burla ni nada es que es así de simple, lo aclaro por si acaso) Decenas * 10 + unidades. Ejemplo

primer número 3
segundo número 2

3 * 10 = 30 + 2 = 32 El número es 32.

Edito... o también puedes concatenar los string o char. En cualquier caso es muy simple.

Como podría hacer para reconocer el primer número, después el segundo y así poder juntarlos?

Cuando digitas un número qué ocurre?

 char key = keypad.getKey();      // Captura una tecla del teclado.
   if (key) Serial.println(key); 

Esto lo entiendes?
Ahi dice... si se presionó algo imprímelo.
key cambia de 0 o sea nada presionado y por lo tanto false en el if a algo que corresponde al valor de la table con la que has diseñado tu teclado matricial.
Ahora presionas 1 fila 0 columa 0
ese 1 vale unidad si no presionas otro número
si presionas otro número ya deberia ser decena, o sea.. tenerlo almacenado, multiplicarlo por 10 y sumarlo al nuevo numero digitado.
y asi vas multiplicando x 10 la suma de dos numeros hasta cuando? Hasta que una tecla que puede ser por ejemplo # indique que se terminó el ingreso del número.
Por lo tanto tienes una secuencia repetitiva que empieza con una variable en 0, que lleva la suma
A ese valor lo multiplicas por 10 pero como es 0 seguira en 0, y le sumas lo ingresado.
Resultado para el primer digito tienes la unidad.
supongamos presionas 1 y valor que es tu variable = 0.
1er digito: Vas a presionar 1 x ejemplo

// en globales defino
int valor = 0;
int tecla;

// en tu loop
tecla = key - '0';                  // convierto a key en número entero
valor = valor*10+tecla;  

Entonces valor = 1
2do digito : Presionas 4 x ejemplo
valor = 1*10+4 = 10+4 = 14
ya tienes dos números guardados.
Eso se mantiene hasta que decidas terminarlo con un

if (key =='#') {
   // presentas el valor o haces lo que gustes con valor 
    // pero tmb es el momento para ponerlo a 0 y dejarlo
    // listo para próximo ingreso.
}

#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir constantes
byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
String Alvaro = "";
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
int paso=0;
int randomNumber;
int valor = 0;
int tecla;
const byte ROWS = 4; // Cuatro filas.
const byte COLS = 4; // Cuatro columnas.
char keys[ROWS][COLS] = {
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0'},
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

boolean blink = false;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
  digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A0));
  randomNumber = random(1, 100);
  // Activamos el objeto display asociado a la pantalla OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  // Tamaño del texto
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("ADIVINA MI NUMERO");
  display.display();
}

void loop() {

  char key = keypad.getKey();      // Captura una tecla del teclado.
  if (key) Serial.println(key);    // La muestra en el Monitor Serial
  tecla = key - '0';                  // convierto a key en número entero
  valor = valor*10+tecla; 
if (key =='#') {}
else if(valor>randomNumber){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MENOR");
  display.display();
}
else if(valor<randomNumber){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MAYOR");
  display.display();
}
else if(valor=randomNumber){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("HAS GANADO");
  display.display();
}
}

He intentado esto, aunque no parece que se junten los números

1 Like

@Pastormald0nad0, más allá de la ayuda que puedas conseguir en el foro, te sugiero que siempre te tomes un rato para, al menos, estudiar los ejemplos de las librerías que uses, así se te hace más fácil comprender su uso.

Por ejemplo, haces esto

  char key = keypad.getKey();      // Captura una tecla del teclado.
  if (key) Serial.println(key);    // La muestra en el Monitor Serial
  tecla = key - '0';                  // convierto a key en número entero

ahora comparemos el ejemplo de la librería

  char key = keypad.getKey();
  
  if (key != NO_KEY){
    Serial.println(key);
  }

Veamos, la captura de la tecla... Bien.
La validación de la tecla... Hmm... Funciona pero analicemos por qué.
La librería declara la constante

const char NO_KEY = '\0';

o sea, que la comparación es verdadera si el caracter devuelto por getKey() es distinto al caracter con código ASCII 0 (caracter nulo).
Como resulta que para el compilador, el valor 0 es lo mismo que false y cualquier otro valor equivale a true, es solo por esta razón que te funciona

if (key) Serial.println(key);

porque si key contiene un valor distinto a 0 es verdadera la condición.
Y hasta ahí llega el ejemplo, envía por consola el caracter pulsado en el keypad, si lo hay.
Pero fíjate un detalle, tu quieres hacer algo más provechoso entonces a continuación haces

tecla = key - '0';

lo cual funciona bien y te devuelve el número equivalente al representado por la tecla pulsada pero solo si hay tecla pulsada.
¿Y si no la hay, qué devuelve getKey()?
El valor NO_KEY, que equivale a '\0', que equivale al caracter código 0 y que finalmente equivale al número 0.
Y tu a 0 le restas el '0', o sea el código del caracter '0' que resulta que tiene el valor 48.
En resumen haces la operación 0 - 48 que da como resultado -48 (48 negativo).
Ahora resulta que el tipo char equivale a signed byte o sea un byte con signo, y tu variable tecla es integer por lo tanto tiene signo y almacena sin ningún problema el número -48 al igual que lo almacena valor que también es integer y unos microsegundos después, en la siguiente pasada si no llegas a pulsar una tecla, valor contendrá -528 (-48 * 10 + -48) y en la siguiente -5328 y así sucesivamente hasta que haya desbordamiento (2 pasadas después) porque, además, nunca reseteas el contenido de valor.

O sea, tienes que fijarte que la tecla sea válida y hacer la operación de resta solo si lo es, entonces tiene que estar dentro del if().
Y además, quieres trabajar con 2 dígitos, pero no controlas si se leyeron 2 teclas antes de entrar a tu cascada de comparaciones.
Y finalmente tienes que poner valor a 0 luego de procesar un resultado válido (aunque no sea la respuesta correcta al desafío, obviamente).

Ya se que lo que he escrito es largo pero es la única forma de entender por qué no funciona lo que uno intenta hacer, leyendo.

Saludos

1 Like

Nono, no tienen porque ser solo 2 dígitos, podría ser perfectamente un número de 1 dígitos como por ejemplo introducir el 8 o uno de 3 dígitos como el 100, ya que ambos números podrían generarse aleatoriamente.
Por otro lado, con implementar esto no sería todavía válido no?


const char NO_KEY = '\0';

Saludos y muchas gracias por su ayuda

Controla la cantidad de digitos que gustes pero para terminar debes usar una tecla que lo determine, sea + o # o cualquiera de A a D.

Exactamente, tal como lo dice @Surbyte , debes usar una tecla a modo de enter para saber cuando has terminado de ingresar los dígitos y recién entonces haces el resto.

NO_KEY ya está definida por la librería, no la tienes que volver a definir.
Por otro lado, lo que te quise hacer notar es que getKey() devuelve un char hayas o no pulsado una tecla.

Saludos

He comprobado con el monitor serial si la string valor es la deseada y si que lo es, pero al compararlo con el randomNumber generado, siempre me sale que el valor es menor que el número independientemente del valor que introduzcamos. Adjunto código


#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir constantes
byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
int paso=0;
int randomNumber;
String valor = "";
int tecla;
const byte ROWS = 4; // Cuatro filas.
const byte COLS = 4; // Cuatro columnas.
char keys[ROWS][COLS] = {
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0'},
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

boolean blink = false;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
  digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A0));
  randomNumber = random(1, 100);
  // Activamos el objeto display asociado a la pantalla OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  // Tamaño del texto
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("ADIVINA MI NUMERO");
  display.display();
}

void loop() {

char key = keypad.getKey();      // Captura una tecla del teclado.
//if (key) Serial.println(key);    // La muestra en el Monitor Serial
valor = valor + String(key); 
  Serial.println(valor);
if (key =='#') {
  if(valor>String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MENOR");
  display.display();
}

  if(valor<String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MAYOR");
  display.display();
}
  if(valor==String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("HAS GANADO");
  display.display();
}
}
}

Muchas gracias y saludos

Estas comparando Strings no números. Ojo con eso.

Entonces, tengo que cambiar la variable string por otra o no tiene nada que ver con eso?

Tenés que convertir el texto a número, de otro modo, por ejemplo, "126" es menor a "16".

Métodos para convertir texto a número...

Saludos


#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir constantes
byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
int paso=0;
int randomNumber;
String valor = "";
int tecla;
const byte ROWS = 4; // Cuatro filas.
const byte COLS = 4; // Cuatro columnas.
char keys[ROWS][COLS] = {
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0'},
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

boolean blink = false;
void setup() {
  Serial.begin(9600);
  long valor;
   value = text.toInt();
   DEBUG(valor);
  pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
  digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A0));
  randomNumber = random(1, 100);

}

Esto no sería válido para pasarlo a número no?
Saludos

No sé a que te refieres.
Si te refieres a toInt() si, para eso sirve, como habrás leído en el artículo que te linkié.

El código que muestras está lleno de errores.
Debes tratar de entender lo que estás programando, copiar y pegar sin comprender muy pocas veces te va a llevar a algo que funcione (si es que tienes muchísima suerte).

Saludos

PD:
Algunos errores:
valor está declarada 2 veces, una como String y luego como long.
value no está declarada.
text no está declarada.
La macro DEBUG no está definida.
Y el código, en general, así como está no va ni siquiera a compilar.

Lo he intentado corregir y ahora si que me compila, aunque el programa además de estar continuamente parpadeando, siempre indica que hay que introducir un número menor. Adjunto código


#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir constantes

byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
int paso=0;
int randomNumber;
String valorar = "";
int tecla;
const byte ROWS = 4; // Cuatro filas.
const byte COLS = 4; // Cuatro columnas.
char keys[ROWS][COLS] = {
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0'},
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

boolean blink = false;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
  digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A0));
  randomNumber = random(1, 100);


}

void loop() {
  // Activamos el objeto display asociado a la pantalla OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  // Tamaño del texto
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("ADIVINA MI NUMERO");
  display.display();
char key = keypad.getKey();      // Captura una tecla del teclado.
//if (key) Serial.println(key);    // La muestra en el Monitor Serial
valorar = valorar + String(key); 
  Serial.println(valorar);
  Serial.println(randomNumber);

  valorar.toInt();

if (key =='#') {
  if(valorar>String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MENOR");
  display.display();
  delay(2000);
}

  if(valorar<String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("INTRODUCIR NUMERO MAYOR");
  display.display();
  delay(2000);
  
}
  if(valorar==String(randomNumber)){
  display.clearDisplay();
  display.setTextSize(1);
  // Color del texto
  display.setTextColor(SSD1306_WHITE);
  // Posición del texto
  display.setCursor(16, 30);
  // Escribir texto
  display.println("HAS GANADO");
  display.display();
}
}
}

Saludos

Ya me he dado cuenta de porque no para de parpadear.
Saludos

#include <Keypad.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Definir constantes
int paso1 = 0;
byte const ANCHO_PANTALLA = 128; // ancho pantalla OLED
byte const ALTO_PANTALLA = 64;   // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
int paso = 0;
int randomNumber;
String valor = "";
char Caracter[0];
int tecla;
const byte ROWS = 4; // Cuatro filas.
const byte COLS = 4; // Cuatro columnas.
char keys[ROWS][COLS] = {
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0'},
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; // Pines a los que se conectan las filas del teclado.
byte colPins[COLS] = {9, 8, 7, 6}; // Pines a los que se conectan las columnas.

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

boolean blink = false;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // Establece el pin del LED integrado como salida.
  digitalWrite(ledPin, HIGH);   // Enciende el LED
  randomSeed(analogRead(A2));

  // Activamos el objeto display asociado a la pantalla OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  randomNumber = random(1, 100);

}

void loop() {
  char key = keypad.getKey();      // Captura una tecla del teclado.
  //if (key) Serial.println(key);    // La muestra en el Monitor Serial
  valor = valor + String(key);
  Serial.println(valor);
  Serial.println(randomNumber);
  valor.toInt();

  switch ( paso1 ) {
    case 0:
      display.clearDisplay();
      display.setTextSize(1);
      // Color del texto
      display.setTextColor(SSD1306_WHITE);
      // Posición del texto
      display.setCursor(16, 30);
      // Escribir texto
      display.println("ADIVINA MI NUMERO");
      display.display();
      if (key == '#') {
        if (valor > String(randomNumber)) {
          paso1 = 1;
        }
        if (valor < String(randomNumber)) {
          paso1 = 2;
        }
        if (valor == String(randomNumber)) {
          paso1 = 3;
        }
        break;
      case 1:
        display.clearDisplay();
        display.setTextSize(1);
        // Color del texto
        display.setTextColor(SSD1306_WHITE);
        // Posición del texto
        display.setCursor(16, 30);
        // Escribir texto
        display.println("INTRODUCIR NUMERO MENOR");
        display.display();
        delay(2000);
        paso1 = 0;
        break;
      case 2:
        display.clearDisplay();
        display.setTextSize(1);
        // Color del texto
        display.setTextColor(SSD1306_WHITE);
        // Posición del texto
        display.setCursor(16, 30);
        // Escribir texto
        display.println("INTRODUCIR NUMERO MAYOR");
        display.display();
        delay(2000);
        paso1 = 0;
        break;
      case 3:
        display.clearDisplay();
        display.setTextSize(1);
        // Color del texto
        display.setTextColor(SSD1306_WHITE);
        // Posición del texto
        display.setCursor(16, 30);
        // Escribir texto
        display.println("HAS GANADO");
        display.display();
        delay(2000);
        valor = "";
        paso1 = 0;
        break;
      }
  }
}

He conseguido pasar a esto, aunque no se si estará mejor, peor o igual
Saludos