⬤ LCD · Intermédio
📋 Menu Navegável com Botões
⏱️ 35 min🧩 Menu UI · Botões · Scroll de menu · Cursor ▶
📋 Estrutura de Menu em Array
ex_menu.ino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define BTN_UP 2
#define BTN_DOWN 3
#define BTN_OK 4
const char* opcoes[] = {
"1 Motor DC: ON/OFF",
"2 Servo: posicao",
"3 Velocidade",
"4 Ver sensores",
"5 Reiniciar"
};
#define N 5
int sel=0, scroll=0;
void desenhar() {
lcd.clear();
for(int i=0; i<4 && (scroll+i)<N; i++) {
lcd.setCursor(0,i);
lcd.print((scroll+i)==sel ? ">" : " ");
lcd.print(opcoes[scroll+i]);
}
}
void setup() {
lcd.init(); lcd.backlight();
pinMode(BTN_UP,INPUT_PULLUP); pinMode(BTN_DOWN,INPUT_PULLUP); pinMode(BTN_OK,INPUT_PULLUP);
desenhar();
}
void loop() {
if(digitalRead(BTN_UP)==LOW) {
if(sel>0) sel--;
if(seldesenhar(); delay(200);
}
if(digitalRead(BTN_DOWN)==LOW) {
if(sel1) sel++;
if(sel>=scroll+4) scroll++;
desenhar(); delay(200);
}
if(digitalRead(BTN_OK)==LOW) {
executar(sel); delay(300);
}
}
>1 Motor DC: ON/OFF 2 Servo: posicao 3 Velocidade 4 Ver sensores
💡A variável scroll controla o primeiro item visível. Quando sel sai da janela de 4 linhas, scroll ajusta para manter o item selecionado sempre visível.
✅ Executar Ações por Opção
menu_exec.ino
void executar(int op) {
lcd.clear();
switch(op) {
case 0:
lcd.print("Motor: TOGGLE");
// motor.run(motorOn ? RELEASE : FORWARD);
delay(1000); desenhar(); break;
case 1:
lcd.print("Submenu Servo...");
delay(1000); desenhar(); break;
default:
lcd.print("Em construcao...");
delay(800); desenhar(); break;
}
}
🏆 Para ir mais longe
- Substitui o cursor '>' por char personalizado ▶ criado na CGRAM
- Adiciona indicador de posição '2/5' no canto superior direito
- Implementa submenu para Servo com opções 0°/45°/90°/135°/180°
- Adiciona timeout de 10s: sem botão → mostra ecrã principal de sensores