·
  • #esp32
  • #esphome
  • #home-assistant
  • #sntp
  • #rtttl
  • #oled
  • #making

Costruire una sveglia con ESPHome quando il telefono sul comodino è il problema

Costruire una sveglia vera per togliere il telefono dal comodino. ESP32-C3, OLED, buzzer, Home Assistant.

-

5 min read

Il problema

Uso il telefono come sveglia. Come tutti.

Il risultato è che il telefono finisce sul comodino, e prima di dormire scrollo per venti minuti cose che non mi servono. La mattina, prima ancora di alzarmi, controllo le notifiche. Lo so che è un problema, ma finché il telefono ha un motivo per stare lì — la sveglia — non c’è verso di spostarlo.

Serviva un oggetto fisico che facesse solo quello: suonare a un’ora precisa, con un pulsante per spegnerla.

Il contesto

Ho Home Assistant in casa. Ho un ESP32-C3 Mini nel cassetto. Ho un display OLED 128x64 e un buzzer piezo passivo avanzati da un altro progetto.

La soluzione ovvia sarebbe comprare una sveglia da 10 euro. Ma volevo una cosa che:

  • si integrasse con Home Assistant per configurare le sveglie da telefono (non dal comodino)
  • funzionasse anche se Home Assistant è spento
  • avesse più allarmi con giorni della settimana

ESPHome era la scelta naturale: YAML, OTA, integrazione nativa con HA, niente codice Arduino da mantenere.

Il ragionamento

L’orologio deve essere autonomo

La prima tentazione è usare Home Assistant come sorgente dell’ora. ESPHome lo supporta nativamente con platform: homeassistant. Ma se HA si riavvia, o se il server è giù, la sveglia non sa più che ore sono.

Ho scelto SNTP (il protocollo standard per sincronizzare l’orologio via rete): l’ESP32 si sincronizza direttamente con i server NTP via WiFi. Serve solo la rete, non Home Assistant.

time:
  - platform: sntp
    id: sntp_time
    timezone: "Europe/Rome"
    servers:
      - 0.pool.ntp.org
      - 1.pool.ntp.org
      - 2.pool.ntp.org

Quanti allarmi?

Volevo “N allarmi”, configurabili. Il problema è che ESPHome è statico: le entità si dichiarano in YAML a compile time. Non puoi creare switch e number a runtime.

Le opzioni realistiche erano:

  1. Un numero fisso di slot (es. 5), tutti dichiarati in YAML. Quelli non usati restano disabilitati.
  2. Allarmi gestiti da HA e inviati all’ESP via servizi o sensori. Più flessibile, ma dipende da HA — proprio quello che volevo evitare.

Ho scelto 5 slot fissi. Copre qualsiasi uso reale di una sveglia da comodino. È verboso nel YAML (ogni allarme ha ora, minuti, 7 toggle per i giorni, e un enable), ma è semplice da capire e funziona offline.

Ogni allarme: cosa serve

Per ogni slot:

  • Ora e minuti — due number con restore_value: true (sopravvivono al riavvio)
  • Enable/disable — un switch con restore_mode
  • Giorni della settimana — 7 switch (lun-dom), ciascuno con restore_mode

Totale: 10 entità per allarme × 5 = 50, più il master switch e la durata suoneria. 52 entità in HA. Tante, ma ognuna ha un significato chiaro.

Il display

128×64 pixel monocromatici. Non c’è spazio per fronzoli.

Layout:

  • Header (in alto a sinistra): Giorno della settimana corrente (LUN, MAR, ecc.)
  • Icona (in alto a destra): Una piccola icona sveglia MDI (12×12px), visibile solo se c’è almeno una sveglia attiva nelle prossime 12 ore
  • Centro: Orologio grande, 32px, formato HH:MM, centrato nel display
  • Footer: !! SVEGLIA N !! quando una sveglia sta suonando, altrimenti vuoto

Il limite di 12 ore per l’icona è una scelta di utilità: sul comodino ti interessa sapere se la sveglia suona stanotte o domattina, non se suona domani sera.

Il calcolo della prossima sveglia è fatto nel lambda del display: scorre i 5 slot, controlla giorno e ora, trova il delta minore entro 12 ore. Niente di elegante, ma non richiede componenti o entità aggiuntive.

Il buzzer

Piezo passivo su GPIO10, pilotato via il componente rtttl di ESPHome. RTTTL (Ring Tone Text Transfer Language) è un formato testuale per melodie — lo stesso usato dai Nokia negli anni ‘90. ESPHome lo supporta nativamente e gestisce il PWM in modo asincrono, senza bloccare il resto del firmware.

La suoneria è la ninna nanna di Brahms. Non un beep a 2200Hz: qualcosa di riconoscibile, che si sente senza essere aggressivo.

La suoneria si ferma in tre modi:

  1. Pulsante fisico sul comodino (GPIO4)
  2. Pulsante in Home Assistant (per test o emergenze)
  3. Timeout automatico — durata configurabile da 1 a 15 minuti, default 5

La soluzione

L’hardware:

ComponenteModello
MCUESP32-C3 Mini
DisplaySH1106 128x64 I2C
BuzzerPiezo passivo
PulsanteNormalmente aperto, pullup interno

I pin:

FunzioneGPIO
I2C SDA (display)GPIO6
I2C SCL (display)GPIO7
Buzzer PWMGPIO10
Pulsante stopGPIO4

Il software è un singolo file YAML ESPHome (~750 righe). La logica degli allarmi gira in un interval da 1 secondo: costruisce un array di struct con i dati dei 5 allarmi, li scorre, e se ora e giorno corrispondono fa partire il suono. Un guard basato sul timestamp del minuto corrente impedisce di ritriggerare lo stesso allarme più volte: una volta scattato, quell’allarme viene ignorato finché non cambia il minuto.

Se il WiFi non è raggiungibile al boot, l’ESP32 attiva automaticamente un hotspot di emergenza che permette di raggiungere il captive portal di ESPHome per diagnostica o riconfigurazione.

Il codice sara disponibile nel repository sveglia-esphome su GitHub.

I limiti

  • 52 entità in Home Assistant. Sono tante. L’interfaccia di default di HA le mostra tutte in lista, senza raggruppamento. Serve una card custom o un’automazione per renderle usabili. Questo è un problema di UX, non di funzionamento.
  • Il YAML è lungo e ripetitivo. 5 allarmi × 10 entità ciascuno = molta copia-incolla. ESPHome supporta i package e le substitution, ma non i loop sulle entità. Si potrebbe usare un generatore esterno (Jinja2, script Python), ma aggiunge complessità alla build.
  • Nessuna batteria di backup, nessun RTC hardware. L’ESP32 si alimenta via USB e usa il WiFi per sincronizzare l’ora. Se manca la corrente, al ritorno deve riconnettersi e sincronizzarsi prima di funzionare. È una scelta voluta: mantenere il progetto semplice, senza componenti aggiuntivi. Le implicazioni pratiche e le possibili evoluzioni (RTC esterno, batteria di backup) saranno oggetto di un post dedicato.
  • Niente snooze. Per scelta. Nella v2 magari, ma per ora il pulsante fa solo stop.
  • Il display non è retroilluminato in modo controllabile. L’OLED è sempre acceso. In una stanza buia potrebbe dare fastidio. Si potrebbe aggiungere un sensore di luminosità o un timer di spegnimento display, ma aggiunge hardware e complessità.

Conclusione

Un ESP32, un display, un buzzer e un pulsante. Configurazione da telefono via Home Assistant, funzionamento autonomo via NTP.

Non è la sveglia perfetta. Ma fa esattamente quello che serve: suona quando deve, si spegne quando la premi, e il telefono resta in un’altra stanza.

Il prossimo post sarà sull’integrazione con Home Assistant: come rendere usabili 52 entità senza impazzire.

Link utili: