Иногда подвисают RTC ds1307. Время перестаёт идти, а потом продолжает.
- Войдите на сайт для отправки комментариев
Пнд, 03/10/2016 - 11:31
1. приветствие
Привет, я новичёк, как в физике так и в программирование.
2. проблема
Стало отстовать время, иногда вообще перестаёт идти. Использую "Arduino Uno R3" и модуль RTC ds1307, в качестве будильника. Батарейка нормальная - заряд держит. Без батарейки тоже всё нормально, часы идут. В стандартном примере работы "ds1307RTC" ввод и ввывод (последняя версия библиотек => примеров), проблема тоже наблюдалась.
Один раз задел батарейку и проблема проявилась. Все последующии попытки воздействия на батарейку без результатны.

Подключение:

IDE - v.1.6.12. Скетч:
#include "DS1307.h"
#include <Wire.h>
#include <EEPROM.h>
#define DS1307_ADDRESS 0x68
byte zero = 0x00;
int led = 13; // Lampo4ka
int rel = 10; // rele
//Массив, содержащий время компиляции
char compileTime[] = __TIME__; //Для работы с микросхемой часов мы используем библиотеку
DS1307 clock;
void setup() {
pinMode(led, OUTPUT);//Лампочка
pinMode(rel, OUTPUT);//Реле
Serial.begin(9600);
//Запускаем часы реального времени
clock.begin();
//Получаем число из строки, зная номер первого символа
byte hour = getInt(compileTime, 0);
byte minute = getInt(compileTime, 3);
byte second = getInt(compileTime, 6);
//Функция для сохранения точности времени, при отключении электричества(нашёл в инете)
//Импровизированный хэш времени
//Содержит в себе количество секунд с начала дня
unsigned int hash = hour * 60 * 60 + minute * 60 + second;
//Проверяем несовпадение нового хэша с хэшем в EEPROM
if (EEPROMReadInt(0) != hash) {
//Сохраняем новый хэш
EEPROMWriteInt(0, hash);
//Готовим для записи в RTC часы, минуты, секунды
clock.fillByHMS(hour, minute, second);
//Записываем эти данные во внутреннюю память часов.
//С этого момента они начинают считать нужное для нас время
clock.setTime();
clock.begin();//тест
}
}
//Функция для сохранения точности времени, при отключении электричества(нашёл в инете)
void EEPROMWriteInt(int address, int value) {
EEPROM.write(address, lowByte(value));
EEPROM.write(address + 1, highByte(value));
}
//Функция для сохранения точности времени, при отключении электричества(нашёл в инете)
unsigned int EEPROMReadInt(int address) {
byte lowByte = EEPROM.read(address);
byte highByte = EEPROM.read(address + 1);
return (highByte << 8) | lowByte;
}
//Функция для сохранения точности времени, при отключении электричества(нашёл в инете)
char getInt(const char* string, int startIndex) {
return int(string[startIndex] - '0') * 10 + int(string[startIndex + 1]) - '0';
}
//Функция для сохранения точности времени, при отключении электричества(нашёл в инете)
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val) {
return ( (val / 16 * 10) + (val % 16) );
}
void printDate() {
Serial.print(clock.hour);
Serial.print(":");
Serial.print(clock.minute);
Serial.print(":");
Serial.print(clock.second);
Serial.print(" ");
Serial.print(clock.dayOfMonth);
Serial.print("/");
Serial.print(clock.month);
Serial.print("/");
Serial.print(clock.year);
Serial.print(" ");
Serial.println(clock.dayOfWeek);
}
void loop() {
delay(1000);
clock.getTime();
printDate();
if (
((clock.hour == 9 && clock.minute == 30) ||
(clock.hour == 11 && clock.minute == 00) ||
(clock.hour == 11 && clock.minute == 10) ||
(clock.hour == 12 && clock.minute == 40) ||
(clock.hour == 13 && clock.minute == 20) ||
(clock.hour == 14 && clock.minute == 50) ||
(clock.hour == 15 && clock.minute == 00) ||
(clock.hour == 16 && clock.minute == 30) ||
(clock.hour == 16 && clock.minute == 40) ||
(clock.hour == 18 && clock.minute == 10) ||
(clock.hour == 18 && clock.minute == 30) ||
(clock.hour == 20 && clock.minute == 00)) &&
clock.second == 0
) {
Serial.println("zvon start");
digitalWrite(led, HIGH);
digitalWrite(rel, HIGH);
delay(10000);
digitalWrite(led, LOW);
digitalWrite(rel, LOW);
Serial.println("zvon stop");
}
}
В большенстве случаяв время не продолжает идти.
избавьтесь от delay(); и будет вам счастье :)
Избавился от delay(1000);,
void loop() { delay(1000);это случаем не посадит кварц, где-то на этом форуме об этом писали. И что это даёт если даже в стандартном примере зависает иногда.
Стандартный пример на ввод
#include <Wire.h> #include <TimeLib.h> #include <DS1307RTC.h> const char *monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; tmElements_t tm; void setup() { bool parse=false; bool config=false; // get the date and time the compiler was run if (getDate(__DATE__) && getTime(__TIME__)) { parse = true; // and configure the RTC with this info if (RTC.write(tm)) { config = true; } } Serial.begin(9600); while (!Serial) ; // wait for Arduino Serial Monitor delay(200); if (parse && config) { Serial.print("DS1307 configured Time="); Serial.print(__TIME__); Serial.print(", Date="); Serial.println(__DATE__); } else if (parse) { Serial.println("DS1307 Communication Error :-{"); Serial.println("Please check your circuitry"); } else { Serial.print("Could not parse info from the compiler, Time=\""); Serial.print(__TIME__); Serial.print("\", Date=\""); Serial.print(__DATE__); Serial.println("\""); } } void loop() { } bool getTime(const char *str) { int Hour, Min, Sec; if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false; tm.Hour = Hour; tm.Minute = Min; tm.Second = Sec; return true; } bool getDate(const char *str) { char Month[12]; int Day, Year; uint8_t monthIndex; if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false; for (monthIndex = 0; monthIndex < 12; monthIndex++) { if (strcmp(Month, monthName[monthIndex]) == 0) break; } if (monthIndex >= 12) return false; tm.Day = Day; tm.Month = monthIndex + 1; tm.Year = CalendarYrToTm(Year); return true; }и вывод
#include <Wire.h> #include <TimeLib.h> #include <DS1307RTC.h> void setup() { Serial.begin(9600); while (!Serial) ; // wait for serial delay(200); Serial.println("DS1307RTC Read Test"); Serial.println("-------------------"); } void loop() { tmElements_t tm; if (RTC.read(tm)) { Serial.print("Ok, Time = "); print2digits(tm.Hour); Serial.write(':'); print2digits(tm.Minute); Serial.write(':'); print2digits(tm.Second); Serial.print(", Date (D/M/Y) = "); Serial.print(tm.Day); Serial.write('/'); Serial.print(tm.Month); Serial.write('/'); Serial.print(tmYearToCalendar(tm.Year)); Serial.println(); } else { if (RTC.chipPresent()) { Serial.println("The DS1307 is stopped. Please run the SetTime"); Serial.println("example to initialize the time and begin running."); Serial.println(); } else { Serial.println("DS1307 read error! Please check the circuitry."); Serial.println(); } delay(9000); } delay(1000); } void print2digits(int number) { if (number >= 0 && number < 10) { Serial.write('0'); } Serial.print(number); }это случаем не посадит кварц, где-то на этом форуме об этом писали
Вы что-то неправильно поняли, кварц не может "садиться". Он непрерывно генерирует тактовые импульсы на своей постоянной частоте, независимо от программы и вообще от микроконтроллера. Таков его принцип работы.
Никак не помогло. Всвё еще зависают часы. Дописал скетч, чтобы спикер(взял с ПК) пищал когда происходит сбой. Сбой - "RTC.chipPresent()". "chipPresent" как понял когда в часах не установлено время и они не запущены.
Единственный вариант без докупки модулей - каждую секунду записывать текущие время и тут же проверять не сбился ли модуль часов, если да то перезаписывать время из сохраннёного + 1/2 сек..
Глупый вопрос - такая постоянная перезапись не навредит ли ардуино?
imsgs, что за изврат? Вы занимаетесь чем угодно, но не борьбой с причиной. А причина у такого поведения одна -хреновое питание Vbat.
Сдесь мне ответили что причина в delay "избавьтесь от delay(); и будет вам счастье :)".
Насчёт Vbat - мне нужно поменять батарейку или что(лучше конкретики)? Нашёл http://arduino.ru/forum/apparatnye-voprosy/ne-mogu-pravilno-schitat-napryazhenie-batareiki-iz-rtc , но боюсь кроме выше описанных модулей у меня больше ничего нет.
по вашей схеме перепутано питание модуля vcc и gnd
imsgs, про delay видимо была шутка юмора. Меняйте батарейку для начала, подогните контакты если они не плотно прижимают. Вот тот держатель что на картинке крайне паршивый, если у вас такой-же то лучше его поменять на нормальный.
Фото с troyka shield взял из интернета, у меня контакты на ней в обратном порядке стоят. Т.е. земля в землю и vcc в vcc.
ну это получается гадание на кофейной гуще...
модулей RTC - мильон... многие из них глючные..
есть стандартно включение модуля +5, gnd, i2c больше ничего не надо всё здорово работает
здесь Вам никто не сможет подсказать по фоткам взятыс с интернета что у Вас не работает.
стандартное подключение - стандартаня библиотека все должно работать, если не работает - смотрите железо....
как-то вот так...