PROGETTI ARDUINO

  • HOME
  • 200 Progetti
  • Progetti e Tutorial
  • Reti
    • Impara le reti
    • internet fibra
    • wifi mesh
    • modem router
    • diagnostica reti
    • ethernet lan
    • sicurezza configurazione
  • Elettronica
  • Recensioni
  • Manuale
  • Contatti
  • HOME
  • 200 Progetti
  • Progetti e Tutorial
  • Reti
    • Impara le reti
    • internet fibra
    • wifi mesh
    • modem router
    • diagnostica reti
    • ethernet lan
    • sicurezza configurazione
  • Elettronica
  • Recensioni
  • Manuale
  • Contatti

Progetto 132
​Interfaccia con encoder rotativo

🚀 Introduzione

Vuoi controllare un progetto Arduino con una manopola, proprio come nei dispositivi elettronici professionali? 🎛️

In questo progetto utilizzerai un encoder rotativo con pulsante integrato per modificare un valore visualizzato su display OLED.

Ruotando la manopola potrai aumentare o diminuire il valore selezionato. Premendo l’encoder potrai invece cambiare parametro.
​
👉 L’encoder rotativo è ideale per menu, regolazioni, timer, termostati, controlli di velocità e pannelli di configurazione.

🎯 Cosa realizzerai
​

Con Arduino creerai un’interfaccia che:
  • 🎛️ rileva la rotazione dell’encoder;
  • ➕ aumenta il valore ruotando verso destra;
  • ➖ diminuisce il valore ruotando verso sinistra;
  • ✅ rileva la pressione della manopola;
  • 🌡️ permette di modificare una temperatura impostata;
  • 💡 permette di modificare una luminosità;
  • 📟 mostra i valori su display OLED;
  • 🔄 cambia il parametro selezionato;
  • ⏱️ utilizza un controllo antirimbalzo;
  • 🚫 impedisce ai valori di superare i limiti stabiliti.

🧰 Materiale necessario
​
  • 1x Arduino UNO;
  • 1x encoder rotativo KY-040 o compatibile;
  • 1x display OLED 0,96 pollici I2C SSD1306;
  • cavetti jumper;
  • breadboard;
  • cavo USB.
​
Il modulo KY-040 integra normalmente le resistenze necessarie per i segnali dell’encoder.

🛒 Non hai ancora i componenti?

Molti dei progetti presenti su progettiarduino.com utilizzano componenti elettronici di base come LED, resistenze, sensori e breadboard.
Se stai iniziando con Arduino, il modo più semplice è utilizzare un kit completo per principianti, che include quasi tutti i componenti necessari per realizzare molti dei progetti presenti sul sito.

👉 Kit Arduino consigliato:
ℹ️ Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
https://amzn.to/4b3dxjW

📘 Vuoi imparare Arduino passo dopo passo?
Se vuoi approfondire e realizzare progetti più completi, puoi dare un'occhiata anche ai miei libri dedicati ad Arduino.
All'interno troverai spiegazioni semplici, schemi chiari e molti progetti pratici pensati per chi parte da zero.

👉 Scopri i miei libri su Arduino:
ℹ️ Link di affiliazione Amazon: in qualità di Affiliato Amazon ricevo un guadagno dagli acquisti idonei, senza alcun costo aggiuntivo per te.
https://amzn.to/4rfzjXE
​

📚 Librerie necessarie
​

Per utilizzare il display OLED devi installare:
  • Adafruit SSD1306;
  • Adafruit GFX Library.
La libreria Wire è già inclusa nell’Arduino IDE.
Per la lettura dell’encoder non è necessaria alcuna libreria esterna.

🔌 Schema di collegamento
​

Display OLED SSD1306
  • VCC → 5V;
  • GND → GND;
  • SDA → A4;
  • SCL → A5.
L’indirizzo I2C utilizzato nel codice è 0x3C.

Encoder rotativo KY-040
  • + → 5V;
  • GND → GND;
  • CLK → pin digitale 2;
  • DT → pin digitale 3;
  • SW → pin digitale 4.
​
Il pin SW corrisponde al pulsante integrato nella manopola.
Nel codice viene utilizzata la modalità INPUT_PULLUP, quindi il pulsante premuto viene letto come LOW.
Foto

💻 Codice Arduino

Il programma gestisce due parametri:
  • temperatura impostata;
  • luminosità impostata.
Ruotando l’encoder:
  • il valore aumenta verso destra;
  • il valore diminuisce verso sinistra.
Premendo la manopola, Arduino passa da un parametro all’altro.
​/*
  ============================================================
  Progetto 132 - Interfaccia con encoder rotativo
  Modifica temperatura e luminosita tramite encoder KY-040
  ============================================================
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Dimensioni e indirizzo del display OLED
#define LARGHEZZA_DISPLAY 128
#define ALTEZZA_DISPLAY 64
#define RESET_OLED -1
#define INDIRIZZO_OLED 0x3C

// Collegamenti dell'encoder rotativo
#define PIN_CLK 2
#define PIN_DT 3
#define PIN_SW 4

// Intervalli utilizzati per ridurre
// rimbalzi e letture multiple
const unsigned long TEMPO_DEBOUNCE_PULSANTE = 180;
const unsigned long TEMPO_MINIMO_ROTazione = 3;

// Oggetto utilizzato per controllare il display OLED
Adafruit_SSD1306 display(
  LARGHEZZA_DISPLAY,
  ALTEZZA_DISPLAY,
  &Wire,
  RESET_OLED
);

// Parametri regolabili
int temperaturaImpostata = 22;
int luminositaImpostata = 50;

// Indica quale parametro è selezionato
enum ParametroSelezionato {
  PARAMETRO_TEMPERATURA,
  PARAMETRO_LUMINOSITA
};

ParametroSelezionato parametroAttuale =
  PARAMETRO_TEMPERATURA;

// Memorizza lo stato precedente del segnale CLK
int statoPrecedenteClk = HIGH;

// Variabili temporali per encoder e pulsante
unsigned long ultimaRotazione = 0;
unsigned long ultimaPressione = 0;

// Indica quando il display deve essere ridisegnato
bool aggiornamentoDisplayRichiesto = true;

void setup() {
  // I segnali dell'encoder utilizzano
  // le resistenze interne di Arduino
  pinMode(PIN_CLK, INPUT_PULLUP);
  pinMode(PIN_DT, INPUT_PULLUP);
  pinMode(PIN_SW, INPUT_PULLUP);

  // Memorizza lo stato iniziale del segnale CLK
  statoPrecedenteClk = digitalRead(PIN_CLK);

  // Inizializza il display OLED
  if (!display.begin(
        SSD1306_SWITCHCAPVCC,
        INDIRIZZO_OLED
      )) {
    // Se il display non viene rilevato,
    // il programma rimane bloccato
    while (true) {
    }
  }

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextWrap(false);

  mostraAvvio();
  mostraInterfaccia();

  aggiornamentoDisplayRichiesto = false;
}

void loop() {
  // Controlla continuamente la rotazione
  gestisciEncoder();

  // Controlla il pulsante integrato
  gestisciPulsante();

  // Ridisegna il display soltanto
  // quando cambia un valore o una selezione
  if (aggiornamentoDisplayRichiesto) {
    mostraInterfaccia();
    aggiornamentoDisplayRichiesto = false;
  }
}

void gestisciEncoder() {
  // Legge lo stato attuale del segnale CLK
  int statoAttualeClk = digitalRead(PIN_CLK);

  // Rileva soltanto il fronte di discesa,
  // evitando di contare due volte ogni scatto
  if (statoPrecedenteClk == HIGH &&
      statoAttualeClk == LOW &&
      millis() - ultimaRotazione >=
      TEMPO_MINIMO_ROTazione) {
    ultimaRotazione = millis();

    // Confronta DT con CLK per stabilire
    // la direzione della rotazione
    if (digitalRead(PIN_DT) != statoAttualeClk) {
      aumentaValore();
    } else {
      diminuisciValore();
    }

    aggiornamentoDisplayRichiesto = true;
  }

  // Salva lo stato per il controllo successivo
  statoPrecedenteClk = statoAttualeClk;
}

void gestisciPulsante() {
  // Con INPUT_PULLUP il pulsante premuto
  // viene letto come livello LOW
  if (digitalRead(PIN_SW) == LOW &&
      millis() - ultimaPressione >=
      TEMPO_DEBOUNCE_PULSANTE) {
    ultimaPressione = millis();

    // Passa da un parametro all'altro
    if (parametroAttuale ==
        PARAMETRO_TEMPERATURA) {
      parametroAttuale =
        PARAMETRO_LUMINOSITA;
    } else {
      parametroAttuale =
        PARAMETRO_TEMPERATURA;
    }

    aggiornamentoDisplayRichiesto = true;
  }
}

void aumentaValore() {
  // Modifica il parametro attualmente selezionato
  if (parametroAttuale ==
      PARAMETRO_TEMPERATURA) {
    temperaturaImpostata++;

    // Limita la temperatura al valore massimo
    temperaturaImpostata = constrain(
      temperaturaImpostata,
      10,
      35
    );
  } else {
    luminositaImpostata += 5;

    // Limita la luminosità al 100%
    luminositaImpostata = constrain(
      luminositaImpostata,
      0,
      100
    );
  }
}

void diminuisciValore() {
  // Modifica il parametro attualmente selezionato
  if (parametroAttuale ==
      PARAMETRO_TEMPERATURA) {
    temperaturaImpostata--;

    // Limita la temperatura al valore minimo
    temperaturaImpostata = constrain(
      temperaturaImpostata,
      10,
      35
    );
  } else {
    luminositaImpostata -= 5;

    // Impedisce valori inferiori a zero
    luminositaImpostata = constrain(
      luminositaImpostata,
      0,
      100
    );
  }
}

void mostraInterfaccia() {
  // Pulisce completamente il display
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);

  // Titolo dell'interfaccia
  display.setCursor(0, 0);
  display.print("ENCODER ROTATIVO");

  display.drawLine(
    0,
    10,
    127,
    10,
    SSD1306_WHITE
  );

  // Mostra la voce temperatura
  display.setCursor(0, 18);

  if (parametroAttuale ==
      PARAMETRO_TEMPERATURA) {
    display.print("> ");
  } else {
    display.print("  ");
  }

  display.print("Temperatura");

  display.setCursor(91, 18);
  display.print(temperaturaImpostata);
  display.print((char)247);
  display.print("C");

  // Mostra la voce luminosità
  display.setCursor(0, 34);

  if (parametroAttuale ==
      PARAMETRO_LUMINOSITA) {
    display.print("> ");
  } else {
    display.print("  ");
  }

  display.print("Luminosita");

  display.setCursor(97, 34);
  display.print(luminositaImpostata);
  display.print("%");

  // Disegna una barra grafica
  // relativa al valore di luminosità
  display.drawRect(
    3,
    48,
    100,
    9,
    SSD1306_WHITE
  );

  int larghezzaBarra = map(
    luminositaImpostata,
    0,
    100,
    0,
    96
  );

  display.fillRect(
    5,
    50,
    larghezzaBarra,
    5,
    SSD1306_WHITE
  );

  // Indicazioni per l'utente
  display.setCursor(106, 48);
  display.print("RUOTA");

  display.setCursor(106, 57);
  display.print("PREMI");

  // Invia al display tutti gli elementi disegnati
  display.display();
}

void mostraAvvio() {
  display.clearDisplay();
  display.setTextSize(1);

  display.setCursor(15, 15);
  display.print("Encoder rotativo");

  display.setCursor(20, 31);
  display.print("Interfaccia OLED");

  display.setCursor(28, 47);
  display.print("Progetto 132");

  display.display();

  delay(1800);
}

⚙️ Come funziona
​

Un encoder rotativo genera due segnali digitali chiamati normalmente:
  • CLK;
  • DT.
​
Durante la rotazione, i due segnali cambiano stato con un piccolo sfasamento.

Arduino confronta i segnali per capire la direzione della rotazione.

Se il segnale DT è diverso da CLK, la rotazione viene interpretata in una direzione.
​
Se i due segnali sono uguali, viene interpretata nella direzione opposta.

🎛️ Differenza tra encoder e potenziometro

Un potenziometro possiede una posizione minima e una posizione massima.
Un encoder rotativo può invece ruotare continuamente in entrambe le direzioni.
​
Questo permette di:
  • modificare valori senza limiti meccanici;
  • navigare in menu molto lunghi;
  • controllare più parametri;
  • creare interfacce più compatte.
​
👉 Il valore minimo e massimo vengono stabiliti nel programma, non dalla posizione fisica della manopola.

🌡️ Regolazione della temperatura
​

La temperatura impostata può variare tra:
  • minimo: 10 °C;
  • massimo: 35 °C.
Ogni scatto dell’encoder modifica il valore di un grado.
La funzione constrain() impedisce di superare questi limiti.

💡 Regolazione della luminosità
​

La luminosità può variare da 0% a 100%.
Ogni scatto modifica il valore di 5 punti percentuali.
Questo parametro potrebbe essere successivamente utilizzato per controllare un LED tramite PWM.

✅ Pulsante integrato
​

Premendo l’encoder, Arduino cambia il parametro selezionato.
​
Il display evidenzia la voce attiva attraverso il simbolo >.
Per esempio:
> Temperatura
oppure:
> Luminosita
Il pulsante viene gestito con un controllo antirimbalzo basato su millis().

📟 Interfaccia OLED
​

Il display mostra:
  • titolo del progetto;
  • temperatura impostata;
  • luminosità impostata;
  • parametro attualmente selezionato;
  • indicazione della pressione dell’encoder.
​
La schermata viene aggiornata soltanto quando cambia un valore o viene premuto il pulsante.

⚠️ Direzione invertita
​

Alcuni encoder possono aumentare il valore quando vengono ruotati verso sinistra.
In questo caso puoi:
  • invertire i collegamenti CLK e DT;
  • invertire nel codice le istruzioni di incremento e decremento.
Non si tratta di un guasto, ma di una diversa disposizione interna dei contatti.

🧠 Perché è un progetto importante
​

Con questo progetto impari a:
  • utilizzare un encoder rotativo;
  • riconoscere la direzione di rotazione;
  • leggere un pulsante integrato;
  • modificare più parametri;
  • creare un’interfaccia compatta;
  • gestire valori minimi e massimi;
  • utilizzare un display OLED;
  • ridurre gli aggiornamenti inutili;
  • applicare un controllo antirimbalzo;
  • preparare la base per menu più complessi.
​
👉 Nel prossimo progetto utilizzeremo l’encoder per navigare in un vero menu.

🔄 Varianti possibili
​

Vuoi migliorare il progetto?
  • 💡 collega un LED PWM;
  • 🌡️ collega un sensore di temperatura;
  • ⚡ controlla un relè;
  • 🔊 aggiungi un buzzer alla rotazione;
  • 💾 salva i valori nella EEPROM;
  • 📋 crea più parametri;
  • ⏱️ regola un timer;
  • 🚗 controlla la velocità di un motore;
  • 🎚️ modifica la sensibilità dell’encoder;
  • 📟 utilizza un display OLED più grande;
  • 🔐 aggiungi una schermata di blocco;
  • 🎛️ usa una pressione lunga per azzerare i valori.

Foto
Foto

© ProgettiArduino.com 2026 - Fancello Salvatore
​ Layout, immagini e testi sono di esclusiva proprietà di www.progettiarduino.com 
Privacy Policy