Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 18 of 18

Thread: Teensy 3 RTC incorrect time question

  1. #1
    Junior Member
    Join Date
    Nov 2012
    Posts
    6

    Teensy 3 RTC incorrect time question

    Hello all! hope this is the right section to post this...

    Today i finally soldered on my crystal and battery, and they both appear to be working and keeping time, which is fantastic.

    The problem that I'm running into is that the RTC is about 3.5 months behind...

    right now: 1/22/2013 @ 8:37pm

    Teensy RTC: 10/1/2012 @ 1:03am

    this is using the TimeTeensyRTC default example sketch in the latest Beta12 release.

    I am currently using Windows 8, so i dont know if it reads the system time differently, but I may try it tomorrow on my Windows 7 machine if that might be the case.

    Any help would be great, thanks.

  2. #2
    Did you set the timer prior to first use?

    Teensy3Clock.set(atime_t)

    You can get the current epoch time from here: http://www.epochconverter.com/

  3. #3
    Junior Member
    Join Date
    Nov 2012
    Posts
    6
    Quote Originally Posted by darkness View Post
    Did you set the timer prior to first use?

    Teensy3Clock.set(atime_t)

    You can get the current epoch time from here: http://www.epochconverter.com/
    That is the piece of the puzzle i was missing! thanks a bunch.

  4. #4
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    455
    Quote Originally Posted by e30Andrew View Post
    Hello all! hope this is the right section to post this...

    Today i finally soldered on my crystal and battery, and they both appear to be working and keeping time, which is fantastic.

    The problem that I'm running into is that the RTC is about 3.5 months behind...

    right now: 1/22/2013 @ 8:37pm

    Teensy RTC: 10/1/2012 @ 1:03am

    this is using the TimeTeensyRTC default example sketch in the latest Beta12 release.

    I am currently using Windows 8, so i dont know if it reads the system time differently, but I may try it tomorrow on my Windows 7 machine if that might be the case.

    Any help would be great, thanks.
    That date (Oct 1, 2012) is the default start time (when Teensy 3 was born ?) -- defined in pins_teensy.c

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    14,678
    Quote Originally Posted by Jp3141 View Post
    That date (Oct 1, 2012) is the default start time (when Teensy 3 was born ?) -- defined in pins_teensy.c
    On my TO-DO list is a patch for Arduino to automatically define TIME_T to the time the program was compiled, and use that instead of a fixed date. The idea is the RTC would be automatically initialized to within a second or two of your computer's time, if the crystal is present and it's not previously been initialized. Of course, if you ever remove the Vbat power and reboot without reprogramming, the new default init time would be the moment when you compiled the program.... but at least it would give a nice "out of the box" initialization for working on projects.

  6. #6
    Senior Member
    Join Date
    Apr 2013
    Posts
    106
    Quote Originally Posted by PaulStoffregen View Post
    On my TO-DO list is a patch for Arduino to automatically define TIME_T to the time the program was compiled, and use that instead of a fixed date. The idea is the RTC would be automatically initialized to within a second or two of your computer's time, if the crystal is present and it's not previously been initialized. Of course, if you ever remove the Vbat power and reboot without reprogramming, the new default init time would be the moment when you compiled the program.... but at least it would give a nice "out of the box" initialization for working on projects.
    May I can help a little bit, I did some progging around the TimeTeensyRTC Sample, and get this to work to use the Compiler Time from the Arduino IDE after soldered the crystal to the Teensy
    Code:
    /*
     * TimeRTC.pde
     * example code illustrating Time library with Real Time Clock.
     * 
     */
    
    #include <Time.h>
    
    // Unixtimeseconds from 1. Januar 1970  00:00:00
    // to 1. Januar 2000   00:00:00 UTC-0
    #define SECONDS_FROM_1970_TO_2000 946684800
    
    int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    
    void setup() {
      timefromcompiler(__DATE__,__TIME__);
      // set the Time library to use Teensy 3.0's RTC to keep time
      setSyncProvider(Teensy3Clock.get);
    
      Serial.begin(115200);
      while (!Serial);  // Wait for Arduino Serial Monitor to open
      delay(100);
      if(timeStatus()!= timeSet) 
         Serial.println("Unable to sync with the RTC");
      else
         Serial.println("RTC has set the system time");      
    }
    
    void loop() {
       digitalClockDisplay();  
       delay(1000);
    }
    
    void digitalClockDisplay() {
      // digital clock display of the time
      printDigits(hour());
      Serial.print(":");
      printDigits(minute());
      Serial.print(":");
      printDigits(second());
      Serial.print(" ");
      printDigits(day());
      Serial.print(".");
      printDigits(month());
      Serial.print(".");
      Serial.println(year());
    }
    
    void printDigits(int digits){
      // utility function for digital clock display: prints preceding colon and leading 0
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }
    
    int conv2d(char* p){
      int v = 0;
      if ('0' <= *p && *p <= '9')
      	v = *p - '0';
      return 10 * v + *++p - '0';
    }
    
    void timefromcompiler(char* date, char* time){
      int _days, _month, _year, _hour, _minute, _second;
      uint32_t _ticks;
      
      //Day
      _days = conv2d(date + 4);
    	
      //Month
      switch (date[0]) {
        case 'J': _month = date[1] == 'a' ? 1 : _month = date[2] == 'n' ? 6 : 7; break;
        case 'F': _month = 2; break;
        case 'A': _month = date[2] == 'r' ? 4 : 8; break;
        case 'M': _month = date[2] == 'r' ? 3 : 5; break;
        case 'S': _month = 9; break;
        case 'O': _month = 10; break;
        case 'N': _month = 11; break;
        case 'D': _month = 12; break;
      }
      
      //Year
      _year = conv2d(date + 9);
      
      //Time
      _hour = conv2d(time);
      _minute = conv2d(time + 3);
      _second = conv2d(time + 6);
      
      //Date & Time to Unixtime
      for (int i = 1; i < _month; ++i)
        _days += daysInMonth[i - 1];
      if (_month > 2 && _year % 4 == 0)
        ++_days;
      _days += 365 * _year + (_year + 3) / 4 - 1;
    
      _ticks = ((_days * 24 + _hour) * 60 + _minute) * 60 + _second;
      _ticks += SECONDS_FROM_1970_TO_2000;
      
      Teensy3Clock.set(_ticks);
    }
    This Sketch convert the Compilertime to Unixtime (the format the Freescale Chip saved the time) and set it in the Teensy.
    Attached Files Attached Files

  7. #7
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    FYIO ... A 20 PPM "watch crystal" will give you an 1.73 deviation per day or 10.51 minutes per year.
    http://www.maximintegrated.com/desig...design/rtc.cfm

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    14,678
    The Time library was recently updated. Teensyduino 1.13 still has the old copy. The latest code is here:

    http://www.pjrc.com/teensy/td_libs_Time.html

    The 1.14 installer will have this new version. I highly recommend using this newer Time library. Many small bugs were fixed.


    Teensyduino tries to automatically initialize the RTC, if it has a 32 kHz crystal connected but the time has never been set. This is the line in mk20ds128.c which sets the time:

    Code:
            if (RTC_SR & RTC_SR_TIF) rtc_set(TIME_T);
    If the RTC was previously set and it's been running since (either normal or battery power), then rtc_set() is not called.

    TIME_T is passed from the Arduino IDE when the code is compiled. The idea is for the clock to automatically set the first time you program a board with a freshly installed crystal and battery. Of course, if you ever remove the battery, the time will default to when you compiled the program.

    However, there's 2 bugs. I'm working on them. #1: the TIME_T is in UTC. I'm planning to change the number Arduino passes to the compiler to localtime. #2: mk20dx128.c isn't recompiled every time you use upload or verify, so the time defaults to the last time that particular file was compiled.

    Of course, you can call rtc_set() or Teensy3Clock.set() to set the time correctly. Someday I'm going to fix those 2 bugs, so in the common case where you add the crystal and battery and just try the examples, the clock will automatically to your correct local time.

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    14,678
    There's also a Teensy3Clock.compensate(num) function. It takes a signed integer, so you can slightly increase or decrease the RTC speed to compensate for inaccuracy in the crystal. The compensation is units of 0.1192 ppm. Using -100 slows the RTC by 11.92 ppm.

  10. #10
    Senior Member
    Join Date
    Jan 2013
    Location
    Dallas, TX USA
    Posts
    106
    Quote Originally Posted by PaulStoffregen View Post
    The Time library was recently updated. Teensyduino 1.13 still has the old copy. The latest code is here:

    However, there's 2 bugs. I'm working on them. #1: the TIME_T is in UTC. I'm planning to change the number Arduino passes to the compiler to localtime. #2: mk20dx128.c isn't recompiled every time you use upload or verify, so the time defaults to the last time that particular file was compiled.

    Of course, you can call rtc_set() or Teensy3Clock.set() to set the time correctly. Someday I'm going to fix those 2 bugs, so in the common case where you add the crystal and battery and just try the examples, the clock will automatically to your correct local time.
    Paul,
    I don't consider #1 a bug.
    Time should always be kept and tracked in UTC.
    Using anything else breaks time keeping particularly when using
    the time or comparing the time to an external device or to a time in some other locality.
    (Think alarms sync'd to google calendar, or events synchronized to a cell phone)
    The unix guys figured this out 40+ years ago. Always track time in a common epoch, then convert
    it to the users local time zone when necessary as the human wants to see it.
    i.e. timezones are a human creation and are only for the convenience of the human viewer.

    The CPM/DOS/Windows guys never understood this and only tracked a local date/time
    in human readable form.
    Tracking date/time as a broken down local time is a bad idea, not only because it makes tracking and comparing
    times much more difficult but because it makes an assumption of locality. If you are not in
    the assumed locality the time is wrong. Or if you are trying to compare times from two
    different localities, things don't work. This does not happen when using a single epoch.

    Using a epoch timer tick to track time, solves the complexity in tracking time
    and comparing times, but once you start attempting to offset that epoch by some sort of local time offset,
    all kinds of bad things will start to creep into the code and things become a mess.

    The problem is if the epoch is shifted, then you have no idea what time it really is from looking at the epoch tick counter,
    since the counter is no longer an epoch and there is nothing in the epoch counter value to indicate that it is offset
    from the real epoch.

    If you were going to do anything, then my preference would be keep the time tracking in UTC using
    a single common epoch as it should be,
    and then set the users timezone offset automatically for them.
    That way you don't break the true timekeeping and all the existing time functions like:
    mktime() localtime() asctime(), gmtime(), etc.. will still continue to work properly.

    I've been through many date/time tracking issues in quite some detail, as I was involved
    with some Scuba Diving s/w that logged dive information in a database.

    Tracking the date/times of dives sounds so simple at first but
    it can actually get quite messy because of the way different dive computers track time
    and the way most people tend to think of "time".
    Typically when diving, you are traveling to some other location which is a different timezone from you own.
    Having to deal with epoch times vs local time tracking is a real mess for s/w trying to figure
    when the dive was actually done.
    Also, when storing the logging information in a data base you want it to be consistent no matter where
    you are physically standing or where the dive was done, when you later review the log.

    Then you have the issue of trying to figure out the amount of time between dives.
    If all you have is a local time, you can't figure this out with 100% reliability because the local time
    does not have any locality information to indicate the timezone offset and the two dives
    might not have been done in the same timezone.

    I know that Michaels Time library only used GMT and didn't deal with timezones.
    But consider where he lives:
    We had conversation about it one time, and joked and laughed about how timezone was not an issue that
    he had to worry about.

    In the end, the only thing that really works for all situations,
    is using a single epoch and then converting to timezone offsets
    as needed. The unix guys really did get it right way back then.

    Maybe I can help you get the time stuff in Teensy working "properly"?


    --- bill

  11. #11
    Junior Member
    Join Date
    Apr 2014
    Posts
    5
    Is there a similar function where I can pass (Hour, Minute, Second, Day, Month, Year) instead of Unix time? The 'regular' timeSet() function accepts that format, but I can't seem to get it to work on Teensy 3.1

    Quote Originally Posted by darkness View Post
    Did you set the timer prior to first use?

    Teensy3Clock.set(atime_t)

    You can get the current epoch time from here: http://www.epochconverter.com/

  12. #12
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    455
    Paul -- any ETA for this TIME_T ? it would be very convenient to keep track of things.
    Quote Originally Posted by PaulStoffregen View Post
    On my TO-DO list is a patch for Arduino to automatically define TIME_T to the time the program was compiled, and use that instead of a fixed date. The idea is the RTC would be automatically initialized to within a second or two of your computer's time, if the crystal is present and it's not previously been initialized. Of course, if you ever remove the Vbat power and reboot without reprogramming, the new default init time would be the moment when you compiled the program.... but at least it would give a nice "out of the box" initialization for working on projects.

  13. #13
    I struggled to figure it out but I do the following which seems to work:


    Code:
     
    // This sets the system time (NOT the Teensy RTC Clock)
    // set your seperated date/time variables out as normal and update system time FIRST
    setTime(TimeHour,TMinute,TSecond,DateDay,DateMonth,DateYear);
    
    // now we can use the system time to update the Teensy's RTC bits
    // This sets the RTC Clock from system time - epoch stylee, just like it wants :)
    Teensy3Clock.set(now());
    I trust that helps someone out coz i've been looking all weekend trying to figure it out and only just sussed it

    Great little board, only had it a few days, totally luvin' it! (cheers Paul!)

    Andy

  14. #14
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    14,678
    Quote Originally Posted by Jp3141 View Post
    Paul -- any ETA for this TIME_T ? it would be very convenient to keep track of things.
    This was done quite some time ago. It's in Teensyduino 1.18. Near the end of mk20dx128.c is this code:

    Code:
            if (RTC_SR & RTC_SR_TIF) rtc_set(TIME_T);
    If you turn on verbose info from File > Preferences, you'll see the -DTIME_T=xxxx info is being given to the compiler.

    There's a patch in Arduino so it always recompiles mk20dx128.c, even if the file hasn't changed, so that code always gets a fresh TIME_T.

    If you have the crystal added to your board, try removing the battery. Upload a sketch, and then quickly power cycle the board right after the upload. When it powers up, the RTC will be in the uninitialized state (because you took off the battery) and it'll get configured automatically with the TIME_T from your recent compile.

  15. #15
    Senior Member
    Join Date
    Jan 2013
    Location
    Dallas, TX USA
    Posts
    106
    Paul,
    I just looked at the value of TIME_T and it is wrong.
    The time_t value in a time library should be the epoch time as the number of seconds
    since 00:00:00 Coordinated Universal Time
    The value I see in the TIME_T is a value that represents the current time but is offset
    by the current timezone including the current local DST condition.

    If this value is used, then the actual time being set is wrong unless you happen to be
    in the GMT timezone.

    I know a while back that you said you wanted to change it from UTC to local time but that is wrong
    and will break other libraries that know that unix time is an epoch that is based on UTC and
    does not ever include any DST offsets.
    It will also break compatibility with other external systems which also know how to track unix epoch time.

    For users that want to abuse the time API and track time in localtime vs UTC,
    then I think a better solution would be to create different defines and let the user pick
    the one he wants vs forcing all the users to have their clocks set incorrectly to local time.
    i.e. have the user call a function to set the clock, vs blindly just doing it and assuming
    the user want to abuse the time API by using a time_t value that is offset by the localtime
    and DST offset.

    So for example, have users call a function and pass in the time_t value.
    You could have two defines say
    TIME_T and LOCALTIME_T
    Or even better maybe the names:
    UTC_TIME_T
    LOCAL_TIME_T
    So there is no confusion which you are getting and to avoid any confusion
    over any association with the time_t typedef.

    Then the user could pass in whichever he wanted.
    For those what want to use the API properly, they would use TIME_T or UTC_TIME_T
    for those that want to abuse the API, they would use LOCALTIME_T or LOCAL_TIME_T


    That way nobody is forced into having their clock set in a way
    that won't work for them.



    --- bill

  16. #16
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    14,678
    Let's talk of time zone stuff in a month, after Maker Faire, when I'm working on Teensyduino 1.20 (version 1.19 will likely be a maintenance release with only small fixes).

    Until 1.20, this won't (nor will anything else) be changing.

  17. #17
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    455
    I saw that there and it's defined on the command line when mk20dx128.c gets compiled so the current time gets defined, but was hoping to (ab)use it as a simple version indicator -- i.e. Serial.println(TIME_T);
    but I get:
    error: 'TIME_T' was not declared in this scope

    I'm not using a crystal or the RTC on this Teensy.

    Could you also define it for the Arduino sketch ?

  18. #18
    Senior Member
    Join Date
    Jan 2013
    Location
    Dallas, TX USA
    Posts
    106
    Jp3141,
    You could use __DATE__ and __TIME__ which is probably more what you are looking for.
    You can print them directly or even do some fancy things with them if you do some pre-processor magic.
    Ex: http://stackoverflow.com/questions/1...gers-then-stri
    --- bill

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •