#include <Wire.h>
#include <RTClib.h>
#include <SD.h>
#include <SPI.h>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
#include <avr/wdt.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
// Número de sensores de temperatura
#define NUM_SENSORES 8
#define PINO_SENSORES 34
#define NUM_MOSTRAR 10 // Número de valores para média móvel
// Definições para os sensores de temperatura
OneWire oneWire(PINO_SENSORES);
DallasTemperature sensores(&oneWire);
DeviceAddress sensoresTemperatura[NUM_SENSORES];
// Definições para o display OLED
#define I2C_ADDRESS 0x3C
SSD1306AsciiAvrI2c oled;
// Definições para o RTC DS3231
RTC_DS3231 rtc;
// Definições para o SD Card
const int chipSelect = 53;
File arquivoCSV;
unsigned long tamanhoArquivoCSV = 0;
bool cartaoSDPresente = false;
// Definições para os sensores de umidade
const int numSensores = 8;
const int pinosSensores[numSensores] = {A0, A1, A2, A3, A4, A5, A6, A7};
const char* nomesSensores[numSensores] = {
"U1", "U2", "U3", "U4",
"U5", "U6", "U7", "U8"
};
bool sensoresConectados[numSensores] = {false};
// Arrays para armazenar os últimos 10 valores
float ultimosTemperaturas[NUM_SENSORES][NUM_MOSTRAR] = {0};
float ultimosUmidades[numSensores][NUM_MOSTRAR] = {0};
int indiceTemperatura[NUM_SENSORES] = {0};
int indiceUmidade[numSensores] = {0};
// Pinos e variáveis para o botão de delete e reset
const int pinoBotaoReset = 6;
const int pinoBotaoSwitch = 8;
const int pinoBotaoDelete = 10;
unsigned long tempoPressionadoDelete = 0;
bool buttonPressedDelete = false;
const unsigned long tempoBarraProgresso = 4000;
// Variáveis para rastrear o tempo
unsigned long ultimoVerificaConexao = 0;
const unsigned long intervaloVerificaConexao = 1000;
const unsigned long intervaloAtualizacaoUmidade = 10000;
unsigned long ultimoAtualizacaoUmidade = 0;
unsigned long ultimoMonitoramentoArquivo = 0;
const unsigned long intervaloMonitoramentoArquivo = 20000;
// Intervalo de tempo para leitura da temperatura
const unsigned long INTERVALO = 1000;
unsigned long tempoAnterior = 0;
// Variáveis para os sensores de temperatura
DeviceAddress ds18;
byte c;
int i;
float tempC;
// Fatores de calibração específicos para cada sensor DS18B20
float CALIBRACAO_TEMP[] = {
0, 0.5, -0.3, 0.2, 0.5, 0.2, 0.2, 0.2
};
// Funções
void exibirErro(const char* mensagem);
void abrirOuCriarArquivoCSV();
void verificarConexaoSensores();
void atualizarUmidadeSensores();
void verificarEstadoSD();
void monitorarTamanhoArquivoCSV();
void deletarArquivo();
void mostrarBarraProgresso(unsigned long tempoPressionado, unsigned long tempoBarraProgresso);
void verificarEstadoSwitch();
void atualizarDisplaySensores();
void imprimirDadosMonitorSerial();
void resetarArduino();
float calcularMedia(float* valores, int tamanho);
void setup() {
Serial.begin(115200);
Wire.begin();
oled.begin(&Adafruit128x64, I2C_ADDRESS);
oled.setFont(System5x7);
if (!rtc.begin()) {
exibirErro("Erro: RTC nao encontrado!");
while (true);
}
if (!SD.begin(chipSelect)) {
exibirErro("Erro: Cartao SD nao encontrado!");
while (true);
}
abrirOuCriarArquivoCSV();
pinMode(pinoBotaoReset, INPUT_PULLUP);
pinMode(pinoBotaoDelete, INPUT_PULLUP);
pinMode(pinoBotaoSwitch, INPUT_PULLUP);
oled.clear();
oled.println("Iniciando Sensor...");
oled.displayRows();
delay(2000);
oled.clear();
oled.println("Modulos OK");
oled.displayRows();
delay(2000);
sensores.begin();
for (int i = 0; i < NUM_SENSORES; i++) {
if (sensores.getAddress(sensoresTemperatura[i], i)) {
Serial.print("Sensor ");
Serial.print(i);
Serial.print(": ");
for (int j = 0; j < 8; j++) {
Serial.print(sensoresTemperatura[i][j], HEX);
Serial.print(" ");
}
Serial.println();
} else {
Serial.print("Falha ao obter o endereço do sensor ");
Serial.println(i);
}
}
}
void loop() {
unsigned long tempoAtual = millis();
sensores.requestTemperatures();
for (int i = 0; i < NUM_SENSORES; i++) {
float tempC = sensores.getTempCByIndex(i);
// Aplicar calibração
tempC += CALIBRACAO_TEMP[i];
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(tempC, 1);
Serial.println(" °C");
// Atualiza os valores de temperatura
ultimosTemperaturas[i][indiceTemperatura[i]] = tempC;
indiceTemperatura[i] = (indiceTemperatura[i] + 1) % NUM_MOSTRAR; // Circular
}
if (tempoAtual - ultimoVerificaConexao >= intervaloVerificaConexao) {
ultimoVerificaConexao = tempoAtual;
verificarConexaoSensores();
}
if (tempoAtual - ultimoAtualizacaoUmidade >= intervaloAtualizacaoUmidade) {
ultimoAtualizacaoUmidade = tempoAtual;
atualizarUmidadeSensores();
}
verificarEstadoSD();
if (tempoAtual - ultimoMonitoramentoArquivo >= intervaloMonitoramentoArquivo) {
ultimoMonitoramentoArquivo = tempoAtual;
monitorarTamanhoArquivoCSV();
}
if (digitalRead(pinoBotaoDelete) == LOW) {
if (!buttonPressedDelete) {
tempoPressionadoDelete = millis();
buttonPressedDelete = true;
} else {
unsigned long tempoPressionado = millis() - tempoPressionadoDelete;
if (tempoPressionado >= tempoBarraProgresso) {
deletarArquivo();
while (digitalRead(pinoBotaoDelete) == LOW) {
delay(10);
}
buttonPressedDelete = false;
} else {
mostrarBarraProgresso(tempoPressionado, tempoBarraProgresso);
}
}
} else {
buttonPressedDelete = false;
}
if (digitalRead(pinoBotaoReset) == LOW) {
resetarArduino();
while (digitalRead(pinoBotaoReset) == LOW) {
delay(50);
}
}
verificarEstadoSwitch();
atualizarDisplaySensores();
imprimirDadosMonitorSerial();
}
void mostrarBarraProgresso(unsigned long tempoInicial, unsigned long duracao) {
unsigned long tempoAtual = millis();
float progresso = float(tempoAtual - tempoInicial) / duracao;
oled.clear();
oled.setCursor(0, 0);
oled.println("Deletando arquivo...");
int barraComprimento = 16;
int barraPreenchida = int(barraComprimento * progresso);
oled.print("[");
for (int i = 0; i < barraComprimento; i++) {
if (i < barraPreenchida) {
oled.print("#");
} else {
oled.print("-");
}
}
oled.print("]");
oled.displayRows();
delay(100);
}
void verificarEstadoSwitch() {
if (digitalRead(pinoBotaoSwitch) == LOW) {
oled.ssd1306WriteCmd(SSD1306_DISPLAYOFF);
} else {
oled.ssd1306WriteCmd(SSD1306_DISPLAYON);
}
}
void deletarArquivo() {
unsigned long tempoInicio = millis();
unsigned long duracao = tempoBarraProgresso;
oled.clear();
oled.println("Aguarde...");
oled.displayRows();
while (millis() - tempoInicio < duracao) {
mostrarBarraProgresso(tempoInicio, duracao);
}
if (SD.exists("dados.csv")) {
if (SD.remove("dados.csv")) {
oled.clear();
oled.println("Arquivo deletado com sucesso");
} else {
oled.clear();
oled.println("Erro ao deletar arquivo");
}
} else {
oled.clear();
oled.println("Arquivo nao encontrado");
}
oled.displayRows();
}
void resetarArduino() {
oled.clear();
oled.println("Reiniciando...");
oled.displayRows();
delay(1000);
wdt_enable(WDTO_15MS);
while (true) {
}
}
void verificarConexaoSensores() {
for (int i = 0; i < numSensores; i++) {
int leituraSensor = analogRead(pinosSensores[i]);
if (leituraSensor <= 376) { //
sensoresConectados[i] = false;
} else {
sensoresConectados[i] = true;
}
}
}
void atualizarUmidadeSensores() {
if (!arquivoCSV) {
return;
}
DateTime agora = rtc.now();
String data = String(agora.day()) + "/" + String(agora.month()) + "/" + String(agora.year());
String hora = String(agora.hour()) + ":" + String(agora.minute()) + ":" + String(agora.second());
arquivoCSV.print(data);
arquivoCSV.print(", ");
arquivoCSV.print(hora);
arquivoCSV.print(", ");
for (int i = 0; i < NUM_SENSORES; i++) {
float tempC = sensores.getTempCByIndex(i);
if (tempC == DEVICE_DISCONNECTED_C) {
arquivoCSV.print("--");
} else {
arquivoCSV.print(tempC);
}
if (i < NUM_SENSORES - 1) {
arquivoCSV.print(", ");
}
}
for (int i = 0; i < numSensores; i++) {
if (sensoresConectados[i]) {
int umidade = analogRead(pinosSensores[i]);
umidade = constrain(map(umidade, 600, 373, 0, 100), 0, 100);
arquivoCSV.print(umidade,1);
} else {
arquivoCSV.print("--");
}
if (i < numSensores - 1) {
arquivoCSV.print(", ");
}
}
arquivoCSV.println();
arquivoCSV.flush();
tamanhoArquivoCSV = arquivoCSV.size();
}
void verificarEstadoSD() {
if (!SD.begin(chipSelect)) {
if (cartaoSDPresente) {
cartaoSDPresente = false;
oled.clear();
oled.println("Erro: Cartao SD removido!");
oled.displayRows();
}
} else {
if (!cartaoSDPresente) {
cartaoSDPresente = true;
abrirOuCriarArquivoCSV();
}
}
}
void monitorarTamanhoArquivoCSV() {
oled.clear();
oled.println("CSV:");
float tamanhoKB = tamanhoArquivoCSV / 1024.0;
oled.print(tamanhoKB, 1);
oled.println(" KB");
oled.displayRows();
delay(2000);
}
void atualizarDisplaySensores() {
oled.clear(); // Limpa o display antes de atualizar
if (digitalRead(pinoBotaoSwitch) == HIGH) {
oled.setCursor(0, 0); // Posiciona o cursor no início da primeira linha
for (int i = 0; i < numSensores; i++) {
oled.setCursor(0, (i + 1) * 8); // Ajusta a posição para cada linha, começando na segunda linha
// Identificador dos sensores
String idUmidade = String("U") + String(i + 1);
String idTemperatura = String("T") + String(i + 1);
// Leitura de umidade
String umidadeTexto = "--";
if (sensoresConectados[i]) {
int leituraSensor = analogRead(pinosSensores[i]);
int umidade = constrain(map(leituraSensor, 600, 373, 0, 100), 0, 100);
umidadeTexto = String(umidade) + "%";
}
// Leitura de temperatura
float tempC = sensores.getTempCByIndex(i);
String temperaturaTexto = (tempC == DEVICE_DISCONNECTED_C) ? "--" : String(tempC, 1) + " C";
// Exibe as informações formatadas
oled.print(idUmidade + ":" + umidadeTexto + " / ");
oled.println(idTemperatura + ":" + temperaturaTexto);
}
oled.displayRows(); // Atualiza o display com as informações
delay(3000);
}
}
float calcularMedia(float* valores, int tamanho) {
float soma = 0;
for (int i = 0; i < tamanho; i++) {
soma += valores[i];
}
return soma / tamanho;
}
void exibirErro(const char* mensagem) {
oled.clear();
oled.println(mensagem);
oled.displayRows();
delay(2000);
}
void abrirOuCriarArquivoCSV() {
Serial.println("Tentando abrir ou criar arquivo CSV...");
arquivoCSV = SD.open("dados.csv", FILE_WRITE);
if (!arquivoCSV) {
Serial.println("Arquivo não encontrado, criando um novo...");
arquivoCSV = SD.open("dados.csv", FILE_WRITE);
if (!arquivoCSV) {
exibirErro("Erro: Falha ao abrir/criar arquivo CSV!");
while (true);
} else {
// Inserir cabeçalho personalizado
arquivoCSV.print("Data, Hora");
for (int i = 1; i <= 8; i++) {
arquivoCSV.print(", U");
arquivoCSV.print(i);
}
for (int i = 1; i <= 8; i++) {
arquivoCSV.print(", T");
arquivoCSV.print(i);
}
arquivoCSV.println(); // Finaliza a linha do cabeçalho
arquivoCSV.flush();
Serial.println("Arquivo criado e cabeçalho inserido.");
}
} else {
Serial.println("Arquivo aberto com sucesso.");
}
}
void imprimirDadosMonitorSerial() {
Serial.println("Dados dos Sensores:");
for (int i = 0; i < numSensores; i++) {
if (sensoresConectados[i]) {
int leituraSensor = analogRead(pinosSensores[i]);
if (leituraSensor >= 0 && leituraSensor <= 1023) {
int umidade = constrain(map(leituraSensor, 600, 373, 0, 100), 0, 100);
Serial.print(nomesSensores[i]);
Serial.print(": ");
Serial.print(umidade);
Serial.println("%");
} else {
Serial.print(nomesSensores[i]);
Serial.println(": --");
}
} else {
Serial.print(nomesSensores[i]);
Serial.println(": --");
}
}
Serial.print("Tamanho do arquivo CSV: ");
float tamanhoKB = tamanhoArquivoCSV / 1024.0;
Serial.print(tamanhoKB, 1);
Serial.println(" KB");
Serial.println();
}