#include <EEPROM.h>
#include <Arduino.h>
#include <Button.h> // Assumindo que esta biblioteca Button é compatível com o uso.
#include <ACI_10K_an.h> // Biblioteca para o sensor de temperatura NTC 10K.
#include <IRremote.h> // Biblioteca para o controle remoto infravermelho.
// --- Definições de Pinos ---
// Usar um enum para nomear os pinos torna o código mais legível e fácil de manter.
enum Pin {
PIN_SENSOR_TEMPERATURA = A1,
PIN_BOTAO_BOMBEAMENTO = A2,
PIN_BOTAO_OSCILADOR = A3,
PIN_BOTAO_IONIZADOR = A4,
PIN_IR_RECEIVER = A5, // Pino para o receptor IR. (Verifique se A0 está disponível e não conflita com ACI_10K_an)
PIN_SENSOR_NIVEL_TANQUE = 2, // Entrada com PULLUP para sensor de nível (LOW = vazio, HIGH = cheio).
PIN_BOTAO_VELOCIDADE_MANUAL = 7,
PIN_BOTAO_VELOCIDADE_AUTOMATICA = 8,
PIN_LED_VELOCIDADE_BAIXA = 9,
PIN_LED_VELOCIDADE_MEDIA = 6,
PIN_LED_VELOCIDADE_ALTA = 5,
PIN_BUZZER = 3, // Buzzer para alerta de alta temperatura.
PIN_MODO_AUTOMATICO_INDICATION = 4, // Pino para indicar o modo automático (Ex: um LED).
PIN_SAIDA_BOMBA = 10,
PIN_SAIDA_OSCILADOR = 11,
PIN_SAIDA_IONIZADOR = 12,
PIN_LED_INDICADOR_TANQUE_CHEIO = 13 // LED para indicar tanque cheio.
};
// --- Definições de Botões ---
Button button1(PIN_BOTAO_BOMBEAMENTO);
Button button2(PIN_BOTAO_VELOCIDADE_MANUAL);
Button button3(PIN_BOTAO_IONIZADOR);
Button button4(PIN_BOTAO_OSCILADOR);
Button button5(PIN_BOTAO_VELOCIDADE_AUTOMATICA);
// --- Variáveis Globais ---
int velocidadeManualAtual = 1; // 1: Baixa, 2: Média, 3: Alta, 4-6: Brisa (correspondendo aos LEDs).
bool modoAutomaticoAtivo = false; // Flag para controlar o modo de velocidade automática.
int estadoNivelTanque = HIGH; // HIGH: Tanque cheio, LOW: Tanque vazio.
unsigned long tempoUltimaLeituraTemperatura = 0;
const unsigned long INTERVALO_LEITURA_TEMPERATURA = 1000; // Leitura de temperatura a cada 1 segundo (1000 ms).
const byte EEPROM_MAGIC_NUMBER = 123; // Número mágico para verificar se o EEPROM foi inicializado.
// --- Variáveis Globais para controle de FADE ---
// Estrutura para gerenciar o estado de um LED em fading.
struct FadingLEDState {
int pin; // Pino do LED.
int currentBrightness; // Brilho atual (0-255).
int targetBrightness; // Brilho alvo (0 ou 255).
unsigned long startTime; // Tempo em que o fade começou.
unsigned long duration; // Duração total do fade.
bool active; // Se o fade está ativo.
bool fadingIn; // Se está fazendo fade-in (true) ou fade-out (false).
};
// Array para armazenar o estado de fading para cada um dos 3 LEDs de velocidade.
FadingLEDState ledStates[3];
// --- Variáveis Globais para Controle Remoto IR ---
IRrecv irrecv(PIN_IR_RECEIVER); // Objeto receptor IR, conectado ao pino PIN_IR_RECEIVER.
decode_results results; // Estrutura para armazenar os resultados da decodificação IR.
unsigned long lastIrReadTime = 0; // Último tempo em que um código IR foi lido para debounce.
const unsigned long IR_DEBOUNCE_TIME = 200; // Tempo de debounce para evitar leituras múltiplas de um único pressionamento.
// --- Códigos IR (SUBSTITUA ESTES PELOS CÓDIGOS DO SEU CONTROLE REMOTO!) ---
// Para obter os códigos do seu controle, use um sketch como "IRrecvDumpV2" da biblioteca IRremote.
#define IR_CODE_POWER 0xFF00FF // Exemplo: Botão Ligar/Desligar (ou o mesmo para Sleep)
#define IR_CODE_SPEED_UP 0xFF5AA5 // Exemplo: Aumentar Velocidade
#define IR_CODE_SPEED_DOWN 0xFF1AE5 // Exemplo: Diminuir Velocidade
#define IR_CODE_AUTO_MODE 0xFF42BD // Exemplo: Modo Automático
#define IR_CODE_BRISA_MODE 0xFFD22D // Exemplo: Modo Brisa
#define IR_CODE_IONIZADOR 0xFF6897 // Exemplo: Ionizador
#define IR_CODE_OSCILADOR 0xFF52AD // Exemplo: Oscilador
#define IR_CODE_SLEEP 0xFF9867 // Exemplo: Botão Sleep (pode ser diferente do Power)
#define IR_CODE_VEL_1 0xFF30CF // Exemplo: Velocidade 1
#define IR_CODE_VEL_2 0xFF18E7 // Exemplo: Velocidade 2
#define IR_CODE_VEL_3 0xFF7A85 // Exemplo: Velocidade 3
// --- Variáveis Globais para Modo Sleep ---
bool isSleeping = false; // Flag para indicar se o sistema está no modo sleep.
unsigned long sleepStartTime = 0; // Tempo em que o modo sleep foi ativado.
unsigned long sleepDurationMillis = 0; // Duração do sleep em ms (0 para sleep indefinido).
// --- Protótipos de Funções ---
float lerTemperatura();
void desligarTodosLEDsVelocidade();
void startFade(int ledIndex, int startVal, int endVal, unsigned long duration);
void updateFadingLEDs();
void controlarVelocidadeManual();
void controlarVelocidadeAutomatica();
void controlarBombeamento();
void controlarOscilador();
void controlarIonizador();
void handleIRRemote(); // Função para lidar com comandos do controle remoto.
void enterSleepMode(unsigned long duration); // Função para ativar o modo sleep.
void exitSleepMode(); // Função para sair do modo sleep.
void processSleepTimer(); // Função para verificar o tempo de sleep.
// --- Setup Inicial ---
void setup() {
Serial.begin(9600); // Inicia a comunicação serial.
// Configuração dos pinos.
pinMode(PIN_BOTAO_BOMBEAMENTO, INPUT_PULLUP);
pinMode(PIN_BOTAO_VELOCIDADE_MANUAL, INPUT_PULLUP);
pinMode(PIN_BOTAO_IONIZADOR, INPUT_PULLUP);
pinMode(PIN_BOTAO_OSCILADOR, INPUT_PULLUP);
pinMode(PIN_BOTAO_VELOCIDADE_AUTOMATICA, INPUT_PULLUP);
pinMode(PIN_SENSOR_NIVEL_TANQUE, INPUT_PULLUP); // Sensor de nível com pull-up.
pinMode(PIN_SENSOR_TEMPERATURA, INPUT); // Pino analógico para sensor de temperatura.
pinMode(PIN_IR_RECEIVER, INPUT); // Pino para o receptor IR.
pinMode(PIN_LED_VELOCIDADE_BAIXA, OUTPUT);
pinMode(PIN_LED_VELOCIDADE_MEDIA, OUTPUT);
pinMode(PIN_LED_VELOCIDADE_ALTA, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_MODO_AUTOMATICO_INDICATION, OUTPUT);
pinMode(PIN_SAIDA_BOMBA, OUTPUT);
pinMode(PIN_SAIDA_OSCILADOR, OUTPUT);
pinMode(PIN_SAIDA_IONIZADOR, OUTPUT);
pinMode(PIN_LED_INDICADOR_TANQUE_CHEIO, OUTPUT);
// Inicializa o estado dos LEDs para fading.
ledStates[0] = {PIN_LED_VELOCIDADE_BAIXA, 0, 0, 0, 0, false, false};
ledStates[1] = {PIN_LED_VELOCIDADE_MEDIA, 0, 0, 0, 0, false, false};
ledStates[2] = {PIN_LED_VELOCIDADE_ALTA, 0, 0, 0, 0, false, false};
// Inicializa os botões.
button1.begin();
button2.begin();
button3.begin();
button4.begin();
button5.begin();
// Checa e inicializa a EEPROM na primeira vez.
if (EEPROM.read(0) != EEPROM_MAGIC_NUMBER) {
for (int i = 0; i < EEPROM.length(); i++) {
EEPROM.write(i, 0); // Escreve 0 em todas as posições.
}
EEPROM.write(0, EEPROM_MAGIC_NUMBER); // Marca o EEPROM como inicializado.
Serial.println("EEPROM inicializado pela primeira vez.");
} else {
Serial.println("EEPROM já inicializado.");
}
// Garante que todas as saídas estejam em um estado inicial conhecido.
digitalWrite(PIN_MODO_AUTOMATICO_INDICATION, LOW);
digitalWrite(PIN_SAIDA_BOMBA, LOW);
digitalWrite(PIN_SAIDA_OSCILADOR, LOW);
digitalWrite(PIN_SAIDA_IONIZADOR, LOW);
digitalWrite(PIN_LED_INDICADOR_TANQUE_CHEIO, LOW);
desligarTodosLEDsVelocidade(); // Desliga todos os LEDs de velocidade.
irrecv.enableIRIn(); // Inicia o receptor IR.
Serial.println("Receptor IR ativado.");
}
// --- Loop Principal ---
void loop() {
// handleIRRemote(); // Sempre verifica por comandos IR, mesmo no modo sleep.
// É importante ler o estado dos botões físicos continuamente,
// pois eles podem ser usados para "acordar" o dispositivo do sleep.
button1.read();
button2.read();
button3.read();
button4.read();
button5.read();
if (isSleeping) {
processSleepTimer(); // Verifica se o tempo de sleep expirou.
// Se qualquer botão físico for pressionado enquanto está dormindo, "acorda" o dispositivo.
if (button1.pressed() || button2.pressed() || button3.pressed() || button4.pressed() || button5.pressed()) {
Serial.println("Botao fisico pressionado. Saindo do modo Sleep.");
exitSleepMode();
}
return; // Pula todas as outras lógicas se estiver no modo sleep.
}
// --- Operação Normal (apenas se não estiver no modo sleep) ---
controlarVelocidadeManual();
controlarVelocidadeAutomatica();
controlarBombeamento();
controlarOscilador();
controlarIonizador();
updateFadingLEDs(); // Chama a função para atualizar os LEDs em fading.
// Leitura e exibição da temperatura em um intervalo definido.
if (millis() - tempoUltimaLeituraTemperatura >= INTERVALO_LEITURA_TEMPERATURA) {
tempoUltimaLeituraTemperatura = millis(); // Atualiza o tempo da última leitura.
float temperatura = lerTemperatura();
Serial.print("Temperatura: ");
Serial.print(temperatura);
Serial.println(" ℃");
}
}
// --- Funções de Controle ---
/**
* @brief Lê o valor do sensor de temperatura NTC 10K e converte para Celsius.
* @return A temperatura em graus Celsius.
*/
float lerTemperatura() {
Aci_10K an10k; // Cria uma instância do objeto Aci_10K.
return an10k.getTemp(analogRead(PIN_SENSOR_TEMPERATURA));
delay(1000);
}
/**
* @brief Desliga todos os LEDs de velocidade e desativa qualquer fade ativo.
* Usa analogWrite(0) para garantir que saídas PWM também sejam desligadas.
*/
void desligarTodosLEDsVelocidade() {
for (int i = 0; i < 3; i++) {
ledStates[i].active = false; // Desativa qualquer fade ativo para este LED.
analogWrite(ledStates[i].pin, 0); // Define o brilho para 0.
ledStates[i].currentBrightness = 0; // Reinicia o brilho atual.
}
}
/**
* @brief Inicia um efeito de fade para um LED específico.
* @param ledIndex Índice do LED (0, 1 ou 2).
* @param startVal Brilho inicial (0-255).
* @param endVal Brilho final (0-255).
* @param duration Duração do fade em milissegundos.
*/
void startFade(int ledIndex, int startVal, int endVal, unsigned long duration) {
if (ledIndex < 0 || ledIndex > 2) return; // Garante que o índice é válido.
ledStates[ledIndex].active = true;
ledStates[ledIndex].startTime = millis();
ledStates[ledIndex].duration = duration;
ledStates[ledIndex].currentBrightness = startVal;
ledStates[ledIndex].targetBrightness = endVal;
ledStates[ledIndex].fadingIn = (endVal > startVal); // Define a direção do fade.
}
/**
* @brief Atualiza o brilho dos LEDs que estão em fading.
* Esta função deve ser chamada repetidamente no loop principal para gerenciar os efeitos de fade.
*/
void updateFadingLEDs() {
for (int i = 0; i < 3; i++) {
if (ledStates[i].active) {
unsigned long elapsedTime = millis() - ledStates[i].startTime; // Tempo decorrido desde o início do fade.
if (elapsedTime < ledStates[i].duration) {
// Calcula o progresso do fade e o novo brilho.
float progress = (float)elapsedTime / ledStates[i].duration;
int brightnessRange = ledStates[i].targetBrightness - ledStates[i].currentBrightness;
int newBrightness = ledStates[i].currentBrightness + (brightnessRange * progress);
analogWrite(ledStates[i].pin, newBrightness); // Aplica o novo brilho.
} else {
// Fade concluído, define o brilho final e transiciona para o próximo estado da "brisa".
analogWrite(ledStates[i].pin, ledStates[i].targetBrightness);
ledStates[i].currentBrightness = ledStates[i].targetBrightness;
// Lógica para alternar entre fade-in e fade-out para o efeito de "brisa".
if (ledStates[i].fadingIn && ledStates[i].targetBrightness == 255) {
// Se era um fade-in para 255, iniciar um fade-out para 0 com duração aleatória.
startFade(i, 255, 0, random(500, 1500));
} else if (!ledStates[i].fadingIn && ledStates[i].targetBrightness == 0) {
// Se era um fade-out para 0, iniciar um fade-in para 255 com duração aleatória.
startFade(i, 0, 255, random(500, 1500));
} else {
// Se não for um ciclo de brisa contínuo, apenas desativar o fade.
ledStates[i].active = false;
}
}
}
}
}
/**
* @brief Controla a velocidade manual e os modos de "brisa".
* Altera entre 6 estados (3 velocidades fixas, 3 modos de brisa).
*/
void controlarVelocidadeManual() {
// Só permite a mudança de velocidade manual se o modo automático não estiver ativo.
if (!modoAutomaticoAtivo) {
if (button2.pressed()) { // Se o botão de velocidade manual for pressionado.
velocidadeManualAtual = (velocidadeManualAtual % 6) + 1; // Cicla entre 1 e 6.
}
desligarTodosLEDsVelocidade(); // Desliga todos os LEDs e para quaisquer fades ativos.
// Lógica para acender os LEDs e ativar os modos de brisa.
switch (velocidadeManualAtual) {
case 1: // Velocidade Baixa
analogWrite(PIN_LED_VELOCIDADE_BAIXA, 255); // LED aceso fixo.
Serial.println("Velocidade: Baixa");
break;
case 2: // Velocidade Média
analogWrite(PIN_LED_VELOCIDADE_MEDIA, 255); // LED aceso fixo.
Serial.println("Velocidade: Media");
break;
case 3: // Velocidade Alta
analogWrite(PIN_LED_VELOCIDADE_ALTA, 255); // LED aceso fixo.
Serial.println("Velocidade: Alta");
break;
case 4: // Modo Brisa Baixa
startFade(0, 0, 255, random(500, 1500)); // Começa com fade-in para 255.
Serial.println("Velocidade: Brisa Baixa");
break;
case 5: // Modo Brisa Média
startFade(1, 0, 255, random(500, 1500)); // Começa com fade-in para 255.
Serial.println("Velocidade: Brisa Media");
break;
case 6: // Modo Brisa Alta
startFade(2, 0, 255, random(500, 1500)); // Começa com fade-in para 255.
Serial.println("Velocidade: Brisa Alta");
break;
}
}
}
/**
* @brief Controla o modo de velocidade automática baseado na temperatura.
* Alterna o estado do modo automático com cada pressionamento de botão.
*/
void controlarVelocidadeAutomatica() {
if (button5.pressed()) { // Se o botão de velocidade automática for pressionado.
modoAutomaticoAtivo = !modoAutomaticoAtivo; // Alterna o estado.
digitalWrite(PIN_MODO_AUTOMATICO_INDICATION, modoAutomaticoAtivo); // Acende/apaga LED indicador.
if (modoAutomaticoAtivo) {
Serial.println("Modo Automatico: ATIVADO");
} else {
Serial.println("Modo Automatico: DESATIVADO");
desligarTodosLEDsVelocidade(); // Desliga LEDs ao sair do modo automático.
}
}
if (modoAutomaticoAtivo) {
float celsius = lerTemperatura(); // Lê a temperatura.
// Mapeia a temperatura para um brilho PWM (0-255).
int brilho = constrain(map(celsius, 18, 30, 0, 255), 0, 255);
desligarTodosLEDsVelocidade(); // Desliga todos os LEDs para garantir que apenas um esteja ativo.
// Ajusta a velocidade e acende o LED correspondente com base na temperatura.
if (celsius < 20) {
analogWrite(PIN_LED_VELOCIDADE_BAIXA, brilho);
Serial.print("Auto Velocidade: Baixa ("); Serial.print(celsius); Serial.println("C)");
} else if (celsius < 25) {
analogWrite(PIN_LED_VELOCIDADE_MEDIA, brilho);
Serial.print("Auto Velocidade: Media ("); Serial.print(celsius); Serial.println("C)");
} else if (celsius < 30) {
analogWrite(PIN_LED_VELOCIDADE_ALTA, brilho);
Serial.print("Auto Velocidade: Alta ("); Serial.print(celsius); Serial.println("C)");
} else {
tone(PIN_BUZZER, 2000, 250); // Toca um tom de 2kHz por 250ms.
Serial.print("ALERTA: Temperatura muito alta! ("); Serial.print(celsius); Serial.println("C)");
}
}
}
/**
* @brief Controla o bombeamento de água com base no botão e no nível do tanque.
*/
void controlarBombeamento() {
// Alterna o estado da bomba ao pressionar o botão, se o tanque não estiver vazio.
// `toggled()` verifica se o estado do botão mudou, e `read() == Button::PRESSED` confirma que foi um pressionamento.
if (button1.toggled() && button1.read() == Button::PRESSED) {
// A bomba só liga se o sensor de nível não indicar "vazio" (LOW) e a bomba estiver desligada.
// Ou, se a bomba estiver ligada, o botão a desliga.
if (digitalRead(PIN_SENSOR_NIVEL_TANQUE) == HIGH) { // Se o tanque está vazio (sensor !LOW).
Serial.println("Tanque vazio, bomba nao pode ser ligada manualmente.");
// Opcional: feedback visual ou sonoro de tanque vazio.
} else {
digitalWrite(PIN_SAIDA_BOMBA, !digitalRead(PIN_SAIDA_BOMBA)); // Alterna o estado da bomba.
Serial.print("Bomba: ");
Serial.println(digitalRead(PIN_SAIDA_BOMBA) == HIGH ? "LIGADA" : "DESLIGADA");
}
}
// Monitora continuamente o nível do tanque para desligar a bomba se ficar vazio.
int leituraNivelAtual = digitalRead(PIN_SENSOR_NIVEL_TANQUE);
if (estadoNivelTanque != leituraNivelAtual) { // Se o nível do tanque mudou.
estadoNivelTanque = leituraNivelAtual; // Atualiza o estado.
if (leituraNivelAtual == LOW) { // Se o tanque está cheio.
digitalWrite(PIN_LED_INDICADOR_TANQUE_CHEIO, HIGH); // Acende o LED de tanque cheio.
//digitalWrite(PIN_SAIDA_BOMBA, LOW); // Desliga a bomba se o tanque estiver cheio (comentado se a bomba for controlada apenas pelo botão).
Serial.println("Tanque Cheio");
} else { // Se o tanque está vazio.
digitalWrite(PIN_LED_INDICADOR_TANQUE_CHEIO, LOW); // Apaga o LED de tanque cheio.
digitalWrite(PIN_SAIDA_BOMBA, LOW); // **Essencial**: Desliga a bomba se o tanque ficar vazio.
Serial.println("Tanque Vazio");
}
}
}
/**
* @brief Controla o oscilador (movimento).
* Alterna o estado do oscilador a cada pressionamento de botão.
*/
void controlarOscilador() {
if (button4.toggled() && button4.read() == Button::PRESSED) {
digitalWrite(PIN_SAIDA_OSCILADOR, !digitalRead(PIN_SAIDA_OSCILADOR));
Serial.print("Oscilador: ");
Serial.println(digitalRead(PIN_SAIDA_OSCILADOR) == HIGH ? "LIGADO" : "DESLIGADO");
}
}
/**
* @brief Controla o ionizador.
* Alterna o estado do ionizador a cada pressionamento de botão.
*/
void controlarIonizador() {
if (button3.toggled() && button3.read() == Button::PRESSED) {
digitalWrite(PIN_SAIDA_IONIZADOR, !digitalRead(PIN_SAIDA_IONIZADOR));
Serial.print("Ionizador: ");
Serial.println(digitalRead(PIN_SAIDA_IONIZADOR) == HIGH ? "LIGADO" : "DESLIGADO");
}
}
/**
* @brief Lida com os comandos recebidos do controle remoto IR.
* Esta função deve ser chamada no loop principal.
*/
void handleIRRemote() {
if (irrecv.decode(&results)) { // Se um código IR foi recebido.
unsigned long currentMillis = millis();
// Debounce para evitar múltiplas leituras de um único pressionamento de botão.
if (currentMillis - lastIrReadTime > IR_DEBOUNCE_TIME) {
lastIrReadTime = currentMillis;
Serial.print("Codigo IR recebido: 0x");
Serial.println(results.value, HEX);
// Se o sistema estiver dormindo, qualquer sinal IR (ou um botão específico)
// pode ser usado para acordá-lo. Aqui, qualquer sinal IR acorda o dispositivo.
if (isSleeping) {
Serial.println("Sinal IR recebido. Saindo do modo Sleep.");
exitSleepMode();
irrecv.resume(); // Continua esperando pelo próximo sinal IR.
return; // Pula o processamento do comando se acabou de acordar, para evitar ações indesejadas.
}
// Processa o comando IR apenas se o sistema não estiver dormindo.
switch (results.value) {
case IR_CODE_POWER:
// O botão Power agora alterna entre ligar/desligar (entrar/sair do sleep).
if (!isSleeping) {
enterSleepMode(0); // Sleep indefinido (até ser acordado por IR ou botão físico).
} else {
exitSleepMode();
}
break;
case IR_CODE_SLEEP:
// O botão Sleep pode ser usado para um temporizador de sleep, por exemplo, 30 minutos.
enterSleepMode(30 * 60 * 1000UL); // 30 minutos de sleep.
break;
case IR_CODE_SPEED_UP:
// Aumenta a velocidade manual (simula pressionar o botão 2)
if (velocidadeManualAtual < 6) { // Max 6 estados de velocidade/brisa.
velocidadeManualAtual++;
} else {
velocidadeManualAtual = 1; // Volta para a velocidade 1.
}
Serial.print("IR: Velocidade "); Serial.println(velocidadeManualAtual);
desligarTodosLEDsVelocidade(); // Garante que os LEDs são resetados antes de aplicar a nova velocidade.
break;
case IR_CODE_SPEED_DOWN:
// Diminui a velocidade manual (simula pressionar o botão 2 ao contrário)
if (velocidadeManualAtual > 1) {
velocidadeManualAtual--;
} else {
velocidadeManualAtual = 6; // Volta para a velocidade 6 (brisa alta).
}
Serial.print("IR: Velocidade "); Serial.println(velocidadeManualAtual);
desligarTodosLEDsVelocidade();
break;
case IR_CODE_VEL_1:
velocidadeManualAtual = 1;
Serial.println("IR: Velocidade 1");
desligarTodosLEDsVelocidade();
break;
case IR_CODE_VEL_2:
velocidadeManualAtual = 2;
Serial.println("IR: Velocidade 2");
desligarTodosLEDsVelocidade();
break;
case IR_CODE_VEL_3:
velocidadeManualAtual = 3;
Serial.println("IR: Velocidade 3");
desligarTodosLEDsVelocidade();
break;
case IR_CODE_AUTO_MODE:
modoAutomaticoAtivo = !modoAutomaticoAtivo;
digitalWrite(PIN_MODO_AUTOMATICO_INDICATION, modoAutomaticoAtivo);
Serial.print("IR: Modo Automatico: "); Serial.println(modoAutomaticoAtivo ? "ATIVADO" : "DESATIVADO");
desligarTodosLEDsVelocidade();
break;
case IR_CODE_BRISA_MODE:
velocidadeManualAtual = 4; // Pode definir para uma brisa específica, ex: Brisa Baixa (estado 4).
Serial.println("IR: Modo Brisa (Baixa) ativado.");
desligarTodosLEDsVelocidade();
break;
case IR_CODE_IONIZADOR:
digitalWrite(PIN_SAIDA_IONIZADOR, !digitalRead(PIN_SAIDA_IONIZADOR));
Serial.print("IR: Ionizador: "); Serial.println(digitalRead(PIN_SAIDA_IONIZADOR) == HIGH ? "LIGADO" : "DESLIGADO");
break;
case IR_CODE_OSCILADOR:
digitalWrite(PIN_SAIDA_OSCILADOR, !digitalRead(PIN_SAIDA_OSCILADOR));
Serial.print("IR: Oscilador: "); Serial.println(digitalRead(PIN_SAIDA_OSCILADOR) == HIGH ? "LIGADO" : "DESLIGADO");
break;
default:
Serial.println("Codigo IR desconhecido.");
break;
}
}
irrecv.resume(); // Prepara o receptor para o próximo sinal IR.
}
}
/**
* @brief Ativa o modo de sleep do sistema.
* Desliga todas as saídas para economizar energia.
* @param duration Duração do sleep em milissegundos (0 para sleep indefinido).
*/
void enterSleepMode(unsigned long duration) {
if (isSleeping) return; // Já está dormindo.
isSleeping = true;
sleepStartTime = millis();
sleepDurationMillis = duration;
// Desliga todas as saídas ativas para economizar energia.
digitalWrite(PIN_MODO_AUTOMATICO_INDICATION, LOW);
digitalWrite(PIN_SAIDA_BOMBA, LOW);
digitalWrite(PIN_SAIDA_OSCILADOR, LOW);
digitalWrite(PIN_SAIDA_IONIZADOR, LOW);
digitalWrite(PIN_LED_INDICADOR_TANQUE_CHEIO, LOW);
desligarTodosLEDsVelocidade(); // Isso também para os LEDs em fading.
Serial.print("Entrando no modo Sleep por ");
if (duration == 0) {
Serial.println("tempo indefinido (esperando IR ou botao fisico)...");
} else {
Serial.print(duration / 1000);
Serial.println(" segundos...");
}
// Para um "deep sleep" real (consumo de energia muito baixo), você precisaria
// usar bibliotecas como avr/sleep.h ou LowPower.h e lidar com interrupções para acordar.
// Esta implementação desliga periféricos e pausa a lógica principal, mas não o chip.
}
/**
* @brief Sai do modo de sleep.
* Reativa as saídas e a lógica principal.
*/
void exitSleepMode() {
if (!isSleeping) return; // Não está dormindo.
isSleeping = false;
sleepDurationMillis = 0; // Reseta a duração do sleep.
// Opcional: Aqui você pode restaurar o estado anterior dos dispositivos,
// ou deixá-los desligados para que o usuário os ative novamente.
// Por simplicidade, eles começam desligados ao acordar.
digitalWrite(PIN_MODO_AUTOMATICO_INDICATION, LOW);
digitalWrite(PIN_SAIDA_BOMBA, LOW);
digitalWrite(PIN_SAIDA_OSCILADOR, LOW);
digitalWrite(PIN_SAIDA_IONIZADOR, LOW);
digitalWrite(PIN_LED_INDICADOR_TANQUE_CHEIO, LOW);
desligarTodosLEDsVelocidade();
Serial.println("Saindo do modo Sleep.");
}
/**
* @brief Verifica se o tempo de sleep programado expirou.
* Se expirou, chama a função para sair do modo sleep.
*/
void processSleepTimer() {
// Se a duração do sleep for maior que 0 (sleep temporizado) e o tempo expirou.
if (sleepDurationMillis > 0 && millis() - sleepStartTime >= sleepDurationMillis) {
Serial.println("Tempo de Sleep esgotado. Saindo do modo Sleep.");
exitSleepMode();
}
}