ESP8266: Aggiungere la data all'orologio NTP

Ciao a tutti

Vorrei aggiungere la visualizzazione della data all'orologio NTP con 8 matrici di LED che ho realizzato tempo fa. Mi spiegate qualcosa?

Queste sono le librerie già in uso:

#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>

Leggo in time che c'è weekday(), ma il compilatore indica errore:
funzioni:92:17: error: 'weekday' was not declared in this scope
Perché?

Per leggere l'orario è stato usato time.substring (11,19), anziché hour(), minute(), second(): perché?

Se anche volessi usare time.substring (0, 10), come faccio a sapere che cosa contiene la stringa time per estrarre la data?

Queste sono la funzione dell'orario, funzionante, e quella della data che ho provato a scrivere poco fa:

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()
{
matrix.fillScreen(LOW);
switch (weekday())
  {
  case 1: char giorno="Do"; break;
  case 2: char giorno="Lu"; break;
  case 3: char giorno="Ma"; break;
  case 4: char giorno="Me"; break;
  case 5: char giorno="Gi"; break;
  case 6: char giorno="Ve"; break;
  case 7: char giorno="Sa"; break;
  }    
matrix.drawChar(2,0,  giorno[0], HIGH,LOW,1); // Giorno 1
matrix.drawChar(8,0,  giorno[1], HIGH,LOW,1); // Giorno 2
matrix.drawChar(14,0, day()/10,  HIGH,LOW,1); // Giorno d
matrix.drawChar(20,0, day()%10,  HIGH,LOW,1); // Giorno u
matrix.drawChar(26,0, month()/10,HIGH,LOW,1); // Mese d
matrix.drawChar(32,0, month()%10,HIGH,LOW,1); // Mese u
uint16_t anno=year();
matrix.drawChar(56,0, anno%10, HIGH,LOW,1); // Anno u
anno/=10;
matrix.drawChar(50,0, anno%10,   HIGH,LOW,1); // Anno d
anno/=10;
matrix.drawChar(44,0, anno%10,   HIGH,LOW,1); // Anno c
anno/=10;
matrix.drawChar(38,0, anno%10,   HIGH,LOW,1); // Anno m
matrix.write();
}

Tra l'altro, mi sembra che il compilatore non ammetta le definizioni multiple di char giorno nello switch, seppure una sola per volta possa essere eseguita.

Grazie
Gianluca

Purtroppo ho anche io scoperto che della time.h esistono varie versioni che sono legate alla piattaforma ... se guardi, difatti, non c'è neanche nella time.h che è presente in AVR libc. :confused:

Guglielmo

EDIT: QUESTA dovrebbe essere la time.h per ESP8266 ... :roll_eyes:

1 Like

Ma funziona?

Compilare dovrebbe
Ma funzionare dubito

"Do" è una stringa letterale, dovrebbe leggerla come puntatore a carattere
E puntatore viene castato a carattere
Il "valore" del puntatore viene usato modulo 256 come carattere
Non la stringa

Giusto anche questo...

...ma neanche lì c'è scritto che cosa contiene time! >:(

@Standardoil, come potrei fare? Devo dichiarare la char e poi riempirla così?:

case 1:
giorno[0]='D'; giorno[1]='o'; break;
case 2:
giorno[0]='L'; giorno[1]='u'; break;
...

Fatto.

Ma no...
Io farei così, senza nessun case:

const char dow[7][3] = { "Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa" };
...
  byte d = weekday() -1; // Indice dell'array
  matrix.drawChar(2,0,  dow[d][0], HIGH,LOW,1); // Giorno 1
  matrix.drawChar(8,0,  dow[d][1], HIGH,LOW,1); // Giorno 2
...
1 Like

Purtroppo weekday() non è implementata in time() per l'ESP8266! >:(

Ho fatto una prova, scrivendo di fila i caratteri di time.substring (0,9). Ottengo:

0123456789
Tue Oct 1

e con time.substring (10,19):

0123456789
 15:49:05

Quindi la stringa esce già pronta per la visualizzazione dell'ora e della data (ma non ho capito perché c'è 1 Ottobre!)

Uhmm... Con time.substring (2,11) il 18 del giorno esce!

Per visualizzare i caratteri da 0 a 9 ho dovuto scrivere:
time.substring(0, 10).toCharArray(time_value, 11);
non meno di 10 in substring e non meno di 11 in CharArray.

Indagando oltre:

          11111111112222
012345678901234567890123
Tue Oct 18 15:49:05 2022

Andando oltre escono cifre ripetute di ore, minuti e secondi, quindi la stringa è finita e non si sa che altro trova in memoria.

Resta il fatto che appare in inglese:
Tue Oct 18
Per averla in italiano, dovrei incorporare la libreria e modificarla, oppure mettere una serie di if che sostituiscono i caratteri dei giorni e mesi italiani a quelli dei giorni e mesi inglesi... >:(
if (strcmp(... ...)) scrivi "Lu" per Lunedì
if (strcmp(... ...)) scrivi "10" per Ottobre
ma dovrei prima andare a estrarre i caratteri dalla stringona.
Mi sa che la lascio in inglese... >:(

... mmm ... io vedo tutta una serie di definizioni di funzioni ... :roll_eyes:

Comunque, scusa, ma per sapere il giorno della settimana, non ti basta leggere il valore della struttura 'tm' identificato da tm_wday (days since Sunday - [ 0 to 6 ])?

Guglielmo

Eh... Tu sei bravo! :slight_smile:
Come lo uso? Per provare ho scritto così, ma non funziona:
matrix.drawChar(2,0, 48+tm_wday, HIGH,LOW,1);

Ehm... "tm_wday" fa parte della struct tm quindi penso tu debba fare "time.tm_wday"...

Avevo fatto qualche prova... Forse non esattamente così...
Scrivendo così:
matrix.drawChar(2,0, 48+time.tm_wday, HIGH,LOW,1);

exit status 1
'class String' has no member named 'tm_wday'

Allora, tm_wday, come ti è stato detto, è uno degli elementi di una struttura di tipo tm:

struct tm
{
  int	tm_sec;
  int	tm_min;
  int	tm_hour;
  int	tm_mday;
  int	tm_mon;
  int	tm_year;
  int	tm_wday;
  int	tm_yday;
  int	tm_isdst;
#ifdef __TM_GMTOFF
  long	__TM_GMTOFF;
#endif
#ifdef __TM_ZONE
  const char *__TM_ZONE;
#endif
};

... stuttura che tu non hai definito e che quindi come fai ad usare?

Devi definire una struttura di tipo 'tm', convertire con la funzione gmtime() il valore in formato 'time_t' che hai nella struttura di tipo 'tm' e quindi hai accesso a tutti gli elementi con nome_struttura.nome_elemento.

Guglielmo

Sicuramente sono quattro righe di codice, ma non avendo idea di come impostarle è come se fosse giapponese... e non è che se sbaglio una virgola funziona quasi, facendo solo un difettuccio... :frowning:

In che variabile hai la data/ora, in formato 't_time', che vuoi usare?

Vuoi tenere conto della TZ (time zone)?

Guglielmo

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... :frowning:

#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;}
}

Io avevo fatto una cosa simile

time_t now;
struct tm timeinfo; 

now = time(nullptr);   // Ottengo l'ora aggiornata dal sistema
timeinfo = *localtime(&now);  // Aggiorno la struct timeinfo con il tempo localizzato secondo il timezone definito

adesso puoi usare 
timeinfo.tm_year
timeinfo.tm_mon
timeinfo.tm_mday
timeinfo.tm_hour
timeinfo.tm_min
timeinfo.tm_sec
e tutti gli altri elementi.

Ad essere onesto non ci avevo capito molto nemmeno io, all'epoca mi aveva aiutato cotestatnt.

Grazie, Fratt!
Così funziona, salvo che inspiegabilmente il mese viene 09... ???...

void scrive_data()
{
time_t now;
struct tm timeinfo; 
now = time(nullptr); // Ottengo l'ora aggiornata dal sistema.
timeinfo = *localtime(&now); // Aggiorno la struct timeinfo con il tempo localizzato secondo il timezone definito.
matrix.fillScreen(LOW);
const char giorno[7][3]={"Lu","Ma","Me","Gi","Ve","Sa","Do"};
byte d = timeinfo.tm_wday-1; // Indice dell'array
matrix.drawChar(1,0,  giorno[d][0], HIGH,LOW,1); // Giorno 1
matrix.drawChar(7,0,  giorno[d][1], HIGH,LOW,1); // Giorno 2
matrix.drawChar(17,0, 48+timeinfo.tm_mday/10, HIGH,LOW,1); // Giorno d
matrix.drawChar(23,0, 48+timeinfo.tm_mday%10, HIGH,LOW,1); // Giorno u
matrix.drawChar(34,0, 48+timeinfo.tm_mon/10, HIGH,LOW,1); // Mese d
matrix.drawChar(40,0, 48+timeinfo.tm_mon%10, HIGH,LOW,1); // Mese u
uint16_t anno=timeinfo.tm_year; // Scrivo l'anno a partire dalle unità.
matrix.drawChar(57,0, 48+anno%10, HIGH,LOW,1); // Anno u
anno/=10;
matrix.drawChar(51,0, 48+anno%10, HIGH,LOW,1); // Anno d
matrix.write(); // Send bitmap to display
delay(3000);
}

Attento, "tm_wday" va da 0 a 6, quindi devi togliere il "-1" che avevo aggiunto nel tuo precedente codice (dove il giorno della settimana l'avevi definita tra 1 e 7):

byte d = timeinfo.tm_wday; // Indice dell'array
matrix.drawChar(1,0,  giorno[d][0], HIGH,LOW,1); // Giorno 1
matrix.drawChar(7,0,  giorno[d][1], HIGH,LOW,1); // Giorno 2

oppure evitare del tutto quella variabile byte e fare direttamente:

matrix.drawChar(1,0,  giorno[timeinfo.tm_wday][0], HIGH,LOW,1); // Giorno 1
matrix.drawChar(7,0,  giorno[timeinfo.tm_wday][1], HIGH,LOW,1); // Giorno 2

Il giorno della settimana funziona, docdoc. Appariva il giorno sbagliato, ma ho risolto facendo iniziare la settimana di Lunedì. A quanto pare, qui il giorno 1 è Lunedì.
Il mese viene sbagliato!
Eppure prima, prendendo i caratteri dalla stringa, appariva Oct...

Però non riesco a capire...
In esp8266/time.h at master · arduino/esp8266 · GitHub vedo le dichiarazioni di tm_sec, tm_min, ecc., ma da dove vengono i valori?...