C'è in testa un #define TZ "CET-1CEST,M3.5.0/2,M10.5.0/3". Certo, il giorno deve seguirla...
time_t now, credo.
Non so se riuscirò mai a capire tutte queste cose che devono interagire con le librerie... 
#include <ESP8266WiFi.h> // URL aggiuntivo per il gestore schede: http://arduino.esp8266.com/stable/package_esp8266com_index.json
#include <SPI.h> // Mi sembra che funzioni anche senza...
#include <Adafruit_GFX.h> // Usato da Max72xxPanel
#include <Max72xxPanel.h> // Installare da zip: https://github.com/markruys/arduino-Max72xxPanel
#include <time.h>
// #include <TimeLib.h>
#define sys_pin D3 // Pin a cui è collegato il pulsante verso massa per la lettura di sysinfo.
// Scheda WeMos D1 R1
int numberOfHorizontalDisplays = 8;
int numberOfVerticalDisplays = 1;
char time_value[20];
byte lum=0; // Luminosità dei caratteri.
byte capov=0; // 0:Normale; 1:Capovolto.
byte capovPrec=2; // Stato precedente di capov. E' impostato a 2 per essere sicuramente diverso
// dal valore che viene letto all'inizio e far eseguire se_capovolto() nel setup.
byte pinCS=2;
uint32_t t1_sysinfo=0; // Per misurare la durata lunga della pressione del pulsante sysinfo.
uint32_t t2_sysinfo=0; // Per misurare la durata breve della pressione del pulsante sysinfo.
byte sysinfo_prem=0; // 1: E' stato premuto sysinfo.
const char* ssid[] = {"Rete 1", "Rete 2", "Guest"};
const char* pwd[] = {"pwd1", "pwd2", "" };
Max72xxPanel matrix=Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
/*
Sono partito da: https://www.hackster.io/FilippoOnesti/esp8266-clock-using-max7219-led-matrix-display-b036c7
Connessioni dell'ESP8266 D1 mini alle 2x4 matrici di LED 8x8 in cascata:
5V -> Vcc
Gnd -> Gnd
D2 -> CS
Clk (D5) -> CLK
MOSI (D7) -> DIN
---
D0 1Hz out
sys_pin (D3) Pulsante verso massa per la lettura di sysinfo.
D6 Interruttore al mercurio verso massa: chiuso -> visualizzazione capovolta.
*/
#define TZ "CET-1CEST,M3.5.0/2,M10.5.0/3"
/*
Sull'ora legale: https://forum.arduino.cc/index.php?topic=643074.0
Per l'Italia/Roma:
CET-1CEST,M3.5.0/2,M10.5.0/3
CET = lo Standard Time quando non è presente l'ora legale (Central Europan Time)
-1 = indica 1 ora a Est di Greenwich (quindi CET = GMT+1 = UTC+1)
CEST = lo Standard Time quando è presente l'ora legale (Central Europan Summer Time) con spostamento di 1 ora (default)
M3.5.0 = quando inizia l'ora legale, ossia a Marzo (3) nell'ultima (5) Domenica (0)
/2 = l'ora locale di quando inizia l'ora legale (le 2 di notte)
M10.5.0 = quando termina l'ora legale, ossia a Ottobre (10) nell'ultima (5) Domenica (0)
/3 = l'ora locale di quando termina l'ora legale (le 3 di notte)
Il (5) è inteso come ultima settimana.
Mese.Settimana.Giorno/Ora
Mese va da 1 a 12
Settimana va 1 a 5 (con 5 si intende sempre l'ultima settimana, indipendentemente da quante ce ne sono in quel mese)
Giorno va da 0 a 6 (0=domenica)
*/
void hw_wdt_disable(){*((volatile uint32_t*) 0x60000900) &= ~(1);} // Hardware WDT OFF
void hw_wdt_enable() {*((volatile uint32_t*) 0x60000900) |= 1;} // Hardware WDT ON
char id[30];
char *percorso=__FILE__; // Dalla macro __FILE__ prende il percorso del file in uso. Questa parte di programma,
// però, si trova nel file/cartella dell'IDE c_setup, in cui non è scritta la versione
// del programma. La versione è scritta nel file principale, che ha lo stesso nome della
// cartella che contiene tutti i file del programma. Questa riga, quindi, non può stare
// nel setup.
char ver[10];
unsigned long t_scan=0; // Per il conteggio del tempo tra una scansione e l'altra della rete (che impiega 2s) durante il loop
int periodo_scan=5000; // Periodo di scansione se c'è già stata una prima conessione
byte prima_conn_ok=0;
byte scan_fatta=0; // Va a 1 dopo aver fatto la scansione ai primi secondi del minuto, per non ripeterla ogni 2s per 10s.
unsigned long t_display; // Temporizzazione per la lettura del potenziometro per la regolazione della luminosità e per la verifica del capovolgimento.
byte P=5; byte L=7; // Posizione dell'orario nel loop (per le scritte "Wi-Fi" e del numero dell'SSID vengono ridefinite localmente).
uint32_t adesso=0;
byte sec_prec; // Memorizzazione delle unità di secondi per la commutazione dell'uscita D0.
unsigned long t_prec; // Prende il tempo per far tornare a 0 D0.
void se_capovolto()
{
if(!digitalRead(D6)) capov=1; else capov=0; // Se sta a massa, capovolge.
//Serial.print (capovPrec); Serial.println(capov);
if(capov!=capovPrec) // capovPrec è inizializzato a 2 per assicurare il primo se_capovolto().
{
capovPrec=capov;
for(byte x=0; x<8; x++) {matrix.setRotation(x, 1+capov*2);} // capov=0:imposta a 1 (90°); capov=1:imposta a 3 (270°).
if (capov) for(byte x=0; x<8; x++) {matrix.setPosition(x, 7-x, 0);} // Se sta sottosopra, li inverte: mette ogni display 7-x nella posizione x.
else for(byte x=0; x<8; x++) {matrix.setPosition(x, x, 0);} // Se sta dritto, rimette in ordine i display: ogni display x in posizione x.
}
}
void WiFiScan()
{
byte n_ssid=0;
byte n=WiFi.scanNetworks();
if(prima_conn_ok) scrive_orario();
memset(id,'\0',sizeof(id));
for (byte i=0; i<n; ++i) // WiFi.SSID(i) è un oggetto String, che deve essere convertito per poter essere conrontato con un char*.
{
strcpy(id, WiFi.SSID(i).c_str()); // WiFi.SSID(i) è un oggetto String, che deve essere convertito per poter essere conrontato con un char*.
for (byte z=0; z<sizeof(ssid)/sizeof(char*); z++)
{
if(!strcmp(id, ssid[z])) {WiFi.begin(ssid[z], pwd[z]); n_ssid=z+1; break;}
}
} // Il break interrompe il for quando viene trovata una rete nella lista.
configTime(TZ,"time.google.com", "pool.ntp.org");
// Scrivendo configTime(TZ, 0, "it.pool.ntp.org","time.nist.gov"); appena connesso scrive 01:00:08...09...10... per circa 15 secondi prima di mostrare l'ora corretta!
// pool.ntp.org
// it.pool.ntp.org
// time.nist.gov
// time.google.com: 216.239.35.0
// time2.google.com: 216.239.35.4
// ntp1.inrim.it: 193.204.114.232
// ntp2.inrim.it: 193.204.114.233
delay(1000);
matrix.fillScreen(LOW);
if (n_ssid>0 && n_ssid<10)
{
matrix.drawChar(P+L*8-1,0,' ', HIGH,LOW,1);
matrix.drawChar(30,0,48+n_ssid,HIGH,LOW,1);
matrix.write(); delay(500);
}
//setenv("TZ", TZ, 3);
tzset();
}
void scrive_WiFi()
{
byte P=16; byte L=7; // Variabili ridefinite localmente per la posizione della scritta Wi-Fi
matrix.fillScreen(LOW);
matrix.drawChar(P, 0, 'W', HIGH,LOW,1); // H
matrix.drawChar(P+L, 0, 'i', HIGH,LOW,1); // HH
matrix.drawChar(P+L*2,0, '-', HIGH,LOW,1); // HH:
matrix.drawChar(P+L*3,0, 'F', HIGH,LOW,1); // HH:M
matrix.drawChar(P+L*4,0, 'i', HIGH,LOW,1); // HH:MM
matrix.write(); // Send bitmap to display
}
void scrive_orario()
{
time_t now = time(nullptr); // Facendo now variabile globale, perdeva il fuso orario.
if (now!=t_prec)
{
t_prec=now;
matrix.fillScreen(LOW);
String time = String(ctime(&now));
time.trim();
time.substring(11,19).toCharArray(time_value, 10);
if(time_value[7]!=sec_prec) {t_prec=millis(); digitalWrite(D0, HIGH); sec_prec=time_value[7];/*GP16O|=1;*/} // Porta a livello alto la porta GPIO16 (D0).
// Visualizza lo '0' iniziale prima delle ore 9.00:
matrix.drawChar(P,0, time_value[0], HIGH,LOW,1); // H
// Cancella lo '0' iniziale prima delle ore 9.00:
// if(time_value[0]!='0') {matrix.drawChar(P,0,time_value[0],HIGH,LOW,1);} // H
matrix.drawChar(P+L, 0,time_value[1], HIGH,LOW,1); // _H
matrix.drawChar(P+L*2,0,time_value[2], HIGH,LOW,1); // __:
matrix.drawChar(P+L*3,0,time_value[3], HIGH,LOW,1); // ___M
matrix.drawChar(P+L*4,0,time_value[4], HIGH,LOW,1); // ____M
matrix.drawChar(P+L*5,0,time_value[5], HIGH,LOW,1); // _____:
matrix.drawChar(P+L*6,0,time_value[6], HIGH,LOW,1); // ______S
matrix.drawChar(P+L*7,0,time_value[7], HIGH,LOW,1); // _______S
matrix.write();
}
if (millis()-t_prec>499) digitalWrite(D0, LOW); /*GP16O&=0;*/ // digitalWrite (D0, LOW); // Porta a livello basso la porta GPIO16 (D0).
}
void scrive_data()
{
char giorno[]="xx";
matrix.fillScreen(LOW);
time_t now = time(nullptr); // Facendo now variabile globale, perdeva il fuso orario.
String time = String(ctime(&now));
time.trim();
time.substring(0,10).toCharArray(time_value, 11);
//uint8_t n=(time_value[0]);
//switch (time_value)
// {
// case 1: giorno[0]='D'; giorno[1]='o'; break;
// case 2: giorno[0]='L'; giorno[1]='u'; break;
// case 3: giorno[0]='M'; giorno[1]='a'; break;
// case 4: giorno[0]='M'; giorno[1]='e'; break;
// case 5: giorno[0]='G'; giorno[1]='i'; break;
// case 6: giorno[0]='V'; giorno[1]='e'; break;
// case 7: giorno[0]='S'; giorno[1]='a'; break;
// }
matrix.drawChar(2,0, time_value[0], HIGH,LOW,1); // Giorno 1
matrix.drawChar(8,0, time_value[1], HIGH,LOW,1); // Giorno 2
matrix.drawChar(14,0, time_value[2], HIGH,LOW,1); // Giorno d
matrix.drawChar(20,0, time_value[3], HIGH,LOW,1); // Giorno u
matrix.drawChar(26,0, time_value[4], HIGH,LOW,1); // Mese d
matrix.drawChar(32,0, time_value[5], HIGH,LOW,1); // Mese u
matrix.drawChar(38,0, time_value[6], HIGH,LOW,1); // Anno u
matrix.drawChar(44,0, time_value[7], HIGH,LOW,1); // Anno d
matrix.drawChar(50,0, time_value[8], HIGH,LOW,1); // Anno c
matrix.drawChar(56,0, time_value[9], HIGH,LOW,1); // Anno m
matrix.write(); // Send bitmap to display
delay(3000);
}
void carica_cifre(int n, byte pos)
{
if(n>99) matrix.drawChar(pos, 0, 48+n/100,HIGH,LOW,1); // 48='0'; 49='1'; ...
else matrix.drawChar(pos, 0, ' ',HIGH,LOW,1);
if(n>9) matrix.drawChar(pos+6, 0, 48+(n%100)/10,HIGH,LOW,1);
else matrix.drawChar(pos, 0, ' ',HIGH,LOW,1);
matrix.drawChar(pos+12, 0, 48+n%10,HIGH,LOW,1);
}
void carica_mac(byte n, byte pos)
{
byte a=n/16;
if(a<=9) a+=48;
else a+=55;
byte b=n%16;
if(b<=9) b+=48;
else b+=55;
matrix.drawChar(pos, 0, a,HIGH,LOW,1);
matrix.drawChar(pos+6, 0, b,HIGH,LOW,1);
}
void scrive_wait_for_NTP()
{
byte P=1; // Variabile ridefinita localmente per la posizione della scritta RSSI...
matrix.fillScreen(LOW);
matrix.drawChar(P,0, 'W', HIGH,LOW,1); P+=6;
matrix.drawChar(P,0, 'a', HIGH,LOW,1); P+=5;
matrix.drawChar(P,0, 'i', HIGH,LOW,1); P+=4;
matrix.drawChar(P,0, 't', HIGH,LOW,1); P+=5;
matrix.drawChar(P,0, ' ', HIGH,LOW,1); P+=4;
matrix.drawChar(P,0, 'f', HIGH,LOW,1); P+=5;
matrix.drawChar(P,0, 'o', HIGH,LOW,1); P+=6;
matrix.drawChar(P,0, 'r', HIGH,LOW,1); P+=6;
matrix.drawChar(P,0, ' ', HIGH,LOW,1); P+=4;
matrix.drawChar(P,0, 'N', HIGH,LOW,1); P+=6;
matrix.drawChar(P,0, 'T', HIGH,LOW,1); P+=6;
matrix.drawChar(P,0, 'P', HIGH,LOW,1);
matrix.write();
}
void sysinfo()
{
matrix.fillScreen(LOW);
matrix.write();
// --------------- Visualizza la versione di questo file che è stato caricato ---------------
char *ver_ext=strrchr(percorso,'v'); // Va a cercare l'ultima 'v' nel percorso.
byte n_car=strlen(ver_ext)-4; // Calcola la lunghezza escludendo .ino.
strncpy(ver, ver_ext, n_car); // Copia i primi n_car caratteri da ver_ext a ver.
ver[n_car]='\0'; // Mette il terminatore in fondo.
for(byte x=0; x<n_car; x++) // Da 0 a n_car-1
{
matrix.drawChar((65-6*n_car)/2+6*x,0,ver[x],HIGH,LOW,1); // Scrive la versione al centro, con una colonna di spazio tra i caratteri.
}
matrix.write();
for (byte i=0; i<=lum; i++){matrix.setIntensity(i); delay(100);} // Aumenta progressivamente l'intensità
delay(1500);
sfumo();
// --------------- Scrive l'SSID, cioè il nome della rete ---------------
for(byte n=0; n<10; n++)
{
matrix.drawChar(2+n*6, 0, WiFi.SSID()[n],HIGH,LOW,1);
}
matrix.write();
delay(2000);
matrix.fillScreen(LOW);
matrix.write();
// --------------- Scrive l'RSSI (intensità del segnale WiFi) ---------------
byte P=2; // Variabile ridefinita localmente per la posizione della scritta RSSI...
int rssi=WiFi.RSSI();
matrix.fillScreen(LOW);
matrix.drawChar(P, 0, 'S', HIGH,LOW,1);
matrix.drawChar(P+6, 0, 'I', HIGH,LOW,1);
matrix.drawChar(P+6*2,0, 'G', HIGH,LOW,1);
matrix.drawChar(P+6*3,0, '=', HIGH,LOW,1);
matrix.drawChar(P+6*4,0, '-', HIGH,LOW,1);
matrix.drawChar(P+6*5,0,48+(-rssi/10),HIGH,LOW,1);
matrix.drawChar(P+6*6,0,48+(-rssi%10),HIGH,LOW,1);
matrix.drawChar(P+6*7,0, 'd', HIGH,LOW,1);
matrix.drawChar(P+6*8,0, 'B', HIGH,LOW,1);
matrix.drawChar(P+6*9,0, 'm', HIGH,LOW,1);
matrix.write();
delay(2000);
matrix.fillScreen(LOW); // Cancella i display
matrix.write();
// --------------- Scrive l'indirizzo IP che gli è stato assegnato ---------------
IPAddress IP = WiFi.localIP();
carica_cifre(IP[0], 7); // Carica sui display il primo byte dell'indirizzo
matrix.drawChar(26, 0, '.',HIGH,LOW,1);
carica_cifre(IP[1], 32); // Carica sui display il secondo byte dell'indirizzo
matrix.drawChar(50, 0, '.',HIGH,LOW,1);
matrix.write();
delay(2000);
matrix.fillScreen(LOW); // Cancella i display per visualizzare gli altri due byte
matrix.write();
carica_cifre(IP[2], 7); // Carica sui display il terzo byte dell'indirizzo
matrix.drawChar(26, 0, '.',HIGH,LOW,1);
carica_cifre(IP[3], 32); // Carica sui display il quarto byte dell'indirizzo
matrix.write();
delay(2000);
matrix.fillScreen(LOW); // Cancella i display per visualizzare gli altri due byte
matrix.write();
// --------------- Scrive il MAC address --------------
byte mac[6];
WiFi.macAddress(mac);
carica_mac(mac[0], P); // Carica sui display il primo byte del MAC address
matrix.drawChar(P+L*2, 0, ':',HIGH,LOW,1);
carica_mac(mac[1], P+L*3); // Carica sui display il secondo byte del MAC address
matrix.drawChar(P+L*5, 0, ':',HIGH,LOW,1);
carica_mac(mac[2], P+L*6); // Carica sui display il terzo byte del MAC address
matrix.drawChar(P+L*8, 0, ':',HIGH,LOW,1);
matrix.write();
delay(3000);
matrix.fillScreen(LOW); // Cancella i display per visualizzare gli altri due byte
matrix.write();
carica_mac(mac[3], P); // Carica sui display il primo byte del MAC address
matrix.drawChar(P+L*2, 0, ':',HIGH,LOW,1);
carica_mac(mac[4], P+L*3); // Carica sui display il secondo byte del MAC address
matrix.drawChar(P+L*5, 0, ':',HIGH,LOW,1);
carica_mac(mac[5], P+L*6); // Carica sui display il terzo byte del MAC address
matrix.write();
delay(3000);
sfumo();
}
// --------------- Sfumo ---------------
void sfumo()
{
for (byte i=lum+1; i>0; i--){matrix.setIntensity(i-1); delay(70);} // Diminuisce progressivamente l'intensità
matrix.fillScreen(LOW); // Vuota il buffer.
matrix.write();
delay(1000);
matrix.setIntensity(lum);
}
void setup()
{
//ESP.wdtDisable(); // Disabilita il watchdog software.
//hw_wdt_disable(); // Disabilita il watchdog hardware.
pinMode(D0, OUTPUT); // 1Hz.
pinMode(sys_pin,INPUT_PULLUP); // Chiudere a massa durante il loop per leggere sysinfo.
pinMode(D6,INPUT_PULLUP); // Chiudere a massa in qualsiasi momento per capovolgere il display.
// Serial.begin(9600);
// setSyncInterval(600); // 600 secondi.
se_capovolto(); // Imposta la disposizione delle matrici di LED.
if (!digitalRead(sys_pin)) sysinfo();
matrix.fillScreen(LOW); // Cancella i display
matrix.write();
delay(500);
matrix.setIntensity(lum);
delay(1000);
// ---------- Scrive Wi-Fi, fa la scansione delle reti disponibili e si connette alla prima di quelle nella lista ----------
do
{
se_capovolto();
scrive_WiFi();
WiFiScan();
delay(1500);
matrix.fillScreen(LOW); // Cancella i display per far lampeggiare la scritta (se una rete è disponibile, andrà avanti prima che lampeggino).
matrix.write();
if (!digitalRead(sys_pin)) sysinfo();
delay(1500);
}
while (WiFi.status()!=WL_CONNECTED);
scrive_wait_for_NTP();
delay(1000);
while(time(nullptr)<3600000) {} // A volte, pur essendosi connesso, non aveva letto l'orario e appariva 01:00:00 (apposta
// avevo messo prima un delay(1000);!). Ora, invece, verifica che siano trascorse almeno 1000 ore dal tempo zero Unix: in caso
// contrario, resta fermo nel while continuando a leggere. Il delay(1000), però, facilita la lettura dopo la connessione.
matrix.fillScreen(LOW); // Cancella i display
matrix.write();
delay(500);
}
void loop()
{
if(millis()-t_display>200)
{
t_display=millis();
lum=map(analogRead(0),0,1023,0,15); matrix.setIntensity(lum); // Ogni 200ms legge il potenziometro (1023 con 3,3V).
se_capovolto();
}
scrive_orario();
if (digitalRead(sys_pin)) // Il pulsante è a riposo.
{
sysinfo_prem=0;
t1_sysinfo=millis();
if(millis()-t2_sysinfo<500) scrive_data();
}
else // Il pulsante è premuto.
{
if (sysinfo_prem==0)
{
t2_sysinfo=millis(); // Se non era premuto, prende il tempo per la pressione breve.
sysinfo_prem=1;
}
if (millis()-t1_sysinfo>=500) sysinfo(); // A 500ms di pressione salta a sysinfo.
}
if (WiFi.status()!=WL_CONNECTED) // Non connesso
{
matrix.drawChar(P+L*8-1,0,'°', HIGH,LOW,1);
matrix.write();
if (millis()-t_scan>10000 && scan_fatta==0) {t_scan=millis(); scan_fatta=1; WiFiScan();} // Se non è connesso, ogni 5 secondi rifà la scansione.
else scan_fatta=0;
}
else {prima_conn_ok=1;}
}