Shop OBEX P1 Docs P2 Docs Learn Events
Ds1302 — Parallax Forums

Ds1302

BobValBobVal Posts: 48
edited 2005-11-29 15:33 in General Discussion
Hello once again, now I am on to the DS1302

I hook a battery pack (3.7v) to vcc1 line and it appears that my time is still being lost.

My rotine does the following:

·················· mClock····· ··· = new DS1302(CPU.pin2, CPU.pin3, CPU.pin4);
·················· mTemperature = new DS1620(CPU.pin5, CPU.pin6, CPU.pin7);

·················· mClock.charge(false);
·················· mClock.updateTimeDate();

·················· if· (mClock.getDOW(true) <= 0)· {
······················· mClock.writeTime(3, 14, 0, 11, 23, 5, 4);
·················· }

And because the DOW (routine I added to return the interger dayOfWeek) routine always returns less or zero causing the default date to be sent.

New DS1302 getDOW routine
··················public·· int· getDOW(boolean Update)· {
································· if· (Update)· {
······································· updateTimeDate();
························ ········ }
································· return dayOfWeek;
················· }

Any ideas.

BobVal

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-28 04:53
    Your code does not show how DayOfWeek is calculated or retrieved.
    I do not use the DS1302 but I do use the DS1307. They differ only
    in their interface, the DS1307 uses I2C whereas the DS1302 uses SPI.

    Take a look at my DS1307 class here
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/peripheral/rtc/

    You also find some other time/date related classes there.
    In the class Calendar I have a method that calculates the DayOfWeek

    · /**
    ·· * Calculate weekday 0-6 (sunday = 0) and update weekday field
    ·· * The fields day, month and year must be valid
    ·· */
    · public void weekDay() {
    ··· int dy, mn, yr;
    ··· dy = day+1;·· //adjust to 1-31
    ··· mn = month+1; //adjust to 1-12
    ··· yr = year;
    ··· if (mn < 3) { //Jan & Feb = 13 & 14 preceding year
    ····· mn += 12;
    ····· yr--;
    ··· }
    ··· weekday = (dy + 2*mn + 3*(mn+1)/5 + yr + yr/4 - yr/100 + yr/400 + 1) % 7;
    · }
    regards peter
    ·
  • BobValBobVal Posts: 48
    edited 2005-11-28 19:44
    The Java class DS1302 (under lib / stamp / peripheral / rtc) that comes with the IDE uses 1 - 7 where 1 = sunday.

    So if I get a 0 back I assume the clock is not set adn set it to some default time. Then I manually change the clock to the proper time using my software and disconnect the power (except the battery to the ds1302) then I plug back in the javelin and it checks the DOW or any field and I get a what I believe to be an invalid time.

    Seems like there is something missing from the code for the battery to be in effect.

    I will have to dig deeper (hard to believe this doesn't work, they give you this chip and code with the developement board)

    BobVal
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-28 20:56
    Sunday = 1 for the clock register, also in my ds1307 class.
    In my ds1307 class there are

    · /**
    ·· * Convert calendar record to clock registers.
    ·· */
    · private void cal2regs(Calendar cal) {
    ··· regs[noparse][[/noparse]SC] = (char)cal.dec2bcd(cal.seconds);··· //seconds (0-59 bcd)
    ··· regs[noparse][[/noparse]MN] = (char)cal.dec2bcd(cal.minutes);··· //minutes (0-59 bcd)
    ··· regs[noparse][[/noparse]HR] = (char)cal.dec2bcd(cal.hours);····· //hours (0-23 bcd, 24h format)
    ··· regs[noparse][[/noparse]DW] = (char)cal.dec2bcd(cal.weekday+1);· //weekday (1-7 bcd)
    ··· regs[noparse][[/noparse]DT] = (char)cal.dec2bcd(cal.day+1);····· //date (1-31 bcd)
    ··· regs[noparse][[/noparse]MO] = (char)cal.dec2bcd(cal.month+1);··· //month (1-12 bcd)
    ··· regs[noparse][[/noparse]YR] = (char)cal.dec2bcd(cal.year%100);·· //year (0-99 bcd)
    · }
    · /**
    ·· * Convert clock registers to calendar record.
    ·· */
    · private void regs2cal(Calendar cal) {
    ··· cal.hundredth = 0;
    ··· cal.seconds = cal.bcd2dec(regs[noparse][[/noparse]SC]&0x7F);······· //seconds (0-59)
    ··· cal.minutes = cal.bcd2dec(regs[noparse][[/noparse]MN]&0x7F);······· //minutes (0-59)
    ··· cal.hours = cal.bcd2dec(regs[noparse][[/noparse]HR]&0x3F);········· //hours (0-23)
    ··· cal.weekday = cal.bcd2dec(regs[noparse][[/noparse]DW]&0x07)-1;····· //weekday (0-6)
    ··· cal.day = cal.bcd2dec(regs[noparse][[/noparse]DT]&0x3F)-1;········· //date (0-30)
    ··· cal.month = cal.bcd2dec(regs[noparse][[/noparse]MO]&0x1F)-1;······· //month (0-11)
    ··· cal.year = century + cal.bcd2dec(regs[noparse][[/noparse]YR]&0xFF); //year (2000-2099)
    · }

    So internally, in my code I use 0..n for all fields, which I find easier to work with.
    The weekday routine is from an old C source (in C, weekday is specified as 0 to 6).
    Just add 1 to make it 1 to 7.
    Check if your DOW routine returns the same value as my weekday routine
    for the date, month and year value you read from the ds1302.
    You must convert those bcd values to binary values before using them in
    my weekday routine.

    · /**
    ·· * Convert bcd data to decimal data.
    ·· * Valid bcd data range 0x0000 to 0x9999.
    ·· *
    ·· * @param bcdData bcd data to be converted.
    ·· * @return decimal representation (0 to 9999) of bcd data.
    ·· */
    · public int bcd2dec(int bcdData) {
    ··· int result;
    ··· result = ((bcdData>>12)&0x0F)*1000;
    ··· result = result + (((bcdData>>8)&0x0F)*100);
    ··· result = result + (((bcdData>>4)&0x0F)*10);
    ··· return result + (bcdData&0x0F);
    · }

    So you have bcdday, bcdmonth and bcdyear you read from your clock.
    int day = bcd2dec(bcdday)-1; //binary day, 0-30
    int month = bcd2dec(bcdmonth)-1; //binary month, 0-11
    int year = bcd2dec(bcdyear)+2000; //binary year, 2000-2099

    · /**
    ·· * Calculate weekday 0-6 (sunday = 0) and update weekday field
    ·· * The fields day, month and year must be valid
    ·· */
    · public void weekDay() {
    ··· int dy, mn, yr;
    ··· dy = day+1;·· //adjust to 1-31
    ··· mn = month+1; //adjust to 1-12
    ··· yr = year;
    ··· if (mn < 3) { //Jan & Feb = 13 & 14 preceding year
    ····· mn += 12;
    ····· yr--;
    ··· }
    ··· weekday = (dy + 2*mn + 3*(mn+1)/5 + yr + yr/4 - yr/100 + yr/400 + 1) % 7;
    · }

    Calculate weekday and you get 0 to 6.
    if (weekday+1 != DOW) {
    · System.out.println("no match\n");
    }

    regards peter




    ·
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-11-28 21:07
    Bob,

    ·· While I have no information on the JAVA classes regarding this, Peter seems to have a lot of information there (Thanks Peter).· I do have extensive knowledge of the DS1302 in general.· Attached is a picture of the typical connections for a BASIC Stamp.· These would be similar on a Javelin, but the main thing is what type of battery are you connecting?· If you're using a standard battery, there are no settings in the DS1302 that need to be made.· If the battery is 3V, as shown in my example, the back-up battery will take-over as soon as the main supply drops below 3V.· A 3V coin-cell or even a pair of AA batteries will keep the DS1302 time, date and RAM all backed-up for quite some time.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-28 21:38
    Try to set the time and date and then enter a forever loop

    to observe the clock running.

    myclock.writeTime(...); //pick a nice time like jan 1, 2000, 00:00

    while (true) {

    · myclock.readTime(false); //display time in 24h format or use readTime(true) if you use AM/PM

    · CPU.delay(21000); //wait 2 seconds

    }

    You should see the time incrementing each 2 seconds.

    If not, or if you get strange time, your communication with the chip is not working or the clock is halted.

    regards peter



    ·
  • BobValBobVal Posts: 48
    edited 2005-11-29 01:04
    My Javelin has run non-stop for 3 days and keeps perfect time when connected to the main power source.

    When I disconnect the power the DS1302 should be running off of the Battery.

    When I reconnect the power and my code calls the DS1302.java code.

    Is there any DS1302 control registers that need to be set to get it to run from the battery?

    I want to thank everyone for trying to help.

    BobVal
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-29 01:18
    What if you display time in a forever loop, then disconnect main power, wait a few minutes,

    reapply main power and just display time again, without setting the clock or even checking if it

    should be set. Do you then still get the correct time?

    regards peter
  • BobValBobVal Posts: 48
    edited 2005-11-29 01:30
    Figured it out.

    There is a routine called updateTimeDate that I call when I start which is suppose to update the interal fields but on closer inspection it only updates them when a timer has expired.

    public void updateTimeDate(){
    if (t1.timeout(UPDATE_PERIOD)) {
    CPU.writePin(enablePin,true); // enable chip
    // transfer 7 bytes of data all at once (bulk transfer)
    ...

    Rather them make another routine that did the same thing but did it always I did the following

    changed updateTimeDate to call my new routine readTimeDate and pass a bool which indicate if a force read is wanted this allows all the existing calls to updateTimeDate to work properly. I then had updateTimeDate call the changed code passing a bool of force which will cause it to use the timer to see if a read of the registers is needed.


    public void updateTimeDate(){
    readTimeDate(false);
    }


    My startup routine now calls the function readTimeDate passing a bool of true forcing a read of the registers even if the timer is not expired. My readTimeDate function is the origional updateTimeDate function that now takes a parameter.


    public void readTimeDate(boolean force) {

    if (force || t1.timeout(UPDATE_PERIOD)) {
    CPU.writePin(enablePin,true); // enable chip
    // transfer 7 bytes of data all at once (bulk transfer)
    ...


    This all seems to have fixed the problem

    Thanks for all the help guys.

    This board is great.

    BobVal
  • BobValBobVal Posts: 48
    edited 2005-11-29 02:04
    This BBS editor stripped out all my TABs so here is the DST code with SPACEs to keep formating

    private static boolean DST_Done = false;



    //
    // Daylight Savings Time Check
    //
    if (hour == 2) { // Is it 2am
    if (DST_Done) { // Have we done DST?
    return;
    }

    if (year >= 7) { // New for 2007 and greater
    if (month == 3) { // Spring Ahead Month? March
    if (dayOfWeek == 1) { // Is it Sunday
    if (date >= 8 && date <= 14) { // 2nd Sunday
    DST_Done = true; // Mark As Done
    hour += 1; // Spring Ahead 1 hour

    writeTime(hour, minute, second, month, date, year, dayOfWeek);
    return;
    }
    }
    }

    if (month == 11) { // Fall Behind? November
    if (dayOfWeek == 1) { // Is it Sunday
    if (date >= 1 && date <= 7) { // 1st Sunday
    DST_Done = true; // Mark As Done
    hour -= 1; // Fall Behind 1 hour

    writeTime(hour, minute, second, month, date, year, dayOfWeek);
    return;
    }
    }
    }
    }
    else { // Old DST 2006 and less
    if (month == 4) { // Spring Ahead Month? April
    if (dayOfWeek == 1) { // Is it Sunday
    if (date >= 1 && date <= 7) { // 1st Sunday
    DST_Done = true; // Mark As Done
    hour += 1; // Spring Ahead 1 hour

    writeTime(hour, minute, second, month, date, year, dayOfWeek);
    return;
    }
    }
    }

    if (month == 10) { // Fall Behind? October
    if (dayOfWeek == 1) { // Is it Sunday
    if (date >= 25) { // Last Sunday
    DST_Done = true; // Mark As Done
    hour -= 1; // Fall Behind 1 hour

    writeTime(hour, minute, second, month, date, year, dayOfWeek);
    return;
    }
    }
    }
    }
    }
    else {
    //
    // Once we pass 4am clear the DST Flag
    //
    if (hour >= 4) {
    DST_Done = false;
    }
    }
  • BobValBobVal Posts: 48
    edited 2005-11-29 02:05
    Well the BBS editor did it again.

    Oh well.

    BobVal
  • Jon KeinathJon Keinath Posts: 146
    edited 2005-11-29 02:35
    BobVal -



    Thanks for posting the DST code, I was about to work on a solution like this myself for my BellController project.

    Anyone -

    I'm not sure if it is just me, but I had to edit the "readTime(boolean ap)" method in the ds1302 class from > 12 to >= 12 in order for it to correctly display the "a" or "p" on my LCD. The code below shows my corrected change. :
      public String readTime(boolean ap) {
        boolean pmFlag = false;                   // create flag for pm in 12hr mode
        updateTimeDate();                         // update internal class variables
        buf10.clear();                            // clear buffer
        if (ap && (hour >= 12)) {                  // if 12hr clock and time > 12   ***THIS LINE IS THE ONE IN QUESTION***
          pmFlag = true;                          // set flag to pm
          hour -= 12;                             // adjust time from 24hr clock
        }//end if
        if (ap && hour == 0) hour = 12;           // adjust for 12am
    
       // create string
       buf10.append(numToString2(hour));
       buf10.append(":");
       buf10.append(numToString2(minute));
       buf10.append(":");
       buf10.append(numToString2(second));
    
       // add am/pm character to return string if displaying 12hr time
       if (ap) {
         if (pmFlag) buf10.append("p");
         else buf10.append("a");
       }//end if
    
       return (buf10.toString());
      }//end method: readTime
    
    




    I will soon be posting the compleated project in the Projects Forum, but you can visit the website in progress here.... http://www.kettering.edu/~kein0105/bellControl.htm

    -Jon Keinath

    Post Edited (Jon Keinath) : 11/29/2005 2:39:02 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-29 08:09
    Some additional info on DST:

    attachment.php?attachmentid=74025

    regards peter




    Post Edited (Peter Verkaik) : 11/29/2005 8:12:20 AM GMT
    780 x 351 - 8K
  • BobValBobVal Posts: 48
    edited 2005-11-29 15:10
    I'm confused:

    April (2+6*y-y/4) mod 7 + 1 is supposed to equal April 3 2005 (assuming I was talking about this past year DST)

    2+6 = 8 * 5 = 40 - (5 / 4) = 40 Mod 7 = 5 + 1 = 6 ??????
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-29 15:33
    (2 + 6*y - y/4) mod 7 + 1 =

    (2 + 6*2005 - 2005/4) mod 7 + 1 =

    (2 + 12030 - 501) mod 7 + 1 =

    11531 mod 7 + 1 =

    (1647*7 rest 2) mod 7· + 1 =

    2 + 1 = 3

    looks ok to me.

    regards peter




    Post Edited (Peter Verkaik) : 11/29/2005 3:40:27 PM GMT
Sign In or Register to comment.