Shield DS 3231 RTC, gestire ora legale

Ho acquistato un RTC DS 3231 e dilibrerie per utilizzarlo ne ho trovato diverse.
Il mio dubbio però è:
Dovendo chiudere tutto in un box poco accessibile, come gestire in modo automatico la sincronizzazione automatica per l'aggiornamento all'ora legale/solare senza utilizzare internet o pc?

La butto li: se hai spazio almeno per un piccolo pulsante (magari anche un foro nel case in cui infilare uno stecchino) lo potresti usare per l'ora legale/solare.

Ad ogni tocco inverti una bool o cambi 0/1 in una byte, a seconda del valore assunto o/false o 1/true togli o aggiungi un'ora all'ora corrente, ricalcoli tutto (che se lo fai intorno a mezzanotte potrebbe sbarellare tutto) e riscrivi l'RTC.

My 10b cents :slight_smile:

Puoi calcolare il cambio orario.
Ci sono esempi in rete.
Ciao Uwe

https://forum.arduino.cc/index.php?topic=409107.msg3143667#msg3143667

brunello22:
Ricevere dati dal server esterno su richiesta di arduino - #53 by SukkoPera - Software - Arduino Forum

Sbaglio o usa il collegamento ad un pc per la sincronizzazione?

Karellen:
La butto li: se hai spazio almeno per un piccolo pulsante (magari anche un foro nel case in cui infilare uno stecchino) lo potresti usare per l'ora legale/solare.

Ad ogni tocco inverti una bool o cambi 0/1 in una byte, a seconda del valore assunto o/false o 1/true togli o aggiungi un'ora all'ora corrente, ricalcoli tutto (che se lo fai intorno a mezzanotte potrebbe sbarellare tutto) e riscrivi l'RTC.

My 10b cents :slight_smile:

sto aspettando che mi arrivi la centralina

ma credo di riuscire a trovare spazio per un lcd ed ovviamente 3 tastini per settare alcune impostazioni orarie utili al mio progetto.
Ovviamente potrei prevedere una voce di menù per settare l'ora legale o solare però preferirei che lo facesse autonomamente.

ziopippo:
Sbaglio o usa il collegamento ad un pc per la sincronizzazione?

Sbagli ;D.

Controllerò più attentamente :wink:

HO provato

SukkoPera:
Sbagli ;D.

Sto provando il codice che mi hai consigliato :

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h" // https://github.com/adafruit/RTClib

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"};

void setup () {

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(9600);

  delay(3000); // wait for console opening

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

byte dstOffset (byte d, byte m, unsigned int y, byte h) {
  /* This function returns the DST offset for the current UTC time.
    This is valid for the EU, for other places see
    http://www.webexhibits.org/daylightsaving/i.html

    Results have been checked for 2012-2030 (but should work since
    1996 to 2099) against the following references:
    - http://www.uniquevisitor.it/magazine/ora-legale-italia.php
    - http://www.calendario-365.it/ora-legale-orario-invernale.html
  */

  // Day in March that DST starts on, at 1 am
  byte dstOn = (31 - (5 * y / 4 + 4) % 7);

  // Day in October that DST ends  on, at 2 am
  byte dstOff = (31 - (5 * y / 4 + 1) % 7);

  if ((m > 3 && m < 10) ||
      (m == 3 && (d > dstOn || (d == dstOn && h >= 1))) ||
      (m == 10 && (d < dstOff || (d == dstOff && h <= 1))))
    return 1;
  else
    return 0;
}

const int utcOffset = 1;

DateTime getLocalTime() {
  DateTime now = rtc.now();
  int32_t deltaSecs = (utcOffset + dstOffset (now.day(), now.month(), now.year(), now.hour()) * 3600UL);
  // int32_t deltaSecs = (utcOffset + dstOffset (now.day(), now.month(), now.year(), now.hour())) * SECS_PER_HOUR
  const unsigned long SECS_PER_HOUR = 3600;
  DateTime correctedNow (now + TimeSpan(deltaSecs));
  return correctedNow;
}

void loop () {
  DateTime now = getLocalTime();

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  Serial.print(" since midnight 1/1/1970 = ");
  Serial.print(now.unixtime());
  Serial.print("s = ");
  Serial.print(now.unixtime() / 86400L);
  Serial.println("d");

  // calculate a date which is 7 days and 30 seconds into the future
  DateTime future (now + TimeSpan(7, 12, 30, 6));

  Serial.print(" now + 7d + 30s: ");
  Serial.print(future.year(), DEC);
  Serial.print('/');
  Serial.print(future.month(), DEC);
  Serial.print('/');
  Serial.print(future.day(), DEC);
  Serial.print(' ');
  Serial.print(future.hour(), DEC);
  Serial.print(':');
  Serial.print(future.minute(), DEC);
  Serial.print(':');
  Serial.print(future.second(), DEC);
  Serial.println();

  Serial.println();
  delay(3000);
}

però sulla seriale mi riporta:

2018/4/7 (Sabato) 18:11:40
 since midnight 1/1/1970 = 1523124700s = 17628d
 now + 7d + 30s: 2018/4/15 6:41:46

ovvero un'ora esatta in più; Come mai secondo voi?

Stampa anche l'ora reale dell'RTC (rtc.now()) e poi vediamo. Ricorda che quella deve rimanere impostata su GMT/UTC.

SukkoPera:
Stampa anche l'ora reale dell'RTC (rtc.now()) e poi vediamo. Ricorda che quella deve rimanere impostata su GMT/UTC.

2018/4/9 (Luned⸮) 18:12:26
 since midnight 1/1/1970 = 1523297546s = 17630d
 now + 7d + 30s: 2018/4/17 6:42:32

ovvero l'ora esatta

Se invece modifico in questo modo:

DateTime getLocalTime() {
  DateTime now = rtc.now();
  //int32_t deltaSecs = (utcOffset + dstOffset (now.day(), now.month(), now.year(), now.hour()) * 3600UL);
  const unsigned long SECS_PER_HOUR = 3600;
  int32_t deltaSecs = (utcOffset + dstOffset (now.day(), now.month(), now.year(), now.hour())) * SECS_PER_HOUR;
  
  DateTime correctedNow (now + TimeSpan(deltaSecs));
  return correctedNow;
}

void loop () {
 DateTime now = getLocalTime();
  //DateTime now = rtc.now();
...
...

addirittura mi aumenta di due ore :frowning:

Allora non ci capiamo: l'RTC deve rimanere impostato sull'ora di Greenwich. Insomma, rtc.now() in questo momento deve essere indietro di due ore.

Inizia a sistemare questo e poi andiamo avanti.

SukkoPera:
Allora non ci capiamo: l'RTC deve rimanere impostato sull'ora di Greenwich. Insomma, rtc.now() in questo momento deve essere indietro di due ore.

Inizia a sistemare questo e poi andiamo avanti.

Ipostando DateTime now = rtc.now(); ti avevo già scritto che mi dava l'ora atuale :wink:

ziopippo:

2018/4/9 (Luned⸮) 18:12:26

since midnight 1/1/1970 = 1523297546s = 17630d
now + 7d + 30s: 2018/4/17 6:42:32




ovvero l'ora esatta

...

ziopippo:
ti avevo già scritto che mi dava l'ora attuale :wink:

... ti ha appena ribadito che è SBAGLIATO ... deve darti due ore prima della nostra ora attuale (... ovvero l'ora GMT), quindi rimetti l'orario nel RTC.

Guglielmo

gpb01:
... ti ha appena ribadito che è SBAGLIATO ... deve darti due ore prima della nostra ora attuale (... ovvero l'ora GMT), quindi rimetti l'orario nel RTC.

Guglielmo

Scusa ma non avevo copreso bene.

Domanda: Per impostare l'ora non si usa:

rtc.adjust(DateTime(2018, 4, 9, 18, 10, 0));

Se si, perchè ignora questo comando lasciando l'ora attuale alle 20 invece che alle 18? (Da me sono ovviamente le 20).

ho provato con un codice "pulito" come questo:

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {
  while (!Serial); // for Leonardo/Micro/Zero

  Serial.begin(57600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
     rtc.adjust(DateTime(2018, 4, 9, 18, 10, 0));
  }
}

void loop () {
    DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since midnight 1/1/1970 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("d");
    
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now + TimeSpan(7,12,30,6));
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

Piccolo aggiornamento:

Non capisco perchè con il codice postato non riesco in alcun modo a risincronizzare il modulo all'ora UTC corretta

rtc.adjust(DateTime(2018, 4, 9, 18, 10, 0));

Correggendo però l'ora usando altre librerie e codici sono riuscito a correggere l'orario su UTC e ricaricando poi il codice in questione ottengo finalmente l'ora UTC (2 ore prima) impostando su

DateTime now = rtc.now();

e l'orario corrente (con il fuso orario a +1 per l'italia e l'ora l'egale a +1 quindi come dice il caro Guglelmo tutto a due ore in più :wink: impostando su

DateTime now = getLocalTime();

Ora resta il dilemma sul perchè non riesca a correggere l'orario con questo codice :frowning:

Dubito dipenda dal fatto che oltre al modulo DS1302 ho collegato alla I2C anche un LCD; Ho provato a staccarlo e ricaricare lo sketch con la correzione dell'orario e non l'ha accettata ugualmente...

Come mai secodo voi?

Altra domanda, posso settare DateTime future (now + TimeSpan(7, 30, 00, 6)); in modo da simulare una data con l'ora solare per verificarne il giusto funzionamento?

L'ora dell'RTC va sempre messa in UTC, quindi configuri quale fuso orario usare e la libreria ti converte l'orario UTC in quello attuale tenendo conto di orario invernale e estivo.

Per l'RTC usa la TimeLib.

Il modulo DS1302 ha però un errore variabile a seconda della qualità del modulo. Io ne ho avuto uno che perdeva 30 secondi al giorno. Il DS3231 è meglio.

Garzie per

zoomx:
GitHub - JChristensen/Timezone: Arduino library to facilitate time zone conversions and automatic daylight saving (summer) time adjustments.
L'ora dell'RTC va sempre messa in UTC, quindi configuri quale fuso orario usare e la libreria ti converte l'orario UTC in quello attuale tenendo conto di orario invernale e estivo.

Per l'RTC usa la TimeLib.

Il modulo DS1302 ha però un errore variabile a seconda della qualità del modulo. Io ne ho avuto uno che perdeva 30 secondi al giorno. Il DS3231 è meglio.

Ottimo grazie lo proverò :wink:
Non sapevo del problema del DS1302 altrimenti acquistavo altro. A questo punto considerando che devo mettere qualche tasto per settare alcune opzioni, credo che sia conveniente prevedere anche un cambio dell'ora manuale...

Prevedi qualcosa per sistemare l'orologio, di solito va ma se succede qualcosa di imprevisto....
Se però c'è la possibilità di una WiFi ti consiglierei di realizzare il tutto con un ESP8266 e di prendere l'ora con il protocollo NTP, usando sempre le librerie TimeLib e Timezone ma con un RTC software.
Se però la WiFi non è garantita, ad esempio se manca per più giorni, allora non conviene usare un RTC software ma sempre un DS3231, magari sempre con ESP8266.

Ma dipende dal progetto.

All'inizio avevo previsto di usare solo una WEMOS poi però ho riflettuto meglio ed ho optato per un RTC Hardware perchè il tutto andrà in un'abitazione di un amico che di arduino ne sa meno di zero. Se dovesse pertanto sostituire il router (come gli è già capitato) sarebbe difficoltoso aggiornare il SSID, password ecc.

Ho provato a compilare alcuni esempi della libreria Timezone (con una nano) ma ricevo alcuni errori e devo capire ancora come risolverli.