Библиотека времени Arduino и библиотеки RTC
Я использую RTClib.h и TimeLib.h с Uno.
В течение нескольких дней я пытался разобраться в различных доступных библиотеках RTC и в том, как использовать их с библиотекой времени Arduino.
Вопрос 1.
Если я не хочу создавать новый объект now() каждый раз в цикле, как мне синхронизировать библиотеку времени с RTC каждые x секунд? Каждый раз, когда я пытаюсь использовать функцию RTClib сейчас.hour now.minute и т. Д. Это требует, чтобы я использовал DateTime now = RTC.now() для создания объекта now().
Есть ли эквивалентная функция в RTClib как setSyncProvider(RTC.get) в библиотеке DS1307RTC?
Существует ли эквивалент setSyncInterval(5000)
Вопрос 2.
Какой RTClib я должен вызвать? В примерах используется несколько вариантов:
<RTClib.h>
"RTClib" с использованием кавычек
<RTClib.h> с большой буквы L
а иногда еще и выкрикивает что-нибудь из этого:
RTC_DS1307 RTC
или RTC_DS1307 rtc
или RTC_DS3231 rtc
Вопрос 3
a. Являются ли tmElements_t tm частью библиотеки DS1307RTC?
б. Являются ли эти тм.Час tm.Минута от RTC?
c. Есть ли эквивалент в RTClib.h?
И, наконец, я опубликовал ниже некоторый код, просто чтобы показать свое использование:
#include "RTClib.h"
#include <Wire.h>
#include <TimeLib.h>
RTC_DS1307 RTC;
void setup() {
Serial.begin(9600);
Wire.begin(); //устанавливает I2C
RTC.begin(); // инициализирует I2C для RTC
if (! RTC.begin()) {
Serial.println("Couldn't find RTC");
}
// Установите время RTC на 5:10:30 3 ноября 2020 года
RTC.adjust(DateTime(2020,11,3,5,10,30));
// Установите библиотеку времени Arduino, отличную от времени RTC, чтобы увидеть,
setTime(9, 27, 05, 14, 07, 2015);
}
void loop() {
/*
// Как мне синхронизировать библиотеку времени с RTC через x секунд?
setSyncProvider(RTC.get); // Это находится в библиотеке DS1307RTC.h
setSyncInterval(5000); // Есть ли такие функции в RTClib?
*/
DateTime now = RTC.now(); // Извлекает время RTC в now(). Не синхронизируется с библиотекой времени
// Не хочу делать это каждый цикл.
//Вывести время RTC
Serial.println();
Serial.print("RTC now.hour ");
Serial.println(now.hour());
Serial.print("RTC now.minute ");
Serial.println(now.minute());
Serial.print("RTC now.second: ");
Serial.println(now.second());
Serial.println();
Serial.println();
//Печать Arduino TimeLib Время
Serial.print("Time Lib Hour: ");
Serial.print(hour());
Serial.println();
Serial.print("Time Lib Min: ");
Serial.print(minute());
Serial.println();
Serial.print("Time Lib Sec: ");
Serial.print(second());
Serial.println();
Serial.println();
delay(1000);
}
Обновлено 5 ноября 2020 года
Мне кажется, я почти понимаю. Пожалуйста, дайте мне знать, делает ли этот код то, что я думаю, что он делает, в частности:
В настройках:
Установите RTC на 5:10:30.
Установите библиотеку времени на 9:27:05 с помощью функции setTime().
Установить библиотеку времени на время RTC с указанием даты и времени сейчас (вместо записи 9:27:05)?
Установите переменные библиотеки времени в значение RTC с помощью tm.Час = сейчас.Час и т.д.
В цикле:
Каждые 5 секунд обновляйте hour(), minute() second() с указанием времени RTC.
Каждый цикл обновляет tm.час с часом () и т.д.
Я знаю, что это все еще неправильно, так как серийные отпечатки показывают тм.Час, тм.Минута, чередуя каждую петлю, как показано внизу.
#include "RTClib.h"
#include <Wire.h>
#include <TimeLib.h>
RTC_DS1307 RTC;
time_t time_provider()
{
return RTC.now().unixtime();
}
tmElements_t tm; //часть библиотеки времени
void setup() {
//setSyncProvider(time_provider);
Serial.begin(9600);
Wire.begin(); //настраивает I2C
RTC.begin(); //инициализирует I2C для RTC
if (! RTC.begin()) {
Serial.println("Couldn't find RTC");
}
// Установите время RTC на 5:10:30 3 ноября 2020 года
RTC.adjust(DateTime(2020,11,3,5,10,30));
//Установите библиотеку времени Arduino, отличную от времени RTC 9:27:05
setTime(9, 27, 05, 14, 07, 2015);
//Установка библиотеки времени на время RTC
DateTime now = RTC.now();
tm.Hour = now.hour();
tm.Minute = now.minute();
tm.Second = now.second();
}
void loop() {
setSyncProvider(RTC.now);
setSyncInterval(5000);
// Библиотека времени время обновляется до RTC каждые 5 секунд
tm.Hour = hour();
tm.Minute = minute();
tm.Second = second();
Serial.print("tm.Hour: ");
Serial.print(tm.Hour);
Serial.println();
Serial.print("tm.Minute: ");
Serial.print(tm.Minute);
Serial.println();
Serial.print("tm.Seconds: ");
Serial.print(tm.Second);
Serial.println();
Serial.println();
delay(1000);
}
Серийные отпечатки:
tm.Hour: 5
tm.Minute: 34
tm.Seconds: 56
tm.Hour: 18
tm.Minute: 0
tm.Seconds: 0
tm.Hour: 5
tm.Minute: 34
tm.Seconds: 56
tm.Hour: 18
tm.Minute: 0
tm.Seconds: 0
tm.Hour: 5
tm.Minute: 34
tm.Seconds: 56
tm.Hour: 18
tm.Minute: 0
tm.Seconds: 0
@RickH, 👍1
2 ответа
Есть ли эквивалентная функция в RTClib как setSyncProvider(RTC.get) в библиотеке DS1307RTC?
Существует ли эквивалент setSyncInterval(5000)
Это функции TimeLib. Нет никакого "эквивалента", поскольку вы используете TimeLib.
Первый просто ожидает указатель на функцию, которая возвращает time_t
. Что входит в эту функцию, зависит только от вас.
Какой RTClib я должен вызвать? В примерах используется несколько вариантов:
Заглавные буквы должны совпадать с именем заголовочного файла. Windows это не волнует, и OS X обычно это не волнует, но может быть настроено на это. Linux действительно заботится о нем и нуждается в том, чтобы он соответствовал. Если вы хотите, чтобы ваш код был переносимым, вы должны сохранить заглавные буквы такими же, как в файле.
а иногда еще и выкрикивает что-нибудь из этого:
Вам нужно создать объект, соответствующий вашему физическому RTC.
a. Являются ли tmElements_t tm частью библиотеки DS1307RTC?
Нет. Они являются частью TimeLib.
b. Являются ли эти тм.Час tm.Минута от RTC?
Это все, что присваивается им вызываемой функцией. Это всего лишь переменные. Они могут содержать все, что угодно.
c. Есть ли эквивалент в RTClib.h ?
Нет. Но тогда вам это и не нужно, если вы используете TimeLib.
Итак: вам нужно
- Создайте функцию, которая получает время из RTC через любую библиотеку, которую вы хотите использовать (например, RTClib), и вычисляет количество секунд с 00:00:00 01/01/1970, которое затем возвращается как
time_t
. - Передайте это в setSyncProvider() TimeLib
setSyncProvider()
- Установите частоту синхронизации с
помощью setSyncInterval()
.
Позвольте мне сначала рассказать немного об этих библиотеках.
Библиотека времени использует millis()
для хронометража. Поскольку это может быть
подвержено значительному отклонению, это обеспечивает возможность периодической синхронизации
с внешним поставщиком времени. Отсюда и функции setSyncProvider()
и setSyncInterval()
.
RTClib предназначен для взаимодействия с RTC. Он не обеспечивает хронометраж сам по
себе: вы получаете текущее время, запрашивая RTC через его
метод now()
.
Эти две библиотеки могут прекрасно дополнять друг друга, так как RTClib можно использовать в качестве поставщика времени для библиотеки времени:
// Укажите время RTC в библиотеке времени.
time_t time_provider() {
return RTC.now().unixtime();
}
void setup() {
// ...
setSyncProvider(time_provider);
}
Если я не хочу создавать новый объект now() [...]
На самом деле он называется объектом DateTime.
Есть ли эквивалент [для
tmElements_t
] в RTClib
Да, класс DateTime. Обратите внимание, что, в отличие
от
структуры tmElements_t, поля данных DateTime
не являются общедоступными,
и для их получения необходимо использовать средства доступа: year()
, month()
,
day()
...
Альтернативный метод хронометража
Поскольку вы используете Arduino Uno, существует третий метод
хронометража, который вы, возможно, захотите рассмотреть. Вместо того, чтобы запрашивать RTC на
каждой итерации цикла (RTClib) или интерполировать показания RTC с
millis()
(Библиотека времени), вы можете направить 1 Гц вывод RTC
на вывод прерывания и отсчет секунд в ISR. Код синхронизации avr-libc
предназначен для обеспечения хронометража таким
образом. Все это сводится к следующему:
// Инициализируйте системное время из RTC.
set_system_time(RTC.now().secondstime());
// Синхронизируйте время, используя выходной сигнал RTC частотой 1 Гц.
pinMode(pin1Hz, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(pin1Hz), system_tick, FALLING);
Для получения более подробной информации см. Пример прерывания скетча 1Hz.ino предоставляется с помощью RTClib.
Правка 1: Ответ на комментарий
к какому выводу [вывод прерывания Arduino] подключается к RTC?
Это зависит от RTC, который вы используете. Я предполагаю, что это DS1307, как следует из кода в вашем вопросе. Взгляните на техническое описание RTC. На странице 6 есть таблица под названием “Описание PIN”. Из этой таблицы:
pin-код: 7
название: SQW/OUT
функция: Драйвер прямоугольной волны/выходного сигнала. При включении бита SQWE, установленного на 1, вывод SQW/OUT выводит одну из четырех прямоугольных частот (1 Гц, 4 кГц, 8 кГц, 32 кГц). Вывод SQW/OUT имеет открытый сток и требует внешнего подтягивающего резистора. SQW / OUT работает с любым Применяется VCC или VBAT. Напряжение вытягивания может составлять до 5,5 В независимо от напряжения на VCC. Если этот контакт не используется, его можно оставить плавающим.
Если вы используете модуль RTC, вам нужно будет выяснить, где этот вывод находится на разъеме модуля.
В любом случае вам придется включить прямоугольный выходной сигнал частотой 1 Гц с
RTC.writeSqwPinMode(DS1307_SquareWave1HZ);
Обновление 2: Комментарий к обновлению вопроса:
// Установите время RTC на 5:10:30 3 ноября 2020 года RTC.adjust(DateTime(2020,11,3,5,10,30));
Правильно.
// Установите библиотеку времени Arduino, отличную от времени RTC 9:27:05 setTime(9, 27, 05, 14, 07, 2015);
Правильно. Дата - 2015-07-14.
// Установка библиотеки времени на время RTC DateTime now = RTC.now(); tm.Hour = now.hour(); tm.Minute = now.minute(); tm.Second = now.second();
Нет. Это лишь частичная инициализация переменной tm
. Это никак не
влияет на представление библиотеки Времени о текущем времени. Обратите внимание, что
поля даты tm
на данный момент не были инициализированы и
вполне могут быть недействительными (например, месяц 23, день 125).
setSyncProvider(RTC.now);
Это неверно и должно было сгенерировать предупреждение компилятора.
setSyncProvider()
ожидает функцию, которая возвращает текущее время в виде
Время Unix (простое целое число типа time_t
). Вы предоставляете
функцию, которая возвращает текущее время в разбитом виде (год,
месяц ...) с типом DateTime
. Библиотека времени этого не поймет
и может выдать мусор, например, 18:00:00.
Время, возвращаемое RTC.now()
, может быть преобразовано во время Unix с
помощью метода unixtime()
. Вот почему я дал вам time_provider()
функция.
Кроме того, вы не должны вызывать setSyncProvider()
и
setSyncInterval()
на каждой итерации цикла. Сделайте это раз и навсегда в
setup()
.
// Библиотека времени время обновляется до RTC каждые 5 секунд tm.Hour = hour(); tm.Minute = minute(); tm.Second = second();
Опять же, это всего лишь обновление переменной tm
. Это никак не влияет на то, что
библиотека времени считает текущим временем.
- Разница между «time_t» и «DateTime»
- Синхронизация библиотеки времени и RTClib
- Как получить текущее время и дату в Arduino без внешнего источника?
- Преобразование в Unix Timestamp и обратно
- Как запустить цикл на определенное время?
- Почему мои часы реального времени показывают неверное время с моего ПК?
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- Оси X и Y на последовательном плоттере Arduino?
-Я много читал об этих библиотеках и до сих пор в замешательстве. Спасибо за вашу помощь. Пара последующих действий: 1. Получает ли функция now.hour() время от RTC? 2. Получает ли hour() время из библиотеки времени? 3. Устанавливает ли setSyncProvider() значение hour() для RTC?, @RickH
сейчас
- это время из RTC в момент, когда вы назначаете объектсейчас
..hour()
- это просто час, содержащийся внутри этого объекта.hour ()
- это время из библиотеки TimeLib, да. setSyncProvider() ничего не отправляет в RTC, он регулярно получает время из RTC и обновляет TimeLib текущим временем., @Majenko@Edgar Bonet - Использование PIN прерывания выглядит очень красиво и чисто. Если вывод 2 используется на Arduino для прерывания, к какому выводу подключается вывод 2 на RTC? Я предполагаю, что это в дополнение к контактам SCL и SDA (?)., @RickH
"setSyncProvider() ничего не отправляет в RTC, он регулярно получает время от RTC и обновляет TimeLib с текущим временем". Да, значит, если hour() - это время из библиотеки TimeLib, то setSyncProvider() делает hour() равным часу RTC?, @RickH
Все немного сложнее, чем это. TimeLib использует
millis()
для отслеживания времени. Он регулярно обновляет свое внутреннее представление о том, сколько времени зависит отsetSyncInterval ()
. когда вы запрашиваетеhour ()
, если прошло больше времени с тех пор, как он в последний раз получал реальное время, указанное вами вsetSyncInterval ()
, он перейдет и получит время из RTC. В противном случае он просто скажет вам, что он * думает * о времени в соответствии со своими собственными внутренними расчетами., @MajenkoЯ обновил свой пост с помощью предоставленной помощи. Почти все это поняли., @RickH
Почему выводятся альтернативные значения для tm.hour и т.д.? Смотрите нижнюю часть обновленного вопроса. Спасибо, @RickH
Потому что вы постоянно меняете поставщика синхронизации и интервал. Вы устанавливаете их один раз и только один раз в программе настройки, и больше никогда., @Majenko
Спасибо, что сработало. Глядя на мой обновленный код, чтобы убедиться, что я не обманываю себя, я получаю результаты tm.Значения библиотеки времени Hour tm.Minute. tm.Second, которые обновляются из RTC каждые 5 секунд? И разве я не создаю объект в каждом цикле?, @RickH
Да, это выглядит правильно. Хотя вам вообще не нужна структура
tmElements_t
, поскольку все, с чем вы имеете дело, - это простые числа.tmElements_t
- это просто удобный способ объединить их все вместе, если вы хотите передать его другой функции. ПростоSerial.print(hour());
, @Majenkoспасибо за всю вашу помощь. Я опубликую окончательный код в качестве ответа для всех, кому еще нужно это изучить., @RickH