#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.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 e per i relay
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
// Encoder e variabili di stato
Encoder encoder(encoderPinA, encoderPinB);
int menuPosition = 0;
bool lightState = false;
bool fanState = false;
long encoderPosition = -999;
long lastEncoderPos = 0;
bool lastButtonState = HIGH;
void setup() {
// Inizializza OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, oledAddress)) { // Inizializzazione con indirizzo I2C 0x3C
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);
// 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;
// Filtro di cambiamento: aggiorna solo se la variazione supera una certa soglia
if (abs(newPos - lastEncoderPos) >= 2) {
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 il menu solo se cambia posizione
}
// Leggi lo stato del pulsante e attiva il relay corrispondente
bool buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) { // rileva solo la pressione
delay(50); // debounce per il pulsante
toggleRelay();
}
lastButtonState = buttonState;
}
// 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(0, 0);
display.print("Spray Booth Control");
// Contenuto del menu
if (menuPosition == 0) {
display.setCursor(0, 16);
display.print("> Light:");
display.setCursor(80, 16);
display.print(lightState ? "ON" : "OFF");
display.setCursor(0, 32);
display.print(" Fan:");
display.setCursor(80, 32);
display.print(fanState ? "ON" : "OFF");
} else if (menuPosition == 1) {
display.setCursor(0, 16);
display.print(" Light:");
display.setCursor(80, 16);
display.print(lightState ? "ON" : "OFF");
display.setCursor(0, 32);
display.print("> Fan:");
display.setCursor(80, 32);
display.print(fanState ? "ON" : "OFF");
}
// Suggerimenti per l'utente
display.setCursor(0, 48);
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
}