include unixtime support question for DS3231 time module

I am using the example given in the 3231 library below is the code

#include <Wire.h>
#include "ds3231.h"
#include "rtc_ds3231.h"

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 5000;

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");
}

void loop()
{
    char in;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
#endif

        Serial.println(buff);
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = inp2toi(cmd, 7);
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

I have a question about this particular section

// there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
t.mon, t.mday, t.hour, t.min, t.sec);
#endif

My question is, it says there is a compile time option in the library to include unixtime support... Does anyone know how to do this though? Do I need to include the WiFiUdpNtpClient code and write t.unixtime = unixtime from that the Ntp code or is there a different way to do this?

My second question about the DS3231 chip is about the alarm option. I am under the impression you can set two alarms, and it works by triggering the interrupt. What has me confused is that for two alarms you would set the interrupt on pins two and three on the arduino presumably. However, do the interrupts initiate from two different pins on the DS3231?

The third and final question for now is how to work this line of code to set the alarm

} else if (cmd[0] == 65 && cmdsize == 9) { // "A" set alarm 1
DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
//ASSMMHHDD

I tried typing A in the serial monitor display but that didn't seem to work. Do I need to write A in one of the flag functions in the code instead?

My question is, it says there is a compile time option in the library to include unixtime support... Does anyone know how to do this though?

Edit the .h file and add:
#define CONFIG_UNIXTIME

Do I need to include the WiFiUdpNtpClient code

No.

when I add

Edit the .h file and add:
#define CONFIG_UNIXTIME

I get the following error when I try to compile

rtc_ds3231.ino: In function 'void loop()':
rtc_ds3231.ino:36:53: error: 'struct ts' has no member named 'unixtime'
Error compiling.

The attachment shows how I edited the .h file. Did I do this correctly? I've never messed with a side program within the same sketch before like this .h file is.

Did I do this correctly?

Looks OK to me. Now, you need to post links to all the libraries you are using, so we can look at the code.

Library links for all the code used in the example. The example I am using is one of the three examples that comes with the library labeled rtc_ds3231

It looks like the #define CONFIG_UNIXTIME is in a file called config.h in the ds3231 library.

#ifndef __config_h_
#define __config_h_

// comment this out if you need unixtime support
// this will add about 324bytes to your firmware
//#define CONFIG_UNIXTIME

#endif

My second question about the DS3231 chip is about the alarm option. I am under the impression you can set two alarms, and it works by triggering the interrupt. What has me confused is that for two alarms you would set the interrupt on pins two and three on the arduino presumably. However, do the interrupts initiate from two different pins on the DS3231?

The two alarms both can produce a high signal level on a pin which has dual function for either square wave output or an alarm timer match interrupt signal. This pin should be broken out on the ds3231 module and is often just labeled SQW. Since the timer resolution is only to the second, if you read this pin through polling you will pick up any changes and you do not need hardware interrupts on the arduino to read the status of this pin.

Once you know about the timer interrupt match status, you then have to read the Alarm1 and Alarm2 flags to determine which one has been triggered. Once status has been determined, you reset the flag which then clears the signal on the int/sqw pin.

There are many different ds3231 libraries and how they handle setting, reading and clearing the alarms may differ.

You would gain alot by spending some time studying the datasheet for the ds3231.

It looks like the #define CONFIG_UNIXTIME is in a file called config.h in the ds3231 library.

Where does this go in the code? In the main code up top, or in the secondary DS3231.h folder?

Why did they create a secondary folder by the way? Is there a reason they didn't just have it in the main code?

"through polling" This is a new term. I will youtube and google this!

There are many different ds3231 libraries and how they handle setting, reading and clearing the alarms may differ.

Yes, but in the example below it says A will set alarm1. It doesn't work when you type A in the serial monitor, so where do you put A? - I'm a complete newb trying to learn how to read code

    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);

You would gain alot by spending some time studying the datasheet for the ds3231.

You have no idea how hard i'm trying to learn how to read a datasheet. I've asked around many times if anyone knew a great book, or tutorial of any kind that would be ideal for a beginner to learn the ropes of reading datasheets.

Where does this go in the code? In the main code up top, or in the secondary DS3231.h folder?

I would go to the config.h file and remove the comment // lines from in front of the //#define CONFIG_UNIXTIME.

"through polling"

This means you just put in the main loop, a digital read of the arduino pin which is connected to the sqw/int pin of the ds3231 module.

For me, the data sheet is far easier to understand than the Rodan ds3231 library.

I have looked at several of the ds3231 libraries, and use one by Jack Christensen for ds3231/3232 GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

DS3232RTC is an Arduino library that supports the Maxim Integrated DS3232 and DS3231 Real-Time Clocks. This library is intended to be used with the Arduino Time library.

The DS3232RTC library is a drop-in replacement for the DS1307RTC.h library by Michael Margolis that is supplied with the Arduino Time library above. To change from using a DS1307 RTC to an DS323x RTC, it is only necessary to use #include <DS3232RTC.h> instead of #include <DS1307RTC.h>.

DS3232RTC also implements functions to support the additional features of the DS3232 and DS3231. The DS3231 has the same features as the DS3232 except: (1) Battery-backed SRAM, (2) Battery-backed 32kHz output (BB32kHz bit in Control/Status register 0x0F), and (3) Adjustable temperature sensor sample rate (CRATE1:0 bits in the Control/Status register).

"Arduino DS3232RTC Library" by Jack Christensen is licensed under CC BY-SA 4.0.

Here is a sketch I put together using the Christensen library which sets and reads the alarms. It shows the data in the ds3231 registers, and demonstrates the relationship between the interrupt pin and the alarm status flags. To fill the input required in the RTC.setAlarm() function from the serial monitor is pretty straight forward using the serial read and parse methods shown in Robin2's tutorial Serial Input Basics - Programming Questions - Arduino Forum

#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)

tmElements_t tm;
const byte rtcAlarmPin = 8;//pin read by polling

void setup(void)
{
  pinMode(rtcAlarmPin,INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("DS3231RTC Alarm Test");
  setSyncProvider(RTC.get);   // the function to get the unix time from the RTC
  if(timeStatus() != timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");
  Serial.println(); 

  //enable alarm interrupts on match;also sets status flags A1F,A2F
  RTC.alarmInterrupt(1,1);//enable alarm 1 interrupt A1IE
  RTC.alarmInterrupt(2,1);//enable alarm 2 interrupt A2IE

  //enable or disable the square wave output,
  // no square wave (NONE) sets ITCN bit=1  
  //enables alarm interrupt on square wave pin set from A1F, A2F
  //digitalRead with INPUT_PULLUP; LOW is alarm interrupt
  RTC.squareWave(SQWAVE_NONE);


  /*Alarm_Types defined in RTC3232.h.............................................
   
   ALM1_EVERY_SECOND 
   ALM1_MATCH_SECONDS
   ALM1_MATCH_MINUTES     //match minutes *and* seconds
   ALM1_MATCH_HOURS       //match hours *and* minutes, seconds
   ALM1_MATCH_DATE        //match date *and* hours, minutes, seconds
   ALM1_MATCH_DAY         //match day *and* hours, minutes, seconds
   ALM2_EVERY_MINUTE 
   ALM2_MATCH_MINUTES     //match minutes
   ALM2_MATCH_HOURS       //match hours *and* minutes
   ALM2_MATCH_DATE       //match date *and* hours, minutes
   ALM2_MATCH_DAY        //match day *and* hours, minutes
   */
  //setAlarm Format (Alarm_Type, seconds, minutes, hours, date(or day))
  RTC.setAlarm(ALM2_EVERY_MINUTE, 0,0,0,0);
  RTC.setAlarm(ALM1_MATCH_SECONDS,30,0,0,0);

  RegisterDump();

}
void loop()
{
  TimeDateDisplay();
  Serial.print("rtcAlarmPin   ");
  Serial.println(digitalRead(rtcAlarmPin));//resets with status reset
  Serial.print("Alarm1 status  ");
  Serial.println(RTC.alarm(1));//reads and resets status
  Serial.print("Alarm2 status  ");
  Serial.println(RTC.alarm(2));//reads and resets status
  Serial.println();
  delay(5000);
}

void TimeDateDisplay(void)
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits) // utility function for TimeDateDisplay prints preceding colon and leading 0
{
  Serial.print(':');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void RegisterDump(){
  Serial.print("Register");
  Serial.print("\t");
  Serial.println("Bit Values");
  Serial.println();
  for (int a = 0x00; a < 0x13; a++)
  {
    byte b=readNVRAM(a);
    Serial.print("0X");
    if(a<16)
      Serial.print("0");
    Serial.print(a, HEX);
    Serial.print("\t");
    //Serial.print("\t");
    for (int i = 7; i > -1; i--)//routine for printing full 8 bits, leading zeros
    {

      Serial.print((b >> i) & 0X01);//shift and select first bit
    }
    Serial.println();
    //delay(100);
  }
  Serial.println();
}

byte readNVRAM(byte location)
// retrieves data from DS1307 NVRAM location
{
  byte result;
  Wire.beginTransmission(RTC_ADDR);
  Wire.write(location); 
  Wire.endTransmission();  
  Wire.requestFrom(RTC_ADDR, 1);//only 1 byte, does not need wire.available
  result = Wire.read();
  return result;
}

Between the code you posted (which by the way i love the serial monitor display setup) and Robins example reference, with all the references listed in Robins example, I have probably two or three days of homework to do to understand all of it thoroughly.

Thanks for the starting point!

Just to make sure i'm understanding a little at first glance

  //enable alarm interrupts on match;also sets status flags A1F,A2F
  RTC.alarmInterrupt(1,1);//enable alarm 1 interrupt A1IE
  RTC.alarmInterrupt(2,1);//enable alarm 2 interrupt A2IE
                             | |
                             | 1 = alarm on, 0 = alarm off
                             1= alarm 1, 2 = alarm 2
  //setAlarm Format (Alarm_Type, seconds, minutes, hours, date(or day))
 RTC.setAlarm(ALM2_EVERY_MINUTE, 45,0,0,0); 
 RTC.setAlarm(ALM1_MATCH_SECONDS,30,0,0,0);
                                               |       |  | | |
                                               |       seconds
                                               |           | | |
                                               |           minutes
                                               |             | |
                                               |             hours
                                               |                | 
                                               |                date or day
                                               From RTC.alarmInterrupt(1,1) // name Minute/Seconds is really // throwing me off. But then again, this is only at first glance
                             
  RegisterDump();

for (int a = 0x00; a < 0x13; a++) Guessing this is binary language?

Anyway, I have a few days worth of homework now. Thanks for taking the time to post this! Really appreciated! Does the code for temp readings work the same on this library as it does on the 3231 library? If not, I'll have even more homework to do. Not that I mind.

================edit=====================
So my |||| illustration arrows didn't turn out like I expected. They were supposed to point to where the spots were, but it didn't work out that way for some reason

I'm still trying to figure this out.

#ifndef _config_h
#define _config_h

// comment this out if you need unixtime support
// this will add about 324bytes to your firmware
//#define CONFIG_UNIXTIME

#endif

I would go to the config.h file and remove the comment // lines from in front of the //#define CONFIG_UNIXTIME

What I am not understanding is how do I get to the config.h file? Is this in the sketch below? I swear i've looked many times. Or is this file somewhere in my computer?

This is the code example i'm going from.

#include <Wire.h>
#include "ds3231.h"
#include "rtc_ds3231.h"

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 5000;

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");
}

void loop()
{
    char in;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // there is a compile time option in the library to include unixtime support
#ifdef CONFIG_UNIXTIME
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d %ld", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec, t.unixtime);
#else
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
#endif

        Serial.println(buff);
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = inp2toi(cmd, 7);
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

What I am not understanding is how do I get to the config.h file? Is this in the sketch below? I swear i've looked many times. Or is this file somewhere in my computer?

The ds3231 library is installed on your computer. If you are using windows, it should be in a path like this
C:\Users\you\Documents\Arduino\libraries. This users library folder will be in the same folder as your saved sketches. It is not the libraries folder in the program files(x86) where the IDE resides.

Find the ds3231 library and open the folder. You should see all the components of the library including a file called config.h. Open that with wordpad or another text editor and modify the //#define CONFIG_UNIXTIME statement to remove the comments. Save the modified file. Restart the IDE.

Just to be clear about exactly what I should remove.

Before

#ifndef _config_h
#define _config_h

// comment this out if you need unixtime support
// this will add about 324bytes to your firmware
//#define CONFIG_UNIXTIME

#endif

After:

#ifndef _config_h
#define _config_h

// #define CONFIG_UNIXTIME

#endif

Is this right?

Is this right?

No. The written comments are confusing. It can only mean "remove the comment marks from the #define if you need unixtime sujpport."

#ifndef __config_h_
#define __config_h_

#define CONFIG_UNIXTIME

#endif

Thanks,

I don't suppose you would be interested in showing me how to read the RTC?
This is the code I combined from two examples in hope of it taking the time from the Ntp website, and syncing it to my RTC so I don't have to set it manually. I can't figure out if the first code that writes the time to the RTC is wrong, or if the second code that takes the time from the RTC is off.

/*
 * TimeRTCSet.pde
 * example code illustrating Time library with Real Time Clock.
 *
 * RTC clock is set in response to serial port time message 
 * A Processing example sketch to set the time is included in the download
 * On Linux, you can use "date +T%s > /dev/ttyACM0" (UTC time zone)
 */

#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov


const int timeZone = 1;     // Central European Time
//const int timeZone = -5;  // Eastern Standard Time (USA)
//const int timeZone = -4;  // Eastern Daylight Time (USA)
//const int timeZone = -8;  // Pacific Standard Time (USA)
//const int timeZone = -7;  // Pacific Daylight Time (USA)


EthernetUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets


void setup()  {
  Serial.begin(9600);
  while (!Serial) ; // Needed for Leonardo only
  delay(250);
  Serial.println("TimeNTP Example");
  if (Ethernet.begin(mac) == 0) {
    // no point in carrying on, so do nothing forevermore:
    while (1) {
      Serial.println("Failed to configure Ethernet using DHCP");
      delay(10000);
    }
  setSyncProvider(getNtpTime);   // the function to get the time from the RTC
  if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");      
}
  Serial.print("IP number assigned by DHCP is ");
  Serial.println(Ethernet.localIP());
  Udp.begin(localPort);
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
}
time_t prevDisplay = 0; // when the digital clock was displayed

void loop()
{ if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();  
    }
  }
  if (Serial.available()) {
    time_t t = getNtpTime();
    if (t != 0) {
      RTC.set(t);   // set the RTC and the system time to the received value
      setTime(t);          
    }
  }
  digitalClockDisplay();  
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

When I load this sketch, the serial monitor

TimeNTP Example

IP number assigned by DHCP is 192.168.1.107

waiting for sync

Transmit NTP Request

Receive NTP Response

0:05:28 15 1 2015

0:05:28 15 1 2015

0:05:29 15 1 2015

This is the code that I have from an example that is supposed to read RTC without writing to it.

/*
 * TimeRTC.pde
 * example code illustrating Time library with Real Time Clock.
 * 
 */

#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

void setup()  {
  Serial.begin(9600);
  while (!Serial) ; // wait until Arduino Serial Monitor opens
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");      
}

void loop()
{
  if (timeStatus() == timeSet) {
    digitalClockDisplay();
  } else {
    Serial.println("The time has not been set.  Please run the Time");
    Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
    Serial.println();
    delay(4000);
  }
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

However, When After I load this it says the time is

RTC has set the system time

1:05:23 1 1 2066

1:05:24 1 1 2066

1:05:25 1 1 2066

1:05:26 1 1 2066

There are several different things going on here and you need to understand each part.

First, the time library can use many different sources of "real time" with which to syncronize the internal arudino millis clock. It can syncronize with an RTC, it can syncronize with NTP, and can syncronize with GPS. There are examples of each in the Time library. When it has its sync source defined, the program goes back every so often (default is every 5 minutes) to check its internal clock against the outside world and make corrections if necessary.

From your first print out, it looks like you were successful in syncronizing the time library with NTP. This is very positive news. The standard library example TimeNTP has nothing to do with the RTC. I haven't fully studied your cut and pasted sketch which tried to set the RTC from with the TimeNTP example to see why RTC.set(t) did not work in that context. I'll take a deeper look at it tonight.

Second, its clear that your RTC is not set to the current time. Use the Time library sketch TimeRTCSet. Open the serial monitor, and enter the capital letter T and the 10 digit unix time which can be found at http://www.epochconverter.com/ There are links there for corrections to your local time if needed. Enter T and the number and press send. This should set the RTC. You can also use the example sketch in the ds1307 library called SetTime which will set the RTC to the sketch compile time from your computer.

Third, I understand that you are trying to set the RTC from NTP on a regular basis. Since the ds3231 is quite accurate, I doubt you need this, but if you do, I'm sure it can be done.

Please try to explain what you are trying to do with the RTC, NTP, the Time Library, and the alarms, as we have touched on all of them. It will also influence your use of libraries. You may no need all of them together, and simplification will help cut some of the confusion.

if (Serial.available()) {
    time_t t = getNtpTime();
    if (t != 0) {
      RTC.set(t);   // set the RTC and the system time to the received value
      setTime(t);          
    }

I think that this piece of code where you were trying to set the RTC was not called because there were no characters in the serial buffer. Furthermore, you want to do your time setting one time in setup and not in the loop. Remove that section of code.

setSyncProvider(getNtpTime);   // the function to get the time from the RTC
  if (timeStatus() != timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");

You are duplicating a call to setSyncProvider. Remove that section of code.

Here's how I think you can set the RTC with the return value from getNtpTime

void setup()  {
 Serial.begin(9600);
 while (!Serial) ; // Needed for Leonardo only
 delay(250);
 Serial.println("TimeNTP Example");
 if (Ethernet.begin(mac) == 0) {
   // no point in carrying on, so do nothing forevermore:
   while (1) {
     Serial.println("Failed to configure Ethernet using DHCP");
     delay(10000);
   }
 
}
 Serial.print("IP number assigned by DHCP is ");
 Serial.println(Ethernet.localIP());
 Udp.begin(localPort);
 Serial.println("waiting for sync");
 setSyncProvider(getNtpTime);
 RTC.set(getNtpTime());

time_t prevDisplay = 0; // when the digital clock was displayed
}

I don't like the double call to getNtpTime, but see if it works.

If for some reason RTC.set does not like being passed the function, try

time_t t = getNtpTime();
      RTC.set(t);

Your first Void setup() sniplet resulted in the serial monitoring being correct, but then when I loaded the sketch that was designed to read the time dirrectly from the RTC the serial monitor showed

GET time
1915.01.15 04:16:28 0
1915.01.15 04:16:33 0
1915.01.15 04:16:38 0
1915.01.15 04:16:43 0
1915.01.15 04:16:48 0
1915.01.15 04:16:53 0

which is strange because the last zero is the UNIX time. Shouldn't it be changing with the time?

I did as you suggested, but am unsure if this is where it should go. The results were the same
before

void loop()
{ if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
if (Serial.available()) {
time_t t = getNtpTime();
if (t != 0) {
RTC.set(t); // set the RTC and the system time to the received value
setTime(t);
}
}

after

void loop()
{ if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
if (Serial.available()) {
time_t t = getNtpTime();
RTC.set(t);

Now I did find this code which I was able to set the RTC by hand, and it keeps the time when I upload the other code, but wheres the fun in that?

#include <Wire.h>
#include "ds3231.h"
#include "rtc_ds3231.h"
#include <LiquidCrystal.h>

LiquidCrystal lcd(8,9,4,5,6,7); 

#define BUFF_MAX 128

uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);
    Serial.println("GET time");
    lcd.begin(16, 2);
    lcd.clear();
    
    //Serial.println("Setting time");
    //parse_cmd("T302911604102014",16);
}

void loop()
{
    char in;
    char tempF[6]; 
    float temperature;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t); //Get time
        parse_cmd("C",1);
        temperature = DS3231_get_treg(); //Get temperature
        dtostrf(temperature, 5, 1, tempF);

        lcd.clear();
        lcd.setCursor(1,0);
        
        lcd.print(t.mday);
        
        printMonth(t.mon);
        
        lcd.print(t.year);
        
        lcd.setCursor(0,1); //Go to second line of the LCD Screen
        lcd.print(t.hour);
        lcd.print(":");
        if(t.min<10)
        {
          lcd.print("0");
        }
        lcd.print(t.min);
        lcd.print(":");
        if(t.sec<10)
        {
          lcd.print("0");
        }
        lcd.print(t.sec);
        
        lcd.print(' ');
        lcd.print(tempF);
        lcd.print((char)223);
        lcd.print("C ");
        prev = now;
    }

    
    if (Serial.available() > 0) {
        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]
        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time
    if (cmd[0] == 84 && cmdsize == 16) {
        //T355720619112011
        t.sec = inp2toi(cmd, 1);
        t.min = inp2toi(cmd, 3);
        t.hour = inp2toi(cmd, 5);
        t.wday = inp2toi(cmd, 7);
        t.mday = inp2toi(cmd, 8);
        t.mon = inp2toi(cmd, 10);
        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);
        DS3231_set(t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3231_get_aging(), DEC);
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0, 0 };
        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        boolean flags[5] = { 0, 0, 0, 0 };
        DS3231_set_a2(time[0], time[1], time[2], flags);
        DS3231_get_a2(&buff[0], 59);
        Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3231_get_treg(), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3231_get_sreg();
        reg_val &= B11111100;
        DS3231_set_sreg(reg_val);
    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct
        reg_val = DS3231_get_addr(0x5);
        Serial.print("orig ");
        Serial.print(reg_val,DEC);
        Serial.print("month is ");
        Serial.println(bcdtodec(reg_val & 0x1F),DEC);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3231_set_aging(0);
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3231_get_sreg(), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

void printMonth(int month)
{
  switch(month)
  {
    case 1: lcd.print(" January ");break;
    case 2: lcd.print(" February ");break;
    case 3: lcd.print(" March ");break;
    case 4: lcd.print(" April ");break;
    case 5: lcd.print(" May ");break;
    case 6: lcd.print(" June ");break;
    case 7: lcd.print(" July ");break;
    case 8: lcd.print(" August ");break;
    case 9: lcd.print(" September ");break;
    case 10: lcd.print(" October ");break;
    case 11: lcd.print(" November ");break;
    case 12: lcd.print(" December ");break;
    default: lcd.print(" Error ");break;
  } 
}

In the code above, this is how you set the time by commenting this,and changing these numbers //parse_cmd("T302911604102014",16); It might be possible to take the time from the Ntp site, and merge it here by using a modified version of this code, designed to take chars, and convert them to long integers.

float decade = pow(10, (commandFile.available() - 1));
    while(commandFile.available())
    {
      float temp = (commandFile.read() - '0');
      refresh_rate = temp*decade+refresh_rate;
      decade = decade/10;
    }
    Serial.print("Refresh Rate = ");
    Serial.print(refresh_rate);

My biggest concern with using the RTC without an automatic check up every month or so is

I am a bit anal about those cheap clock-modules as they drift far too much for my liking... after a week, I'm unhappy with the results.

mrburnette's comment on post # 11 I don't know how much the time will "drift" if left uncheck for a year.

You need to get the RTC.set(t) expression outside of some if serial test. Why do you keep posting code which has it in there.

You have obviously worked out the getting of the NTP time stamp, and I can work with you to get the RTC set to that. You will not need any parsing. You will just feed the unix time stamp to RTC.set which is a function in the very small and simple ds1307 library.

then when I loaded the sketch that was designed to read the time dirrectly from the RTC

What sketch is that? I am not clear about the Rodan ds3231 library and if you are trying to get the unixtime out of that sketch. I do not think that the Rodan library is of any help in your project.

Here is a small sketch which sets and reads the RTC to unixtime Jan1 2014 00:00:00. You can use it to get a known wrong time in the RTC and then reset it with NTP. The RTC.get() function pulls unix time from the RTC. On the other hand, you can use the Time library with an NTP sync and not use the RTC at all.

#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>

void setup() {
  
  Serial.begin(9600);
 
  Serial.println("Setting Unix time on RTC");
  Serial.println("1388534400  Jan 1, 2014 00:00:00");
  Serial.println();
  
  time_t unixTimeStamp = 1388534400; //Jan 1, 2014 00:00:00
  RTC.set(unixTimeStamp);
  
  
  Serial.println("RTC Read Test");
  Serial.println("-------------------");
}

void loop() {
  tmElements_t tm;

  if (RTC.read(tm)) {
    Serial.print("Ok, Time = ");
    print2digits(tm.Hour);
    Serial.write(':');
    print2digits(tm.Minute);
    Serial.write(':');
    print2digits(tm.Second);
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(tm.Day);
    Serial.write('/');
    Serial.print(tm.Month);
    Serial.write('/');
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.println();
    Serial.println("Unix Time");
    Serial.println(makeTime(tm));
    Serial.println(RTC.get()); //from RTC
    
    
  
    
  } 
  
  delay(1000);
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}