// === PINOS DE RELÉS ===
#define REL_VALVULA 14
#define REL_DRENAGEM 27
#define REL_RESIST 26
#define REL_CIRCULA 25
#define REL_DOSADOR 33
// === PINOS DE SENSORES ===
#define SENSOR_NIVEL_ALTO 32
#define SENSOR_NIVEL_BAIXO 35
#define SENSOR_TEMP 34
// === BOTÃO INÍCIO/PAUSA ===
#define BOTAO_START_PAUSE 13
bool emExecucao = false;
bool cicloFinalizado = false;
// === TEMPOS DE ETAPAS (em milissegundos) ===
#define TEMPO_CIRCULA_FRIO (8 * 60 * 100UL)
#define TEMPO_AQUECIMENTO_MAX (15 * 60 * 100UL)
#define TEMPO_CIRCULA_QUENTE (40 * 60 * 100UL)
#define TEMPO_ENXAGUE_QUENTE (2 * 60 * 100UL)
#define TEMPO_SECAGEM (30 * 60 * 100UL)
#define TEMP_LIMITE_CIRCULA 60.0 // Celsius
#define TEMPO_ABASTECER 30000 // segurança: desliga válvula após 30s
bool estadoValvula = false;
bool estadoDreno = false;
bool estadoCircula = false;
bool estadoResist = false;
bool estadoDosador = false;
void setup() {
Serial.begin(115200);
// Relés
pinMode(REL_VALVULA, OUTPUT);
pinMode(REL_DRENAGEM, OUTPUT);
pinMode(REL_RESIST, OUTPUT);
pinMode(REL_CIRCULA, OUTPUT);
pinMode(REL_DOSADOR, OUTPUT);
// Sensores
pinMode(SENSOR_NIVEL_ALTO, INPUT_PULLUP);
pinMode(SENSOR_NIVEL_BAIXO, INPUT_PULLUP);
pinMode(SENSOR_TEMP, INPUT);
pinMode(BOTAO_START_PAUSE, INPUT_PULLUP);
desligarTudo();
Serial.println("=== Sistema pronto. Pressione o botão para iniciar. ===");
}
void loop() {
static bool estadoAnteriorBotao = HIGH;
bool estadoAtualBotao = digitalRead(BOTAO_START_PAUSE);
// Verifica botão com debounce manual
if (estadoAnteriorBotao == HIGH && estadoAtualBotao == LOW) {
emExecucao = !emExecucao;
Serial.print("🟢 Estado alterado: ");
Serial.println(emExecucao ? "EXECUTANDO" : "PAUSADO");
delay(300); // debounce
}
estadoAnteriorBotao = estadoAtualBotao;
if (emExecucao && !cicloFinalizado) {
lavarI();
lavarII();
enxague(1);
enxague(2);
enxagueComSecante();
secagemFinal();
Serial.println("=== CICLO CONCLUÍDO ===");
desligarTudo();
cicloFinalizado = true;
emExecucao = false;
}
delay(100);
}
// === FUNÇÕES DE ETAPAS ===
void lavarI() {
Serial.println("[LAVAR I] Pré-lavagem...");
aguardarExecucao(); encherAgua();
aguardarExecucao(); circularFrio(TEMPO_CIRCULA_FRIO);
aguardarExecucao(); drenarAgua();
}
void lavarII() {
Serial.println("[LAVAR II] Lavagem principal...");
aguardarExecucao(); encherAgua();
aguardarExecucao(); circularQuente(TEMPO_AQUECIMENTO_MAX, TEMP_LIMITE_CIRCULA);
aguardarExecucao(); drenarAgua();
}
void enxague(int numero) {
Serial.printf("[ENXÁGUE %d] Circulação quente...\n", numero);
aguardarExecucao(); encherAgua();
aguardarExecucao(); circularQuente(TEMPO_ENXAGUE_QUENTE, TEMP_LIMITE_CIRCULA);
aguardarExecucao(); drenarAgua();
}
void enxagueComSecante() {
Serial.println("[ENXÁGUE 3] Com secante...");
aguardarExecucao(); encherAgua();
aguardarExecucao(); aplicarSecante();
aguardarExecucao(); circularQuente(TEMPO_ENXAGUE_QUENTE, TEMP_LIMITE_CIRCULA);
aguardarExecucao(); drenarAgua();
}
void secagemFinal() {
Serial.println("[SECAGEM] Iniciando secagem...");
digitalWrite(REL_RESIST, HIGH);
delayComPausa(TEMPO_SECAGEM, "Secagen Final");
digitalWrite(REL_RESIST, LOW);
}
// === SUBROTINAS ===
void desligarTudo() {
// Salvar estados atuais
estadoValvula = digitalRead(REL_VALVULA);
estadoDreno = digitalRead(REL_DRENAGEM);
estadoCircula = digitalRead(REL_CIRCULA);
estadoResist = digitalRead(REL_RESIST);
estadoDosador = digitalRead(REL_DOSADOR);
// Desligar fisicamente
digitalWrite(REL_VALVULA, LOW);
digitalWrite(REL_DRENAGEM, LOW);
digitalWrite(REL_RESIST, LOW);
digitalWrite(REL_CIRCULA, LOW);
digitalWrite(REL_DOSADOR, LOW);
}
void encherAgua() {
Serial.println("⏳ Enchendo água...");
digitalWrite(REL_VALVULA, HIGH);
unsigned long inicio = millis();
while (digitalRead(SENSOR_NIVEL_ALTO) == HIGH) {
aguardarExecucao();
if (millis() - inicio > TEMPO_ABASTECER) {
Serial.println("⚠️ Tempo limite abastecimento!");
break;
}
delay(100);
}
digitalWrite(REL_VALVULA, LOW);
Serial.println("✅ Boia de nível alto detectada.");
}
void drenarAgua() {
Serial.println("⏳ Drenando...");
digitalWrite(REL_DRENAGEM, HIGH);
while (digitalRead(SENSOR_NIVEL_BAIXO) == HIGH) {
aguardarExecucao();
delay(100);
}
digitalWrite(REL_DRENAGEM, LOW);
Serial.println("✅ Boia de nível baixo detectada.");
}
void circularFrio(unsigned long tempo) {
Serial.println("♻️ Circulação fria...");
digitalWrite(REL_CIRCULA, HIGH);
delayComPausa(tempo, "Circular Frio");
digitalWrite(REL_CIRCULA, LOW);
}
void circularQuente(unsigned long tempoMax, float tempLimiteC) {
Serial.println("🔥 Circulação com aquecimento...");
unsigned long inicio = millis();
digitalWrite(REL_CIRCULA, HIGH);
digitalWrite(REL_RESIST, HIGH);
while (millis() - inicio < tempoMax) {
aguardarExecucao();
float temp = lerTemperatura();
Serial.printf("🌡️ Temp atual: %.2f°C\n", temp);
if (temp >= tempLimiteC) {
Serial.println("✅ Temperatura alvo atingida.");
break;
}
delay(500);
}
digitalWrite(REL_RESIST, LOW);
Serial.println("♻️ Mantendo circulação quente...");
delayComPausa(TEMPO_CIRCULA_QUENTE, "Circula Quente");
digitalWrite(REL_CIRCULA, LOW);
}
void aplicarSecante() {
Serial.println("💧 Aplicando secante...");
digitalWrite(REL_DOSADOR, HIGH);
delayComPausa(1000, "Secante"); // 1s
digitalWrite(REL_DOSADOR, LOW);
}
float lerTemperatura() {
int leitura = analogRead(SENSOR_TEMP);
float tensao = leitura * (3.3 / 4095.0);
return (tensao - 0.5) * (100.0 / 2.5); // conversão simples simulada
}
void delayComPausa(unsigned long duracao, const char* nomeEtapa = "") {
Serial.printf("🕐 Iniciando etapa: %s (%.1f segundos)\n", nomeEtapa, duracao / 1000.0);
unsigned long tempoExecutado = 0;
unsigned long tempoAnterior = millis();
while (tempoExecutado < duracao) {
aguardarExecucao(); // já lida com pause/play
unsigned long agora = millis();
unsigned long delta = agora - tempoAnterior;
tempoAnterior = agora;
tempoExecutado += delta;
float restante = (duracao - tempoExecutado) / 1000.0;
Serial.printf("⏳ [%s] Restante: %.1f segundos\r", nomeEtapa, restante);
delay(500); // Atualiza a cada meio segundo
}
Serial.println(); // quebra linha final
}
void aguardarExecucao() {
static bool estadoAnteriorBotao = HIGH;
bool leituraAtual = digitalRead(BOTAO_START_PAUSE);
// Verifica mudança de estado do botão (falling edge)
if (estadoAnteriorBotao == HIGH && leituraAtual == LOW) {
emExecucao = !emExecucao;
if (!emExecucao) {
// Salvamos e desligamos tudo
desligarTudo();
Serial.println("⏸️ Pausado. Relés desligados.");
} else {
// Retoma o estado anterior dos relés
restaurarReleAnterior();
Serial.println("▶️ Retomando execução e restaurando relés.");
}
delay(300); // debounce
}
estadoAnteriorBotao = leituraAtual;
// Fica preso aqui até voltar a execução
while (!emExecucao) {
leituraAtual = digitalRead(BOTAO_START_PAUSE);
if (estadoAnteriorBotao == HIGH && leituraAtual == LOW) {
emExecucao = true;
restaurarReleAnterior();
Serial.println("▶️ Retomando execução e restaurando relés.");
delay(300);
}
estadoAnteriorBotao = leituraAtual;
delay(100);
}
}
void restaurarReleAnterior() {
digitalWrite(REL_VALVULA, estadoValvula);
digitalWrite(REL_DRENAGEM, estadoDreno);
digitalWrite(REL_CIRCULA, estadoCircula);
digitalWrite(REL_RESIST, estadoResist);
digitalWrite(REL_DOSADOR, estadoDosador);
}
VALVULA
RESISTENCIA
DRENAGEM
CIRCULAÇÃO
INICIO/PAUSE