Часы реального времени DS1307
Я пытаюсь создать проект Arduino на основе Sparkfun DS1307 RTC (часы реального времени).
Есть несколько проблем, связанных с тем, что библиотеки Arduino не поддерживают проверку того, отключена ли плата Arduino, и проверьте это.
Затем используйте это как условное условие, когда программа должна вернуться к скомпилированному времени, если время RTC еще не установлено по какой-то другой причине.
Когда я выключаю часы, они каждый раз автоматически возвращаются к скомпилированному времени, независимо от того, что в данный момент находится на RTC. Очевидно, это не то, чего вы хотели бы.
Отредактировано. Это мой текущий код. Имейте в виду, что есть еще несколько изменений, которые я мог бы сделать, например, убрать объявление нулевого байта из цикла, чтобы он все еще был грубым.
#include <Wire.h>
#include <SparkFunDS1307RTC.h>
#define DS1307_ADDRESS 0x68
void setup() {
Wire.begin();
Serial.begin(9600);
rtc.begin();
if(false){
// Должен как-то проверить RTC, чтобы определить, следует ли откатиться к скомпилированному времени здесь.
Serial.println("The DS1307 clock has lost power and reset to compiler's time");
rtc.autoTime();
}
}
void loop() {
if(digitalRead(7)==LOW)
printDate();
delay(1000);
}
byte bcdToDec(byte val){
return ((val/16*10) + (val%16));
}
void printDate(){
rtc.update();
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.read());
int minute = bcdToDec(Wire.read());
int hour = bcdToDec(Wire.read() & 0b111111); // 24-часовое время
int weekDay = bcdToDec(Wire.read()); //0-6-> Воскресенье суббота
int monthDay = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());
// Печатаем дату, например 01.03.11 23:59:59
Serial.print(month);
Serial.print("/");
Serial.print(monthDay);
Serial.print("/");
Serial.print(year);
Serial.print(" ");
Serial.print(hour);
Serial.print(":");
Serial.print(minute);
Serial.print(":");
Serial.println(second);
}
@Vyndicu, 👍2
Обсуждение4 ответа
Есть несколько проблем, связанных с тем, что библиотеки arduino не поддерживают проверку того, отключена ли плата arduino, и проверьте это.
Как это сделать? Плата выключена.
Когда я выключил часы. Он будет автоматически возвращаться к скомпилированному времени каждый раз, независимо от того, что в данный момент находится в RTC. Очевидно, это не то, чего вы хотели бы.
Так что не скомпилируйте вовремя.
Я видел, что в одной из пользовательских библиотек есть флаг, который проверяет, не потеряли ли часы RTC питание (из-за разрядки или отключения батареи или чего-то еще). Но это было для другого бренда RTC DS1307, который у меня есть., @Vyndicu
Легко. Вот один из способов сделать это.
- Считайте часы с rtc.
- Подождите известный период времени, основанный на частоте MCU,
- Снова прочтите показания часов с rtc.
- Сравните два показания времени, и они должны были увеличиться. Если нет, вернитесь к времени компиляции.
Есть и другие способы сделать это, например, bor или вывод прямоугольной волны, прерывание на линии vbat, ......
Эти часы реального времени RTC, насколько мне известно, всегда идут вперед. Таким образом, проверка этой дельты времени не говорит мне, были ли часы сброшены на время по умолчанию или нет. Вот о чем вопрос., @Vyndicu
DS1307 выдает прямоугольный сигнал на выходе, который можно настроить на определенные частоты, указанные в техническом описании. Первоначально выходной сигнал прямоугольной формы отключен. Вы можете включить его, когда установите время. Когда вы снова включите питание, проверьте прямоугольную волну, и если она отсутствует, вы можете снова установить время. Это можно легко сделать, создав код тайм-аута и сбросив таймер тайм-аута в прерывании. Если присутствует прямоугольная волна, будет сгенерировано соответствующее прерывание, и период тайм-аута будет установлен на начальное значение. Если время ожидания истекает, вы устанавливаете часы. Это может даже отслеживать сбои часов в режиме реального времени. Также вы можете использовать то же самое прерывание для извлечения данных из RTC, так как прямоугольный сигнал может быть настроен на 1 Гц, и, следовательно, вы можете опрашивать RTC каждую 1 Гц и получать данные из RTC.
Вы можете периодически сохранять дату и время в SRAM с батарейным питанием в DS1307. Каждые несколько секунд, раз в минуту, что-то в этом роде. При запуске скетча, возможно, в setup(), прочитайте текущее время RTC, сравните с сохраненным временем, если текущее время позже, чем сохраненное время, вы можете выполнить математику и посмотреть, как долго Arduino не работает. Или используйте EEPROM Arduino для хранения последнего сохраненного времени, если вы обеспокоены тем, что RTC потеряет свою батарею и сбросит дату и время по умолчанию, которые будут раньше, чем время EEPROM.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Вам нужно только один раз установить время в RTC. Нет необходимости держать это в коде. Но если вы все еще хотите, DS1307 имеет бит остановки часов, который устанавливается, когда RTC теряет питание. Таким образом, вы можете установить время только тогда, когда установлен этот бит., @Gerben
Как проверить, установлен ли этот бит?, @Vyndicu
https://learn.adafruit.com/ds1307-часы-в-режиме-прорыва-набор-платы/понимание-кода#установка-времени, @Gerben
Эта ссылка не отвечает на мой вопрос. Как проверить, не потерял ли RTC питание? Все, что делает ссылка, это показывает коды, о которых я уже знаю. Я могу установить RTC на новое время. Проблема в том, что каждый раз, когда я включаю плату Arduino, она будет предполагать, что RTC неправильный, и перезаписывать его. В результате RTC все еще думает, что это январь, но на самом деле, например, июнь, в зависимости от времени компиляции., @Vyndicu
Когда RTC теряет питание, бит CH устанавливается в 1. Когда вы устанавливаете время, этот бит также устанавливается в 0. Поэтому, когда Arduino перезагружается, а этот бит по-прежнему равен 0, вы знаете, что вам не следует изменять время., @Gerben
Пожалуйста, покажите нам свой код!, @Gerben
Изменено, чтобы опубликовать мой код., @Vyndicu
Ссылка действительно ответила на ваш вопрос. Используйте
if (! rtc.initialized()) {
вместо текущегоif(false){
. Но все равно не вижу пользы. Вы устанавливаете время только один раз на RTC. Если по какой-то причине в будущем RTC потеряет питание, не имеет значения, если вы не установите время или используете скомпилированное время, так как и то, и другое будет неправильным., @GerbenЯ пытаюсь написать книгу, объясняющую базовый код, и мне нужна хорошая простая программа. Вместо того, чтобы возвращаться в код, чтобы изменить значение true/false в зависимости от ваших потребностей. Я проверю это сегодня вечером. Изменить: похоже, что initialized() работает только с библиотекой adafruit, а не с библиотекой sparkfun DS1307., @Vyndicu
Это действительно облегчило бы задачу другим. Библиотека sparkfun не может прочитать бит CH. Вместо этого вы можете проверить, меньше ли текущий год, чем 2017. Значение года по умолчанию — 2000, если микросхема теряет питание., @Gerben
Да, это сработает., @Vyndicu