Skip to main content
Arduino

Return to Answer

Updated question.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Edit 1: Answering a comment


Edit 2: Commenting on the update to the question:

// Set the RTC Time to 5:10:30 Nov 3 2020
RTC.adjust(DateTime(2020,11,3,5,10,30));

Correct.

// Set Arduino Time Library different than RTC time 9:27:05
setTime(9, 27, 05, 14, 07, 2015);

Correct. Date is 2015年07月14日.

// Setting Time Library to RTC time
DateTime now = RTC.now();
tm.Hour = now.hour();
tm.Minute = now.minute();
tm.Second = now.second();

No. This is only partially initializing the tm variable. It has no effect on the idea the Time library has of the current time. Note that the date fields of tm have not been initialized at this point, and could well be invalid (like month 23, day 125).

setSyncProvider(RTC.now);

This is incorrect, and should have generated a compiler warning. setSyncProvider() expects a function that returns the current time as Unix time (a simple integer, of type time_t). You are providing a function that returns the current time in broken down form (year, month...), with type DateTime. The Time library will not understand that and may yield garbage like, say, 18:00:00.

The time returned by RTC.now() can be converted to Unix time with the unixtime() method. That's why I gave you the time_provider() function.

Also, you are not supposed to call setSyncProvider() and setSyncInterval() on every loop iteration. Do it once and for all in setup().

// Time Library time updates to RTC every 5 seconds
tm.Hour = hour();
tm.Minute = minute();
tm.Second = second();

Again, this is only updating the variable tm. It has no effect on what the Time library believes is the current time.

Edit: Answering a comment

Edit 1: Answering a comment


Edit 2: Commenting on the update to the question:

// Set the RTC Time to 5:10:30 Nov 3 2020
RTC.adjust(DateTime(2020,11,3,5,10,30));

Correct.

// Set Arduino Time Library different than RTC time 9:27:05
setTime(9, 27, 05, 14, 07, 2015);

Correct. Date is 2015年07月14日.

// Setting Time Library to RTC time
DateTime now = RTC.now();
tm.Hour = now.hour();
tm.Minute = now.minute();
tm.Second = now.second();

No. This is only partially initializing the tm variable. It has no effect on the idea the Time library has of the current time. Note that the date fields of tm have not been initialized at this point, and could well be invalid (like month 23, day 125).

setSyncProvider(RTC.now);

This is incorrect, and should have generated a compiler warning. setSyncProvider() expects a function that returns the current time as Unix time (a simple integer, of type time_t). You are providing a function that returns the current time in broken down form (year, month...), with type DateTime. The Time library will not understand that and may yield garbage like, say, 18:00:00.

The time returned by RTC.now() can be converted to Unix time with the unixtime() method. That's why I gave you the time_provider() function.

Also, you are not supposed to call setSyncProvider() and setSyncInterval() on every loop iteration. Do it once and for all in setup().

// Time Library time updates to RTC every 5 seconds
tm.Hour = hour();
tm.Minute = minute();
tm.Second = second();

Again, this is only updating the variable tm. It has no effect on what the Time library believes is the current time.

+ answer pinout question.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Edit: Answering a comment

which pin does [the Arduino interrupt pin] connect to on the RTC?

It depends on the RTC you are using. I will assume it's a DS1307, as implied by the code in your question. Take a look at the datasheet of the RTC. On page 6, there is a table titled "Pin description". From this table:

pin: 7
name: SQW/OUT
function: Square Wave/Output Driver. When enabled, the SQWE bit set to 1, the SQW/OUT pin outputs one of four square-wave frequencies (1Hz, 4kHz, 8kHz, 32kHz). The SQW/OUT pin is open drain and requires an external pullup resistor. SQW/OUT operates with either VCC or VBAT applied. The pullup voltage can be up to 5.5V regardless of the voltage on VCC. If not used, this pin can be left floating.

If you are using an RTC module, you will have to figure out where this pin is exposed on the module's connector.

In any case, you will have to enable the 1 Hz square wave output with

RTC.writeSqwPinMode(DS1307_SquareWave1HZ);

Edit: Answering a comment

which pin does [the Arduino interrupt pin] connect to on the RTC?

It depends on the RTC you are using. I will assume it's a DS1307, as implied by the code in your question. Take a look at the datasheet of the RTC. On page 6, there is a table titled "Pin description". From this table:

pin: 7
name: SQW/OUT
function: Square Wave/Output Driver. When enabled, the SQWE bit set to 1, the SQW/OUT pin outputs one of four square-wave frequencies (1Hz, 4kHz, 8kHz, 32kHz). The SQW/OUT pin is open drain and requires an external pullup resistor. SQW/OUT operates with either VCC or VBAT applied. The pullup voltage can be up to 5.5V regardless of the voltage on VCC. If not used, this pin can be left floating.

If you are using an RTC module, you will have to figure out where this pin is exposed on the module's connector.

In any case, you will have to enable the 1 Hz square wave output with

RTC.writeSqwPinMode(DS1307_SquareWave1HZ);
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Let me first give some background about these libraries.

The Time library uses millis() for timekeeping. Since this can be subject to significant drift, it provides a means to periodically sync to an external time provider. Hence the functions setSyncProvider() and setSyncInterval().

RTClib is meant to interface an RTC. It does not provide timekeeping on its own: you get the current time by querying an RTC through it's now() method.

These two libraries can nicely complement each other, as RTClib can be used as a time provider for the Time library:

// Provide the RTC time to the Time library.
time_t time_provider() {
 return RTC.now().unixtime();
}
void setup() {
 // ...
 setSyncProvider(time_provider);
}

If I do not want to create a new now() object [...]

It is actually called a DateTime object.

Is there an equivalent [to tmElements_t] in the RTClib

Yes, the DateTime class. Note that, unlike the tmElements_t structure, the data fields of DateTime are not public, and you have to use accessors to get them: year(), month(), day()...

Alternative timekeeping method

Since you are using an Arduino Uno, there is a third method of timekeeping you may want to consider. Instead of querying the RTC on every loop iteration (RTClib) or interpolating the RTC readings with millis() (Time library), you may route a 1 Hz output of the RTC to an interrupt pin, and count the seconds in the ISR. The avr-libc timing code is designed to provide timekeeping in this fashion. It all boils down to:

// Initialize the system time from the RTC.
set_system_time(RTC.now().secondstime());
// Keep the time in sync using the 1 Hz output of the RTC.
pinMode(pin1Hz, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pin1Hz), system_tick, FALLING);

For more details, see the example sketch interrupts1Hz.ino provided with RTClib.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /