Aruino RTC, использующий rtclib, не понимает функций
Мне не хватает чего-то фундаментального при использовании RTClib.
Когда я использую функцию rtc.adjust для изменения времени в RTC, я не могу получить обновленное время из RTC, просто увеличиваю фиксированное время. Я искал примеры того, что мне нужно, и все время цитируют одни и те же образцы кода.
Я хочу, чтобы мой код устанавливал RTC при компиляции в системное время, что он и делает, затем в цикле я хочу увеличить час. На самом деле я буду использовать для этого кнопку, но пока я просто пытаюсь понять, как работают DateTime now = rtc.now и rtc.adjust. Как записать в RTC, как прочитать обратно. Я что-то упустил в отношении этих переменных.
Две версии моего кода. Один с выводом, показывающим, что часы работают, а другой, где вывод является статическим, просто увеличивает час.
Это работает:
#include <RTClib.h>
#include <Wire.h>
int ArduinoHour;
int ArduinoMin;
int ArduinoSec;
RTC_DS1307 rtc;
void setup()
{
Serial.begin(250000);
Wire.begin(); //настраиваем I2C
rtc.begin(); //инициализирует I2C для RTC
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
if (rtc.isrunning()) {
Serial.println("RTC IS running!");
rtc.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop()
{
DateTime now = rtc.now(); // пингует RTC и загружает информацию о времени в переменную now.
ArduinoHour = now.hour();
ArduinoMin = now.minute();
ArduinoSec = now.second();
Serial.print("AT TOP");
Serial.println();
Serial.print("RTC Time");
Serial.println();
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.println();
delay(1000);
Serial.print("Arduino Time");
Serial.println();
Serial.print(ArduinoHour, DEC);
Serial.print(':');
Serial.print(ArduinoMin, DEC);
Serial.print(':');
Serial.print(ArduinoSec, DEC);
Serial.println();
Serial.println();
delay(1000);
//RTC увеличивается, когда они закомментированы. Не работает при активном
//ArduinoHour = ArduinoHour +1;
//rtc.adjust(DateTime(now.year(),now.month(),now.day(),ArduinoHour,ArduinoMin,ArduinoSec));
}
Вот результат. Выглядит нормально:
RTC IS running!
AT TOP
RTC Time
11:38:3
Arduino Time
11:38:3
AT TOP
RTC Time
11:38:5
Arduino Time
11:38:5
AT TOP
RTC Time
11:38:7
Arduino Time
11:38:7
AT TOP
RTC Time
11:38:9
Arduino Time
11:38:9
Это не работает: Теперь я пытаюсь просто увеличить переменную ArduinoHour, а затем записать ее в RTC, используя rtc.adjust. Единственное изменение состоит в том, что две строки внизу раскомментированы.
#include <RTClib.h> //https://learn.adafruit.com/ds1307-часы реального времени-breakout-board-kit/понимание-кода
#include <Wire.h>
int ArduinoHour;
int ArduinoMin;
int ArduinoSec;
RTC_DS1307 rtc;
void setup()
{
Serial.begin(250000);
Wire.begin(); //настраиваем I2C
rtc.begin(); //инициализирует I2C для RTC
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
}
if (rtc.isrunning()) {
Serial.println("RTC IS running!");
rtc.adjust(DateTime(__DATE__, __TIME__));
}
}
void loop()
{
DateTime now = rtc.now(); // пингует RTC и загружает информацию о времени в переменную now.
ArduinoHour = now.hour();
ArduinoMin = now.minute();
ArduinoSec = now.second();
Serial.print("AT TOP");
Serial.println();
Serial.print("RTC Time");
Serial.println();
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.println();
delay(1000);
Serial.print("Arduino Time");
Serial.println();
Serial.print(ArduinoHour, DEC);
Serial.print(':');
Serial.print(ArduinoMin, DEC);
Serial.print(':');
Serial.print(ArduinoSec, DEC);
Serial.println();
Serial.println();
delay(1000);
//RTC увеличивается, когда они закомментированы
ArduinoHour = ArduinoHour +1;
rtc.adjust(DateTime(now.year(),now.month(),now.day(),ArduinoHour,ArduinoMin,ArduinoSec));
}
Вот результат: время RTC не меняется. Я знаю, что делаю что-то принципиально неправильное, когда обновляю запись/чтение переменных из RTC. Не могу понять.
RTC IS running!
AT TOP
RTC Time
11:41:54
Arduino Time
11:41:54
AT TOP
RTC Time
12:41:54
Arduino Time
12:41:54
AT TOP
RTC Time
13:41:54
Arduino Time
13:41:54
AT TOP
RTC Time
14:41:54
Arduino Time
14:41:54
@RickH, 👍1
2 ответа
Лучший ответ:
Если под "время RTC не меняется" вы имеете в виду минуты и секунды, застывшие на одном и том же значении, то это полностью ваша заслуга.
Ваш скетч проходит 99% времени между первоначальным запросом rtc.now()
DateTime now = rtc.now(); // пингует RTC и загружает информацию о времени в переменную now.
и последний вызов rtc.adjust()
rtc.adjust(DateTime(now.year(),now.month(),now.day(),ArduinoHour,ArduinoMin,ArduinoSec));
Этот период — это период, когда ваш RTC должен "тикать", продвигаясь вперед.
Но на самом деле вы сохраняете исходные значения минут и секунд в ArduinoMin
и ArduinoSec
в начале этого периода. А позже, в конце этого периода, вы возвращаете эти значения обратно в часы. Делая это, вы принудительно стираете любой прогресс, достигнутый часами между этими двумя строками. Неудивительно, что ваши минуты и секунды не меняются.
На самом деле у этой проблемы нет идеального решения. Класс RTC_DS1307
(и, как я подозреваю, лежащее в его основе оборудование RTC) не предоставляет средств для изменения только значения часов без нарушения минут и секунд. Когда вы вызываете adjust()
, вы должны установить все, а это значит, что вы всегда будете как-то «срывать» все часы.
В своем скетче вы можете свести к минимуму неблагоприятные последствия, повторно запросив значения минут и секунд непосредственно перед выполнением adjust()
:
//RTC увеличивается, когда они закомментированы
ArduinoHour = ArduinoHour +1;
now = rtc.now();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), ArduinoHour, now.minute(), now.second()));
Обратите внимание, что я использую ваши обновленные значения ArduinoHour
, но все остальное берется из только что обновленного объекта now
.
Это все еще не идеально, так как все еще страдает от состояния гонки с часами реального времени, но это лучше, чем то, что у вас было изначально.
Это содержимое метода ajust
:
void RTC_DS1307::adjust(const DateTime& dt) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE((byte)0); // начинаем с позиции 0
Wire._I2C_WRITE(bin2bcd(dt.second()));
Wire._I2C_WRITE(bin2bcd(dt.minute()));
Wire._I2C_WRITE(bin2bcd(dt.hour()));
Wire._I2C_WRITE(bin2bcd(0));
Wire._I2C_WRITE(bin2bcd(dt.day()));
Wire._I2C_WRITE(bin2bcd(dt.month()));
Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
Wire.endTransmission();
}
Вы можете записать новое значение Hour
непосредственно в часы, не стирая другие данные часов:
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE((byte)2); // Часовая позиция
Wire._I2C_WRITE(bin2bcd(ArduinoHour));
Wire.endTransmission();
- Преобразование в Unix Timestamp и обратно
- Разница между «time_t» и «DateTime»
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- DS1307RTC Выводит загадочную дату 165/165/2165. Какие возможны исправления?
- RtcDateTime' не называет тип
- Библиотека времени Arduino и библиотеки RTC
- Не удалось выделить SSD1306 при добавлении константы
- Как получить текущую дату
@АнТ - Спасибо. Это прекрасно объясняет это., @RickH
@AnT, есть предлагаемое изменение, которое перемещает
ArduinoHour = ArduinoHour +1;
послеnow = rtc.now();
. его следует принять?, @Juraj@Юрай: Я не понимаю, почему. Вся идея обходного пути состоит в том, чтобы поместить второй вызов
now = rtc.now();
**как можно ближе** к вызовуrtc.adjust
- чтобы минимизировать "потерянное" время между этими вызовами. действия. ПеремещениеArduinoHour = ArduinoHour + 1;
послеnow = rtc.now();
(по какой причине?) противоречит этой идее., @AnTИзвините, это была моя ошибка. Мои правки не содержат ничего полезного, еще раз извините., @Alexander