#include <Arduino.h>
#include "Button.h"
#include "ACI_10K_an.h"
#include "LED.h" // Biblioteca para controle de LEDs
#include <Wire.h> // Biblioteca para comunicação I2C
#include "LiquidCrystal_I2C.h"// Biblioteca para LCD I2C
// ------------------------ Pinos e Objetos ------------------------
Button button2(7); // AMARELO - alterVeloc
Button button5(8); // PRETO - alterna Modo (Manual/Auto)
Button button1(A2); // AZUL - bombeamento
Button button3(A3); // VERMELHO - ionizador
Button button4(A4); // VERDE - oscilador
const int PIN_SENSOR_NIVEL = 2; // entrada com pull-up
const int PIN_BUZZER = 3; // buzzer (tone)
const int PIN_BOMBA = 10; // bomba
const int PIN_OSCILADOR = 11; // oscilador
const int PIN_IONIZADOR = 12; // ionizador
const int PIN_LED_ALARME = 13; // LED onboard (nível/alertas)
const int leds[] = {9, 6, 5, 4}; // Pinos dos LEDs (4 não é PWM)
LED led0(leds[0]);
LED led1(leds[1]);
LED led2(leds[2]);
LED led3(leds[3]);
// LCD I2C (endereço comum: 0x27 ou 0x3F)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ------------------------ Estados e Variáveis ------------------------
int autVeloc = 0;
int alterVeloc = 1;
int nivelTanque = HIGH;
int value = HIGH;
unsigned long tempoAnterior = 0;
const unsigned long intervaloLeitura = 100; // ms
const int tempBlinkMs = 2000; // não usado, mas mantido
int fanSpeedPWM = 0;
bool modoAutomatico = false; // Manual=botões | Auto=temperatura
// Temperatura global (atualizada periodicamente)
float temperaturaAtual = NAN;
// ------------------------ Protótipos ------------------------
void configurarPinos();
void velocidade();
void autaTemperatura();
void bombeamento();
void oscilador();
void ionizador();
void atualizarDisplay();
void autocontroleTermico();
float lerTemperatura();
// Função utilitária: mapeia float [in_min..in_max] -> int PWM [0..255]
static inline int mapFloatToPWM(float x, float in_min, float in_max) {
if (isnan(x)) return 0;
if (x < in_min) x = in_min;
if (x > in_max) x = in_max;
float frac = (x - in_min) / (in_max - in_min); // 0..1
int pwm = (int)round(frac * 255.0f);
if (pwm < 0) pwm = 0;
if (pwm > 255) pwm = 255;
return pwm;
}
void setup() {
Serial.begin(9600);
configurarPinos();
button1.begin();
button2.begin();
button3.begin();
button4.begin();
button5.begin();
// Semente randômica
randomSeed(analogRead(A0));
// LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Iniciando...");
lcd.setCursor(0, 1);
lcd.print("Aguarde...");
delay(1500);
lcd.clear();
// Primeira leitura para iniciar
temperaturaAtual = lerTemperatura();
}
void loop() {
// Atualiza a leitura da temperatura por tempo (não bloqueante)
if (millis() - tempoAnterior >= intervaloLeitura) {
tempoAnterior = millis();
temperaturaAtual = lerTemperatura();
Serial.print("Temperatura: ");
Serial.print(temperaturaAtual, 1);
Serial.println(" C");
}
// Alterna modo Manual/Automático (botão 5)
if (button5.pressed()) {
// Limpa saídas PWM/LEDs visuais ao trocar modo
analogWrite(leds[0], 0);
analogWrite(leds[1], 0);
analogWrite(leds[2], 0);
modoAutomatico = !modoAutomatico;
tone(PIN_BUZZER, 440, 200);
}
// Controle principal de velocidade (um ou outro, não ambos)
if (modoAutomatico) {
autocontroleTermico();
} else {
velocidade();
}
// Funções auxiliares
autaTemperatura();
bombeamento();
oscilador();
ionizador();
atualizarDisplay();
}
// ------------------------ Implementações ------------------------
void configurarPinos() {
// Entradas
pinMode(PIN_SENSOR_NIVEL, INPUT_PULLUP); // sensor de nível no pino 2 (pull-up interna)
// Os botões são gerenciados pela lib Button; se precisar, ative PULLUP conforme seu hardware.
// Saídas
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_BOMBA, OUTPUT);
pinMode(PIN_OSCILADOR, OUTPUT);
pinMode(PIN_IONIZADOR, OUTPUT);
pinMode(PIN_LED_ALARME, OUTPUT);
// LEDs
for (uint8_t i = 0; i < 4; i++) {
pinMode(leds[i], OUTPUT);
analogWrite(leds[i], 0);
}
// **NÃO** configurar A4/A5 (I2C) como saída
// **NÃO** configurar pino 1 (TX) como saída -> conflita com Serial
}
float lerTemperatura() {
// Ajuste estes parâmetros conforme sua placa/sensor:
// Aci_10K an10k(Vref, resolução_bits)
// Em Uno, ADC é 10 bits. Se seu sensor usa 3.3V como referência real, ok.
// Se usar 5V, troque 3.3 por 5.0 e 14 por 10 (dependendo da lib).
Aci_10K an10k(3.3, 14);
delayMicroseconds(500);
int leituraADC = analogRead(A1);
return an10k.getTemp(leituraADC); // °C
}
void autaTemperatura() {
// Usa a leitura global (consistente)
float T = temperaturaAtual;
if (!isnan(T) && T >= 35.0f) {
// Aviso visual/sonoro simples (bloqueante — pode ser tornado não-bloqueante depois)
analogWrite(leds[3], 255); // LEDs[3] = pino 4 (não-PWM, OK para on/off)
tone(PIN_BUZZER, 262, 250);
delay(100);
analogWrite(leds[3], 0);
noTone(PIN_BUZZER);
delay(100);
} else {
analogWrite(leds[3], 0);
noTone(PIN_BUZZER);
}
}
void autocontroleTermico() {
// Converte 22~32 °C -> 0~255 PWM
int pwmValue = mapFloatToPWM(temperaturaAtual, 22.0f, 32.0f);
// Usa leds[2] como “fan/motor”
analogWrite(leds[2], pwmValue);
// Garante os demais apagados (somente o "canal" do motor em uso)
analogWrite(leds[0], 0);
analogWrite(leds[1], 0);
}
void velocidade() {
// Brilho base em função da temperatura (18~30 °C -> 100~255)
int brightness = mapFloatToPWM(temperaturaAtual, 18.0f, 30.0f);
if (brightness < 100) brightness = 100; // piso
// Velocidade aleatória do efeito por ciclo (2~6 ms)
int velocidade = random(2, 7);
// Brilho máximo aleatório até o teto calculado
int brilhoMaximo = random(brightness + 1); // inclui 'brightness'
if (button2.pressed()) {
tone(PIN_BUZZER, 262, 250);
alterVeloc++;
if (alterVeloc > 6) alterVeloc = 1;
}
// Limpa canais visuais antes de aplicar
analogWrite(leds[0], 0);
analogWrite(leds[1], 0);
analogWrite(leds[2], 0);
switch (alterVeloc) {
case 1:
analogWrite(leds[0], 255);
break;
case 2:
analogWrite(leds[1], 255);
break;
case 3:
analogWrite(leds[2], 255);
break;
case 4:
// Fade no leds[0]
for (int b = 0; b <= brilhoMaximo; b++) { analogWrite(leds[0], b); delay(velocidade); }
delay(1500);
for (int b = brilhoMaximo; b >= 0; b--) { analogWrite(leds[0], b); delay(velocidade); }
delay(random(500));
break;
case 5:
// Fade no leds[1]
for (int b = 0; b <= brilhoMaximo; b++) { analogWrite(leds[1], b); delay(velocidade); }
delay(1500);
for (int b = brilhoMaximo; b >= 0; b--) { analogWrite(leds[1], b); delay(velocidade); }
delay(random(500));
break;
case 6:
// Fade no leds[2]
for (int b = 0; b <= brilhoMaximo; b++) { analogWrite(leds[2], b); delay(velocidade); }
delay(1500);
for (int b = brilhoMaximo; b >= 0; b--) { analogWrite(leds[2], b); delay(velocidade); }
delay(random(500));
break;
default:
alterVeloc = 1;
break;
}
}
void bombeamento() {
// Botão AZUL alterna a bomba (com condicionais do nível)
if (button1.toggled() && button1.read() == Button::PRESSED) {
// Liga bomba somente se nível OK (sensor com pull-up: LOW = OK)
bool nivelOK = (digitalRead(PIN_SENSOR_NIVEL) == LOW);
bool bombaLigada = (digitalRead(PIN_BOMBA) == HIGH);
digitalWrite(PIN_BOMBA, (nivelOK && !bombaLigada) ? HIGH : LOW);
}
// Monitora mudança de nível e aplica segurança
int novoValor = digitalRead(PIN_SENSOR_NIVEL);
if (novoValor != value) {
value = novoValor;
if (value == HIGH) { // HIGH = sem água (com pull-up)
digitalWrite(PIN_LED_ALARME, HIGH);
digitalWrite(PIN_BOMBA, LOW); // segurança: desliga bomba
Serial.println("Nivel: VAZIO");
} else {
digitalWrite(PIN_LED_ALARME, LOW);
Serial.println("Nivel: OK");
}
}
}
void oscilador() {
if (button4.toggled() && button4.read() == Button::PRESSED) {
digitalWrite(PIN_OSCILADOR, !digitalRead(PIN_OSCILADOR));
}
}
void ionizador() {
if (button3.toggled() && button3.read() == Button::PRESSED) {
digitalWrite(PIN_IONIZADOR, !digitalRead(PIN_IONIZADOR));
}
}
void atualizarDisplay() {
static unsigned long ultimoUpdate = 0;
if (millis() - ultimoUpdate >= 1000) {
ultimoUpdate = millis();
lcd.clear();
// Linha 0: Temperatura e Nível de Água
lcd.setCursor(0, 0);
lcd.print("T:");
if (isnan(temperaturaAtual)) {
lcd.print("--.-");
} else {
lcd.print(temperaturaAtual, 1);
}
lcd.print("C");
lcd.setCursor(10, 0);
lcd.print((value == LOW) ? "H2O:OK" : "VAZIO!");
// Linha 1: Modo de Operação
lcd.setCursor(0, 1);
if (modoAutomatico) {
int pot = mapFloatToPWM(temperaturaAtual, 22.0f, 32.0f) * 100 / 255;
if (pot < 0) pot = 0;
if (pot > 100) pot = 100;
lcd.print("AUTO: ");
lcd.print(pot);
lcd.print("%");
} else {
lcd.print("MANUAL: M-");
lcd.print(alterVeloc);
}
}
}