Code Logic Correction

I'm making a project about a "bomb", however I'm having a problem with the part of the code that concerns writing the deactivation code, the part of the code that concerns that is between lines 200 to 227.
The error it's giving me is that when I'm on the code selection screen I can't write any numbers. Can anyone help me?

#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

LiquidCrystal_I2C lcd(0x20, 16, 2);

const byte numLinhas = 4;
const byte numColunas = 4;

char teclas[numLinhas][numColunas] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

byte pinosLinhas[numLinhas] = { 9, 8, 7, 6 };
byte pinosColunas[numColunas] = { 5, 4, 3, 2 };

Keypad meuTeclado = Keypad(makeKeymap(teclas), pinosLinhas, pinosColunas, numLinhas, numColunas);

enum Estado {
  MENU,
  TEMPO1,
  BOMBA_ARMADA_CHAVE,
  BOMBA_DESARMADA_CHAVE,
  TEMPO2,
  BOMBA_ARMADA_BOTAO,
  BOMBA_DESARMADA_BOTAO,
  CODIGO,
  TEMPO3,
  BOMBA_ARMADA_CODIGO,
  BOMBA_DESARMADA_CODIGO,
  BUZZER
};

Estado estadoAtual = MENU;

int modo = 0;

char traco1 = '-';
char traco2 = '-';
char traco3 = '-';
char traco4 = '-';

char digito1 = '-';
char digito2 = '-';
char digito3 = '-';
char digito4 = '-';
char digito5 = '-';

int horas = 0;
int minutos = 0;
int segundos = 0;

int flag = 0;

unsigned long tempoAnterior = 0;
unsigned long tempoAnteriorBuzzer = 0;
const long intervalo = 1000;
const long intervaloBuzzerCurto = 500;

#define CHAVE 10
#define PINO_BUZZER 11
#define BOTAO 12

bool bombaArmada = false;
bool botaoPressionado = false;
bool buzzerAtivo = true;  // Inicia com o buzzer ativado

void setup() {
  lcd.init();
  lcd.clear();
  lcd.backlight();
  pinMode(CHAVE, INPUT);
  pinMode(PINO_BUZZER, OUTPUT);
  pinMode(BOTAO, INPUT);
}

void loop() {
  unsigned long tempoAtual = millis();
  char tecla = meuTeclado.getKey();

  if (tecla == '*') {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Selecione o modo");
    modo = 0;
    estadoAtual = MENU;
    traco1 = '-';
    traco2 = '-';
    traco3 = '-';
    traco4 = '-';
    digito1 = '-';
    digito2 = '-';
    digito3 = '-';
    digito4 = '-';
    digito5 = '-';
    noTone(PINO_BUZZER);
    delay(500);
  }

  if (estadoAtual == MENU) {
    lcd.setCursor(0, 0);
    lcd.print("Selecione o modo");

    if (tecla != NO_KEY) {
      if (tecla >= '0' && tecla <= '9') {
        modo = modo * 10 + (tecla - '0');
        lcd.setCursor(0, 1);
        lcd.print(modo);  // Exibe imediatamente o número digitado
      } else if (tecla == '#') {
        lcd.setCursor(0, 1);  // Move o cursor para a segunda linha
        if (modo == 1) {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Tempo: ");
          lcd.setCursor(7, 0);
          lcd.print(traco1);
          lcd.print(traco2);
          lcd.print(":");
          lcd.print(traco3);
          lcd.print(traco4);
          estadoAtual = TEMPO1;
        } else if (modo == 2) {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Tempo: ");
          lcd.setCursor(7, 0);
          lcd.print(traco1);
          lcd.print(traco2);
          lcd.print(":");
          lcd.print(traco3);
          lcd.print(traco4);
          estadoAtual = TEMPO2;
        } else if (modo == 3) {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Tempo: ");
          lcd.setCursor(7, 0);
          lcd.print(traco1);
          lcd.print(traco2);
          lcd.print(":");
          lcd.print(traco3);
          lcd.print(traco4);
          estadoAtual = TEMPO3;
        } else if (modo == 11) {
          lcd.clear();
          lcd.setCursor(5, 0);
          lcd.print("BUZZER");
          lcd.setCursor(2, 1);
          lcd.print("1-ON  2-OFF");
          estadoAtual = BUZZER;
        } else {
          // Se o modo for inválido, resetar para o menu
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Selecione o modo");
          modo = 0;
          lcd.setCursor(0, 1);
          lcd.print(" ");
        }
      }
    }
  } else if (estadoAtual == TEMPO1 || estadoAtual == TEMPO2 || estadoAtual == TEMPO3) {
    if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
      if (traco1 == '-') {
        traco1 = tecla;
      } else if (traco2 == '-') {
        traco2 = tecla;
      } else if (traco3 == '-') {
        traco3 = tecla;
      } else if (traco4 == '-') {
        traco4 = tecla;
      }

      lcd.setCursor(7, 0);
      lcd.print(traco1);
      lcd.setCursor(8, 0);
      lcd.print(traco2);
      lcd.setCursor(9, 0);
      lcd.print(":");
      lcd.setCursor(10, 0);
      lcd.print(traco3);
      lcd.setCursor(11, 0);
      lcd.print(traco4);

    } else if (tecla == '#' && estadoAtual == TEMPO1 || estadoAtual == TEMPO2) {
      horas = (traco1 - '0') * 10 + (traco2 - '0');
      minutos = (traco3 - '0') * 10 + (traco4 - '0');
      segundos = 0;
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Bomba armada");
      if (estadoAtual == TEMPO1) {
        estadoAtual = BOMBA_ARMADA_CHAVE;
      } else {
        estadoAtual = BOMBA_ARMADA_BOTAO;
      }
    } else if (tecla == '#' && estadoAtual == TEMPO3) {
      if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
        if (digito1 == '-') {
          digito1 = tecla;
        } else if (digito2 == '-') {
          digito2 = tecla;
        } else if (digito3 == '-') {
          digito3 = tecla;
        } else if (digito4 == '-') {
          digito4 = tecla;
        } else if (digito5 == '-') {
          digito5 = tecla;
        }
      }
      lcd.setCursor(0, 1);
      lcd.print("Codigo:");
      lcd.setCursor(8, 1);
      lcd.print(digito1);
      lcd.setCursor(9, 1);
      lcd.print(digito2);
      lcd.setCursor(10, 1);
      lcd.print(digito3);
      lcd.setCursor(11, 1);
      lcd.print(digito4);
      lcd.setCursor(12, 1);
      lcd.print(digito5);
      estadoAtual = CODIGO;
    }

  } else if (estadoAtual == BOMBA_ARMADA_CHAVE || estadoAtual == BOMBA_ARMADA_BOTAO) {
    bool desativaBomba = false;

    if (estadoAtual == BOMBA_ARMADA_CHAVE) {
      if (digitalRead(CHAVE) == HIGH) {
        desativaBomba = true;
      }
    } else if (estadoAtual == BOMBA_ARMADA_BOTAO) {
      if (digitalRead(BOTAO) == LOW) {
        botaoPressionado = true;
      }
      if (botaoPressionado && digitalRead(BOTAO) == HIGH) {
        desativaBomba = true;
      }
    }

    if (desativaBomba) {
      if (horas == 0 && minutos == 0 && segundos == 0) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Tempo esgotado!");
        delay(2000);
      } else {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Bomba desarmada");
        if (estadoAtual == BOMBA_ARMADA_CHAVE) {
          estadoAtual = BOMBA_DESARMADA_CHAVE;
        } else {
          estadoAtual = BOMBA_DESARMADA_BOTAO;
        }
        if (buzzerAtivo) {
          noTone(PINO_BUZZER);
        }
        delay(500);
      }
      botaoPressionado = false;
    } else {
      if (tempoAtual - tempoAnterior >= intervalo) {
        tempoAnterior = tempoAtual;

        if (segundos > 0) {
          segundos--;
        } else {
          if (minutos > 0) {
            minutos--;
            segundos = 59;
          } else {
            if (horas > 0) {
              horas--;
              minutos = 59;
              segundos = 59;
            } else {
              horas = 0;
              minutos = 0;
              segundos = 0;
              bombaArmada = true;
              if (buzzerAtivo) {
                tone(PINO_BUZZER, 1000);
              }
            }
          }
        }

        lcd.setCursor(4, 1);
        if (horas < 10) lcd.print('0');
        lcd.print(horas);
        lcd.print(":");
        if (minutos < 10) lcd.print('0');
        lcd.print(minutos);
        lcd.print(":");
        if (segundos < 10) lcd.print('0');
        lcd.print(segundos);
      }

      if (horas == 0 && minutos == 0 && segundos == 0) {
        if (buzzerAtivo) {
          tone(PINO_BUZZER, 1000);
        }
      } else if (horas == 0 && minutos < 10) {
        if (tempoAtual - tempoAnteriorBuzzer >= intervaloBuzzerCurto) {
          tempoAnteriorBuzzer = tempoAtual;
          if (buzzerAtivo) {
            tone(PINO_BUZZER, 1000);
            delay(100);
            noTone(PINO_BUZZER);
          }
        }
      } else {
        if (tempoAtual - tempoAnteriorBuzzer >= intervalo) {
          tempoAnteriorBuzzer = tempoAtual;
          if (buzzerAtivo) {
            tone(PINO_BUZZER, 1000);
            delay(100);
            noTone(PINO_BUZZER);
          }
        }
      }
    }
  } else if (estadoAtual == BOMBA_DESARMADA_CHAVE || estadoAtual == BOMBA_DESARMADA_BOTAO) {
    if (tecla == '*') {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Selecione o modo");
      estadoAtual = MENU;
      delay(500);
    }
  } else if (estadoAtual == BUZZER) {
    if (tecla == '1') {
      buzzerAtivo = true;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Buzzer ON");
      delay(1000);
      estadoAtual = MENU;
      modo = 0;  
    } else if (tecla == '2') {
      buzzerAtivo = false;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Buzzer OFF");
      delay(1000);
      estadoAtual = MENU;
      modo = 0;  
    }
  }
}

It looks like Spanish comments in the code. Why not post in the Spanish section?

    } else if (tecla == '#' && estadoAtual == TEMPO3) {
      if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {

How could tecla be between '0' and '9' when it needs to be '#' to reach the test for a numeric value ?

I am Portuguese and the Portuguese community is much smaller than the English one.

Because the key only needs to be between 0 and 9 after I press the #, I had already done another part of the code to select the time, in which I used the same logic, and it is working.

But once you press the # key the value can never be between '0' and '9' because it is already '#'

You do not read the keypad again after detecting the '#'

if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
        if (digito1 == '-') {
          digito1 = tecla;
        } else if (digito2 == '-') {
          digito2 = tecla;
        } else if (digito3 == '-') {
          digito3 = tecla;
        } else if (digito4 == '-') {
          digito4 = tecla;
        } else if (digito5 == '-') {
          digito5 = tecla;
        }
      }

This part of the code does the following, when I press the # it will only detect the keypad keys from 0 to 9 and then take 5 readings to assign each value to each digit.
I'm not completely sure if this part of reading the pressed keys is ok, however I had already done a similar thing to write the time using the same logic.

Part of the code to select time:

else if (estadoAtual == TEMPO1 || estadoAtual == TEMPO2 || estadoAtual == TEMPO3) {
    if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
      if (traco1 == '-') {
        traco1 = tecla;
      } else if (traco2 == '-') {
        traco2 = tecla;
      } else if (traco3 == '-') {
        traco3 = tecla;
      } else if (traco4 == '-') {
        traco4 = tecla;
      }

      lcd.setCursor(7, 0);
      lcd.print(traco1);
      lcd.setCursor(8, 0);
      lcd.print(traco2);
      lcd.setCursor(9, 0);
      lcd.print(":");
      lcd.setCursor(10, 0);
      lcd.print(traco3);
      lcd.setCursor(11, 0);
      lcd.print(traco4);

    }

How can it do that ?

Here are a couple of lines of your code formatted to show the structure better and with my added comments

        else if (tecla == '#' && estadoAtual == TEMPO3)  //at this point we know that tecla is '#'
        {
            if (tecla != NO_KEY && tecla >= '0' && tecla <= '9')    //so how can it be between '0' amd '9' ?

I still don't really understand what you're trying to explain because to me that part is making sense, I also don't understand much about code. Can you give me an idea of ​​how I can get this part of the code to work correctly?

I don't know how I can make it any clearer

You read the keypad and test whether the '#' is pressed. If so then you need to read the keypad and test for numbers being entered, but your code does not read the keypad again before testing for numbers

But the "tecla != NO_KEY" part doesn't check if any key was pressed?

tecla != NO_KEY will return true if a key is pressed and we already know that tecla equals '#' so it will return true.

As I have said many times before, if tecla equals '#' then how could it ever equal a value between '0' and '9' at the same time ?

The keypad is only read once in your code, right at the start of the loop() function and that sets the value of tecla

Ok I understand now, I thought the tecla != NO_KEY was to read the keypad, but how can I read the keypad again?

I suspect that the best way forward would be to write the program with a completely different structure known as a finite state machine. What that involves is listing all of the states that the program can be in and writing code for each of them that will only be executed when it is in that state.

For instance, you might have a state waiting for a user to enter a command. One command might be that they enter '#'. When they do that the state changes to one that gets user numerical input until they enter something that end numerical input or maybe that a certain number of numbers has been entered. Then the program would move to a state where the entered number is evaluated. If it is correct then "bomb" is disarmed, otherwise it is exploded

Can you see that by doing things this way the code relevant to the current state is executed ? Of course, you might have an overall timer so that if they program stays in the number entry state for too long the "bomb" explodes and to make things interesting you could display a countdown timer

If you are going down this route then you need to explain exactly how the program works. What starts the defusing process, what stops it, can the user edit numbers already entered, etc, etc

I realise that is a long and daunting answer but to answer your specific question

You need this

    char tecla = meuTeclado.getKey();

for each digit that is to be entered, preferably in a loop of some kind until the number has been entered

Can you give me an example of a simple code that uses the finite state machine structure?

I see delays that eat more cpu cycles than the whole uses to run.
They potentially block sensing key entry, I did not check when they are called and won't waste my time trying to find out.

If you unblock the sketch, you can make the keypad code run in parralel with the rest of the code and always be reading the keypad instead of where in the monolith you have it is permitted.

If you do that then the deactivation code can also always be working to flag the countdown, make it stop.

Having one big block of code makes an execution maze that has to be figured out for everything big or small. Having multiple tasks that run independently lets you approach the program by what function each piece does without what else must happen to let any section run.

I would start by converting the delays to millis-timers and any long loops to run one iteration per void loop() execution and then break out Input, Process and Output into independent tasks that signal each other through variables.

This is not necessarily simple but it illustrates the principle of code staying in a state until something happens to make it move to a different state

Read the comments at the top to understand what it should do in each state

/*
State Machine example
Test system :
2 inputs normally held HIGH using INPUT_PULLUP in pinMode()
2 digital outputs (active LOW)

States :
IDLE
    apparently do nothing.  Actually busy doing nothing
      move to LED_ZERO_ON_10_SECS if inputPins[0] becomes LOW

LED_ZERO_ON_10_SECS
    turn LED 0 on for 10 seconds
      move to BLINK_LED_ONE if 10 second period elapses
      move to ALTERNATE_LEDS if inputPins[1] becomes LOW during the period

BLINK_LED_ONE
    blink LED 1
      move to LED_ZERO_ON_10_SECS if inputPins[0] becomes LOW
      move to IDLE if input 1 becomes LOW

ALTERNATE_LEDS
    turn each LED on and off in turn
    move to IDLE if inputPins[1] becomes LOW
*/

//global variables
enum STATES   //give the states some names
{
  IDLE,
  LED_ZERO_ON_10_SECS,
  BLINK_LED_ONE,
  ALTERNATE_LEDS
};
byte currentState = IDLE;

const byte inputPins[] = {A1, A2};
const byte NUMBER_OF_INPUTS = sizeof(inputPins) / sizeof(inputPins[0]);
const byte ledPins[] = {3, 5};
const byte NUMBER_OF_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);
byte currentInputStates[] = {HIGH, HIGH};
byte previousInputStates[] = {HIGH, HIGH};
byte currentLed = 0;    //index to the current LED when blinking them alternately
unsigned long currentTime;    //time at start of loop() for states using timing
unsigned long startTime;  //used in states requiring timing
unsigned long period;   //used when timing
boolean messageDone = false;    //flag to control message printing

void setup()
{
  Serial.begin(115200);
  for (int pin = 0; pin < NUMBER_OF_INPUTS; pin++)
  {
    pinMode(inputPins[pin], INPUT_PULLUP);
  }
  for (int pin = 0; pin < NUMBER_OF_LEDS; pin++)
  {
    pinMode(ledPins[pin], OUTPUT);
    digitalWrite(ledPins[pin], HIGH); //turn off the LEDs
  }
}

void loop()
{
  currentTime = millis();   //in case it is needed for the current or target state
  switch (currentState)     //execute code for the current state
  {
    case IDLE:
      if (!messageDone)
      {
        showState("In state IDLE.\nTake pin A1 LOW to move to LED_ZERO_ON_10_SECS");
      }
      previousInputStates[0] = currentInputStates[0];
      currentInputStates[0] = digitalRead(inputPins[0]);
      if (currentInputStates[0] != previousInputStates[0] && currentInputStates[0] == LOW)  //input 0 has gone LOW
      {
        startTime = currentTime;    //ready to start timing in target state
        currentState = LED_ZERO_ON_10_SECS;
        period = 10000;
        digitalWrite(ledPins[0], LOW);  //turn on LED 0
        Serial.println(F("Moving to state LED_ZERO_ON_10_SECS"));
        messageDone = false;
      }
      break;
    //
    case LED_ZERO_ON_10_SECS:
      if (!messageDone)
      {
        showState("In state LED_ZERO_ON_10_SECS.\nProgram will appear to pause for 10 seconds then move to BLINK_LED_ONE\nor take pin A2 LOW to move to alternate LED flashing");
      }
      if (currentTime - startTime >= period)  //has the perioed elapsed ?
      {
        digitalWrite(ledPins[0], HIGH);  //turn off LED 0
        startTime = currentTime;        //ready to start timing in target state
        currentState = BLINK_LED_ONE;   //state to move to
        period = 100;   //blink period for new state
        Serial.println(F("Time's up\nMoving to state BLINK_LED_ONE"));
        messageDone = false;
      }
      previousInputStates[1] = currentInputStates[1];
      currentInputStates[1] = digitalRead(inputPins[1]);
      if (currentInputStates[1] != previousInputStates[1] && currentInputStates[1] == LOW)  //input 1 has gone LOW
      {
        digitalWrite(ledPins[1], HIGH);  //turn off both LEDs
        digitalWrite(ledPins[0], HIGH);  //turn off both LEDs
        currentState = ALTERNATE_LEDS;
        Serial.println(F("Moving to state ALTERNATE_LEDS"));
        startTime = currentTime;
        period = 100;
        messageDone = false;
      }
      break;
    //
    case BLINK_LED_ONE:
      if (!messageDone)
      {
        showState("In state BLINK_LED_ONE\nTake pin A1 LOW to move to LED_ZERO_ON_10_SECS\nTake pin A2 LOW to move to IDLE");
      }
      if (currentTime - startTime >= period)  //time to change LED output
      {
        digitalWrite(ledPins[1], !digitalRead(ledPins[1]));
        startTime = currentTime;
      }
      previousInputStates[0] = currentInputStates[0];
      currentInputStates[0] = digitalRead(inputPins[0]);
      if (currentInputStates[0] != previousInputStates[0] && currentInputStates[0] == LOW)  //input 0 has gone LOW
      {
        digitalWrite(ledPins[0], LOW);  //turn on LED 0
        digitalWrite(ledPins[1], HIGH);  //turn off LED 1
        period = 10000;
        startTime = currentTime;    //ready to start timing in target state
        currentState = LED_ZERO_ON_10_SECS;
        Serial.println(F("Moving to state LED_ZERO_ON_10_SECS"));
        messageDone = false;
      }
      previousInputStates[1] = currentInputStates[1];
      currentInputStates[1] = digitalRead(inputPins[1]);
      if (currentInputStates[1] != previousInputStates[1] && currentInputStates[1] == LOW)  //input 1 has gone LOW
      {
        digitalWrite(ledPins[1], HIGH);  //turn off LED 1
        currentState = IDLE;
        Serial.println(F("Moving to state IDLE"));
        messageDone = false;
      }
      break;
    //
    case ALTERNATE_LEDS:
      if (!messageDone)
      {
        showState("In state ALTERNATE_LEDS\nTake pin A2 LOW to move to IDLE");
      }
      if (currentTime - startTime >= period)  //time to change LEDs
      {
        digitalWrite(ledPins[currentLed], HIGH);  //turn off the current LED
        currentLed++;
        currentLed %= 2;  //next LED or back to zero
        digitalWrite(ledPins[currentLed], LOW);  //turn on the new current LED
        startTime = currentTime;
      }
      previousInputStates[1] = currentInputStates[1];
      currentInputStates[1] = digitalRead(inputPins[1]);
      if (currentInputStates[1] != previousInputStates[1] && currentInputStates[1] == LOW)  //input 1 has gone LOW
      {
        digitalWrite(ledPins[1], HIGH);  //turn off both LEDs
        digitalWrite(ledPins[0], HIGH);  //turn off both LEDs
        currentState = IDLE;
        Serial.println(F("Moving to state IDLE"));
        messageDone = false;
      }
  }
}

void showState(const char * message)
{
  Serial.println();
  Serial.println(message);
  messageDone = true;
}


1 Like

I was looking at the example code you gave me, but I didn't understand some things that were there. I tried to make a code just for mode 1, can you point out the errors or if possible, correct it.
Code:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>

enum STATES {
  MENU,
  TEMPO1,
  BOMBA_ARMADA_CHAVE,
  BOMBA_DESARMADA_CHAVE
};
byte estadoAtual = MENU;

const byte rows = 4;
const byte cols = 4;
char keys[rows][cols] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[rows] = {9, 8, 7, 6};
byte colPins[cols] = {5, 4, 3, 2};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

LiquidCrystal_I2C lcd(0x20, 16, 2);

char modo = '-';
char tempoHora1 = '-', tempoHora2 = '-', tempoMin1 = '-', tempoMin2 = '-';
unsigned long startTime, currentTime;
int tempoTotal;
bool chaveAtivada = false;

#define CHAVE_PIN 10
#define BUZZER_PIN 11

void setup() {
  pinMode(CHAVE_PIN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);
  lcd.init();
  lcd.clear();
  lcd.backlight();
  Serial.begin(9600);
  lcd.print("Selecione o modo");
}

void loop() {
  char tecla = keypad.getKey();
  currentTime = millis();

  switch (estadoAtual) {
    case MENU:
      if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
        modo = tecla;
        lcd.clear();
        lcd.print("Selecione o modo");
        lcd.setCursor(0, 1);
        lcd.print(modo);
      }
      if (tecla == '#') {
        estadoAtual = TEMPO1;
        lcd.clear();
        lcd.print("Tempo: --:--");
      }
      if (tecla == '*') {
        lcd.clear();
        lcd.print("Selecione o modo");
        modo = '-';
        estadoAtual = MENU;
      }
      break;

    case TEMPO1:
      if (tecla != NO_KEY && tecla >= '0' && tecla <= '9') {
        if (tempoHora1 == '-') {
          tempoHora1 = tecla;
        } else if (tempoHora2 == '-') {
          tempoHora2 = tecla;
        } else if (tempoMin1 == '-') {
          tempoMin1 = tecla;
        } else if (tempoMin2 == '-') {
          tempoMin2 = tecla;
        }

        lcd.setCursor(7, 0);
        lcd.print(tempoHora1);
        lcd.setCursor(8, 0);
        lcd.print(tempoHora2);
        lcd.setCursor(9, 0);
        lcd.print(':');
        lcd.setCursor(10, 0);
        lcd.print(tempoMin1);
        lcd.setCursor(11, 0);
        lcd.print(tempoMin2);
      }
      if (tecla == '#') {
        estadoAtual = BOMBA_ARMADA_CHAVE;
        lcd.clear();
        lcd.setCursor((16 - 11) / 2, 0);
        lcd.print("Bomba armada");
        startTime = millis();
        tempoTotal = (((tempoHora1 - '0') * 10 + (tempoHora2 - '0')) * 60 + (tempoMin1 - '0') * 10 + (tempoMin2 - '0')) * 60;
      }
      if (tecla == '*') {
        estadoAtual = MENU;
        lcd.clear();
        lcd.print("Selecione o modo");
        modo = '-';
        tempoHora1 = tempoHora2 = tempoMin1 = tempoMin2 = '-';
      }
      break;

    case BOMBA_ARMADA_CHAVE:
      chaveAtivada = digitalRead(CHAVE_PIN) == LOW;
      if (!chaveAtivada) {
        estadoAtual = BOMBA_DESARMADA_CHAVE;
        lcd.clear();
        lcd.setCursor((16 - 15) / 2, 0);
        lcd.print("Bomba desarmada");
        noTone(BUZZER_PIN);
      } else {
        int tempoRestante = tempoTotal - (millis() - startTime) / 1000;
        if (tempoRestante <= 0) {
          estadoAtual = BOMBA_DESARMADA_CHAVE;
          lcd.clear();
          lcd.setCursor((16 - 15) / 2, 0);
          lcd.print("Tempo esgotado!");
          noTone(BUZZER_PIN);
        } else {
          int horas = tempoRestante / 3600;
          int min = (tempoRestante % 3600) / 60;
          int sec = tempoRestante % 60;
          lcd.setCursor((16 - 8) / 2, 1);
          if (horas < 10) lcd.print('0');
          lcd.print(horas);
          lcd.print(':');
          if (min < 10) lcd.print('0');
          lcd.print(min);
          lcd.print(':');
          if (sec < 10) lcd.print('0');
          lcd.print(sec);

          if (tempoRestante <= 600) {
            if (millis() % 500 < 100) {
              tone(BUZZER_PIN, 1000);
            } else {
              noTone(BUZZER_PIN);
            }
          } else {
            if (millis() % 1000 < 100) {
              tone(BUZZER_PIN, 1000);
            } else {
              noTone(BUZZER_PIN);
            }
          }
        }
      }
      break;

    case BOMBA_DESARMADA_CHAVE:
      if (tecla == '*') {
        estadoAtual = MENU;
        lcd.clear();
        lcd.print("Selecione o modo");
        modo = '-';
        tempoHora1 = tempoHora2 = tempoMin1 = tempoMin2 = '-';
        noTone(BUZZER_PIN);
      }
      break;
  }
}

PS: Thank you very much for all the help.

That looks like a good start

What should the code do and what does it actually do ?

What exactly do you mean by "mode 1" ?

A minor observation that will not affect the operation of the sketch but could make it tidier

if (tecla != NO_KEY && tecla >= '0' && tecla <= '9')

You don't need to test whether tecla is not equal to NO_KEY because you are testing whether it is between '0' and '9' anyway

So basically this project is a "Bomb" with several game modes (10 total), when I refer to mode 1 I mean the first game mode, which is disarming by key switch.
The first mode works as follows:
When I am on the MENU screen (to select the game mode) and choose mode 1 by pressing button 1 on the keyboard and then pressing #, it goes to another screen where TIME1 is used to select the time until the game ends through the keyboard, if the operator makes the mistake of writing the time, he will use * to return to the initial screen (MENU), when the operator writes the time he wants on this screen and presses #, he will go to the armed bomb screen (BOMBA_ARMADA_CHAVE) in which the time decreases and the buzzer beeps every second, if the time is less than 10 minutes the buzzer beeps every half second, if the operator activates the key switch the bomb is disarmed, the variables that store the hour values , minutes and seconds will return -, the LCD clears and writes that the bomb has been disarmed, when the operator presses * it returns to the initial screen (MENU), if the time reaches the end the buzzer will beep continuously (I forgot that part ) and the screen shows that the time has run out, when the operator presses * returns to the initial screen (MENU).