Dúvida com Menu, LCD e Botões

Pessoal, estou desenvolvendo um projeto de uma máquina de envase onde há uma esteira, uma bomba, sensor, keypad e botões e utilizando um Arduino Mega

  • Minha principal dúvida é em relação ao menu do LCD onde pretendo ter na primeira tela após ser acionado por um botão "bverde" uma mensagem com o nome da máquina passando então 1 segundo irá mostrar a quantidade a ser envasada. A quantidade será o valor digitado no Keypad;

  • Após o valor ser digitado pelo keypad uma segunda tela é mostrada, nessa tela será contada a quantidade de envasada e pressionando o "bamarelo" muda a tela para a terceira tela onde irá mostrar o nível do tanque de armazenamento, pressionando o "bamarelo" novamente ele volta para a segunda tela, ou seja o "bamarelo" irá funcionar como um botão de opões que transita entre essas duas telas;

  • Usando um decrementador quero que o mesmo decremente o valor digitado na tela 1 mostrando a mensagem de que o Lote esta pronto e que se deve inserir um novo valor;

  • Um terceiro botão "bvermelho" seria o botão de emergência, ou seja se pressionado a máquina trava.

  • Todo esse programa foi baseado em exemplos e projetos que encontrei aqui no fórum e em outros sites.
    Segue o Programa:

//========================================================================
#include <Keypad.h>
#include <LiquidCrystal.h> 
LiquidCrystal lcd(22,23,24,25,26,27); // DECLARAÇÃO DOS PINOS DO LCD NO ARDUINO
// DEFINIÇÃO DOS BOTÕES - VERDE. VERMELHO, AMARELO
#define bverde A1 // Os pinos analógicos podem ser
#define bamarelo A2 // usados como digitais, bastando
#define bvermelho A3 // referenciá-los por A0, A1..
#define bDown A4
#define bverde0 90 // Valor de referência que a
#define bamarelo0 91 // função CheckButton() passa
#define bvermelho0 92 // indicando que um botão foi
#define bDown0 93 // solto
boolean averde, aamarelo, avermelho, aDown; // Grava o ultimo valor lidos nos botões.
// Utilizado pela função Checkbutton p/ identificar quando há uma alteração no estado do pino dos botões
// DEFINIÇÃO DOS PINOS E VALORES PARA O SENSOR, ESTEIRA E BOMBA
int contador = 0; 
int Sensor = 0; 
int sensorPin = A0; 
int MotorEsteira = 11;
int MotorBomb= 12;
int EstadoMotor=0;
int EstadoSensor=1;
int LED1=8;
int LED2=9;
int LED3=10;
int LED4=2;
int buzzer=7;
int variavel; // VARIAVEL A SER ALTERADA PELO MENU
char state=1; // VARIÁVEL QUE GUARDA POSIÇÃO ATUAL DO MENU
int dec=-1;
int i=0;
const byte LIN = 4; // TECLADO POSSUI 4 LINHAS
const byte COL = 3; //TECLADO POSSUI 3 COLUNAS
char keys[LIN][COL] = { 
{//MATRIZ CORRESPONDENTE AOS CARACTERES DO KEYPAD 
'1','2','3' }
, 
{
'4','5','6' }
,
{
'7','8','9' }
,
{
'*','0','#' }
};
byte LinPins[LIN] = {
28,29,30,31}; //PINOS DO ARDUINO CORRESPONDENTES AS COLUNAS
byte ColPins[COL] = {
32,33,34}; //E AS LINHAS DA MATRIZ
Keypad keypad = Keypad( makeKeymap(keys), LinPins, ColPins, LIN, COL );
char key = keypad.getKey();
void setup()
{
lcd.begin(16, 2); // Iniciando a biblioteca do LCD
Serial.begin(9600); // DEFINIÇÃO DA PORTA SERIAL
pinMode(bverde, INPUT); // Botões
pinMode(bamarelo,INPUT);
pinMode(bvermelho, INPUT);
pinMode(bDown, INPUT);
digitalWrite(bverde, HIGH); // Aciona o pull-up interno
digitalWrite(bamarelo,HIGH); // dos botões
digitalWrite(bvermelho, HIGH);
digitalWrite(bDown, HIGH);
pinMode(sensorPin, INPUT); //DEFINIR SE A VARIAVEL É ENTRADA(IMPUT) OU SAIDA(OUTPUT) DE DADOS
pinMode(MotorEsteira, OUTPUT); 
pinMode(MotorBomb, OUTPUT);
pinMode(EstadoSensor, INPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop()
{
Sensor = digitalRead(sensorPin); // A VARIAVEL SENSOR CORRESPONDE AO sensorPin QUE ESTÁ LIGADO A PORTA ANALÓGICA A0 DO ARDUIN
if(Sensor == LOW){ 
digitalWrite(MotorEsteira, HIGH); // SE O SENSOR NÃO ESTIVER ACIONADO O MOTOR DA BOMBA ESTA PARADO E O LED1 ASCESO
digitalWrite(LED1,HIGH); 
digitalWrite(LED2, LOW);
digitalWrite(MotorBomb, LOW);
digitalWrite(buzzer, LOW);
}
if(Sensor == HIGH) { // SE O SENSOR ESTIVER ACIONADO O MOTOR DA ESTEIRA ESTA PARADO E O LED1 APAGA
digitalWrite(MotorEsteira, LOW); // O MOTOR DA BOMBA LIGA E O LED2 ASCENDE E UM TOQUE DE 2 SEGUNDO É 
digitalWrite(MotorBomb, HIGH); // ACIONADO PELO BUZZER 
digitalWrite(LED1, LOW);
digitalWrite(LED2, HIGH);
delay(8000);//ESTE DELAY SERVE PARA A BOMBA JOGAR 200ml DE AGUA NA GARRAFA
contador++;
Sensor == !Sensor; //O SINAL DO SENSOR É INVERTIDO PARA A FUNÇAO RETORNAR DE ONDE ESTAVA
}
EstadoSensor = digitalRead(sensorPin); // O SINAL DO SENSOR É MOSTRADO NO SERIAL MONITOR 
Serial.println(Sensor);
if(EstadoSensor == HIGH){ // A FUNÇAO RETORNA AO ESTADO INICIAL
digitalWrite(MotorEsteira, HIGH); 
digitalWrite(MotorBomb, LOW);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
digitalWrite(buzzer,LOW);
delay(2000);
}
switch (state) { // Define checa qual tela atual
case 1: // executado quando na TELA 1
switch (CheckButton()) {
case bverde:
lcd.setCursor(0,0);
lcd.print("Maquina Envase");
lcd.setCursor(0,2);
lcd.print("Eng. Mecatronica");
delay(5000);
lcd.clear();
lcd.setCursor(0,0); 
lcd.print("Controle Prod.");
Set_state(1);
break;
case bamarelo:
lcd.clear(); 
Set_state(2); // antes de mudar de tela, é necessário limpar o
break; 
lcd.clear(); 
Set_state(3); // display com a função lcd.clear()
break;
lcd.clear(); 
Set_state(1);
break;
default: // Caso nenhum botão tenha sido apertado, ela executa a set_state
Set_state(1); // mesmo assim para atualizar o display.
}
break;
case 2: // executado quando na TELA 2
switch (CheckButton()) {
case bverde: 
lcd.clear(); 
Set_state(1);
break;
case bamarelo: //
lcd.clear(); 
Set_state(3);
break;
lcd.clear(); 
Set_state(1);
break;
lcd.clear(); 
Set_state(2);
break;
default:
Set_state(2);
}
break;
case 3: // executado quando na TELA 3
switch (CheckButton()) {
case bverde: 
lcd.clear(); 
Set_state(1);
case bamarelo:
lcd.clear(); 
Set_state(2);
break;
lcd.clear(); 
Set_state(3);
break;
lcd.clear(); 
Set_state(1);
break;
default:
Set_state(3);
}
break;
case 4: // executado quando na TELA 4
switch (CheckButton()) {
case bamarelo:
lcd.clear(); 
Set_state(1);
break;
default:
Set_state(1);
}
break;
default: 
;
}
}// FIM DO LOOP
char CheckButton() { 
if (averde!=digitalRead(bverde)) { 
averde=!averde; 
if (averde) return bverde0; 
else return bverde;
} 
else
if (aamarelo!=digitalRead(bamarelo)) {
aamarelo=!aamarelo;
if (aamarelo) return bamarelo0; 
else return bamarelo;
} 
else
if (avermelho!=digitalRead(bvermelho)) {
avermelho=!avermelho;
if (avermelho) return bvermelho0; 
else return bvermelho;
} 
else
if (aDown!=digitalRead(bDown)) {
aDown=!aDown;
if (aDown) return bDown0; 
else return bDown;
} 
else
return 0;
}

void PCP() // FUNÇÃO QUE DEFINE A QUANTIDADE DE GARRAFAS A SEREM ENVASADAS NO DIA
{
char key = keypad.getKey();
if (key != NO_KEY){
lcd.setCursor(i,2); 
lcd.print(key);
i++;
}
}
void Set_state(char index) {
state = index; // Atualiza a variável state para a nova tela
switch (state) { // verifica qual a tela atual e exibe o conteúdo correspondente
case 1: //==================== state 1
PCP();
break;
case 2: //==================== state 2
lcd.setCursor(0,0);
lcd.print("Qnt. Envasada:");
lcd.setCursor(0,1);
lcd.print(contador); // mostra os segundos na tela
lcd.print(" garrafas");
delay(20);

// if(contador==key){
// lcd.setCursor(0,0);
// lcd.print("Lote Pronto!");
// lcd.setCursor(0,1);
// lcd.print("Insira Novo");
// }
break;
case 3: //==================== state 3
lcd.setCursor(0,0);
lcd.print("Nivel Tanque");
lcd.setCursor(1,2);
lcd.print("%");
break;
case 4: //==================== state 4
break;
default: 
;
}
}

E a tua dúvida é??

Botão de emergência nunca deve ter código associado para funcionar. Deve ser sempre hardwired e nunca envolver software.

Bubulindo,
Bom saber que não devo associar o botão de emergência com o software. Minha dúvida é saber como organizar os cases para que as ações aconteçam da forma que falei, pois percebi que simplesmente mudando o valor da tela do Set_state muda toda a configuração das telas, ou seja não estou conseguindo fazer esta organização de forma correta.

Outro detalhe, não sei se você pode compilar o código no Arduino, mas conforme digito no keypad e mudo de tela pressionando o "bamarelo" quando volto na tela um e pressiono novamente no keypad o novo valor aparece no próximo caractere do LCD.

Os teus switch estao todos "empenados"

switch (CheckButton()) {
    case bverde:
      lcd.setCursor(0,0);
      lcd.print("Maquina Envase");
      lcd.setCursor(0,2);
      lcd.print("Eng. Mecatronica");
      delay(5000);
      lcd.clear();
      lcd.setCursor(0,0); 
      lcd.print("Controle Prod.");
      Set_state(1);
      break;
    case bamarelo:
      lcd.clear(); 
      Set_state(2); // antes de mudar de tela, é necessário limpar o
      break;  //________>Para que é o break aqui!!
      lcd.clear(); 
      Set_state(3); // display com a função lcd.clear()
      break; //________>Para que é o break novamente aqui!!
      lcd.clear(); 
      Set_state(1);
      break; //So este é que devia estar aqui !
    default: // Caso nenhum botão tenha sido apertado, ela executa a set_state
      Set_state(1); // mesmo assim para atualizar o display.
    }
    break;

Tens isto em quase todos eles ...

char CheckButton() { 
  if (averde!=digitalRead(bverde)) { 
    averde=!averde; 
    if (averde) return bverde0; 
    else return bverde;
  } 
  else
    if (aamarelo!=digitalRead(bamarelo)) {
      aamarelo=!aamarelo;
      if (aamarelo) return bamarelo0; 
      else return bamarelo;
    } 
    else
      if (avermelho!=digitalRead(bvermelho)) {
        avermelho=!avermelho;
        if (avermelho) return bvermelho0; 
        else return bvermelho;
      } 
      else
        if (aDown!=digitalRead(bDown)) {
          aDown=!aDown;
          if (aDown) return bDown0; 
          else return bDown;
        } 
        else
          return 0;
}

Olhando a esta função fico com a impressão que o que pretendes é obter o estado dos botões, mas esta muito confuso para perceber o nó que se esta ai a dar.
Porque não crias antes uma estrutura de dados onde armazenas esses dados.
Algo tipo

#define bverde A1 // Os pinos analógicos podem ser
#define bamarelo A2 // usados como digitais, bastando
#define bvermelho A3 // referenciá-los por A0, A1..
#define bDown A4



typedef struct botoes
{
  boolean averde;
  boolean aamarelo;
  boolean avermelho;
  boolean aDown; 
} 
buttonState_t;
buttonState_t botoes;
void setup()
{
  pinMode(bverde, INPUT); // Botões
  pinMode(bamarelo,INPUT);
  pinMode(bvermelho, INPUT);
  pinMode(bDown, INPUT);
}
void loop()
{
  void updateAllButtons();
}
void updateAllButtons()
{
  botoes.averde = digitalRead(bverde);
  botoes.aamarelo = digitalRead(bamarelo);
  botoes.avermelho = digitalRead(bvermelho);
  botoes.aDown = digitalRead(bDown);
}

HugoPT Então devo retirar estas repetições? pensei que o break funcionasse como uma pausa para para a próxima ação.

Nunca usei esta função:

typedef struct botoes
   {
      boolean averde;
      boolean aamarelo;
      boolean avermelho;
      boolean aDown; 
   } estadoBotoe

Poderia me explicar como usar? E pensei que o switch case armazenasse a função...

Retirei os break que você disse que eram desnecessários ficando desta forma:

 switch (state) {  // Define checa qual tela atual

  case 1:          // executado quando na TELA 1
    switch (CheckButton()) {

    case bverde:
      lcd.setCursor(0,0);
      lcd.print("Maquina Envase");
      delay(1000);
      lcd.setCursor(0,0);    
      lcd.print("Controle Prod.");
      Set_state(1);
      lcd.clear(); 
      Set_state(2);

      break;
    case bamarelo:
      lcd.clear(); 
      Set_state(2); // antes de mudar de tela, é necessário limpar o
       
      lcd.clear(); 
      Set_state(3);        // display com a função lcd.clear()
     
      lcd.clear(); 
      Set_state(1);
    
    default:   // Caso nenhum botão tenha sido apertado, ela executa a set_state
      Set_state(1); // mesmo assim para atualizar o display.
    }
    break;

  case 2:          // executado quando na TELA 2
    switch (CheckButton()) {
    case bverde:  
      lcd.clear(); 
      Set_state(1);
      
    case bamarelo:  //
      lcd.clear(); 
      Set_state(3);
     
      lcd.clear(); 
      Set_state(1);
     
      lcd.clear(); 
      Set_state(2);
      break;
    default:
      Set_state(2);
    }
    break;

  case 3:          // executado quando na TELA 3
    switch (CheckButton()) {
    case bverde:  
      lcd.clear(); 
      Set_state(1);
      case bamarelo:
      lcd.clear(); 
      Set_state(2);
      
      lcd.clear(); 
      Set_state(3);
      
      lcd.clear(); 
      Set_state(1);
     
    default:
      Set_state(3);
    }
    break;

  case 4:          // executado quando na TELA 4
    switch (CheckButton()) {
    case bamarelo:
      lcd.clear(); 
      Set_state(1);
    
    default:
      Set_state(1);
    }
    break;

  default: 
    ;
  }

Mas agora o bmarelo não muda as telas e bverde não vai para a tela onde é requerido a quantidade a ser envasada.

Da forma que tens o código vai te ficar difícil de o manteres, isto porque não o tens organizado e limpo.
Por exemplo isto:

void PCP() // FUNÇÃO QUE DEFINE A QUANTIDADE DE GARRAFAS A SEREM ENVASADAS NO DIA
{
char key = keypad.getKey();
if (key != NO_KEY){
lcd.setCursor(i,2); 
lcd.print(key);
i++; //______>O que faz isto aqui
}
}

este i++ que aqui tens pode ate fazer o teu código funcionar mas é errado fazeres isto porque é má pratica.O que irá acontecer se amanha te esqueces que este i++ anda esta nesta função ao qual perdes-te o rasto.vais andar horas a tentar descobrir porque onde raio esta o erro ...
Uma função faz o seu trabalho da forma mais simples e eficaz sem causar efeitos colaterais noutras partes, a não ser se tal esteja mencionado na função e ao qual o programador sabe o que ira acontecer.

pensei que o break funcionasse como uma pausa para para a próxima ação.

O break interrompe o switch, ou seja entras no break e as avaliaçoes começam quando o pretendido e corrido depois queres saltar fora do switch dai a teres um break no fim
Para perceberes um pouco a estrutura testa isto:

#define bverde A1 // Os pinos analógicos podem ser
#define bamarelo A2 // usados como digitais, bastando
#define bvermelho A3 // referenciá-los por A0, A1..
#define bDown A4



typedef struct botoes
{
  boolean averde;
  boolean aamarelo;
  boolean avermelho;
  boolean aDown; 
} 
buttonState_t; //buttonState_t é agora um tipo de dados que contem  4 elementos do tipo bool
buttonState_t botoes; //botoes é uma variavel do tipo buttonState_t
void setup()
{
  pinMode(bverde, INPUT); // Botões
  pinMode(bamarelo,INPUT);
  pinMode(bvermelho, INPUT);
  pinMode(bDown, INPUT);
}
void loop()
{
  void updateAllButtons();
}
void updateAllButtons()
{
  botoes.averde = digitalRead(bverde);//A variavel botoes tem os quatro elementos que podem ser setados ou acedidos usando "dot notation" para aceder a cada elemento
  botoes.aamarelo = digitalRead(bamarelo);
  botoes.avermelho = digitalRead(bvermelho);
  botoes.aDown = digitalRead(bDown);
}

A vantagem é que assim andas só com uma variável botões no teu código que contem todos os estados dos teus botões de uma forma bem mais fácil de entender para o ser humano e mais facil de manter em termos de codigo.
Amanha se quiseres meter mais botões no teu circuito basta adiciona-los na struct e eles ficam logo disponíveis sem grandes mudanças no código

A vantagem é que assim andas só com uma variável botões no teu código que contem todos os estados dos teus botões de uma forma bem mais fácil de entender para o ser humano e mais facil de manter em termos de codigo.
Amanha se quiseres meter mais botões no teu circuito basta adiciona-los na struct e eles ficam logo disponíveis sem grandes mudanças no código

Continuo não entendendo este código que me mandou, porém que você disse que ficaria mais fácil a programação eu devo substituir com ele onde coloquei isso:

#define bverde    A1  // Os pinos analógicos podem ser
#define bamarelo  A2  // usados como digitais, bastando
#define bvermelho      A3  // referenciá-los por A0, A1..
#define bDown    A4

#define bverde0   90  // Valor de referência que a
#define bamarelo0 91  // função CheckButton() passa
#define bvermelho0     92  // indicando que um botão foi
#define bDown0   93  // solto

boolean averde, aamarelo, avermelho, aDown;

E isso:

  switch (state) {  // Define checa qual tela atual

  case 1:          // executado quando na TELA 1
    switch (CheckButton()) {

    case bverde:
      lcd.setCursor(0,0);
      lcd.print("Maquina Envase");
      delay(1000);
      lcd.setCursor(0,0);    
      lcd.print("Controle Prod.");
      Set_state(1);
      break;
    case bamarelo:
      lcd.clear(); 
      Set_state(2); // antes de mudar de tela, é necessário limpar o
      break;
      lcd.clear(); 
      Set_state(3);        // display com a função lcd.clear()
     // break;
    default:   // Caso nenhum botão tenha sido apertado, ela executa a set_state
      Set_state(1); // mesmo assim para atualizar o display.
    }
    break;

  case 2:          // executado quando na TELA 2
    switch (CheckButton()) {
    case bverde:  
      lcd.clear(); 
      Set_state(1);
      break;
    case bamarelo:  //
      lcd.clear(); 
      Set_state(3);
      break;
      lcd.clear(); 
      Set_state(1);
      break;
      lcd.clear(); 
      Set_state(2);
      break;
    default:
      Set_state(2);
    }
    break;

  case 3:          // executado quando na TELA 3
    switch (CheckButton()) {
    case bverde:  
      lcd.clear(); 
      Set_state(1);
    case bamarelo:
      lcd.clear(); 
      Set_state(2);
      break;
      lcd.clear(); 
      Set_state(3);
      break;
      lcd.clear(); 
      Set_state(1);
      break;
    default:
      Set_state(3);
    }
    break;

  case 4:          // executado quando na TELA 4
    switch (CheckButton()) {
    case bamarelo:
      lcd.clear(); 
      Set_state(1);
      break;
    default:
      Set_state(1);
    }
    break;

  default: 
    ;
  }
}// FIM DO LOOP

char CheckButton() {                                              
  if (averde!=digitalRead(bverde)) {    
    averde=!averde;                    
    if (averde) return bverde0;       
    else return bverde;
  } 
  else
    if (aamarelo!=digitalRead(bamarelo)) {
      aamarelo=!aamarelo;
      if (aamarelo) return bamarelo0; 
      else return bamarelo;
    } 
    else
      if (avermelho!=digitalRead(bvermelho)) {
        avermelho=!avermelho;
        if (avermelho) return bvermelho0; 
        else return bvermelho;
      } 
      else
        if (aDown!=digitalRead(bDown)) {
          aDown=!aDown;
          if (aDown) return bDown0; 
          else return bDown;
        } 
        else
          return 0;
}

Vamos por partes.Quanto mais tento entender o teu codigo mais confuso fica.

void PCP() // FUNÇÃO QUE DEFINE A QUANTIDADE DE GARRAFAS A SEREM ENVASADAS NO DIA
{
char key = keypad.getKey();
if (key != NO_KEY){
lcd.setCursor(i,2); 
lcd.print(key);
i++;
}
}

Esta funçao nao cumpre o que promete ja que se eu nao pressionar nenhuma tecla no teclado nao estas a definir nada!
Ou seja para este bloco de codigo funcionar tu ja tens de ter o dedo no teclado antes da funçao ser executada caso contrario key sera igual à macro NO_KEY e portanto nada ira ser feito.
A maquina ao entrar nesta funçao tem de esperar pela tecla pressionada e continuar la ate que algo seja primido, nao pressupondo que ja alguem la tem o dedo.Assim isso ira falhar 99,99% das vezes!
devias colocar dentro desta funçao algo tipo:

void PCP() // FUNÇÃO QUE DEFINE A QUANTIDADE DE GARRAFAS A SEREM ENVASADAS NO DIA
{
lcd.print("Insira o numero de Garrafas");
while(1){
char key = keypad.getKey();
if (key != NO_KEY){
lcd.setCursor(i,2); 
lcd.print(key);
i++;
break;//Para forçar a sair do while
}
}
}

Se nao pressionares nenhuma tecla o codigo fica travado a espera da tecla pressionada.Isto so ira funcionar para 1 tecla, tens de modificar para mais que uma tecla

Começa por partir o teu programa em partes e assegura-te que elas estao a funcionar bem.Depois é so juntares o bolo aos pedaços.
O que tu pretendes fazer nao é dificil so tens de solucionar pedaço a pedaço.
Dá nomes mais sugestivos as tuas variaveis e as funçoes e faz em papel um esquema do fluxo que o teu programa e do algoritmo que tem de fazer.
Partilha isso aqui e vamos resolvendo

HugoPT, fiz a alteração na função PCP que você orientou, porém ao inserir um número qualquer o mesmo aparece no LCD mas a mensagem Insira qnt. garrafas aparece também. Fiz o fluxograma da melhor maneira que pude:
Basicamente será assim:

Na primeira Tela: TELA 1= Os motores da esteira e da bomba d'agua estarão parados e a mensagem pedindo para inserir a quantidade do lote será mostrada. Após digitado e pressionado o botão verde a máquina liga

Na segunda Tela: TELA 2 = Se o botão amarelo for pressionado a tela muda e será mostrado a quantidade de garrafas já envasada. Sendo que a garrafa é contada a partir que o motor da esteira desliga e a bomba liga. (O Botão amarelo serve somente para transitar entre duas tela somente para verificação.)

Na terceira Tela: TELA 3 = Se o botão amarelo for pressionado novamente será mostrado o nível do tanque do reservatório(Ainda não comprei a boia por isso não precisamos colocar a função que vai medir agora)

Na quarta Tela: TELA 4 = Se o numero digitado na TELA 1 for decrementado até zero a mensagem de que o lote está pronto é mostrada e a máquina para até ser inserido uma nova quantidade.

Na quinta Tela: TELA 5 = Se o botão vermerlho for pressionado a máquina para (funcionara como trava de emergência).

Fiz da melhor mais detalhada que pude de como o processo deve acontecer, o que devo fazer agora ?

HugoPT, fiz a alteração na função PCP que você orientou, porém ao inserir um número qualquer o mesmo aparece no LCD mas a mensagem Insira qnt. garrafas aparece também

É normal não fizemos nenhum lcd.clear para limpar o que já la existia ...
Assim da uma idea melhor do que pretendes.
A minha próxima sugestão é:
Esquece tudo e resto e concentra-te em fazer o Menu pro LCD já que todo o teu programa andara de volta dele.

Fiz te este pequeno exemplo de como podes fazer o menu.
Nao testei o codigo por isso falhas sao esperadas :slight_smile:

#include <Keypad.h>
#include <LiquidCrystal.h> 

#define BOTAO_VERDE A1
#define BOTAO_AMARELO A2

LiquidCrystal lcd(22,23,24,25,26,27); // DECLARAÇÃO DOS PINOS DO LCD NO ARDUINO

typedef struct botoes
{
  boolean estadoBotaoVerde;
  boolean estadoBotaoAamarelo;
}
buttonState_t; //buttonState_t é agora um tipo de dados que contem  4 elementos do tipo bool


const byte LIN = 4; // TECLADO POSSUI 4 LINHAS
const byte COL = 3; //TECLADO POSSUI 3 COLUNAS
char keys[LIN][COL] = { 
  {//MATRIZ CORRESPONDENTE AOS CARACTERES DO KEYPAD 
    '1','2','3'           }
  , 
  {
    '4','5','6'           }
  ,
  {
    '7','8','9'           }
  ,
  {
    '*','0','#'           }
};
byte LinPins[LIN] = {
  28,29,30,31}; //PINOS DO ARDUINO CORRESPONDENTES AS COLUNAS
byte ColPins[COL] = {
  32,33,34}; //E AS LINHAS DA MATRIZ
Keypad keypad = Keypad( makeKeymap(keys), LinPins, ColPins, LIN, COL );

buttonState_t botoes; //botoes é uma variavel do tipo buttonState_t
void setup()
{
  lcd.begin(16, 2); // Iniciando a biblioteca do LCD
  Serial.begin(9600); // DEFINIÇÃO DA PORTA SERIAL
  pinMode(BOTAO_VERDE, INPUT); // Botões
  pinMode(BOTAO_AMARELO,INPUT);
  digitalWrite(BOTAO_VERDE,1);
  digitalWrite(BOTAO_AMARELO,1);
}
void loop()
{
  menuLCD(1);//desenha o menu 1
  delay(1000);
  menuLCD(2);//desenha o menu 2
  delay(1000);
  menuLCD(3);//desenha o menu 3
  delay(1000);
  menuLCD(4);//desenha o menu 4
  delay(1000);
  menuLCD(5);//desenha o menu 5
  delay(1000);

}
void updateAllButtons()
{
  botoes.estadoBotaoVerde = digitalRead(BOTAO_VERDE);//A variavel botoes tem os quatro elementos que podem ser setados ou acedidos usando "dot notation" para aceder a cada elemento
  botoes.estadoBotaoAamarelo = digitalRead(BOTAO_AMARELO);

}

void menuLCD(uint8_t lcdPos)
{
  /*Esta funçao ser responsavel por gerar o menu no LCD e apresenta-lo no ecra.
   Como so pode existir um ecra desenhado de cada vez o parametro passado na funçao indica qual o menu que ira ser desenhado
   */
  switch (lcdPos) {
  case 1:
    //Desenho o menu 1
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Menu 1");
    break;
  case 2:
    //Desenho o menu 2
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Menu 2");
    break;
  case 3:
    //Desenho o menu 3
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Menu 3");
    break;
  case 4:
    //Desenho o menu 4
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Menu 4");
    break;
  case 5:
    //Desenho o menu 5
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Menu 5");
    break;
  default: 
    //Algo estranho foi passado 
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Enganaste-te !!!");
    break;
  }
}

Desenhas cada menu a teu gosto como o representas-te no teu diagrama.Quando tiveres este pedaço concluido depois avanças para colocares o MenuLCD a mudar com os botões.

Fiz te este pequeno exemplo de como podes fazer o menu.
Nao testei o codigo por isso falhas sao esperadas smiley

Infelizmente está ocorrendo um erro na transferência para a placa, ele compila mais não esta enviando.

Desenhas cada menu a teu gosto como o representas-te no teu diagrama

Alterei como mostrei no diagrama.

Infelizmente está ocorrendo um erro na transferência para a placa, ele compila mais não esta enviando.

hehe pois é , bom asssim hoje tambem aprendes outra coisa
O erro esta nisto:

  default: 
    //Algo estranho foi passado 
    lcd.clear();
    lcd.setCursor(0,2);
    lcd.print("Enganaste-te !!!"); ---->Os !!! sao algo muito especial para o bootloader e não pode estar seguido no código.Opps esta escapou me  me mesmo sem intenção  :grin:
    break;
  }

Removendo os !!! já consegues enviar :grin:
Os !!! são os caracteres responsáveis de colocar a board em restart para aceitar um novo firmware logo quando tu estavas a tentar enviar o programa e os !!! passavam ele erradamente pensa que já é um novo programa e reinicia a board para entrar outro firmware.

//Algo estranho foi passado

Vê la bem a ironia do meu comentário e nem foi de propósito, meti o pé em cheio na mina XD XD XD
Testa ai

hehe pois é , bom asssim hoje tambem aprendes outra coisa
O erro esta nisto:

Nossa :astonished: fiquei um tempão procurando o erro nunca imaginaria que o erro estaria aqui "!!!" mesmo estando entre as aspas, rsrs

Bem agora o código está compilando e transferindo certinho, como você disse o próximo passo é trabalhar no menuLCD

Devo fazer algo assim para unir os botões as telas? :

void loop()
{
  if(BOTAO_VERDE == HIGH){
    menuLCD(1);//desenha o menu 1
    delay(1000);
  }
  else{
    menuLCD(2);//desenha o menu 2
    delay(1000);
  }
  if(BOTAO_AMARELO ==HIGH){
    menuLCD(3);//desenha o menu 3
    delay(1000);
  }
  else{
    menuLCD(4);//desenha o menu 4
    delay(1000);
  }
  menuLCD(5);//desenha o menu 5
  delay(1000);
}

Hehe :* Desculpe-me pelo meu lado noob da programação estou tentando me esforçar ao máximo rs

Se fizeres assim como esta não vai funcionar!
No código de exemplo que te deu coloquei la isto

digitalWrite(BOTAO_VERDE,1);
digitalWrite(BOTAO_AMARELO,1);

isto é para activar os pull-ups internos nos pinos de modo a que eles não estejam a "flutuar" entre 0 e 1 ou 1 e 0.No entanto a leitura será sempre 1 em repouso e só se levares o pino aos 0 V e que dará 0.
Tens de prever o debouncing dos botões senão o fizeres vais ter efeitos indesejáveis.
Ve este video para veres o que é o debouncing e como o evitas e aplica no teu codigo

if(BOTAO_VERDE == HIGH){
menuLCD(1);//desenha o menu 1
delay(1000);
}

Lembra-te que BOTAO_VERDE é apenas uma macro que é substituida pelo valor A1 após o pre-processador passar pelo código logo não podes fazer esta avaliação assim BOTAO_VERDE == HIGH, pois não estas a ler o estado do pino !

Se eu quiser ativar o menu 1 com o botão verde devo usar a verificação do estado do mesmo por essa void?

void updateAllButtons()
{
  botoes.estadoBotaoVerde = digitalRead(BOTAO_VERDE);//A variavel botoes tem os quatro elementos que podem ser setados ou acedidos usando "dot notation" para aceder a cada elemento
  botoes.estadoBotaoAamarelo = digitalRead(BOTAO_AMARELO);

}

usando o updateAllButtons() ? dentro do void loop?

Claramente a programação não é o teu forte, mas vais ter de estudar um pouco pois estas a "nadar". Recordo-te que estamos aqui para te ajudar, não para fazer o código todo por ti!

Claramente a programação não é o teu forte, mas vais ter de estudar um pouco pois estas a "nadar"

Sim, não é o meu forte! Mas estou estou me empenhando ]:smiley:

Olá
Tenho um projeto para controlar um aquecedor com um arduino uno, um relé e os botões do LCD (16x2).
O aquecedor pode-se controlar de duas formas:
-Pela temperatura (O utilizador escolhe a temperatura desejada e o aquecedor irá manter-se aceso ate o sensor marcar essa temperatura);
-Pelos dias da semana (O utilizador pode escolher quantos dias é que o aquecedor vai estar aceso).
A minha duvida é: Como posso fazer um menu para que em qualquer momento o utilizador consiga alterar esses valores, sem ter de reiniciar o programa?
Ou seja, eu quero fazer um menu de configurações que possa ser acessado não só no inicio do programar, mas sim em qualquer momento da sua execução.