#include <OneWire.h>
#include <DallasTemperature.h>
#include <RTClib.h>
#include <SD.h>
#include <SPI.h>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
#include <avr/wdt.h> // Inclua a biblioteca para o watchdog timer
// 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 = 10; // Pino do Arduino para o chip select do cartão SD
File arquivoCSV; // Objeto para o arquivo CSV no cartão SD
float tamanhoArquivoCSV = 0; // Variável para armazenar o tamanho do arquivo CSV
// Definições para os sensores de umidade
const int numSensores = 8; // Número de sensores de umidade
const int pinosSensores[numSensores] = {A0, A1, A2, A3, 5, A7, 2, 3}; // Pinos analógicos conectados aos sensores
const char* nomesSensores[numSensores] = {
"SWC120", "SWC140", "SWC160", "SWC180",
"SWC220", "SWC240", "SWC260", "SWC280"
}; // Nomes dos sensores para identificação
bool sensoresConectados[numSensores] = {false}; // Array para rastrear o status de conexão dos sensores
// Pinos e variáveis para o botão de delete e reset
const int pinoBotaoReset = 9;
const int pinoBotaoSwitch = 6; // Defina o pino digital para o botão switch
const int pinoBotaoDelete = 4;
unsigned long tempoPressionadoDelete = 0;
bool buttonPressedDelete = false;
const unsigned long tempoBarraProgresso = 4000; // Tempo para preencher a barra de progresso (4 segundos)
// Variáveis para rastrear o tempo
unsigned long ultimoVerificaConexao = 0; // Tempo da última verificação de conexão dos sensores
const unsigned long intervaloVerificaConexao = 1000; // Intervalo de verificação de 1 segundo
const unsigned long intervaloAtualizacaoUmidade = 600000; // Intervalo de atualização da umidade dos sensores a cada 10 minutos
unsigned long ultimoAtualizacaoUmidade = 0; // Último tempo de atualização da umidade
unsigned long ultimoMonitoramentoArquivo = 0; // Último tempo de monitoramento do tamanho do arquivo CSV
const unsigned long intervaloMonitoramentoArquivo = 20000; // Intervalo de monitoramento do tamanho do arquivo a cada 20 segundos
// Variáveis para rastrear o tempo das verificações
unsigned long ultimoVerificaRTC = 0; // Último tempo de verificação do RTC
const unsigned long intervaloVerificaRTC = 1800000; // Intervalo de verificação do RTC a cada 30 minutos
unsigned long ultimoVerificaSD = 0; // Último tempo de verificação do cartão SD
const unsigned long intervaloVerificaSD = 2000; // Intervalo de verificação do estado do cartão SD a cada 2 segundos
bool cartaoSDPresente = false; // Variável para rastrear o estado do cartão SD
// Protocolo One Wire para DS18B20
OneWire oneWire(7);
DallasTemperature sensors(&oneWire); // Sensores de temperatura
DeviceAddress ds18; // Endereço do sensor DS18B20
byte c; // Contador de sensores
// Fatores de calibração específicos para cada sensor DS18B20
float CALIBRACAO_TEMP[] = {
-1.3, // Calibração para o sensor 1
0.5, // Calibração para o sensor 2
-0.3, // Calibração para o sensor 3
0.2, // Calibração para o sensor 4
0.5, // Calibração para o sensor 5
0.2, // Calibração para o sensor 6
0.2, // Calibração para o sensor 7
0.2 // Calibração para o sensor 8
};
void sensorID(DeviceAddress sensor) {
// Exibe ID do Sensor de temperatura
for (uint8_t i = 0; i < 8; i++) {
if (sensor[i] < 16)
Serial.print("0");
Serial.print(sensor[i], HEX);
}
}
void setupTemperatura() {
// Inicializa Sensores de Temperatura
sensors.begin();
sensors.setResolution(12);
c = sensors.getDeviceCount();
Serial.print("DS18B20 identificados: ");
Serial.println(c);
}
void setup() {
// Inicialização do display OLED
Wire.begin();
oled.begin(&Adafruit128x64, I2C_ADDRESS);
oled.setFont(System5x7);
setupTemperatura();
// Inicialização do RTC
if (!rtc.begin()) {
exibirErro("Erro: RTC nao encontrado!");
while (true); // Travar o código em caso de erro
}
// Verificar se o cartão SD está presente
if (!SD.begin(chipSelect)) {
exibirErro("Erro: Cartao SD nao encontrado!");
while (true); // Travar o código em caso de erro
}
cartaoSDPresente = true;
// Abrir ou criar o arquivo CSV inicial
abrirOuCriarArquivoCSV();
// Configuração dos pinos dos botões
pinMode(pinoBotaoReset, INPUT_PULLUP); // Configurar o pino como entrada com pull-up interno
pinMode(pinoBotaoDelete, INPUT_PULLUP); // Configurar o pino como entrada com pull-up interno
pinMode(pinoBotaoSwitch, INPUT_PULLUP); // Configurar o pino como entrada com pull-up interno
// Inicialização do Monitor Serial
Serial.begin(115200); // Inicializa a comunicação serial
//Inicialização do sistema
oled.clear();
oled.println("Iniciando Sensor...");
oled.displayRows(); // Atualiza o display OLED
delay(2000);
// Outras inicializações e mensagens no OLED
oled.clear();
oled.println("Modulos OK");
oled.displayRows(); // Atualiza o display OLED
delay(2000);
}
void loop() {
unsigned long tempoAtual = millis();
// Verificações periódicas
if (tempoAtual - ultimoVerificaConexao >= intervaloVerificaConexao) {
ultimoVerificaConexao = tempoAtual;
verificarConexaoSensores();
}
if (cartaoSDPresente && tempoAtual - ultimoAtualizacaoUmidade >= intervaloAtualizacaoUmidade) {
ultimoAtualizacaoUmidade = tempoAtual;
atualizarUmidadeSensores();
}
// Verificar o estado do SD Card
verificarEstadoSD();
// Monitorar o tamanho do arquivo CSV a cada 20 segundos
if (tempoAtual - ultimoMonitoramentoArquivo >= intervaloMonitoramentoArquivo) {
ultimoMonitoramentoArquivo = tempoAtual;
monitorarTamanhoArquivoCSV();
}
// Verificar o estado do botão de delete
if (digitalRead(pinoBotaoDelete) == LOW) { // Botão pressionado
if (!buttonPressedDelete) {
tempoPressionadoDelete = millis();
buttonPressedDelete = true;
} else {
unsigned long tempoPressionado = millis() - tempoPressionadoDelete;
if (tempoPressionado >= tempoBarraProgresso) {
deletarArquivo();
// Esperar até que o botão seja liberado para evitar repetição
while (digitalRead(pinoBotaoDelete) == LOW) {
delay(10); // Pequeno atraso para evitar debouncing
}
buttonPressedDelete = false;
} else {
mostrarBarraProgresso(tempoPressionado, tempoBarraProgresso);
}
}
} else {
buttonPressedDelete = false;
}
// Verificar o estado do botão de reset
if (digitalRead(pinoBotaoReset) == LOW) { // Botão pressionado
resetarArduino(); // Chama a função de reset
// Aguardar até que o botão seja liberado para evitar reinicializações repetidas
while (digitalRead(pinoBotaoReset) == LOW) {
delay(50); // Pequeno atraso para evitar debouncing
}
}
// Verificar o estado do botão switch e controlar o display OLED
verificarEstadoSwitch();
// Atualizar a visualização dos sensores conectados
atualizarDisplaySensores();
// Imprimir dados no Monitor Serial
imprimirDadosMonitorSerial();
// Leitura dos sensores de temperatura
sensors.requestTemperatures();
// Leitura e exibição das temperaturas DS18B20
for (byte i = 0; i < c; i++) {
if (sensors.getAddress(ds18, i)) {
float temperatura = sensors.getTempC(ds18) + CALIBRACAO_TEMP[i];
if (temperatura != DEVICE_DISCONNECTED_C) {
// Exibe a temperatura no Monitor Serial
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(temperatura);
Serial.println(" C");
} else {
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.println(" desconectado");
}
}
}
// Verificações periódicas adicionais
if (tempoAtual - ultimoVerificaRTC >= intervaloVerificaRTC) {
ultimoVerificaRTC = tempoAtual;
verificarRTC();
}
delay(10); // Pequeno atraso para evitar sobrecarga do loop
}
void resetarArduino() {
wdt_enable(WDTO_15MS); // Ativa o watchdog timer para reiniciar o Arduino
while (1) {} // Espera até que o watchdog reinicie o Arduino
}
void exibirErro(const char* mensagem) {
oled.clear();
oled.println(mensagem);
oled.displayRows(); // Atualiza o display OLED
delay(5000); // Aguarda 5 segundos para exibir a mensagem de erro
}
void abrirOuCriarArquivoCSV() {
if (cartaoSDPresente) {
// Abre o arquivo CSV, cria se não existir
arquivoCSV = SD.open("dados.csv", FILE_WRITE);
if (arquivoCSV) {
// Escreve o cabeçalho do arquivo CSV com a formatação correta
arquivoCSV.println("Data,Hora,Umidade1,Umidade2,Umidade3,Umidade4,Umidade5,Umidade6,Umidade7,Umidade8,Temperatura1,Temperatura2,Temperatura3,Temperatura4,Temperatura5,Temperatura6,Temperatura7,Temperatura8");
arquivoCSV.close(); // Fecha o arquivo após escrever o cabeçalho
} else {
exibirErro("Erro: Não foi possível criar o arquivo CSV.");
}
} else {
exibirErro("Erro: Cartão SD não encontrado.");
}
}
void deletarArquivo() {
// Limpa a barra de progresso e exibe mensagem de exclusão
oled.clear();
oled.println("Deletando arquivo...");
oled.displayRows();
delay(2000); // Simula o tempo de exclusão do arquivo
// Fecha o arquivo CSV antes de deletá-lo
arquivoCSV.close();
// Deleta o arquivo CSV
if (SD.remove("datalog.csv")) {
oled.println("Arquivo deletado");
delay(2000);
abrirOuCriarArquivoCSV(); // Recria o arquivo CSV após deletá-lo
} else {
oled.println("Erro ao deletar");
delay(2000);
}
oled.displayRows(); // Atualiza o display OLED
}
void verificarConexaoSensores() {
for (int i = 0; i < numSensores; i++) {
int valorSensor = analogRead(pinosSensores[i]);
bool conectado = (valorSensor <= 270); // Define o limiar de desconexão
sensoresConectados[i] = conectado;
}
}
void atualizarUmidadeSensores() {
arquivoCSV.println("Atualizando Umidade...");
arquivoCSV.flush(); // Garante que os dados sejam gravados no arquivo CSV
}
void mostrarBarraProgresso(unsigned long tempoDecorrido, unsigned long tempoTotal) {
oled.clear();
oled.println("Deletando...");
int larguraBarra = (tempoDecorrido * 128) / tempoTotal; // Calcula a largura da barra
int larguraMaxima = 128; // Largura máxima da tela OLED
// Preenche a barra com caracteres '|'
for (int i = 0; i < larguraBarra; i += 6) { // 6 é a largura aproximada de um caractere '|'
oled.setCursor(i, 20);
oled.print("|");
}
// Desenha bordas da barra
oled.setCursor(0, 20);
oled.print("[");
oled.setCursor(larguraMaxima - 6, 20); // Ajusta a posição para o final da barra
oled.print("]");
oled.displayRows(); // Atualiza o display OLED
}
void monitorarTamanhoArquivoCSV() {
tamanhoArquivoCSV = arquivoCSV.size() / 1024.0; // Atualiza o tamanho do arquivo em KB
if (tamanhoArquivoCSV >= 100) { // Verifica se o arquivo CSV excedeu 100 KB
deletarArquivo();
}
}
void verificarEstadoSD() {
if (digitalRead(pinoBotaoSwitch) == LOW) {
if (!SD.begin(chipSelect)) {
exibirErro("Erro: Cartao SD desconectado!");
}
cartaoSDPresente = true;
}
}
void atualizarDisplaySensores() {
oled.clear();
for (int i = 0; i < numSensores; i++) {
oled.setCursor(0, i*2); // Posiciona o cursor para cada sensor
if (sensoresConectados[i]) {
oled.print(nomesSensores[i]);
oled.print(": ");
oled.print(analogRead(pinosSensores[i]));
oled.print(" / ");
// Adicione o valor da temperatura se DS18B20 conectado
if (i < c && sensors.getAddress(ds18, i)) {
float temperatura = sensors.getTempC(ds18) + CALIBRACAO_TEMP[i];
if (temperatura != DEVICE_DISCONNECTED_C) {
oled.print(temperatura);
oled.print(" C");
} else {
oled.print("--");
}
} else {
oled.print("--");
}
} else {
oled.print(nomesSensores[i]);
oled.print(": -- / --");
}
}
oled.displayRows(); // Atualiza o display OLED
}
void imprimirDadosMonitorSerial() {
for (int i = 0; i < numSensores; i++) {
Serial.print(nomesSensores[i]);
Serial.print(": ");
if (sensoresConectados[i]) {
Serial.print(analogRead(pinosSensores[i]));
// Adiciona a temperatura do DS18B20 se o sensor estiver conectado
if (i < c && sensors.getAddress(ds18, i)) {
float temperatura = sensors.getTempC(ds18) + CALIBRACAO_TEMP[i];
if (temperatura != DEVICE_DISCONNECTED_C) {
Serial.print(" / ");
Serial.print(temperatura);
Serial.print(" C");
} else {
Serial.print(" / --");
}
} else {
Serial.print(" / --");
}
} else {
Serial.print("-- / --");
}
Serial.println();
}
}
void verificarEstadoSwitch() {
if (digitalRead(pinoBotaoSwitch) == LOW) {
delay(50); // Pequeno atraso para evitar debouncing
while (digitalRead(pinoBotaoSwitch) == LOW) {
// Espera até que o botão seja liberado
delay(10);
}
delay(50); // Atraso adicional para evitar detecção de múltiplos toques
toggleOLED(); // Chama a função para ligar/desligar o OLED
}
}
void toggleOLED() {
static bool oledLigado = true; // Estado inicial do OLED
if (oledLigado) {
oled.ssd1306WriteCmd(SSD1306_DISPLAYOFF); // Desliga o display
} else {
oled.ssd1306WriteCmd(SSD1306_DISPLAYON); // Liga o display
}
oledLigado = !oledLigado; // Alterna o estado do OLED
}
void verificarRTC() {
if (!rtc.begin()) {
exibirErro("Erro: Falha ao comunicar com RTC!");
} else {
Serial.println("RTC verificado e em execucao.");
}
}
Loading
ds18b20
ds18b20