Come possiamo aiutarti?

Print

Come gestire automaticamente l’ora legale nell’HMI utilizzando una macro?

In questo post vi mostreremo come gestire automaticamente l’ora legale nell’HMI utilizzando una macro. Il cambio dell’ora è stato applicato per la prima volta nel 1916. Dal 2002, il cambio dell’ora viene effettuato in modo uniforme in tutti gli Stati membri dell’Unione Europea:

  • il passaggio all’ora legale avviene nella notte dell’ultimo sabato di marzo
  • il passaggio all’ ora invernale avviene nella notte dell ‘ultimo sabato di ottobre

Come promemoria, i Paesi dell’UE sono attualmente suddivisi in tre fusi orari:

  • Europa occidentale (GMT): Irlanda e Portogallo
  • Europa centrale (GMT 1): Austria, Belgio, Croazia, Repubblica Ceca, Danimarca, Francia, Germania, Ungheria, Italia, Lussemburgo, Malta, Paesi Bassi, Polonia, Slovacchia, Slovenia, Spagna e Svezia
  • Europa orientale (GMT 2): Bulgaria, Cipro, Estonia, Finlandia, Grecia, Lettonia, Lituania e Romania.

Con HMI-Tool

Nell’Editor macro, aggiungere una nuova macro e copiarla.

#include "MacroInit.h"
// Utility function: returns the number of days in a given month/year
int DaysInMonth(int month, int year)
{
switch(month)
{
case 1: return 31; // January
case 2: // February (check leap year)
if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0))
return 29;
else
return 28;
case 3: return 31; // March
case 4: return 30; // April
case 5: return 31; // May
case 6: return 30; // June
case 7: return 31; // July
case 8: return 31; // August
case 9: return 30; // September
case 10: return 31; // October
case 11: return 30; // November
case 12: return 31; // December
default: return 30; // fallback
}
}
void Macro_main(IN *p)
{
MarcoInit
// Automatic Daylight Saving Time (DST) / Winter Time switching
// This function must be called every minute
int minute      = BCD2BIN(LocalWord[60001]); // Current minute (BCD → decimal)
int hour        = BCD2BIN(LocalWord[60002]); // Current hour
int day         = BCD2BIN(LocalWord[60003]); // Day of month
int month       = BCD2BIN(LocalWord[60004]); // Month
int year        = BCD2BIN(LocalWord[60005]); // Year
int dayOfWeek   = BCD2BIN(LocalWord[60006]); // Monday=1 ... Sunday=7
int daysInMonth = DaysInMonth(month, year);
// --- Switch to Summer Time (DST) ---
// Condition: Last Sunday of March at 03:00 → clock jumps to 04:00
if ((month == 3) && (dayOfWeek == 7) && (day + 7 > daysInMonth) && (hour == 3) && (minute == 0))
{
LocalWord[60002] = 4;     // Set hour = 04
LocalBit[65535]  = 0;     // Flag = Summer Time
}
// --- Switch to Winter Time ---
// Condition: Last Sunday of October at 03:00 → clock goes back to 02:00
if ((LocalBit[65535] == 0) && (month == 10) && (dayOfWeek == 7) && (day + 7 > daysInMonth) && (hour == 3) && (minute == 0))
{
LocalWord[60002] = 2;     // Set hour = 02
LocalBit[65535]  = 1;     // Flag = Winter Time (prevents infinite loop)
}
}

Aggiungete la macro all’elenco “Macro globali” e impostate la sua frequenza di esecuzione a 60000 ms (1 minuto) per aggiornare l’orologio ogni minuto.

Come funziona

Il programma viene eseguito ogni minuto e legge l’ora corrente (minuti, ora, giorno, mese, anno, giorno della settimana) dai registri.
Tutti i valori dell’ora sono memorizzati in formato BCD, quindi vengono prima convertiti in decimale.
Una funzione ausiliaria calcola il numero di giorni del mese corrente, compresi gli anni bisestili.
Per individuare l’ultima domenica del mese, il codice controlla: dayOfWeek == 7 (domenica) e day 7 > daysInMonth.
Se è l’ultima domenica di marzo esattamente alle 03:00, l’orologio viene anticipato alle 04:00 (ora legale).
Viene impostato un bit flag (LocalBit[65535]) per indicare l’ora legale.
Se è l’ultima domenica di ottobre esattamente alle 03:00, l’orologio viene spostato indietro alle 02:00 (ora invernale).
Il bit flag viene commutato per indicare l’ora invernale, evitando correzioni ripetute.
In questo modo si evitano loop infiniti in cui la stessa ora verrebbe elaborata più volte.
Il sistema mantiene quindi automaticamente la sincronizzazione dell’ora locale con le regole ufficiali della DST.

È possibile sostituire LB65535 con LB51999 per il backup del valore(tipi di registro HMI: LB, LW, RWI e registro ritentivo/salvataggio)

Vedere anche Come impostare e sincronizzare l’orologio del PLC ACE con l’HMI utilizzando una macro