#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <HX711.h>
// --- MAPEAMENTO DE PINOS ---
#define DHTPIN 4
#define DHTTYPE DHT22
#define MQ2PIN 34
#define BUZZER_PIN 12
#define FAN_PIN 13
#define BOMBA_PIN 14
#define NIVEL_PIN 2
#define BTN_MODO 15
#define LOADCELL_DOUT_PIN 25 // DT do HX711
#define LOADCELL_SCK_PIN 26 // SCK do HX711
// --- CONFIGURAÇÕES ---
const int LIMITE_GAS_PPM = 400;
const int UMIDADE_ALVO = 50;
float Ro = 10.0;
bool modoAutomatico = false;
float maxPPM = 0;
// Configurações da Balança (Botijão P13)
// O fator de calibração você descobre pesando um objeto de peso conhecido
float fator_calibracao = -7050.0;
float peso_vazio = 13.0; // Peso médio do botijão de ferro vazio (kg)
float peso_cheio = 26.0; // Peso total (13kg ferro + 13kg gás)
DHT dht(DHTPIN, DHTTYPE);
HX711 balanca;
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(FAN_PIN, OUTPUT);
pinMode(BOMBA_PIN, OUTPUT);
pinMode(NIVEL_PIN, INPUT_PULLUP);
pinMode(BTN_MODO, INPUT_PULLUP);
dht.begin();
balanca.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
balanca.set_scale(fator_calibracao);
// balanca.tare(); // Use isso se quiser zerar a balança ao ligar
lcd.init();
lcd.backlight();
lcd.print("SISTEMA COMPLETO");
delay(2000);
}
void loop() {
// 1. LEITURA SENSORES BÁSICOS
float h = dht.readHumidity();
float t = dht.readTemperature();
int temAgua = (digitalRead(NIVEL_PIN) == LOW);
// 2. LEITURA GÁS (MQ-2)
int gasRaw = analogRead(MQ2PIN);
float vGas = gasRaw * (3.3 / 4095.0);
float rs = (3.3 - vGas) / (vGas + 0.001);
float ppm = pow(10, ((log10(rs/Ro) * -2.1) + 2.3));
if (ppm > maxPPM) maxPPM = ppm;
// 3. LEITURA PESO (BOTIJÃO)
float pesoAtual = balanca.get_units(5); // Média de 5 leituras
if (pesoAtual < 0) pesoAtual = 0;
// Cálculo de Porcentagem de Gás (Regra de 3 baseada na carga de 13kg)
float cargaGas = pesoAtual - peso_vazio;
int porcGas = constrain((cargaGas / 13.0) * 100, 0, 100);
// 4. LÓGICA DO BOTÃO MODO
if (digitalRead(BTN_MODO) == LOW) {
modoAutomatico = !modoAutomatico;
tone(BUZZER_PIN, 1000, 200);
delay(300);
}
// 5. CONTROLES ATIVOS (FAN / BOMBA)
if (modoAutomatico) {
int velocidade = map(constrain(t, 25, 35), 25, 35, 0, 255);
analogWrite(FAN_PIN, velocidade);
digitalWrite(BOMBA_PIN, (h < UMIDADE_ALVO && temAgua) ? HIGH : LOW);
}
// 6. SEGURANÇA E ALERTAS
if (ppm > LIMITE_GAS_PPM) {
digitalWrite(FAN_PIN, HIGH);
tone(BUZZER_PIN, 2000, 100);
}
// Alerta de Gás Acabando (Menos de 10%)
if (porcGas < 10 && porcGas > 0) {
Serial.println("AVISO: Botijao quase vazio!");
}
// 7. DISPLAY E SERIAL
exibirStatus(t, h, ppm, porcGas, temAgua);
Serial.printf("T:%.1f|U:%.1f|Gas:%d|Peso:%.2fkg|Bot:%d%%\n", t, h, (int)ppm, pesoAtual, porcGas);
delay(500);
}
void exibirStatus(float t, float h, float ppm, int bot, int agua) {
static unsigned long lastLCD = 0;
if (millis() - lastLCD < 2000) return; // Atualiza a cada 2s para dar tempo de ler
lastLCD = millis();
static bool alternar = false;
lcd.clear();
lcd.setCursor(0, 0);
if (alternar) {
// Tela A: Climatização
lcd.print("T:"); lcd.print((int)t); lcd.print("C U:"); lcd.print((int)h); lcd.print("%");
lcd.setCursor(0, 1);
lcd.print(agua ? "Agua: OK" : "AGUA: VAZIO!");
} else {
// Tela B: Gás e Botijão
lcd.print("Gas: "); lcd.print((int)ppm); lcd.print(" ppm");
lcd.setCursor(0, 1);
lcd.print("Botijao: "); lcd.print(bot); lcd.print("%");
}
alternar = !alternar;
}