#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.h>
#include <DHT.h>
// Impostazioni display OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int oledAddress = 0x3C; // Indirizzo I2C del display OLED
// Definizione dei pin per l'encoder, relay e sensore DHT22
const int encoderPinA = 2;
const int encoderPinB = 3;
const int buttonPin = 4;
const int lightPin = 8; // Relay per la luce
const int fanPin = 9; // Relay per la ventola
const int dhtPin = 7; // Pin dati per il sensore DHT22
// Inizializza DHT22
#define DHTTYPE DHT22
DHT dht(dhtPin, DHTTYPE);
// Encoder e variabili di stato
Encoder encoder(encoderPinA, encoderPinB);
int menuPosition = 0;
bool lightState = false;
bool fanState = false;
long lastEncoderPos = 0;
bool lastButtonState = HIGH;
unsigned long lastInteractionTime = 0; // Per tracciare l'ultimo utilizzo dell'encoder
const unsigned long displayTimeout = 1000; // Timeout dopo 1 secondo senza input
void setup() {
// Inizializza OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, oledAddress)) {
for (;;); // Se non si avvia, fermati qui
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(lightPin, OUTPUT);
pinMode(fanPin, OUTPUT);
// Imposta relay (Light e Fan) su OFF inizialmente
digitalWrite(lightPin, LOW);
digitalWrite(fanPin, LOW);
// Inizializza DHT22
dht.begin();
// Visualizza messaggio di benvenuto
displayWelcomeMessage();
// Visualizza subito il menu
displayMenu();
}
void loop() {
// Leggi la posizione dell'encoder per il menu con divisore ridotto
long newPos = encoder.read() / 2;
// Controlla movimento dell'encoder
if (abs(newPos - lastEncoderPos) >= 2) {
lastInteractionTime = millis(); // Aggiorna tempo interazione
if (newPos > lastEncoderPos) {
menuPosition = (menuPosition + 1) % 2; // Sposta verso il basso
} else {
menuPosition = (menuPosition - 1 + 2) % 2; // Sposta verso l'alto
}
lastEncoderPos = newPos;
displayMenu(); // Aggiorna menu solo se cambia posizione
}
// Leggi lo stato del pulsante e attiva relay corrispondente
bool buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) { // rileva solo pressione
delay(50); // debounce per il pulsante
toggleRelay();
lastInteractionTime = millis(); // Aggiorna tempo interazione
}
lastButtonState = buttonState;
// Se non ci sono interazioni per un certo periodo, mostra temperatura e umidità
if (millis() - lastInteractionTime > displayTimeout) {
displayTemperatureHumidity();
}
}
// Funzione per visualizzare il messaggio di benvenuto
void displayWelcomeMessage() {
display.clearDisplay();
display.setCursor(10, 20);
display.print("Spray Booth");
display.setCursor(10, 40);
display.print("By GQ Electronics");
display.display();
delay(1500); // Visualizza la sigla per 1,5 secondi
}
// Funzione per visualizzare il menu e lo stato dei relay
void displayMenu() {
display.clearDisplay();
display.setTextSize(1);
// Intestazione del menu
display.setCursor(10, 0);
display.print("Spray Booth Control");
// Contenuto del menu
if (menuPosition == 0) {
display.setCursor(0, 20);
display.print("> Light:");
display.setCursor(80, 20);
display.print(lightState ? "ON" : "OFF");
display.setCursor(0, 40);
display.print(" Fan:");
display.setCursor(80, 40);
display.print(fanState ? "ON" : "OFF");
} else if (menuPosition == 1) {
display.setCursor(0, 20);
display.print(" Light:");
display.setCursor(80, 20);
display.print(lightState ? "ON" : "OFF");
display.setCursor(0, 40);
display.print("> Fan:");
display.setCursor(80, 40);
display.print(fanState ? "ON" : "OFF");
}
// Suggerimenti per l'utente
display.setCursor(10, 56);
display.print("Press to toggle");
display.display();
}
// Funzione per attivare o disattivare il relay selezionato
void toggleRelay() {
if (menuPosition == 0) {
lightState = !lightState;
digitalWrite(lightPin, lightState ? HIGH : LOW);
} else if (menuPosition == 1) {
fanState = !fanState;
digitalWrite(fanPin, fanState ? HIGH : LOW);
}
displayMenu(); // Aggiorna lo schermo con il nuovo stato
}
// Funzione per visualizzare temperatura e umidità
void displayTemperatureHumidity() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
display.clearDisplay();
// Titolo
display.setCursor(10, 0);
display.print("Spray Booth Monitor");
// Visualizzazione temperatura
display.setCursor(0, 20);
display.print("Temperature: ");
display.print(isnan(temperature) ? "Err" : String(temperature) + "C");
// Visualizzazione umidità
display.setCursor(0, 40);
display.print("Humidity: ");
display.print(isnan(humidity) ? "Err" : String(humidity) + "%");
// Messaggio di suggerimento
display.setCursor(10, 56);
display.print("Move Encoder to Set");
display.display();
}