Hi, currently i’m trying to figure out, how to get right time out of DS2417 RTC chip. It’s based on standart DS18B20 example from OneWire library. I have Arduino 1.0.1 IDE and Arduino UNO .
#include <OneWire.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library
OneWire ds(10); // on pin 10
byte i;
byte present = 0;
byte type_s;
byte data[6];
byte addr[8];
byte set_time_converted[4];
long byte_dec,st_seconds;
double year_leap,day_total; //because floor(x) return double
double time[4];
int ref_time[5]={1970,1,1,0,0}; //Janury 1st 1970 Ooh OOm
int set_time[5]={2013,5,11,5,44};
char* months[]={"January","February","March","April","May","June","July","August", "September", "October","November","December"};
char* days_of_week[]={"Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday","Wednesday"};
//Such order is due to reference point of clock - 1970 Jan 1st is thursday
int day_count,prev_day_count, month, st_daycount_year,st_daycount;
void setup(void) {
Serial.begin(9600);
ds.search(addr);
ds.reset();
ds.select(addr);
st_daycount_year=((set_time[0]-ref_time[0])*365)+floor(((set_time[0]-ref_time[0]-2)/4)); //+2 is correction to the first leap year since 1972
Serial.println(st_daycount_year);
st_daycount=0;
for (i=1;i<set_time[2];i++) {
if (i==2) { //february - leap year or not
if (fmod(set_time[0],4)==0) st_daycount+=29;
else st_daycount+=28;
}
else {
if (i<8) {
if (fmod(i,2)!=0) st_daycount+=31;
else st_daycount+=30;
}
else {
if (fmod(i,2)==0) st_daycount+=31;
else st_daycount+=30;
}
}
}
st_daycount+=st_daycount_year;
st_daycount+=(set_time[1]-1);
Serial.println(st_daycount);
st_seconds=(st_daycount*86400)+(set_time[3]*3600)+(set_time[4]*60);
Serial.println(st_seconds);
for (i=0;i<4;i++) {
set_time_converted[i]=fmod(st_seconds,256);
st_seconds=floor(st_seconds/256);
}
//ds.write(0x99);
//ds.write(0x0C); //write command byte - no interruption, start oscillator (clock start counting)
//for ( i = 0; i < 4; i++) {ds.write(set_time_converted[i]);} // setting time
ds.reset();
}
void loop(void) {
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250); //this delay is reason of disappearing seconds!
return;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x27:
Serial.println(" Clock DS2417"); // or old DS1820
type_s = 1;
break;
default:
Serial.println("Device is not a DS2417 clock.");
return;
}
delay(600);
ds.reset();
ds.select(addr);
ds.write(0x66); // Read Clock command
Serial.print("Data = ");
for ( i = 0; i < 5; i++) { // we need 4 bytes + 1 control byte (first) (for clock)
data[4-i] = ds.read(); // so here we go. 5-i here is due to DS2417 blurting out bytes in backward order
}
byte_dec=0;
for ( i = 0; i < 4; i++) {
Serial.print(data[i], HEX);
// byte_dec+=(pow(256,(3-i)))*data[i];
byte_dec=(byte_dec*256)+data[i];
Serial.print(" ");
}
Serial.print(data[4], HEX); //command byte
Serial.print(" ");
Serial.println();
//Serial.println(byte_dec);
// convert the data to actual time
day_total=floor(byte_dec/86400);
year_leap=floor(byte_dec/126230400); //amount of seconds in 3 years + leap year
byte_dec-=(year_leap*126230400);
time[0]=floor(byte_dec/31536000);
byte_dec-=(time[0]*31536000);
time[0]+=(year_leap*4); //setting year
time[1]=floor(byte_dec/86400); //setting days
byte_dec-=(time[1]*86400);
time[2]=floor(byte_dec/3600); //setting hours
byte_dec-=(time[2]*3600);
time[3]=floor(byte_dec/60); //setting minutes
byte_dec-=(time[3]*60);
time[4]=byte_dec; //setting seconds
for(i=0;i<5;i++){
if (time[i]<10) Serial.print("0"); //formatting output
Serial.print(int(time[i])); //int here removes decimal part for printing
if (i<4) Serial.print(":");
}
Serial.println();
//determine month
day_count=0;
for (i=1;i<13;i++) {
prev_day_count=day_count;
if (i==2) { //february - leap year or not
if (fmod(time[0]+ref_time[0],4)==0) day_count+=29; //calculating current year and checking if leap
else day_count+=28;
}
else {
if (i<8) {
if (fmod(i,2)!=0) day_count+=31;
else day_count+=30;
}
else {
if (fmod(i,2)==0) day_count+=31;
else day_count+=30;
}
}
if (time[1]<=day_count) {
month=i;
Serial.print(months[i-1]);
Serial.print(" ,");
Serial.println(int(time[1]-prev_day_count+1));//because there is no "January, 0"
break;
}
}
Serial.println(days_of_week[int((fmod(day_total,7))+1)]);
}
Issue is - everything is working fine while byte_dec is less then 00FFFFFF. And then printing of time array is all messed up - output of data and byte_dec shows that counter is working, but time is stuttering like this
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 2F C
00:194:04:59:28
July ,14
Tuesday
No more addresses.
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 30 C
00:194:04:59:28
July ,14
Tuesday
No more addresses.
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 31 C
00:194:04:59:28
July ,14
Tuesday
No more addresses.
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 32 C
00:194:04:59:30
July ,14
Tuesday
No more addresses.
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 32 C
00:194:04:59:30
July ,14
Tuesday
No more addresses.
ROM = 27 E6 6 29 0 0 0 B8
Clock DS2417
Data = 1 0 9 33 C
00:194:04:59:32
July ,14
Tuesday
No more addresses.
As you can see, data is read correct, it converted correctly in amount of seconds (byte_dec), but issue with time is beyond my grasp. Everything is beginning as soon as byte_dec going over 0xFFFFFF - so i tried to set byte_dec to double, but it didn’t help. Can anyone help me with that?