Realizziamo una mensola da muro con integrato un orologio Wi-Fi a matrice LED

Nuovo progetto con ESP8266, con la quale realizzeremo un orologio che preleva i dati da un server NTP ed aggiorna l’orario automaticamente. Questo progetto è una variante del progetto di orologio a matrice LED che avevamo visto in questo ARTICOLO. La novità è la mancanza di un modulo RTC e l’utilizzo della connessione Wi-Fi, nonché la realizzazione in stampa 3D di una mensola in cui inserire l’orologio.

Progetto

Il nostro scopo è costruire una mensola su cui porre oggetti che sia anche un orologio su cui mostrare ora, giorno, mese ed anno, tramite effetti di transizione e che si aggiorni automaticamente nel passaggio dell’ora legale a quella solare e viceversa. Come nel precedente progetto, useremo un NodeMCU come dev-board, sfruttando la sua connettività Wi-Fi. Proprio grazie ad essa, ci collegheremo ad un server NTP da cui prelevare le informazioni necessarie che stamperemo su un display a matrice LED.

Componenti

Come già detto sopra, il NodeMCU con ESP8266 è la scheda utilizzata per questo progetto, che collegheremo alla matrice led 8×32, che gestirà i 256 LED rossi che compongono il dispositivo. Abbiamo anche utilizzato una batteria LIPO da 3,7V a 2000mAh che verrà ricaricata da un modulo di ricarica TP4056 con porta Micro-USB. Il modulo fornirà corrente sia per la ricarica della batteria, che per il funzionamento dell’orologio; questo permetterà di alimentare l’intero sistema con un comunissimo alimentatore per smartphone o semplicemente con la batteria, qualora andasse via la corrente.

  • Orologio

Acquista componenti su Amazon:

Acquista componenti su Aliexpress:



Collegamenti

Partiamo collegando il NodeMCU alla matrice LED, collegando il DIN al pin D7, il CLK al pin D5 e il CS al pin D8, mentre il Vcc ai 3,3V e il GND al GND. Il collegamenti del modulo di ricarica sono gli stessi visti già in altri progetto. Sul modulo sono presenti delle indicazioni precise: dove indicato B+ e B- andranno saldati, rispettivamente, il polo positivo e negativo della batteria; mentre, dove troviamo la scritte OUT+ e OUT- ovviamente i 3,3V che arrivano al NodeMCU e il GND.

Codice

Per programmare il nostro orologio a matrice LED (potete scaricare il codice a questo LINK) ci serviranno diverse librerie, alcune per il funzionamento dei moduli, altre per creare effetti visivi. A tal riguardo, la libreria MD_Parola [LINK] sarà utile per lo scrolling di testo modulare su display a matrice. Per gestire la matrice sarà necessaria la libreria MD_MAX72xx [LINK]. Da contorno fa la libreria NTP Client [LINK] che ci servirà per richiedere all’omonimo server le informazioni su data e ora. Includiamo anche il file Font_Data.h, contenente i caratteri alfanumerici da adoperare sulla matrice. Proseguiamo creando gli oggetti per gestire l’orario.


#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include "Font_Data.h"

Impostiamo il server NTP da cui prendere l’orario e impostiamo con 7200 il fuso orario di Roma.


const long utcOffsetInSeconds = 7200;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", utcOffsetInSeconds);

Creiamo ora le variabili per la data e l’orario (ore, minuti, secondi, giorni, mesi e anni), definiamo pure il numero di matrici (4) e la tipologia. Indichiamo, poi, i pin a cui connettere il NodeMCU, l’oggetto P per la gestione della libreria MD_Parola ed una serie di parametri per la gestione degli effetti e delle dimensioni del testo.


int h, m, s;
int yy, mm, dd;

#define MAX_DEVICES 4
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW

//Pin NodeMCU ESP8266
#define CLK_PIN D5
#define DATA_PIN D7
#define CS_PIN D8

MD_Parola P = MD_Parola(HARDWARE_TYPE,CS_PIN, MAX_DEVICES);

#define SPEED_TIME 55
#define PAUSE_TIME 0

#define MAX_MESG 30

char szTime[9];
char szMesg[MAX_MESG+1] = "";

Una parte di codice sarà dedicata alla creazione di array per la gestione dei nomi dei giorni della settimana e dei mesi, in modo da associare una stringa ad ogni numero del mese o del giorno della settimana.


char daysOfTheWeek[7][12] = {"Domenica", "Lunedi", "Martedi", "Mercoledi", "Giovedi", "Venerdi", "Sabato"};

String months[12]={"Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agostot", "Settembre", "Ottobre", "Novembre", "Dicembre"};

Per ottenere l’orario, vediamo la funzione getTime() con cui otteniamo i valori di ore, minuti e secondi, stampando su matrice l’orario, facendo lampeggiare il punto separatore tra ore e minuti.


void getTime(char *psz, bool f = true){
s = timeClient.getSeconds();
m = timeClient.getMinutes();
h = timeClient.getHours();
sprintf(psz, "%02d%c%02d", h, (f ? '.' : ' '), m);
}

La funzione getDate() sarà utilizzata per ottenere giorno, mese e anno, stampando tutto su matrice nel formato Giorno/Mese/Anno, dove il mese è indicato per nome proprio.


void getDate(char *psz){
char szBuf[10];
time_t epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime ((time_t *)&epochTime);

dd = ptm->tm_mday;
mm = ptm->tm_mon+1;
String currentMonthName = months[mm-1];
yy = ptm->tm_year+1900;

sprintf(psz, "%d %s %04d", dd, currentMonthName, yy);
}

Passiamo ora al VOID SETUP, dove creiamo l’oggetto per la gestione degli effetti, settando subito l’orario e la data. Impostiamo pure il comportamento degli effetti, come ad esempio il movimento del testo da destra verso sinistra, la velocità di spostamento ed altro, già dichiarato precedentemente. Avviamo anche la connessione Wi-Fi.


Serial.begin(115200);

timeClient.begin();

P.begin(2);
P.setInvert(false);

P.setZone(0, MAX_DEVICES-4, MAX_DEVICES-1);

P.setZone(1, MAX_DEVICES-4, MAX_DEVICES-1);
P.displayZoneText(1, szTime, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);

P.displayZoneText(0, szMesg, PA_CENTER, SPEED_TIME, 0,PA_PRINT , PA_NO_EFFECT);

Serial.println();
Serial.println();
Serial.print("Connessione a ");
Serial.println(ssid);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("Connesso");
Serial.println("");
Serial.println("IP: ");
Serial.println(WiFi.localIP());

Nel VOID LOOP preleviamo poi i valori temporali e avviamo le animazioni su display.


timeClient.update();

P.displayAnimate();

Con la funzione Switch(case) iniziamo a stampare sulla matrice l’orario, il giorno della settimana e la data completa.


if (P.getZoneStatus(0))
{
switch (display)
{
case 0:
P.setPause(0,1000);
P.setFont(0, numeric7Seg);
P.setTextEffect(0, PA_PRINT, PA_NO_EFFECT);
P.setPause(0,0);

if (millis() - lastTime >= 1000)
{
lastTime = millis();
getTime(szMesg, flasher);
flasher = !flasher;
}
if(s==00&& s<=30){
display++;
P.setTextEffect(0, PA_CLOSING, PA_GROW_DOWN);
}

break;
case 1: // Giorno della settimana
P.setFont(0,nullptr);
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display++;
strcpy (szMesg, daysOfTheWeek[timeClient.getDay()]);

break;
case 2: // Calendario
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display++;
getDate(szMesg);

break;

Concludiamo facendo stampare un messaggio personalizzato e resettiamo il display.


case 3: // Messaggio
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
strcpy(szMesg, "www.fattelodasolo.it");
display=0;
break;
default:
display = 0;
break;

Ricordiamoci, prima di caricare il codice, di selezionare come scheda NodeMCU 0.9 (ESP-12) e selezionare la porta corretta. Una volta caricato lo sketch, la matrice LED stamperà tutte le informazioni raccolte.



Assemblaggio

Per realizzare la scocca con la stampante 3D potete scaricare da questo LINK i file STL. Abbiamo fissato il display a matrice con della colla a caldo, mentre la batteria, il modulo di ricarica e il NodeMCU con del nastro biadesivo. Per aggevolarci, abbiamo dissaldato tutti i pin header dalla dev-board a della matrice, saldando direttamente i cavi sulle componenti. Il tempo di realizzazione della mensola dipende da stampante a stampante, noi abbiamo comunque impiegato circa 16 ore, stampando con PLA Bianca. I supporti invece in PLA Nera. Il supporto a muro è stato fissato con dei tasselli da 5, stando attenti a non serrare eccessivamente le viti, che potrebbero rompere la PLA.