Иногда подвисают RTC ds1307. Время перестаёт идти, а потом продолжает.

imsgs
Offline
Зарегистрирован: 03.10.2016

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");
  }
}

 

imsgs
Offline
Зарегистрирован: 03.10.2016

В большенстве случаяв время не продолжает идти.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

избавьтесь от delay(); и будет вам счастье :)

imsgs
Offline
Зарегистрирован: 03.10.2016

Избавился от 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);
}

 

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

imsgs пишет:

это случаем не посадит кварц, где-то на этом форуме об этом писали

Вы что-то неправильно поняли, кварц не может "садиться". Он непрерывно генерирует тактовые импульсы на своей постоянной частоте, независимо от программы и вообще от микроконтроллера. Таков его принцип работы.

imsgs
Offline
Зарегистрирован: 03.10.2016

Никак не помогло. Всвё еще зависают часы. Дописал скетч, чтобы спикер(взял с ПК) пищал когда происходит сбой. Сбой - "RTC.chipPresent()".  "chipPresent" как понял когда в часах не установлено время и они не запущены.

imsgs
Offline
Зарегистрирован: 03.10.2016

Единственный вариант без докупки модулей - каждую секунду записывать текущие время и тут же проверять не сбился ли модуль часов, если да то перезаписывать время из сохраннёного + 1/2 сек..

Глупый вопрос - такая постоянная перезапись не навредит ли ардуино?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

imsgs, что за изврат? Вы занимаетесь чем угодно, но не борьбой с причиной. А причина у такого поведения одна -хреновое питание Vbat.

imsgs
Offline
Зарегистрирован: 03.10.2016

Сдесь мне ответили что причина в delay "избавьтесь от delay(); и будет вам счастье :)".

Насчёт Vbat - мне нужно поменять батарейку или что(лучше конкретики)? Нашёл http://arduino.ru/forum/apparatnye-voprosy/ne-mogu-pravilno-schitat-napryazhenie-batareiki-iz-rtc , но боюсь кроме выше описанных модулей у меня больше ничего нет.

msng
Offline
Зарегистрирован: 07.06.2012

по вашей схеме перепутано питание модуля vcc и gnd

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

imsgs, про delay видимо была шутка юмора. Меняйте батарейку для начала, подогните контакты если они не плотно прижимают. Вот тот держатель что на картинке крайне паршивый, если у вас такой-же то лучше его поменять на нормальный.

imsgs
Offline
Зарегистрирован: 03.10.2016

Фото с troyka shield взял из интернета, у меня контакты на ней в обратном порядке стоят. Т.е. земля в землю и vcc в vcc.

msng
Offline
Зарегистрирован: 07.06.2012

ну это получается гадание на кофейной гуще...

модулей RTC - мильон... многие из них глючные..

есть стандартно включение модуля +5, gnd, i2c больше ничего не надо всё здорово работает

здесь Вам никто не сможет подсказать по фоткам взятыс с интернета что у Вас не работает.

стандартное подключение - стандартаня библиотека все должно работать, если не работает - смотрите железо....

как-то вот так...