Aruino RTC, использующий rtclib, не понимает функций

rtc

Мне не хватает чего-то фундаментального при использовании 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 

, 👍1


2 ответа


Лучший ответ:

0

Если под "время 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.

Это все еще не идеально, так как все еще страдает от состояния гонки с часами реального времени, но это лучше, чем то, что у вас было изначально.

,

@АнТ - Спасибо. Это прекрасно объясняет это., @RickH

@AnT, есть предлагаемое изменение, которое перемещает ArduinoHour = ArduinoHour +1; после now = rtc.now();. его следует принять?, @Juraj

@Юрай: Я не понимаю, почему. Вся идея обходного пути состоит в том, чтобы поместить второй вызов now = rtc.now(); **как можно ближе** к вызову rtc.adjust - чтобы минимизировать "потерянное" время между этими вызовами. действия. Перемещение ArduinoHour = ArduinoHour + 1; после now = rtc.now(); (по какой причине?) противоречит этой идее., @AnT

Извините, это была моя ошибка. Мои правки не содержат ничего полезного, еще раз извините., @Alexander


0

Это содержимое метода 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();
,