Коррекция часиков на DS1307
- Войдите на сайт для отправки комментариев
Есть у меня одна хорошая плата, но с хреновенько работающими RTC на DS1307 (часы "убегают" за сутки на час(!!!)).
Замена кварцевого резонатора не помогла.
Батарейка свежая, питание на саму микросхему приходит стабильное 5В.
Возможно, проблема в том, что конструктивно кварц подключен не так, как написано в даташите на DS1307 (максимально короткие проводники, никаких кондеров в цепи - на моей плате (это готовая плата не моего производства) - около 7мм от кварца до микросхемы и от каждой ножки кварца на землю висит конденсатор (сдувать их пока не пробовал).
Ну не суть.. есть часы, они работают (плохо, но работают). На плате есть LAN - прикрутил синхронизацию времени по NTP (пример можно посмотерть тут: http://arduino.cc/en/Tutorial/UdpNtpClient). У меня код малость другой (видимо для своего скетча где-то в другом месте выдернул его, но это не важно).
Время по сети выдергивается, правильно преобразуется (вносится поправка моего часового пояса) и это время используется для корректировки времени RTC (привожу целиком функцию, которя дергается в loop():
void ntpRTCupdate() {
if(millis() > nextNTPtime) {
Udp.begin(localPort);
sendNTPpacket(timeServer); // send an NTP packet to a time server
// wait to see if a reply is available
delay(200);
if ( Udp.parsePacket() ) {
// We've received a packet, read the data from it
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
// calculate Unix time:
unsigned long epoch = secsSince1900 - seventyYears;
// print Unix time:
// введем корректировку для часового пояса
epoch = epoch + (TimeOffset * 3600L);
// скорректируем RTC
RTC.adjust(DateTime(epoch));
time2str(RTC.now(), lastNTP);
nextNTPtime = millis()+NTPtimeSync;
}
Udp.stop();
}
}
Время, когда эта корректировка произведена фиксируется (почему-то показалось, что это может пригодиться).
Но вот уже второй раз замечаю, что не смотря на то, что синхронизация прошла "2 минуты назад" - часы бодро "убежали" на несколько минут (т.е. синхронизация не сработала).
Из-за чего такое может быть? Может, есть какая-то "правильная" процедура "подведения" часов (типа, "остановить" - "скорректировать" - "запустить")?
P.S. Сейчас смотрю, что лучше наверное фиксировать именно полученное время, а не брать после время с RTC сразу после корректировки.
Здравствуйте.
У меня самого DS1307, но такого за ним не замечал.
>> Из-за чего такое может быть? Может, есть какая-то "правильная" процедура "подведения" часов (типа, "остановить" - "скорректировать" - "запустить")?
Увы, не подскажу. Попробуйте, явно задавать время, а не корректировать.
Пользовался методами установки времени из примера.
Сам пример.
#include <Wire.h> #include "DS1307.h" DS1307 clock;//define a object of DS1307 class void setup() { Serial.begin(9600); clock.begin(); clock.fillByYMD(2013,1,19);//Jan 19,2013 clock.fillByHMS(15,28,30);//15:28 30" clock.fillDayOfWeek(SAT);//Saturday clock.setTime();//write time to the RTC chip } void loop() { printTime(); } /*Function: Display time on the serial monitor*/ void printTime() { clock.getTime(); Serial.print(clock.hour, DEC); Serial.print(":"); Serial.print(clock.minute, DEC); Serial.print(":"); Serial.print(clock.second, DEC); Serial.print(" "); Serial.print(clock.month, DEC); Serial.print("/"); Serial.print(clock.dayOfMonth, DEC); Serial.print("/"); Serial.print(clock.year+2000, DEC); Serial.print(" "); Serial.print(clock.dayOfMonth); Serial.print("*"); switch (clock.dayOfWeek)// Friendly printout the weekday { case MON: Serial.print("MON"); break; case TUE: Serial.print("TUE"); break; case WED: Serial.print("WED"); break; case THU: Serial.print("THU"); break; case FRI: Serial.print("FRI"); break; case SAT: Serial.print("SAT"); break; case SUN: Serial.print("SUN"); break; } Serial.println(" "); }Сам код установки времени.
У меня работает как часы.
Они начинают идти именно с этого времени и не убегают вперед.
Я для пользуюсь этим скетчем.
#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #include <Wire.h> #include <DS1307.h> void setup() { Serial.begin(9600); use(); read_RTC(); } // use explanation message void use() { Serial.println("\nUSE : u U r R h[00-23]m[00-59]s[00-59]j0[1-7]D[01-31]M[01-12]A[00-49]"); Serial.println("\nEXEMPLE : h09m35d03 set time to 09h35 and day of week 3 (thuesday)."); Serial.println("\nCommands : h** : hour, m** : minutes, s** : seconds, d0* : day of week"); Serial.println(" M** : month, Y** : year, D** : day of month."); Serial.println(" r stops clock, R starts it. "); Serial.println(" u or U shows this message, all other caracter shows time."); } // DS1307 time read function void read_RTC() { Serial.print("\nActual time : "); Serial.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true Serial.print(":"); Serial.print(RTC.get(DS1307_MIN,false));//read minutes without update (false) Serial.print(":"); Serial.print(RTC.get(DS1307_SEC,false));//read seconds Serial.print(" "); // some space for a more happy life Serial.print(RTC.get(DS1307_DOW,false)); Serial.print(" "); Serial.print(RTC.get(DS1307_DATE,false));//read date Serial.print("/"); Serial.print(RTC.get(DS1307_MTH,false));//read month Serial.print("/"); Serial.println(RTC.get(DS1307_YR,false)); //read year } // set clock values void write_RTC() { char value=0; char command=0; command = Serial.read(); delay(50); //delay to allow good serial port reading value=byte((Serial.read()-48)*10); //-48 becaus ASCII value for 0 is 48, 1 is 49, etc and *10 because we read tens first delay(50); value+=byte((Serial.read()-48)); //and then we read units switch (command) { case 'h' : RTC.set(DS1307_HR,value); Serial.print("hours set to "); Serial.println(value,DEC); break; case 'm' : RTC.set(DS1307_MIN,value); Serial.print("minutes set to "); Serial.println(value,DEC); break; case 's' : RTC.set(DS1307_SEC,value); Serial.print("seconds set to "); Serial.println(value,DEC); break; case 'D' : RTC.set(DS1307_DATE,value); Serial.print("day of month set to "); Serial.println(value,DEC); break; case 'd' : RTC.set(DS1307_DOW,value); Serial.print("day of week set to "); Serial.println(value,DEC); break; case 'M' : RTC.set(DS1307_MTH,value); Serial.print("month set to "); Serial.println(value,DEC); break; case 'Y' : RTC.set(DS1307_YR,value); Serial.print("year set to "); Serial.println(value,DEC); break; case 'u' : case 'U' : use(); break; case 'r' : RTC.stop(); Serial.println("Clock stopped"); break; case 'R' : RTC.start(); Serial.println("Clock running"); break; default : break; } read_RTC(); } void loop() { if (Serial.available()) { write_RTC(); } }может вам проще будет прогаммно корректировать ход часов? Вот посмотрите мою тему - http://www.kharkovforum.com/showthread.php?p=35680348#post35680348 может пригодится
У меня была аналогичная проблема - часы убегали вперед за сутки на много. Купил новый кварц в радиомагазине, поставил вместо старого - теперь идут точно. Я думаю проблема с кварцем.
кварц уже один раз менял - попробую еще разок махнуть (пока выкручивюсь синхронизацией часов по сети)
Добрый день, топик старый, но проблема актуальна. Модуль часов спешит на 6 секунде каждый день. Я нашел статью по корректировке, но у меня никак не получается запустить скетч.... подскажите, где косяк?
#include <LiquidCrystal.h> #include <Time.h> #include <Wire.h> #include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t LiquidCrystal lcd(8, 9, 4, 5, 6, 7); float temp; int tempAnalogPin = 1; tmDriftInfo di; void setup () { temp = (float(analogRead(tempAnalogPin))/1024.0)*500.0; // initialize temp using first reading lcd.begin(16, 2); // set the lcd dimension lcd.clear(); // LCD screen clear Serial.begin(9600); setSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()!= timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time"); di = RTC.read_DriftInfo(); di.DriftDays = 1000; // valid value 0 to 65,535 di.DriftSeconds = 2800; // fine tune this until your RTC sync with your reference time, valid value -32,768 to 32,767 RTC.write_DriftInfo(di); // once you're happy with the drift setting you only have to read the DriftInfo and pass it to now2() or now3() function to get your drift corrected time } void loop() { if(Serial.available()) {processSerialCommand();} // SerialDisplayDateTime(now3(di)) // use this if you don't have an LCD Display LcdDisplayDateTime(now3(di)); LcdDisplayTemperature(); } void LcdDisplayTemperature(){ // read LM35 temperature sensor using Arduino anolog pin // takes the average of 300 readings temp = (temp*299/300)+((float(analogRead(tempAnalogPin))/1024.0)*500.0*1/300); lcd.setCursor(11, 1); lcd.print(temp); lcd.setCursor(15, 1); //lcd.print("C"); } void LcdDisplayDateTime(time_t timeToDisplay){ lcd.setCursor(0, 0); lcd.print(year(timeToDisplay)); lcd.print("/"); lcd.print(month(timeToDisplay)); lcd.print("/"); lcd.print(day(timeToDisplay)); lcd.setCursor(11, 0); lcd.print(dayShortStr(weekday(timeToDisplay))); lcd.setCursor(0, 1); int myHour = hourFormat12(timeToDisplay); if (myHour < 10) { lcd.print(" "); lcd.print(myHour); } else { lcd.print(myHour); } lcd.print(":"); int myMinute = minute(timeToDisplay); if (myMinute < 10) { lcd.print("0"); lcd.print(myMinute); } else { lcd.print(myMinute); } lcd.print(":"); int mySec = second(timeToDisplay); if ( mySec < 10) { lcd.print("0"); lcd.print(mySec); } else { lcd.print(mySec); } if(isAM(timeToDisplay)) {lcd.print("AM");} else {lcd.print("PM");}; } void SerialDisplayDateTime(time_t timeToDisplay){ Serial.print(year(timeToDisplay)); Serial.print("/"); Serial.print(monthShortStr(month(timeToDisplay)));Serial.print("/"); Serial.print(day(timeToDisplay));Serial.print(" "); Serial.print(hourFormat12(timeToDisplay)); printDigits(minute(timeToDisplay)); printDigits(second(timeToDisplay)); if(isAM(timeToDisplay)) {Serial.print("AM");} else {Serial.print("PM");}; Serial.print(" "); Serial.print(dayStr(weekday(timeToDisplay))); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } void processSerialCommand() { char c = Serial.read(); switch(c){ case 'T': // Command to set RTC time and update DriftInfo.DriftStart in the RTC battery back memory // Command format: TYYMMDDHHMMSS // Example: 2012 Oct 21 1:23pm is T121021132300 delay(100); // Wait for all data to arrive if( Serial.available() == 12 ){ // process only if all expected data is available tmElements_t tme; time_t newTime; // Parse incomming 12 ASCII charaters into time_t // no error checking for numeric values in YYMDDHHMMSS fields, so be carefull! c = Serial.read(); tme.Year = c - '0'; c = Serial.read(); tme.Year = 10*tme.Year; tme.Year += c-'0'; tme.Year += 30; c = Serial.read(); tme.Month = c - '0'; c = Serial.read(); tme.Month = 10*tme.Month; tme.Month += c-'0'; c = Serial.read(); tme.Day = c - '0'; c = Serial.read(); tme.Day = 10*tme.Day; tme.Day += c-'0'; c = Serial.read(); tme.Hour = c - '0'; c = Serial.read(); tme.Hour = 10*tme.Hour; tme.Hour += c-'0'; c = Serial.read(); tme.Minute = c - '0'; c = Serial.read(); tme.Minute = 10*tme.Minute; tme.Minute += c-'0'; c = Serial.read(); tme.Second = c - '0'; c = Serial.read(); tme.Second = 10*tme.Second; tme.Second += c-'0'; newTime = makeTime(tme); RTC.set(newTime); // set the RTC and the system time to the received value setTime(newTime); tmDriftInfo diUpdate = RTC.read_DriftInfo(); // update DriftInfo in RTC diUpdate.DriftStart = newTime; RTC.write_DriftInfo(diUpdate); Serial.print("RTC Set to: "); SerialDisplayDateTime(newTime); } break; case 'I': // read and display DriftInfo from RTC memory tmDriftInfo diRead = RTC.read_DriftInfo(); if (diRead.DriftStart == 0 | diRead.DriftDays == 0 | diRead.DriftSeconds == 0) { Serial.println("DriftInfo not set yet!"); break; } Serial.println("*** DriftInfo Read from RTC Memory ***"); Serial.print("DriftStart : "); SerialDisplayDateTime(diRead.DriftStart); Serial.println(); Serial.print("DriftDays : "); Serial.println(diRead.DriftDays); Serial.print("DriftSeconds : "); Serial.println(diRead.DriftSeconds); Serial.print("Day(s) since drift start: "); Serial.println(float(now()-diRead.DriftStart)/float(SECS_PER_DAY)); long tmp = now() - diRead.DriftStart; tmp *= diRead.DriftSeconds; Serial.print("Your RTC has Drifted(seconds): "); Serial.println(float(tmp)/float(SECS_PER_DAY * diRead.DriftDays)); break; } while(Serial.available()){ Serial.read(); } // clear serial buffer }======Текст ошибки.=========== In file included from C:\Users\Dell\Desktop\DS1307 Drift Corrected\DriftCorrectedRTC\DriftCorrectedRTC.ino:4:0: C:\Users\Dell\Documents\Arduino\libraries\DS1307RTC/DS1307RTC.h:19:19: error: 'tmElements_t' has not been declared static void read(tmElements_t &tm); ^ C:\Users\Dell\Documents\Arduino\libraries\DS1307RTC/DS1307RTC.h:20:20: error: 'tmElements_t' has not been declared static void write(tmElements_t &tm); ^ C:\Users\Dell\Documents\Arduino\libraries\DS1307RTC/DS1307RTC.h:21:9: error: 'tmDriftInfo' does not name a type static tmDriftInfo read_DriftInfo(); // new function not in original DS1307RC.h ^ C:\Users\Dell\Documents\Arduino\libraries\DS1307RTC/DS1307RTC.h:22:30: error: 'tmDriftInfo' has not been declared static void write_DriftInfo(tmDriftInfo di); // new function not in original DS1307RC.h ^ DriftCorrectedRTC:9: error: 'tmDriftInfo' does not name a type tmDriftInfo di; ^ C:\Users\Dell\Desktop\DS1307 Drift Corrected\DriftCorrectedRTC\DriftCorrectedRTC.ino: In function 'void setup()': DriftCorrectedRTC:19: error: 'setSyncProvider' was not declared in this scope setSyncProvider(RTC.get); // the function to get the time from the RTC ^ DriftCorrectedRTC:20: error: 'timeStatus' was not declared in this scope if(timeStatus()!= timeSet) ^ DriftCorrectedRTC:20: error: 'timeSet' was not declared in this scope if(timeStatus()!= timeSet) ^ DriftCorrectedRTC:25: error: 'di' was not declared in this scopeссылка на библиотеки и скетч.
http://forum.arduino.cc/index.php?action=dlattach;topic=119054.0;attach=192244
Косяк был в момент покупки 1307. Не тратьте время и поставьте 3231. Библиотеки совместимы.
не подскажете проверенного продавца на али?
Там где брал чипы в крайний раз, "страница недоступна". Недорогую мелочевку обычно беру где дешевле, пока без проблем.
понял, спасибо!
кварц уже один раз менял - попробую еще разок махнуть (пока выкручивюсь синхронизацией часов по сети)
Если не секрет , то как ??? Мои убегают в перёд на 21 секунду в сутки ...
у меня тоже матерился нашел в тырнете, поставь #include <TimeLib.h>- библы нет вот и не понимает
'tmElements_t'has not been declared ....Нэкрофил, аднака.)))