// motor_1estagio_manual_dimmer.ino
#include <Arduino.h>
#include "Button.h"
#include "ACI_10K_an.h"
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
// ========================= CONFIGURAÇÕES GERAIS =========================
#define PIN_DIMMER_ZC 2 // Pino de interrupção (Zero-Cross)
#define PIN_DIMMER_GATE 3 // Pino de disparo (Gate)
#define PIN_SENSOR_NIVEL 4
Button button2(7);
Button button5(8);
Button button1(A2);
Button button3(A3);
Button button4(A0);
#define PIN_BOMBA 10
#define PIN_OSCILADOR 11
#define PIN_IONIZADOR 12
#define PIN_BUZZER 13
LiquidCrystal_I2C lcd(0x27, 16, 2);
Aci_10K an10k(5.0, 10);
// ========================= VARIÁVEIS DO DIMMER =========================
volatile int dimmer_power = 0; // 0 a 100
int dimming_delay = 0; // Tempo de espera em microssegundos
// ========================= AJUSTES DO SISTEMA =========================
const int MIN_POWER_PCT = 25;
const float TEMP_MIN = 24.0;
const float TEMP_MAX = 32.0;
unsigned long lastWindChange = 0;
int windTarget = 40;
int modoVelocidade = 1;
bool modoAutomatico = false;
float temperaturaAtual = NAN;
struct Ramp {
int target;
int current;
unsigned long last;
int interval;
};
Ramp motorRamp = {0, 0, 0, 20};
// ========================= INTERRUPÇÃO ZERO CROSS =========================
// Esta função roda toda vez que a onda AC cruza o zero (120 vezes por segundo em 60Hz)
void zero_cross_int() {
if (dimmer_power <= 0) {
digitalWrite(PIN_DIMMER_GATE, LOW);
return;
}
if (dimmer_power >= 100) {
digitalWrite(PIN_DIMMER_GATE, HIGH);
return;
}
// Calcula o atraso: 60Hz -> meio ciclo = 8333us
// Quanto maior o atraso, menor a potência.
int delay_us = map(dimmer_power, 0, 100, 7500, 500);
delayMicroseconds(delay_us);
digitalWrite(PIN_DIMMER_GATE, HIGH);
delayMicroseconds(10); // Pulso do gatilho
digitalWrite(PIN_DIMMER_GATE, LOW);
}
// ========================= FUNÇÕES AUXILIARES =========================
void beep(int duracaoMs, int frequencia = 500) {
unsigned long tempoInicial = millis();
while (millis() - tempoInicial < duracaoMs) {
digitalWrite(PIN_BUZZER, HIGH);
delayMicroseconds(frequencia);
digitalWrite(PIN_BUZZER, LOW);
delayMicroseconds(frequencia);
}
}
// ========================= SETUP =========================
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.print("Motor Iniciando");
pinMode(PIN_DIMMER_GATE, OUTPUT);
pinMode(PIN_DIMMER_ZC, INPUT_PULLUP);
pinMode(PIN_SENSOR_NIVEL, INPUT_PULLUP);
pinMode(PIN_BOMBA, OUTPUT);
pinMode(PIN_OSCILADOR, OUTPUT);
pinMode(PIN_IONIZADOR, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
// Ativa a interrupção no pino 2
attachInterrupt(digitalPinToInterrupt(PIN_DIMMER_ZC), zero_cross_int, RISING);
button1.begin(); button2.begin(); button3.begin();
button4.begin(); button5.begin();
delay(500);
lcd.clear();
beep(100);
}
// ========================= LOOP PRINCIPAL =========================
void loop() {
static unsigned long tLeitura = 0;
if (millis() - tLeitura >= 1000) {
tLeitura = millis();
temperaturaAtual = an10k.getTemp(analogRead(A1));
}
if (button5.pressed()) {
modoAutomatico = !modoAutomatico;
beep(50);
}
if (modoAutomatico) {
if(!isnan(temperaturaAtual)){
int potAuto = map(temperaturaAtual * 10, TEMP_MIN * 10, TEMP_MAX * 10, MIN_POWER_PCT, 100);
motorRamp.target = constrain(potAuto, MIN_POWER_PCT, 100);
}
} else {
if (button2.pressed()) {
modoVelocidade++;
if (modoVelocidade > 4) modoVelocidade = 1;
beep(50, 800);
}
switch (modoVelocidade) {
case 1: motorRamp.target = 40; break;
case 2: motorRamp.target = 70; break;
case 3: motorRamp.target = 100; break;
case 4: // VENTO ALEATÓRIO
if (millis() - lastWindChange > random(3000, 7000)) {
lastWindChange = millis();
windTarget = random(MIN_POWER_PCT, 85);
}
motorRamp.target = windTarget;
break;
}
}
// Atualização da Rampa e do Dimmer
if (millis() - motorRamp.last >= motorRamp.interval) {
motorRamp.last = millis();
if (motorRamp.current < motorRamp.target) motorRamp.current++;
else if (motorRamp.current > motorRamp.target) motorRamp.current--;
// Atualiza a variável volátil usada na interrupção
dimmer_power = motorRamp.current;
}
bombeamento();
oscilador();
ionizador();
atualizarDisplay();
}
void atualizarDisplay() {
static unsigned long lastDisp = 0;
if (millis() - lastDisp < 1000) return;
lastDisp = millis();
lcd.setCursor(0, 0);
lcd.print("T:");
if(isnan(temperaturaAtual)) lcd.print("--"); else lcd.print(temperaturaAtual, 1);
lcd.print("C ");
lcd.print(digitalRead(PIN_SENSOR_NIVEL) == LOW ? "OK " : "VAZ");
lcd.setCursor(0, 1);
if (modoAutomatico) lcd.print("AUTO:");
else if (modoVelocidade == 4) lcd.print("VENTO:");
else lcd.print("MANU:");
lcd.print(motorRamp.current);
lcd.print("% ");
}
void bombeamento() {
if (button1.toggled() && button1.read() == Button::PRESSED) {
if (digitalRead(PIN_SENSOR_NIVEL) == LOW) digitalWrite(PIN_BOMBA, !digitalRead(PIN_BOMBA));
}
if (digitalRead(PIN_SENSOR_NIVEL) == HIGH) digitalWrite(PIN_BOMBA, LOW);
}
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));
}