RTC setup via software (no ide)

Benritrovati,

sto usando un codice per settare l'RTC DS3231 attraverso un progrmmino per windows. Il codice dello sketch e lo stesso programmino li ho prelevati da questo sito:

http://www.lucadentella.it/2013/11/27/rtcsetup/

Anche se nel sito si parla di un RTC DS1307, sistemando leggermente il codice, il tutto funziona bene:

#include <Wire.h>
#include "RTClib.h"

#define BUFFER_SIZE 20
#define VERSION     "1.0"

// RTC object
RTC_DS3231 rtc;

// Buffer for incoming data
char serial_buffer[BUFFER_SIZE];
int buffer_position;

void setup() {

  Serial.begin(57600);
  Wire.begin();
  rtc.begin();

  buffer_position = 0;
}

void loop() {

  // Wait for incoming data on serial port
  if (Serial.available() > 0) {

    // Read the incoming character
    char incoming_char = Serial.read();

    // End of line?
    if (incoming_char == '\n') {

      // Parse the command

      // ##
      if (serial_buffer[0] == '#' && serial_buffer[1] == '#')
        Serial.println("!!");

      // ?V
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'V')
        Serial.println(VERSION);

      // ?T
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'T') {
        DateTime now = rtc.now();
        char time_string[20];
        sprintf(time_string, "%02d/%02d/%d %02d:%02d:%02d",
                now.day(), now.month(), now.year(),
                now.hour(), now.minute(), now.second());
        Serial.println(time_string);
      }

      // !T
      else if (serial_buffer[0] == '!' && serial_buffer[1] == 'T') {

        String time_string = String(serial_buffer);
        int day = time_string.substring(2, 4).toInt();
        int month = time_string.substring(4, 6).toInt();
        int year = time_string.substring(6, 10).toInt();
        int hour = time_string.substring(10, 12).toInt();
        int minute = time_string.substring(12, 14).toInt();
        int second = time_string.substring(14, 16).toInt();
        DateTime set_time = DateTime(year, month, day, hour, minute, second);
        rtc.adjust(set_time);
        Serial.println("OK");
      }

      // Reset the buffer
      buffer_position = 0;
    }

    // Carriage return, do nothing
    else if (incoming_char == '\r');

    // Normal character
    else {

      // Buffer full, we need to reset it
      if (buffer_position == BUFFER_SIZE - 1) buffer_position = 0;

      // Store the character in the buffer and move the index
      serial_buffer[buffer_position] = incoming_char;
      buffer_position++;
    }
  }
  }

Ora lo scopo delle mie prove è quello di fondere questo sketch in uno più ampio in modo tale da poter regolare più facilmente l'ora del RTC. Breve digressione: ho costruito una piccola centralina che ho montato sullo scooter che fornisce alcuni parametri vedi rpm, data e ora, voltmetro e temperatura.
Poichè è possibile che la batteria del rtc si scarichi o venga estratta per manutenzione, ecco che sarà necessario risettarel'RTC. Ho pensato appunto che questo metodo fosse più veloce.

Per cominciare, perchè se aggiungo nel codice di sopra le righe:

Serial.print(' ');
            if (day < 10)  Serial.print('0');
            Serial.print(day, DEC);
            Serial.print('/');
            if (month < 10)  Serial.print('0');
            Serial.print(month, DEC);
            Serial.print('/');
            Serial.print(YY);
            Serial.print(' ');
            if (hour < 10)  Serial.print('0');
            Serial.print(hour, DEC);
            Serial.print(':');
            if (minute < 10) Serial.print('0');
            Serial.print(minute, DEC);
            Serial.println();

il programmino per windows non si sincronizza più con l'RTC?

La comunicazione tra PC e Arduino è su seriale.
Se nel programma usi la seriale per "altro" è logico non funzioni più nulla.
Dovresti pensare ad un sistema per mettere l'Arduino in stato di "sincronizzazione".
Ovvero una variabile globale, di solito false. Se da seriale arriva comando specifico (esempio quel ##) allora setti la globale a true e da quel momento Arduino è in modalità sincronizzazione. Un altro comando dovrebbe farlo finire (esempio @@) e rientrare in modalità "normale"

Ciao nid69ita, ho intuito qualcosina, potresti darmi qualche spunto maggiore?

Un grosso if nel programma, basato su valore di una varibile globale.
Se vero è in modalità sincronizzazione. Se falso in modalità "normale"
In modalità normale se arriva un ## entri in modalità sincronizzazione. Se in modalità sincronizzazione arriva @@ esci da questa modalità (rimetti variabile a false)

In modalità sincronizzazione (variabile a true) metti la parte del primo codice (ma non tutto) e aggiungi l'uscita da questa modalità se arriva @@
In modalità normale metti il secondo codice, oltre però a qualcosa per verificare se arriva ##

Ma i comandi provenienti dal programmino non li posso variare. il programmino è già compilato. Lo sketch si aspetta in sequenza i comandi che il programmino deve inviare. Come creo quindi questa condizione?

I comandi che si scambiano pc e arduino fanno parte di un "protocollo".
E' essenziale poter uscire dalla modalità "sincronizzazione". Non potendo variare il programmino, fai entrare arduino in modalità sincronizzazione e per farlo uscire... resetta arduino e nel setup rimetti a false la variabile globale. Brutto ma funzionale.

quindi così:

dichiaro boolean syncRTC;

nel setup metto:

syncRTC = false;

e poi

 if (syncRTC == false) {
    // Wait for incoming data on serial port
    if (Serial.available() > 0) {

      // Read the incoming character
      char incoming_char = Serial.read();

      // End of line?
      if (incoming_char == '\n') {

        // Parse the command

        // ##
        if (serial_buffer[0] == '#' && serial_buffer[1] == '#')
          Serial.println("!!");

        // ?V
        else if (serial_buffer[0] == '?' && serial_buffer[1] == 'V')
          Serial.println(VERSION);

        // ?T
        else if (serial_buffer[0] == '?' && serial_buffer[1] == 'T') {
          DateTime now = rtc.now();
          char time_string[20];
          sprintf(time_string, "%02d/%02d/%d %02d:%02d:%02d",
                  now.day(), now.month(), now.year(),
                  now.hour(), now.minute(), now.second());
          Serial.println(time_string);
        }

        // !T
        else if (serial_buffer[0] == '!' && serial_buffer[1] == 'T') {

          String time_string = String(serial_buffer);
          int day = time_string.substring(2, 4).toInt();
          int month = time_string.substring(4, 6).toInt();
          int year = time_string.substring(6, 10).toInt();
          int hour = time_string.substring(10, 12).toInt();
          int minute = time_string.substring(12, 14).toInt();
          int second = time_string.substring(14, 16).toInt();
          DateTime set_time = DateTime(year, month, day, hour, minute, second);
          rtc.adjust(set_time);
          Serial.println("OK");
        }

        // Reset the buffer
        buffer_position = 0;
      }

      // Carriage return, do nothing
      else if (incoming_char == '\r');

      // Normal character
      else {

        // Buffer full, we need to reset it
        if (buffer_position == BUFFER_SIZE - 1) buffer_position = 0;

        // Store the character in the buffer and move the index
        serial_buffer[buffer_position] = incoming_char;
        buffer_position++;

      }
    }
    syncRTC = true;
  }

Circa. Il syncRTC quando falso deve verificare se arriva ##, se si entri in modalità syncRTC=true.

if (syncRTC == false) 
{ ...
  if (serial_buffer[0] == '#' && serial_buffer[1] == '#')
  { Serial.println("!!");
    syncRTC=true;
    return;
  }
  // programma normale
}
else
{ // modalità syncRTC dove verifica gli altri comandi, ## escluso, già fatto sopra
}

Non funziona, il programma non rileva l'RTC

E se non posti il codice che consigli ti possiamo dare ?

incollo il codice

#include <Wire.h>
#include "RTClib.h"

#define BUFFER_SIZE 20
#define VERSION     "1.0"

// RTC object
RTC_DS3231 rtc;

// Buffer for incoming data
char serial_buffer[BUFFER_SIZE];
int buffer_position;
boolean syncRTC;
char incoming_char;
int day;
int month;
int year;
int hour;
int minute;
int second;
byte YY = year - 2000;

void setup() {

  Serial.begin(57600);
  Wire.begin();
  rtc.begin();
  syncRTC = false;
  buffer_position = 0;
}

void loop() {

  if (syncRTC == false)
  {

    // Wait for incoming data on serial port
    if (Serial.available() > 0) {

      // Read the incoming character
      char incoming_char = Serial.read();

      // End of line?
      if (incoming_char == '\n') {

        // Parse the command

        // ##
        if (serial_buffer[0] == '#' && serial_buffer[1] == '#')
          Serial.println("!!");
        syncRTC = true;
        return;
      }
      // righe per stampa ora
      Serial.print(' ');
      if (day < 10)  Serial.print('0');
      Serial.print(day, DEC);
      Serial.print('/');
      if (month < 10)  Serial.print('0');
      Serial.print(month, DEC);
      Serial.print('/');
      Serial.print(YY);
      Serial.print(' ');
      if (hour < 10)  Serial.print('0');
      Serial.print(hour, DEC);
      Serial.print(':');
      if (minute < 10) Serial.print('0');
      Serial.print(minute, DEC);
      Serial.println();
    }
    else
    { // ?V
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'V')
        Serial.println(VERSION);

      // ?T
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'T') {
        DateTime now = rtc.now();
        char time_string[20];
        sprintf(time_string, "%02d/%02d/%d %02d:%02d:%02d",
                now.day(), now.month(), now.year(),
                now.hour(), now.minute(), now.second());
        Serial.println(time_string);
      }

      // !T
      else if (serial_buffer[0] == '!' && serial_buffer[1] == 'T') {

        String time_string = String(serial_buffer);
        int day = time_string.substring(2, 4).toInt();
        int month = time_string.substring(4, 6).toInt();
        int year = time_string.substring(6, 10).toInt();
        int hour = time_string.substring(10, 12).toInt();
        int minute = time_string.substring(12, 14).toInt();
        int second = time_string.substring(14, 16).toInt();
        DateTime set_time = DateTime(year, month, day, hour, minute, second);
        rtc.adjust(set_time);
        Serial.println("OK");
      }

      // Reset the buffer
      buffer_position = 0;
    }

    // Carriage return, do nothing
    else if (incoming_char == '\r');

    // Normal character
    else {

      // Buffer full, we need to reset it
      if (buffer_position == BUFFER_SIZE - 1) buffer_position = 0;

      // Store the character in the buffer and move the index
      serial_buffer[buffer_position] = incoming_char;
      buffer_position++;
    }
  }
}
}

CTRL+T per indentazione automatica nell'IDE. E ti dice troppe parentesi graffe chiuse
Abituati a mettere le graffe NON al fondo ma a inizio, vedi post mio successivo, incolonno la aperta con la chiusa, come fà l'autoindentatore

P.S. questo non ha senso:
byte YY = year - 2000;
NON puoi farlo quando dichiari la variabile. In quel momento year=0, è un calcolo che devi fare PRIMA di stampare/usare YY.

Prova così (non ho quel rtc, non posso provarlo realmente):

#include <Wire.h>
#include "RTClib.h"

#define BUFFER_SIZE 20
#define VERSION     "1.0"

RTC_DS3231 rtc;
// Buffer for incoming data
char serial_buffer[BUFFER_SIZE];
int buffer_position;
boolean syncRTC;
char incoming_char;

void setup() 
{ delay(1000);
  Serial.begin(57600);
  Wire.begin();
  rtc.begin();
  syncRTC = false;
  buffer_position = 0;
}

void loop() 
{ 
  if (Serial.available() > 0) // Wait for incoming data on serial port
  { char incoming_char = Serial.read(); // Read the incoming character
    if (incoming_char == '\n')  // End of line?
    { // Parse the command
      // ##
      if (serial_buffer[0] == '#' && serial_buffer[1] == '#')
      { Serial.println("!!");
        syncRTC=true;
        digitalWrite(13,LOW);
      }
      // ?V
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'V')
      { Serial.println(VERSION);
      }
      // ?T
      else if (serial_buffer[0] == '?' && serial_buffer[1] == 'T') 
      { DateTime now = rtc.now();
        char time_string[20];
        sprintf(time_string, "%02d/%02d/%d %02d:%02d:%02d",
        now.day(), now.month(), now.year(),
        now.hour(), now.minute(), now.second());
        Serial.println(time_string);
        Serial.println("12/12/2012 12:12:12");
      }
      // !T
      else if (serial_buffer[0] == '!' && serial_buffer[1] == 'T') 
      { String time_string = String(serial_buffer);
        int day = time_string.substring(2, 4).toInt();
        int month = time_string.substring(4, 6).toInt();
        int year = time_string.substring(6, 10).toInt();
        int hour = time_string.substring(10, 12).toInt();
        int minute = time_string.substring(12, 14).toInt();
        int second = time_string.substring(14, 16).toInt();
        DateTime set_time = DateTime(year, month, day, hour, minute, second);
        rtc.adjust(set_time);
        Serial.println("OK");
      }
      // Reset the buffer
      buffer_position = 0;
    } 
    else if (incoming_char == '\r');
      // Carriage return, do nothing
    else   // Normal character
    { // Buffer full, we need to reset it
      if (buffer_position == BUFFER_SIZE - 1) buffer_position = 0;
      // Store the character in the buffer and move the index
      serial_buffer[buffer_position] = incoming_char;
      buffer_position++;
    }
  }
  if (syncRTC == false)
  { 
    StampaOra();
  }
} 

void StampaOra()
{ DateTime now = rtc.now();
  byte YY = now.year() - 2000;

  Serial.print(' ');
  if (now.day() < 10)  Serial.print('0');
  Serial.print(now.day(), DEC);
  Serial.print('/');
  if (now.month() < 10)  Serial.print('0');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(YY);
  Serial.print(' ');
  if (now.hour() < 10)  Serial.print('0');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  if (now.minute() < 10) Serial.print('0');
  Serial.print(now.minute(), DEC);
  Serial.println();
}

wow va alla grande! Grazie

adesso faccio qualche prova e importo lo sketch in quello papà

Ho inserito la porzione dello sketch di cui sopra nello sketch principale e funziona bene. Ora volendo fare i fighi sapete se esiste una funzione per il passaggio automatico dell'ora da solare a legale e viceversa. Vorrei cercare di automatizzare al massimo la sincronizzazione dell'ora.

Io sto usando da un pò di tempo una serie di if cosi:

// Codice per verificare se ci si trova nell' ora legale o solare, in un caso o nell'altro imposta il relativo flag di controllo
  if (now.month() == 10) // Se sono ad ottobre
  {
    if (now.dayOfTheWeek() == 0)     // Se è domenica
    {
      if ((now.day() + 7) > 31) // Se è l'ultima domenica
      {
        if (now.hour() >= 3) // Se l'ora è >= delle 3.00
        {
          Flag_orario = S;  // setto il flag su S
        }
      }
    }
    else
    {
      if ((now.day() + (7 - now.dayOfTheWeek()) > 31)) // Se non è domenica, ma l'ultima è già passata
      {
        Flag_orario = S;
      }
      else
      {
        Flag_orario = L;
      }
    }
  }
  else if (now.month() == 3) // Se sono a marzo
  {
    if (now.dayOfTheWeek() == 0) // Se è domenica
    {
      if ((now.day() + 7) > 31) // Se è l'ultima domenica
      {
        if (now.hour() >= 2)  // Se l'ora è >= delle 2.00
        {
          Flag_orario = L;
        }
      }
    }
    else
    {
      if ((now.day() + (7 - now.dayOfTheWeek())) > 31) // Se non è domenica, ma l'ultima è già passata
      {
        Flag_orario = L;
      }
      else
      {
        Flag_orario = S;
      }
    }
  }
  else if (now.month() >= 4 && now.month() <= 9) // Se sono nel periodo dell'ora legale
  {
    Flag_orario = L;
  }
  else if ((now.month() >= 1 && now.month() <= 2) || (now.month() >= 11 && now.month() <= 12))   // Se sono nel periodo dell'ora solare
  {
    Flag_orario = S;
  }

che poi si traduce nella stampa dell'ora in questo modo:

// Se sincronizzo l'RTC nel periodo dell'ora legale (MARZO/OTTOBRE), commentare il blocco alle righe: 203-208
        //if (Flag_orario = L) {
        //ora = now.hour();
        //}
        //if (Flag_orario = S) {
        //ora = (now.hour()-1);
        //}
        // Se sincronizzo l'RTC nel periodo dell'ora solare (OTTOBRE/MARZO), commentare il blocco sopra questa riga. Righe: 196-201
        if (Flag_orario == L) {
          ora = (now.hour() + 1);
        }
        if (Flag_orario == S) {
          ora = now.hour();
        }

Il fatto è che c'è sempre bisogno del mio intervento per sistemare lo sketch e dire se ci si trova nell'ora legale o solare. Adesso in virtù della sincronizzazione via programmino non posso adottare questo metodo.

Come posso fare?

droidprova:
Ora volendo fare i fighi sapete se esiste una funzione per il passaggio automatico dell'ora da solare a legale e viceversa.

Si, c'è e se ne è parlato qui sul forum .. però tocca che ti cerchi la discussione perché è di svariati mesi fa ...

Guglielmo

Grazie Guglielmo l'ho trovata è quella di Sukko, adesso continuo di la.

ciao