#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
// ----- Sensores -----
#define DHTPIN 2
#define DHTTYPE DHT22
#define LDR_PIN A0
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ----- LEDs -----
#define LED_OK 6
#define LED_ALERT 7
// ----- Botões -----
#define BUTTON_REG 3
#define BUTTON_RESET 4
// ----- SD Card -----
#define SD_CS 10 // CS deve ser o pino 10 no Arduino Uno
File logFile;
// ----- RTC -----
RTC_DS1307 rtc;
// ----- Controle botões -----
bool lastRegState = HIGH;
bool lastResetState = HIGH;
// ----- Variável alerta -----
bool alerta = false;
void setup() {
Serial.begin(9600);
dht.begin();
lcd.init();
lcd.backlight();
pinMode(LED_OK, OUTPUT);
pinMode(LED_ALERT, OUTPUT);
pinMode(BUTTON_REG, INPUT_PULLUP);
pinMode(BUTTON_RESET, INPUT_PULLUP);
// RTC
if (!rtc.begin()) {
lcd.setCursor(0,0);
lcd.print("Erro RTC!");
while (1);
}
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// SD Card
if (!SD.begin(SD_CS)) {
lcd.setCursor(0,0);
lcd.print("Erro SD Card");
Serial.println("Falha no SD!");
while(1);
}
Serial.println("SD Card OK");
// Cabeçalho do arquivo
logFile = SD.open("datalog.txt", FILE_WRITE);
if (logFile) {
logFile.println("Epoch,Temperatura,Umidade,Luz");
logFile.close();
}
lcd.setCursor(0,0);
lcd.print("Data Logger");
lcd.setCursor(0,1);
lcd.print("Iniciando...");
delay(2000);
lcd.clear();
}
void loop() {
// ----- Leitura sensores -----
float temperatura = dht.readTemperature();
float umidade = dht.readHumidity();
int valorLDR = analogRead(LDR_PIN);
float luminosidade = map(valorLDR, 0, 1023, 0, 100);
if (isnan(temperatura) || isnan(umidade)) {
Serial.println("Erro no sensor DHT!");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Erro sensor DHT");
delay(2000);
return;
}
// ----- RTC -----
DateTime now = rtc.now();
unsigned long epoch = now.unixtime(); // Unix Epoch
char buffer[17];
snprintf(buffer, sizeof(buffer), "%02d/%02d %02d:%02d",
now.day(), now.month(), now.hour(), now.minute());
// ----- Serial Monitor -----
Serial.print("Epoch: "); Serial.print(epoch);
Serial.print(" | Temp: "); Serial.print(temperatura,1);
Serial.print("C | Umid: "); Serial.print(umidade,0);
Serial.print("% | Luz: "); Serial.print(luminosidade,0);
Serial.println("%");
// ----- LCD -----
lcd.setCursor(0,0);
lcd.print("T:"); lcd.print(temperatura,1); lcd.print("C ");
lcd.print("U:"); lcd.print(umidade,0); lcd.print("%");
lcd.setCursor(0,1);
lcd.print("L:"); lcd.print(luminosidade,0); lcd.print("% ");
lcd.setCursor(8,1);
lcd.print(buffer);
// ----- Verifica triggers -----
alerta = false;
if (temperatura < 15 || temperatura > 25) alerta = true;
if (umidade < 30 || umidade > 50) alerta = true;
if (luminosidade > 30) alerta = true;
// ----- Leitura botões -----
bool regState = digitalRead(BUTTON_REG);
bool resetState = digitalRead(BUTTON_RESET);
// ----- Registro manual -----
if (regState == LOW && lastRegState == HIGH) {
salvarRegistro(temperatura, umidade, luminosidade, epoch);
Serial.println("Registro manual!");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Registro Salvo");
delay(800);
lcd.clear();
}
// ----- Reset alerta -----
if (resetState == LOW && lastResetState == HIGH) {
Serial.println("Alerta resetado!");
alerta = false;
digitalWrite(LED_ALERT, LOW);
digitalWrite(LED_OK, HIGH);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Alerta Resetado");
delay(800);
lcd.clear();
}
lastRegState = regState;
lastResetState = resetState;
// ----- LEDs -----
if (alerta) {
digitalWrite(LED_ALERT, HIGH);
digitalWrite(LED_OK, LOW);
} else {
digitalWrite(LED_ALERT, LOW);
digitalWrite(LED_OK, HIGH);
}
delay(500);
}
// ----- Função salvar no SD com Unix Epoch -----
void salvarRegistro(float t, float u, float l, unsigned long epoch) {
logFile = SD.open("datalog.txt", FILE_WRITE);
if (logFile) {
logFile.print(epoch);
logFile.print(",");
logFile.print(t); logFile.print(",");
logFile.print(u); logFile.print(",");
logFile.println(l);
logFile.close();
Serial.println("Registro salvo no SD");
} else {
Serial.println("Erro ao gravar no SD");
}
}