#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "HX711.h"
// Configurações dos pinos
#define BUTTON_400ML_PIN 2
#define BUTTON_500ML_PIN 3
#define BUTTON_770ML_PIN 4
#define BUTTON_OPEN_CLOSE_PIN 5
#define EMERGENCY_BUTTON_PIN 7 // Pino para o botão de emergência
#define RELAY_PIN 6
#define FLOW_SENSOR_PIN 18
#define HX711_DT_PIN 8
#define HX711_SCK_PIN 9
// Configurações do display I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // Endereço do LCD, colunas e linhas
// Configurações da célula de carga
HX711 scale;
float calibration_factor = 0; // Valor inicial de calibração
// Variáveis de contagem do sensor de fluxo
volatile int flowPulseCount = 0;
float flowRate;
float totalMilliLitres = 0;
unsigned long oldTime;
bool isEmergency = false; // Variável para estado de emergência
// Quantidades de enchimento
const float target400ml = 400.0;
const float target500ml = 500.0;
const float target770ml = 770.0;
// Função de interrupção para sensor de fluxo
void flow() {
flowPulseCount++;
}
void setup() {
Serial.begin(9600);
// Inicializa o display
lcd.begin(16, 2); // Adiciona o número de colunas e linhas
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Inicializando...");
// Configurações dos pinos dos botões
pinMode(BUTTON_400ML_PIN, INPUT_PULLUP);
pinMode(BUTTON_500ML_PIN, INPUT_PULLUP);
pinMode(BUTTON_770ML_PIN, INPUT_PULLUP);
pinMode(BUTTON_OPEN_CLOSE_PIN, INPUT_PULLUP);
pinMode(EMERGENCY_BUTTON_PIN, INPUT_PULLUP);
pinMode(RELAY_PIN, OUTPUT);
// Inicializa a célula de carga
scale.begin(HX711_DT_PIN, HX711_SCK_PIN);
//scale.set_scale(calibration_factor);
//scale.tare(); // Zera a balança
// Configura o sensor de fluxo
pinMode(FLOW_SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN), flow, RISING);
lcd.setCursor(0, 0);
lcd.print("Sistema Pronto!");
delay(2000);
lcd.clear();
oldTime = millis();
}
void loop() {
// Verifica o estado do botão de emergência
if (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
delay(300); // Debounce para evitar múltiplas leituras
if (isEmergency) {
deactivateEmergency();
} else {
activateEmergency();
}
}
// Se estiver em estado de emergência, não faz nada
if (isEmergency) {
return;
}
// Leitura dos botões
if (digitalRead(BUTTON_400ML_PIN) == LOW) {
dispense(target400ml);
} else if (digitalRead(BUTTON_500ML_PIN) == LOW) {
dispense(target500ml);
} else if (digitalRead(BUTTON_770ML_PIN) == LOW) {
dispense(target770ml);
} else if (digitalRead(BUTTON_OPEN_CLOSE_PIN) == LOW) {
openAndMonitor();
}
// Monitoramento do nível do barril
monitorBarrelLevel();
// Calibração manual
if (Serial.available()) {
char temp = Serial.read();
if (temp == '+') {
calibration_factor += 10;
} else if (temp == '-') {
calibration_factor -= 10;
}
scale.set_scale(calibration_factor); // Atualiza o fator de calibração
Serial.print("Calibração ajustada para: ");
Serial.println(calibration_factor);
}
}
void dispense(float targetMl) {
digitalWrite(RELAY_PIN, HIGH); // Ativa o relé (abre a válvula)
totalMilliLitres = 0;
flowPulseCount = 0;
while (totalMilliLitres < targetMl) {
// Verifica o estado do botão de emergência durante a operação
if (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
delay(300); // Debounce para evitar múltiplas leituras
activateEmergency();
return;
}
if ((millis() - oldTime) > 1000) {
oldTime = millis();
flowRate = (flowPulseCount / 7.5); // Ajuste este valor para seu sensor específico
flowPulseCount = 0;
totalMilliLitres += (flowRate / 60) * 1000;
lcd.setCursor(0, 0);
lcd.print("Enchendo: ");
lcd.print(totalMilliLitres);
lcd.print(" ml");
}
}
digitalWrite(RELAY_PIN, LOW); // Desativa o relé (fecha a válvula)
lcd.clear();
}
void openAndMonitor() {
digitalWrite(RELAY_PIN, HIGH); // Ativa o relé (abre a válvula)
totalMilliLitres = 0;
flowPulseCount = 0;
while (digitalRead(BUTTON_OPEN_CLOSE_PIN) == LOW) {
// Verifica o estado do botão de emergência durante a operação
if (digitalRead(EMERGENCY_BUTTON_PIN) == LOW) {
delay(300); // Debounce para evitar múltiplas leituras
activateEmergency();
return;
}
if ((millis() - oldTime) > 1000) {
oldTime = millis();
flowRate = (flowPulseCount / 7.5); // Ajuste este valor para seu sensor específico
flowPulseCount = 0;
totalMilliLitres += (flowRate / 60) * 1000;
lcd.setCursor(0, 0);
lcd.print("Total: ");
lcd.print(totalMilliLitres);
lcd.print(" ml");
}
}
digitalWrite(RELAY_PIN, LOW); // Desativa o relé (fecha a válvula)
lcd.clear();
}
void monitorBarrelLevel() {
float weight = scale.get_units(10);
float volumeLiters = weight / 1000; // Converte o peso para litros, ajuste conforme necessário
lcd.setCursor(0, 1); // Atualiza a linha 2 do display com o volume restante
lcd.print("Vol: ");
lcd.print(volumeLiters, 2); // Dois decimais para o volume
if (volumeLiters <= 5) {
lcd.print(" Nivel < 10%!");
} else {
lcd.print(" "); // Limpa a mensagem "Nivel < 10%!" quando não se aplica
}
}
// Função para ativar o estado de emergência
void activateEmergency() {
digitalWrite(RELAY_PIN, LOW); // Fecha a válvula
isEmergency = true;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("PARADO");
Serial.println("Sistema em estado de emergência!");
}
// Função para desativar o estado de emergência
void deactivateEmergency() {
isEmergency = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sistema Pronto");
delay(2000); // Pequeno atraso para exibir a mensagem
lcd.clear();
Serial.println("Sistema retomado!");
}