#include <LiquidCrystal.h>
#include <SD.h>
#include <SPI.h>
#include <DS3232RTC.h>
#include <TimeLib.h>
#include <Wire.h>
#include <DS3232RTC.h> // https://github.com/JChristensen/DS3232RTC
DS3232RTC rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Pinos do LCD
// Pinos dos botões
const int botao1 = 6; // Botão de seleção
const int botao2 = 7; // Botão para cima
const int botao3 = 8; // Botão para baixo
const int botao4 = 9; // Botão de voltar
// Variáveis de controle do menu
int indicemenu = 0;
unsigned long tempoAmostragem = 1000; // Tempo padrão de amostragem em ms
unsigned long ultimaAmostra = 0;
// Variáveis de debouncing
unsigned long debounceDelay = 50;
unsigned long ultimoDebounce[4] = {0, 0, 0, 0}; // Para cada botão
int estadoBotaoAtual[4] = {HIGH, HIGH, HIGH, HIGH}; // Pinos configurados como INPUT_PULLUP
// Configuração do SD
const int chipSelect = 10;
DS3232RTC rtc;
void setup() {
// Inicializa o LCD
lcd.begin(16, 2);
lcd.print("Bem-vindo");
delay(2000); // Mensagem de boas-vindas
// Inicializa o SD
inicializaSD();
// Configura botões
pinMode(botao1, INPUT_PULLUP);
pinMode(botao2, INPUT_PULLUP);
pinMode(botao3, INPUT_PULLUP);
pinMode(botao4, INPUT_PULLUP);
// Inicializa o Serial
Serial.begin(9600);
// Configura o RTC
rtc.begin();
}
void inicializaSD() {
if (!SD.begin(chipSelect)) {
Serial.println("Falha ao inicializar o cartão SD");
} else {
Serial.println("Cartão SD inicializado com sucesso");
}
}
// Função de debouncing
int lerBotao(int botao, int indice) {
int leitura = digitalRead(botao);
if (leitura != estadoBotaoAtual[indice]) {
ultimoDebounce[indice] = millis();
}
if ((millis() - ultimoDebounce[indice]) > debounceDelay) {
if (leitura != estadoBotaoAtual[indice]) {
estadoBotaoAtual[indice] = leitura;
if (estadoBotaoAtual[indice] == LOW) {
return 1; // Botão pressionado
}
}
}
return 0;
}
// Função do datalogger
void datalogger() {
unsigned long tempoAtual = millis();
if (tempoAtual - ultimaAmostra >= tempoAmostragem) {
salvarDadoSD(tempoAtual);
ultimaAmostra = tempoAtual;
}
}
void salvarDadoSD(unsigned long valor) {
File arquivo = SD.open("datalog.txt", FILE_WRITE);
if (arquivo) {
arquivo.print("Tempo (ms): ");
arquivo.println(valor);
arquivo.close();
} else {
Serial.println("Erro ao abrir o arquivo no cartão SD");
}
}
// Tela de repouso com hora
void telaRepouso() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hora: ");
mostrarDataHora();
}
// Função para mostrar data e hora no LCD
void mostrarDataHora() {
tmElements_t tm;
rtc.read(tm);
lcd.setCursor(0, 1);
lcd.print(tm.Hour);
lcd.print(":");
lcd.print(tm.Minute);
}
// Função de controle do menu
void menu() {
switch (indicemenu) {
case 0:
telaRepouso();
if (lerBotao(botao1, 0)) indicemenu = 1; // Entra no menu
break;
case 1:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Menu Principal");
lcd.setCursor(0, 1);
lcd.print("> Iniciar Log");
if (lerBotao(botao2, 1)) indicemenu = 2; // Avança para outra opção
if (lerBotao(botao1, 0)) indicemenu = 3; // Seleciona opção
break;
case 2:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Configurar");
lcd.setCursor(0, 1);
lcd.print("> Tempo Amostr.");
if (lerBotao(botao3, 2)) indicemenu = 1; // Volta
if (lerBotao(botao1, 0)) indicemenu = 4; // Seleciona opção
break;
case 3:
lcd.clear();
lcd.print("Log Iniciado");
datalogger(); // Inicia o datalogger
if (lerBotao(botao4, 3)) indicemenu = 1; // Volta ao menu principal
break;
case 4:
lcd.clear();
lcd.print("Tempo Amostragem:");
ajustarTempoAmostragem(5000); // Ajusta para 5s (pode ser ajustável via menu)
delay(2000);
indicemenu = 1; // Volta ao menu principal
break;
}
}
void ajustarTempoAmostragem(unsigned long novoTempo) {
tempoAmostragem = novoTempo;
Serial.print("Tempo de amostragem ajustado para: ");
Serial.println(tempoAmostragem);
}
void loop() {
menu(); // Controla o menu
datalogger(); // Continua o datalogger quando aplicável
}