Se me vuelve loco este código - [SOLUCIONADO]

Buenas Arduiner@s:

Tengo qeste código usando una LCD Keypad Shield 16x2. Quiero lograr que enviando un comando en el monitor serie se apague y se encienda el Led 13, a parte que lo indica en mensaje en el LCD. No ocurre nada.

Otro fallo que no logro, que al pulsar los botones, como que se envía un bucle y no deja de hacerlo hasta que deje de pulsar, muestra todo mal en el LCD. Solo pulsar una vez un botón, sale resultados no esperados.

Por ejemplo, so pulso el botón arriba, tiene que mostrar en el LCD, la palabra ARRIBA.

Código:

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int lcd_key     = 0;
int adc_key_in  = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
int pinLed10 = 10; // Luz de fondo.
int pinLed13 =  13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

// Leeer todos los botones.
int read_LCD_buttons()
{
  adc_key_in = analogRead(0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (adc_key_in > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (adc_key_in < 50)   return botonDERECHO;
    if (adc_key_in < 250)  return botonARRIBA;
    if (adc_key_in < 450)  return botonABAJO;
    if (adc_key_in < 650)  return botonIZQUIERDA;
    if (adc_key_in < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (adc_key_in < 50)   return botonDERECHO;
  if (adc_key_in < 195)  return botonARRIBA;
  if (adc_key_in < 380)  return botonABAJO;
  if (adc_key_in < 555)  return botonIZQUIERDA;
  if (adc_key_in < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print("Arduino 2020");
  Serial.begin(115200);
}

void loop()
{
  // Esperando lectura botones.
  lcd_key = read_LCD_buttons();

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals("Led_13_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print("1");
    Serial.println("Led 13 encendido.");
  }

  if (comando.equals("Led_13_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print("0");
    Serial.println("Led 13 apagado.");
  }

  if (comando.equals("Led_10_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(9, 1);
    lcd.print("1");
    Serial.println("Led 10 encendido.");
  }

  if (comando.equals("Led_10_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(9, 1);
    lcd.print("0");
    Serial.println("Led 10 apagado.");
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  // Dependiendo de qué botón se presionó, realizamos una acción.
  switch (lcd_key)
  {
    case botonDERECHO:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        break;
      }
    case botonIZQUIERDA:
      {
        lcd.print("Izquierda");
        Serial.write("Izquierda.");
        break;
      }
    case botonARRIBA:
      {
        lcd.print("Arriba   ");
        Serial.write("Arriba.");
        break;
      }
    case botonABAJO:
      {
        lcd.print("Abajo    ");
        Serial.write("Abajo.");
        break;
      }
    case botonSELECT:
      {
        lcd.print("SELECT   ");
        Serial.write("SELECT");
        break;
      }
    case botonNADA:
      {
        //lcd.print("Nada     ");
        break;
      }
  }
}

¿Alguna idea?

Saludazos.

al pulsar los botones, como que se envía un bucle y no deja de hacerlo hasta que deje de pulsar, muestra todo mal en el LCD. Solo pulsar una vez un botón, sale resultados no esperados.

El loop siempre está ejecutándose infinitamente. Cuando tu pulsas un botón aunque solo sea un instante, al no tener en cuenta el estado anterior, ejecutará unas cuantas veces el código que se corresponde a cada tecla.

Convendría controlar el estado actual del botón teniendo en cuenta el anterior, así como un pequeñó debounce para prevenir los estados intermedios y falsas pulsaciones.

Por otro lado, veo algo que no sé si funcionará. Lees todo lo que llegue via serie, y posiblemente lo que mandes contenga un CR+LR al final. Por ejemplo si recibes "Led_13_ON\r\n" y comparas con "Led_13_ON" el resultado será falso. La función indexOf, te devuelve la posición de una cadena dentro de otra o -1 si está no existe dentro.

if ( Commando.indexOf("Led_13_ON")!=-1 ) {
  // codigo a realizar.
}

Por el momento es lo que veo en el código.

Hola:

Tienes razón, solo había que cambiar la parte del "Monitor serie" la opción, Sin ajuste de línea.

Captura.PNG

Ahor falta lo de corregir el bouncer ese de repeticiones. Curioso que lo saqué de este otro código parecido y no me da problemas.

#include <LiquidCrystal.h>

/*******************************************************

  This program will test the LCD panel and the buttons
  Mark Bramwell, July 2010

********************************************************/

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
int pinLed13 =  13;   // Declaramos la variable pin del Led.
int pinLed8 =  8;
int pinLed10 =  10; // Luz de fondo.
char caracter;
String comando;

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  // For V1.1 us this threshold
  /*
    if (adc_key_in < 50)   return btnRIGHT;
    if (adc_key_in < 250)  return btnUP;
    if (adc_key_in < 450)  return btnDOWN;
    if (adc_key_in < 650)  return btnLEFT;
    if (adc_key_in < 850)  return btnSELECT;
  */
  // For V1.0 comment the other threshold and use the one below:

  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;



  return btnNONE;  // when all others fail, return this...
}

void setup()
{
  lcd.begin(16, 2);              // start the library
  lcd.setCursor(0, 0);
  //lcd.print("Pulsa botones"); // print a simple message
  lcd.print("L8:  L10:  L13: ");
  lcd.setCursor(0, 1);
  lcd.print("AtoS 2016");  
  Serial.begin(115200);
  digitalWrite(pinLed10, HIGH);
}

void loop()
{
  //lcd.setCursor(13, 1);           // move cursor to second line "1" and 9 spaces over
  //lcd.print(millis() / 1000);    // display seconds elapsed since power-up


  lcd.setCursor(0, 1);           // move to the begining of the second line
  lcd_key = read_LCD_buttons();  // read the buttons

  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed8, OUTPUT);
  pinMode(pinLed10, OUTPUT);

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
      serie (mientras llegue algún dato allí), y los voy concatenando
      uno tras otro en una cadena. En la práctica, si usamos el
      "Serial monitor" el bucle while acabará cuando pulsemos Enter.
      El delay es conveniente para no saturar el canal serie y que la
      concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }

  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals("Led_13_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(15, 0);
    lcd.print("1");
    Serial.println("Led 13 encendido.");
  }

  if (comando.equals("Led_13_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(15, 0);
    lcd.print("0");
    Serial.println("Led 13 apagado.");
  }

  if (comando.equals("Led_8_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed8, HIGH); // Enciende el Led.
    lcd.setCursor(3, 0);
    lcd.print("1");
    Serial.println("Led 8 encendido.");
  }

  if (comando.equals("Led_8_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed8, LOW); // Apaga el Led.
    lcd.setCursor(3, 0);
    lcd.print("0");
    Serial.println("Led 8 apagado.");
  }

  if (comando.equals("Led_10_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(9, 0);
    lcd.print("1");
    Serial.println("Led 10 encendido.");
  }

  if (comando.equals("Led_10_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(9, 0);
    lcd.print("0");
    Serial.println("Led 10 apagado.");
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
    case btnRIGHT:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        break;
      }
    case btnLEFT:
      {
        lcd.print("Izquierda");
        Serial.write("Izquierda.");
        break;
      }
    case btnUP:
      {
        lcd.print("Arriba   ");
        Serial.write("Arriba.");
        break;
      }
    case btnDOWN:
      {
        lcd.print("Abajo    ");
        Serial.write("Abajo.");
        break;
      }
    case btnSELECT:
      {
        lcd.print("SELECT   ");
        Serial.write("SELECT");
        break;
      }
    case btnNONE:
      {
        //lcd.print("Nada     ");
        break;
      }
  }

}

Código actual de abajo, si me da problemas.

Algo no me cuadra.

Captura.PNG

¿El código del segundo post no da problemas? Lo veo y me parece que es el mismo código... Algun comentario en ingles y nombre de variable pero nada...

Eso es lo que no entiendo.

El mio actual es este y si da problemas de tipo antirebotes. No olvidar que la entrada que sua son unos cuantos pulsadores y modo analógico.

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int lcd_key     = 0;
int adc_key_in  = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
int pinLed10 = 10; // Luz de fondo.
int pinLed13 =  13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

// Leeer todos los botones.
int read_LCD_buttons()
{
  adc_key_in = analogRead(A0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (adc_key_in > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (adc_key_in < 50)   return botonDERECHO;
    if (adc_key_in < 250)  return botonARRIBA;
    if (adc_key_in < 450)  return botonABAJO;
    if (adc_key_in < 650)  return botonIZQUIERDA;
    if (adc_key_in < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (adc_key_in < 50)   return botonDERECHO;
  if (adc_key_in < 195)  return botonARRIBA;
  if (adc_key_in < 380)  return botonABAJO;
  if (adc_key_in < 555)  return botonIZQUIERDA;
  if (adc_key_in < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print("Arduino 2020");
  Serial.begin(115200);
}

void loop()
{
  // Esperando lectura botones.
  lcd_key = read_LCD_buttons();

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals("Led_13_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: ON ");
    Serial.println("Led 13 encendido.");
  }

  if (comando.equals("Led_13_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: OFF");
    Serial.println("Led 13 apagado.");
  }

  if (comando.equals("Led_10_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(14, 1);
    lcd.print("F1");
    Serial.println("Led 10 encendido.");
  }

  if (comando.equals("Led_10_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(14, 1);
    lcd.print("F0");
    Serial.println("Led 10 apagado.");
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  // Dependiendo de qué botón se presionó, realizamos una acción.
  switch (lcd_key)
  {
    case botonDERECHO:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        break;
      }
    case botonIZQUIERDA:
      {
        lcd.print("Izquierda");
        Serial.write("Izquierda.");
        break;
      }
    case botonARRIBA:
      {
        lcd.print("Arriba   ");
        Serial.write("Arriba.");
        break;
      }
    case botonABAJO:
      {
        lcd.print("Abajo    ");
        Serial.write("Abajo.");
        break;
      }
    case botonSELECT:
      {
        lcd.print("SELECT   ");
        Serial.write("SELECT");
        break;
      }
    case botonNADA:
      {
        //lcd.print("Nada     ");
        break;
      }
  }
}

Sigo sin encontrar el fallo.

Tenía la esperanza de cambiar este código.

adc_key_in = analogRead(0);

Por este otro.

adc_key_in = analogRead(A0);

Da exactamente lo mismo.

Saludos.

Hola:

Solucionado. Había que poner el cursor como indica aquí.

void loop()
{
  // Indicar posición.
  lcd.setCursor(0, 1);
  // Esperando lectura botones.
  lcd_key = read_LCD_buttons();

Código compmleto:

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int lcd_key     = 0;
int adc_key_in  = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
int pinLed10 = 10; // Luz de fondo.
int pinLed13 =  13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

// Leeer todos los botones.
int read_LCD_buttons()
{
  adc_key_in = analogRead(A0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (adc_key_in > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (adc_key_in < 50)   return botonDERECHO;
    if (adc_key_in < 250)  return botonARRIBA;
    if (adc_key_in < 450)  return botonABAJO;
    if (adc_key_in < 650)  return botonIZQUIERDA;
    if (adc_key_in < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (adc_key_in < 50)   return botonDERECHO;
  if (adc_key_in < 195)  return botonARRIBA;
  if (adc_key_in < 380)  return botonABAJO;
  if (adc_key_in < 555)  return botonIZQUIERDA;
  if (adc_key_in < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print("Arduino 2020");
  Serial.begin(115200);
}

void loop()
{
  // Indicar posición.
  lcd.setCursor(0, 1);
  // Esperando lectura botones.
  lcd_key = read_LCD_buttons();

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals("Led_13_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: ON ");
    Serial.println("Led 13 encendido.");
  }

  if (comando.equals("Led_13_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: OFF");
    Serial.println("Led 13 apagado.");
  }

  if (comando.equals("Led_10_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(14, 1);
    lcd.print("F1");
    Serial.println("Led 10 encendido.");
  }

  if (comando.equals("Led_10_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(14, 1);
    lcd.print("F0");
    Serial.println("Led 10 apagado.");
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  // Dependiendo de qué botón se presionó, realizamos una acción.
  switch (lcd_key)
  {
    case botonDERECHO:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        break;
      }
    case botonIZQUIERDA:
      {
        lcd.print("Izquierda");
        Serial.write("Izquierda.");
        break;
      }
    case botonARRIBA:
      {
        lcd.print("Arriba   ");
        Serial.write("Arriba.");
        break;
      }
    case botonABAJO:
      {
        lcd.print("Abajo    ");
        Serial.write("Abajo.");
        break;
      }
    case botonSELECT:
      {
        lcd.print("SELECT   ");
        Serial.write("SELECT");
        break;
      }
    case botonNADA:
      {
        //lcd.print("Nada     ");
        break;
      }
  }
}

Saludos.

Pensé que estaba resuelto el problema, pero no.

En el LCD se ve bien. En el monitor Serie se ve repetido muchas veces.

Captura.PNG

¿Hay algúntruco que no se repita de esa manera?

Solo quiero que se comporte como un buen botón normal y corriente.

Si pulso el botón Arriba. En el Monitor Serie se tiene que ver solo la palabra Arriba una vez, no mil cuarenta y cuatro de veces, Xddddddd.

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int teclaLCD = 0;
int teclaEntradaADC = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
int pinLed10 = 10; // Luz de fondo.
int pinLed13 =  13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

// Leeer todos los botones.
int leer_botones_del_LCD()
{
  teclaEntradaADC = analogRead(A0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (teclaEntradaADC > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (teclaEntradaADC < 50)   return botonDERECHO;
    if (teclaEntradaADC < 250)  return botonARRIBA;
    if (teclaEntradaADC < 450)  return botonABAJO;
    if (teclaEntradaADC < 650)  return botonIZQUIERDA;
    if (teclaEntradaADC < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (teclaEntradaADC < 50)   return botonDERECHO;
  if (teclaEntradaADC < 195)  return botonARRIBA;
  if (teclaEntradaADC < 380)  return botonABAJO;
  if (teclaEntradaADC < 555)  return botonIZQUIERDA;
  if (teclaEntradaADC < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print("Arduino 2020");
  Serial.begin(115200);
}

void loop()
{
  // Indicar posición.
  lcd.setCursor(0, 1);
  // Esperando lectura botones.
  teclaLCD = leer_botones_del_LCD();

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals("Led_13_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: ON ");
    Serial.println("Led 13 encendido.");
  }

  if (comando.equals("Led_13_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print("Led 13: OFF");
    Serial.println("Led 13 apagado.");
  }

  if (comando.equals("Led_10_ON") == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(14, 1);
    lcd.print("F1");
    Serial.println("Led 10 encendido.");
  }

  if (comando.equals("Led_10_OFF") == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(14, 1);
    lcd.print("F0");
    Serial.println("Led 10 apagado.");
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  // Dependiendo de qué botón se presionó, realizamos una acción.
  switch (teclaLCD)
  {
    case botonDERECHO:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        break;
      }
    case botonIZQUIERDA:
      {
        lcd.print("Izquierda");
        Serial.write("Izquierda.");
        break;
      }
    case botonARRIBA:
      {
        lcd.print("Arriba   ");
        Serial.write("Arriba.");
        break;
      }
    case botonABAJO:
      {
        lcd.print("Abajo    ");
        Serial.write("Abajo.");
        break;
      }
    case botonSELECT:
      {
        lcd.print("SELECT   ");
        Serial.write("SELECT");
        break;
      }
    case botonNADA:
      {
        //lcd.print("Nada     ");
        //Serial.write("Nada");
        break;
      }
  }
}

Intenté hacerlo hasta con if, pero ni eso.

  if (teclaLCD == botonDERECHO)
  {
    lcd.print("Derecha  ");
    Serial.write("Derecha.");
  }

Saludos.

Captura.PNG

Si, muy simple luego de ejecutar lo que leiste con teclaLCD simplemente ponle

teclaLCD = botonNADA;

como no lo cambias el sistema sigue mostrándolo por cada ciclo del loop.

No se donde dices.

No me funcona ponerlo aquí.

    case botonNADA:
      {
        lcd.print("Nada     ");
        Serial.write("Nada");
        teclaLCD = botonNADA;
        break;
      }

Ni ponerlo aquí.

    case botonDERECHO:
      {
        lcd.print("Derecha  ");
        Serial.write("Derecha.");
        teclaLCD = botonNADA;
        break;
      }

Ni al final del Switch.

Algo se me pasa.

Surge el mismo efecto.

Entonces cambia esto al final.

lcd_key = 6;

Se comporta igual.

De alguna manera hay que saber como se controla bien el LCD con el analógico A0 que incluye la placa. La gente maneja mucho el digital para botones, pero en analógico es otro mundo y no parece fácil.

De tanto buscar en San Google que acabé enterándome por primera vez optimización de la RAM, y mira que hace falta mucho para Arduino UNO.

Sin optimizar.

       lcd.print("SELECT   ");
        Serial.println("SELECT");

Optimizado. De la RAM se pasa a al Flash o memoria programa.

       lcd.print(F("SELECT   "));
        Serial.println(F("SELECT"));

Dejo el código completo.

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int teclaLCD = 0;
int teclaEntradaADC = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
#define pinLed10 10 // Luz de fondo.
#define pinLed13 13   // Declaramos la variable pin del Led.
char caracter;
String comando;

// Leer todos los botones.
int leer_botones_del_LCD()
{
  teclaEntradaADC = analogRead(A0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (teclaEntradaADC > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (teclaEntradaADC < 50)   return botonDERECHO;
    if (teclaEntradaADC < 250)  return botonARRIBA;
    if (teclaEntradaADC < 450)  return botonABAJO;
    if (teclaEntradaADC < 650)  return botonIZQUIERDA;
    if (teclaEntradaADC < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (teclaEntradaADC < 50)   return botonDERECHO;
  if (teclaEntradaADC < 195)  return botonARRIBA;
  if (teclaEntradaADC < 380)  return botonABAJO;
  if (teclaEntradaADC < 555)  return botonIZQUIERDA;
  if (teclaEntradaADC < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print(F("Arduino 2020"));
  Serial.begin(115200);
}

void loop()
{
  // Indicar posición.
  lcd.setCursor(0, 1);
  // Esperando lectura botones.
  teclaLCD = leer_botones_del_LCD();

  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals(F("Led_13_ON")) == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print(F("Led 13: ON "));
    Serial.println(F("Led 13 encendido."));
  }

  if (comando.equals(F("Led_13_OFF")) == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print(F("Led 13: OFF"));
    Serial.println(F("Led 13 apagado."));
  }

  if (comando.equals(F("Led_10_ON")) == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(14, 1);
    lcd.print(F("F1"));
    Serial.println(F("Led 10 encendido."));
  }

  if (comando.equals(F("Led_10_OFF")) == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(14, 1);
    lcd.print(F("F0"));
    Serial.println(F("Led 10 apagado."));
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

  // Dependiendo de qué botón se presionó, realizamos una acción.
  switch (teclaLCD)
  {
    case botonDERECHO:
      {
        lcd.print(F("Derecha  "));
        Serial.println(F("Derecha."));
        break;
      }
    case botonIZQUIERDA:
      {
        lcd.print(F("Izquierda"));
        Serial.println(F("Izquierda."));
        break;
      }
    case botonARRIBA:
      {
        lcd.print(F("Arriba   "));
        Serial.println(F("Arriba."));
        break;
      }
    case botonABAJO:
      {
        lcd.print(F("Abajo    "));
        Serial.println(F("Abajo."));
        break;
      }
    case botonSELECT:
      {
        lcd.print(F("SELECT   "));
        Serial.println(F("SELECT"));
        break;
      }
    case botonNADA:
      {
        //lcd.print("Nada     ");
        //Serial.write("Nada");
        break;
      }
  }
  teclaLCD = 6; // Sigue igual.
}

Me he ahorrado.
El Sketch usa 5106 bytes (15%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 486 bytes (23%) de la memoria dinámica, dejando 1562 bytes para las variables locales. El máximo es 2048 bytes.

Frente ahora.
El Sketch usa 5454 bytes (16%) del espacio de almacenamiento de programa. El máximo es 32256 bytes.
Las variables Globales usan 242 bytes (11%) de la memoria dinámica, dejando 1806 bytes para las variables locales. El máximo es 2048 bytes.

Se nota el cambio.

Saludos.

PD: Siempre aprendo algo nuevo antes de dormir.

Resuelto:

#include <LiquidCrystal.h>

// Seleccionado los pines del LCD.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Definir algunos valores utilizados por el LCD y los botones.
int teclaLCD = 0;
int teclaEntradaADC = 0;
#define botonDERECHO 0
#define botonARRIBA 1
#define botonABAJO 2
#define botonIZQUIERDA 3
#define botonSELECT 4
#define botonNADA 5
#define pinLed10 10 // Luz de fondo.
#define pinLed13 13   // Declaramos la variable pin del Led.
char caracter;
String comando;
int teclaAnt = 0;

// Leer todos los botones.
int leer_botones_del_LCD() {
  teclaEntradaADC = analogRead(A0); //Leer el valor desde el sensor.
  // Los botones cuando se leen están centrados en estos valores: 0, 144, 329, 504, 741.
  // Agregamos aproximadamente 50 a esos valores y verificamos si estamos cerca.

  // Hacemos de esta la primera opción por razones de velocidad,
  // ya que será el resultado más probable.
  if (teclaEntradaADC > 1000) return botonNADA;
  // Para V1.1 nosotros este umbral.
  /*
    if (teclaEntradaADC < 50)   return botonDERECHO;
    if (teclaEntradaADC < 250)  return botonARRIBA;
    if (teclaEntradaADC < 450)  return botonABAJO;
    if (teclaEntradaADC < 650)  return botonIZQUIERDA;
    if (teclaEntradaADC < 850)  return botonSELECT;
  */
  // Para V1.0, comente el otro umbral y use el siguiente:

  if (teclaEntradaADC < 50)   return botonDERECHO;
  if (teclaEntradaADC < 195)  return botonARRIBA;
  if (teclaEntradaADC < 380)  return botonABAJO;
  if (teclaEntradaADC < 555)  return botonIZQUIERDA;
  if (teclaEntradaADC < 790)  return botonSELECT;

  return botonNADA;  // Cuando todos los demás fallan, devuelve esto ...
}
void setup()
{
  pinMode(pinLed13, OUTPUT);
  pinMode(pinLed10, OUTPUT);
  digitalWrite(pinLed10, HIGH); // Dejar encendido luz de fondo.
  lcd.begin(16, 2); // LCD de 16x2.
  lcd.setCursor(0, 0);
  lcd.print(F("Arduino 2020"));
  Serial.begin(115200);
}

void loop()
{
 


  /* Voy leyendo carácter a carácter lo que se recibe por el canal
    serie (mientras llegue algún dato allí), y los voy concatenando
    uno tras otro en una cadena. En la práctica, si usamos el
    "Serial monitor" el bucle while acabará cuando pulsemos Enter.
    El delay es conveniente para no saturar el canal serie y que la
    concatenación se haga de forma ordenada.
  */
  while (Serial.available() > 0)
  {
    caracter = Serial.read();
    comando.concat(caracter);
    delay(10);
  }
  /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago
     que la placa Arduino reaccione según sea este. Aquí podríamos
     hacer lo que quiesiéramos: si el comando es "tal", enciende
     un Led, si es cual, mueve un motor... y así.
  */
  if (comando.equals(F("Led_13_ON")) == true)  // Led_ON.
  {
    digitalWrite(pinLed13, HIGH); // Enciende el Led.
    lcd.setCursor(0, 1);
    lcd.print(F("Led 13: ON "));
    Serial.println(F("Led 13 encendido."));
  }

  if (comando.equals(F("Led_13_OFF")) == true) // Led_OFF.
  {
    digitalWrite(pinLed13, LOW); // Apaga el Led.
    lcd.setCursor(0, 1);
    lcd.print(F("Led 13: OFF"));
    Serial.println(F("Led 13 apagado."));
  }

  if (comando.equals(F("Led_10_ON")) == true)  // Led_ON.
  {
    digitalWrite(pinLed10, HIGH); // Enciende el Led.
    lcd.setCursor(14, 1);
    lcd.print(F("F1"));
    Serial.println(F("Led 10 encendido."));
  }

  if (comando.equals(F("Led_10_OFF")) == true) // Led_OFF.
  {
    digitalWrite(pinLed10, LOW); // Apaga el Led.
    lcd.setCursor(14, 1);
    lcd.print(F("F0"));
    Serial.println(F("Led 10 apagado."));
  }
  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";
  
  // Indicar posición.
  lcd.setCursor(0, 1);
  // Esperando lectura botones.
  teclaLCD = leer_botones_del_LCD();
  if (teclaLCD != teclaAnt) {
      // Dependiendo de qué botón se presionó, realizamos una acción.
      switch (teclaLCD) {
        case botonDERECHO:
          {
            lcd.print(F("Derecha  "));
            Serial.println(F("Derecha."));
            break;
          }
        case botonIZQUIERDA:
          {
            lcd.print(F("Izquierda"));
            Serial.println(F("Izquierda."));
            break;
          }
        case botonARRIBA:
          {
            lcd.print(F("Arriba   "));
            Serial.println(F("Arriba."));
            break;
          }
        case botonABAJO:
          {
            lcd.print(F("Abajo    "));
            Serial.println(F("Abajo."));
            break;
          }
        case botonSELECT:
          {
            lcd.print(F("SELECT   "));
            Serial.println(F("SELECT"));
            break;
          }
        case botonNADA:
          {
            //lcd.print("Nada     ");
            //Serial.write("Nada");
            break;
          }
      }  
  }
  teclaAnt = teclaLCD;
}

Buenas:

Muchísimas gracias, si que estaba traumatizado.

Dejar claro que:

Serial.write(F("Nada"));

No funciona el F, una pena.

Si lo hace con:

Serial.print(F("Nada"));

¿Todavía no hay un Arduino UNO que sea más potente que el ATmega328P?

Saludos.

Diferencias entre write y print:

  • write escribe un byte, y solo un byte, por lo tanto no puedes pasarle una FlashString como parámetro.
  • print esta sobrecargada para funcionar con varios tipos de datos: enteros, caracteres, floats y cadenas.

El Arduino Uno se caracteriza porque está basado en un atMega328p. Si lleva otro microcontrolador se llamará de otra forma. Si te refieres al factor de forma (mismo tamaño de placa), está el Leonardo, que no es mucho más potente, pero si tiene otros perifericos y se basa en el atMega32u4. También está el arduino 101 que se baja en un procesador Intel Curie a 32MHz con 196K de Flash y 24 de SRAM. Solo basta hacer una busqueda en google poniendo alternativas a arduino uno y hay varios. O el bicho mas raro que he visto hasta ahora, el 86Duino Zero, que nos pone un procesador Vortex86EX (arquitectura PC, como un pentium) a 300 MHz con 128 MB de RAM (la version + tiene 1GB)...

¿El código que te pasó Surbyte solucionó el problema?

Gracias por la información.

Sí, ya le puse SOLUCINADO en el tema principal.

En cuanto a procesadores, ufffff, para eso está el famoso y popular el de siempre, jejejej.

Lo malo que non es lo mismo una placa con SO (RP) que otra placa solo con Firmware (Arduino)

Saludos.