Ds1302
BobVal
Posts: 48
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
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
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
·
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
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
·
·· 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
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
·
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
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
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
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;
}
}
Oh well.
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. :
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
regards peter
Post Edited (Peter Verkaik) : 11/29/2005 8:12:20 AM GMT
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 ??????
(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