#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <math.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// PINOS
const int PIN_LED_ALERTA = 17;
const int PIN_BOTAO_SILENCIO = 16;
// Dados simulados
float temperatura = 27.8;
float ph = 7.5;
int nivelRacao = 39;
float nh3 = 0.086;
unsigned long ultimoUpdateDados = 0;
unsigned long ultimaTrocaTela = 0;
unsigned long ultimoPiscaTela = 0;
unsigned long ultimoPiscaLed = 0;
unsigned long ultimoDebounceBotao = 0;
int ciclo = 0;
int telaAtual = 0;
bool alertaVisivel = true;
bool ledLigado = false;
bool alarmeSilenciado = false;
int ultimoEstadoBotao = HIGH;
int estadoBotaoAtual = HIGH;
String obterStatus(float nh3Valor) {
if (nh3Valor >= 0.2) return "CRITICO";
if (nh3Valor >= 0.05) return "ATENCAO";
return "SEGURO";
}
bool nh3EmAlerta(float nh3Valor) {
return nh3Valor >= 0.05;
}
void desenharBarraNivel(int x, int y, int largura, int altura, int percentual) {
display.drawRect(x, y, largura, altura, SSD1306_WHITE);
int larguraInterna = map(percentual, 0, 100, 0, largura - 2);
display.fillRect(x + 1, y + 1, larguraInterna, altura - 2, SSD1306_WHITE);
}
void desenharBarraNH3(int x, int y, int largura, int altura, float valor) {
float valorMax = 0.3;
if (valor > valorMax) valor = valorMax;
int percentual = (valor / valorMax) * 100;
display.drawRect(x, y, largura, altura, SSD1306_WHITE);
int larguraInterna = map(percentual, 0, 100, 0, largura - 2);
display.fillRect(x + 1, y + 1, larguraInterna, altura - 2, SSD1306_WHITE);
}
void desenharIconeSino(int x, int y) {
display.drawCircle(x + 4, y + 4, 4, SSD1306_WHITE);
display.drawLine(x + 1, y + 8, x + 7, y + 8, SSD1306_WHITE);
display.drawLine(x + 2, y + 9, x + 6, y + 9, SSD1306_WHITE);
display.drawPixel(x + 4, y + 10, SSD1306_WHITE);
}
void desenharTelaSensores() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println("Peixuxo - Sensores");
display.setCursor(0, 14);
display.print("Temp: ");
display.print(temperatura, 1);
display.println(" C");
display.setCursor(0, 26);
display.print("pH: ");
display.print(ph, 1);
display.setCursor(0, 38);
display.print("NH3: ");
display.print(nh3, 3);
display.println(" mg/L");
desenharBarraNH3(0, 52, 100, 8, nh3);
display.display();
}
void desenharTelaAlerta() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
desenharIconeSino(110, 0);
display.setTextSize(2);
display.setCursor(8, 0);
display.println("ALERTA");
display.setCursor(22, 20);
display.println("NH3");
display.setTextSize(1);
display.setCursor(6, 44);
display.print("Status: ");
display.println(obterStatus(nh3));
display.setCursor(6, 56);
display.print("NH3: ");
display.print(nh3, 3);
if (alarmeSilenciado) {
display.setCursor(78, 56);
display.print("MUDO");
}
display.display();
}
void desenharTelaApagada() {
display.clearDisplay();
display.display();
}
void atualizarDados() {
ciclo++;
temperatura = 27.5 + sin(ciclo * 0.25) * 1.8;
ph = 7.3 + sin(ciclo * 0.18) * 0.4;
nh3 = 0.03 + (sin(ciclo * 0.14) + 1.0) * 0.04;
}
void lerBotaoSilencio() {
int leitura = digitalRead(PIN_BOTAO_SILENCIO);
if (leitura != ultimoEstadoBotao) {
ultimoDebounceBotao = millis();
}
if ((millis() - ultimoDebounceBotao) > 50) {
if (leitura != estadoBotaoAtual) {
estadoBotaoAtual = leitura;
if (estadoBotaoAtual == LOW && nh3EmAlerta(nh3)) {
alarmeSilenciado = !alarmeSilenciado;
Serial.print("Silenciado: ");
Serial.println(alarmeSilenciado ? "SIM" : "NAO");
}
}
}
ultimoEstadoBotao = leitura;
}
void controlarPiscaTela() {
if (nh3EmAlerta(nh3)) {
if (millis() - ultimoPiscaTela >= 500) {
ultimoPiscaTela = millis();
alertaVisivel = !alertaVisivel;
}
} else {
alertaVisivel = true;
}
}
void controlarLedAlerta() {
if (nh3EmAlerta(nh3)) {
if (millis() - ultimoPiscaLed >= 500) {
ultimoPiscaLed = millis();
ledLigado = !ledLigado;
digitalWrite(PIN_LED_ALERTA, ledLigado ? HIGH : LOW);
}
} else {
ledLigado = false;
digitalWrite(PIN_LED_ALERTA, LOW);
}
}
void desenharTelaAtual() {
if (nh3EmAlerta(nh3)) {
if (alertaVisivel) desenharTelaAlerta();
else desenharTelaApagada();
return;
}
desenharTelaSensores();
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
pinMode(PIN_LED_ALERTA, OUTPUT);
pinMode(PIN_BOTAO_SILENCIO, INPUT_PULLUP);
digitalWrite(PIN_LED_ALERTA, LOW);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Erro no OLED");
for (;;);
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
}
void loop() {
lerBotaoSilencio();
if (millis() - ultimoUpdateDados >= 1000) {
ultimoUpdateDados = millis();
atualizarDados();
Serial.print("Botao: ");
Serial.print(digitalRead(PIN_BOTAO_SILENCIO));
Serial.print(" | NH3: ");
Serial.print(nh3, 3);
Serial.print(" | Status: ");
Serial.print(obterStatus(nh3));
Serial.print(" | Silenciado: ");
Serial.println(alarmeSilenciado ? "SIM" : "NAO");
}
controlarPiscaTela();
controlarLedAlerta();
desenharTelaAtual();
delay(20);
}