Pages: [1] 2   Go Down
Author Topic: DS1388 RTC  (Read 2344 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I'm doing some experiments with this chip, my setup is a breadboarded atmega328P-PU running @ 8MHz with the internal oscillator, the board is powered @ 3.3V and everything runs fine except that I cannot set (or maybe get?) the correct year from the RTC.

I modified the RTClib to support theDS1388 as follows:

Code:

void RTC_DS1388::adjust(const DateTime& dt) {
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(i);
    Wire.write(bin2bcd(0)); // hundreds of seconds 0x00
    Wire.write(bin2bcd(dt.second())); // 0x01
    Wire.write(bin2bcd(dt.minute())); // 0x02
    Wire.write(bin2bcd(dt.hour())); // 0x03
    Wire.write(bin2bcd(0)); // 0x04
    Wire.write(bin2bcd(dt.day())); // 0x05
    Wire.write(bin2bcd(dt.month())); // 0x06
    Wire.write(bin2bcd(dt.year() - 2000)); // 0x07
    /*
    Wire.write(i); // 0x08
    Wire.write(i); // 0x09
    Wire.write(i); // 0x0A
    Wire.write(i); // 0x0B
    Wire.write(i); // 0x0C
    */
    Wire.endTransmission();
}

DateTime RTC_DS1388::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(i);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);
  uint8_t hs = bcd2bin(Wire.read() & 0x7F);  // hundreds of seconds
  uint8_t ss = bcd2bin(Wire.read() & 0x7F);
  uint8_t mm = bcd2bin(Wire.read());
  uint8_t hh = bcd2bin(Wire.read());
  Wire.read();
  uint8_t d = bcd2bin(Wire.read());
  uint8_t m = bcd2bin(Wire.read());
  uint16_t y = bcd2bin(Wire.read()) + 2000;

  return DateTime (y, m, d, hh, mm, ss);
}




but all I get, whatever the year I set is always 2165 (end of the world?)

It comes from 2000 + 165 (converted from BCD) ... 165 must have something special: is the value I got for all bytes when I ran the unprogammed RTC the first time.

From the datasheet, the only difference from the DS1307 (which works perfectly @ 5V in the same circuit)  is the first address which contains hundred seconds in the DS1388, so I just ignored this byte and  shifted all by one in respect to the DS1307.

Any idea or suggestion?

Might be a broken chip... but hour, minute, second, month and day works just fine.

Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8975
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You request 7 bytes and then try to read 8 bytes.

Also, what is the value 'i' being written?
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You request 7 bytes and then try to read 8 bytes.

Also, what is the value 'i' being written?

Oh silly me!

Thanks you, its true that 4 eyballs are better than 2, it works perfectly now.

i is just integer 0 in the lib, should have a better name  though.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

For anyone else stumbling across this topic, I've got a few pieces of info I've learnt from using the DS1388 with an arduino.

Firstly, you need to change isRunning, because the register in question is in a different place!

Secondly, you need to change the adjust code to actually clear the 'time invalid' flag.

There's also some watchdog issues if anyone uses those, which I will post separately.

So, here are my 3 modified functions, adjust(), isRunning() and now()

Code:
uint8_t RTC_DS1307::isrunning(void) {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(0x0b);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 1);
  uint8_t ss = Wire.read();
  return !(ss>>7);
}

void RTC_DS1307::adjust(const DateTime& dt) {
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(i);
    Wire.write(bin2bcd(0)); // hundreds of seconds 0x00
    Wire.write(bin2bcd(dt.second())); // 0x01
    Wire.write(bin2bcd(dt.minute())); // 0x02
    Wire.write(bin2bcd(dt.hour())); // 0x03
    Wire.write(bin2bcd(0)); // 0x04
    Wire.write(bin2bcd(dt.day())); // 0x05
    Wire.write(bin2bcd(dt.month())); // 0x06
    Wire.write(bin2bcd(dt.year() - 2000)); // 0x07
    Wire.endTransmission();

Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(0x0b);
Wire.write(0x00); //clear the flag bit (OSF)
Wire.endTransmission();
}

DateTime RTC_DS1307::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(i);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 8);
  uint8_t hs = bcd2bin(Wire.read() & 0x7F);  // hundreds of seconds
  uint8_t ss = bcd2bin(Wire.read() & 0x7F);
  uint8_t mm = bcd2bin(Wire.read());
  uint8_t hh = bcd2bin(Wire.read());
  Wire.read();
  uint8_t d = bcd2bin(Wire.read());
  uint8_t m = bcd2bin(Wire.read());
  uint16_t y = bcd2bin(Wire.read()) + 2000;

  return DateTime (y, m, d, hh, mm, ss);
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Watchdogs then!

My circuit has the arduino in a deep sleep, woken up every 60 seconds by the RTC interrupt, which then does some logging, and goes straight back to sleep.  Nearly ripped my hair out trying to find out why this didn't work the way I wanted.

Here's what I learnt:

To initialise it in the first place the data sheet says it needs to be disabled before you can write to the watchdog time registers, then re-enabled.

Code:
  //Disable the RTC watchdog first.
  Wire.beginTransmission(0x68); 
  Wire.write(0x0c);
  Wire.write(0x00); 
  Wire.endTransmission();

  //Set the watchdog timer to 60 seconds
 Wire.beginTransmission(0x68);
  Wire.write(0x08);
  Wire.write(0x00);  //08h   
  Wire.write(0x60);  //09h - time 60 seconds
  Wire.write(0x00);  //0ah
  Wire.write(0x00);  //0bh - clear the triggered bit.
  Wire.endTransmission(); 
   
  //Enable the watchdog timer in the RTC.  0x0c -> 0x03 (WDE and WDE/RST)
  Wire.beginTransmission(0x68);
  Wire.write(0x0c);
  Wire.write(0x03);
  Wire.endTransmission();

  attachInterrupt(1, onWake, RISING);   //here's my interrupt handler.


Once it wakes you up, you need to do the following to make it go off in another minute - if you don't, it will never fire again!
You need to re-specify the time, and clear the 'triggered' bit in the 0x0b register, then you can safely sleep, and it will wake you in another 60 seconds  smiley

Code:
  //Reset the watchdog timer
  Wire.beginTransmission(0x68);
  Wire.write(0x08);
  Wire.write(0x00);  //08h   
  Wire.write(0x60);  //09h - time 60 seconds.
  Wire.write(0x00);  //0ah
  Wire.write(0x00);  //0bh - clear the triggered bit.
  Wire.endTransmission();
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your code and ideas,

it would be nice if you could rename the class to match the chip DS1307 -> DS1388 and upload the code on github, I'm sure that somebody will cooperate to check and maybe improve the library.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks!

I did wonder whether it might be better to adjust the class heirarchy a bit, and have a core DSRTC class, with two subclasses (DS1388 and DS1307) etc to improve code re-use.

One problem I've found with some libraries like the DS1307 is that it isn't maintained in simply one place.  I wonder if the arduino 'core' project team has considered adopting it like the I2C libraries etc?  If so, it'd be clear who owned it, and therefore who to submit patches to.

Any thoughts ?   smiley
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 227
Posts: 14029
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Any thoughts ?
Take ownership?

Your proposal makes a lot of sense!
Maybe not primary for code reuse but at least for interface reuse, so all those RTC's can be called in the same manner.

I can review the code if you want.




Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ooh, that'd be interesting!

Take ownership, as in the Arduino project taking ownership?

I could hack the code into some semblance of order certainly, but I'd not have the time to 'maintain' it separately outside the Arduino family.

David
Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 227
Posts: 14029
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but I'd not have the time to 'maintain' it separately outside the Arduino family.
I understand, I maintain some code myself (on playground) and I must say the first releases were hardest smiley-wink

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ooh, that'd be interesting!

Take ownership, as in the Arduino project taking ownership?

I could hack the code into some semblance of order certainly, but I'd not have the time to 'maintain' it separately outside the Arduino family.

David

To drive the DS1388 I used https://github.com/jcw/rtclib , I modified the lib adding a DS1388 class.

I could fork the original lib on github, add my modifications, and you can then add yours.
Or we can do the opposite: you fork (or just start a new repo if yours does not inherit from RTCLib) and I add my modifications (if needed).

I think that github is a very good way to distribute development efforts and maintain the code.

I don't think this lib will ever go into the Arduino core, there are so many chips out there that supporting them all would be a real nightmare for core maintainers.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi elpaso,

If you're happy to fork the lib and add your changes, I can add mine on top.  Be interested to see what else you did :-)

Cheers,

David
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

sorry for the delay, I forked RTClib and added initial support for DS1388

https://github.com/elpaso/rtclib

it's far from being complete (watchdog and charger are completely missing), but it's a start smiley-wink

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great!

I will try to figure out how github works (I was used to cvs in the past!) and am a bit out of date w.r.t. modern source control!

I will send a patch for my changes to isRunning, and adjust().   

Cheers,

David
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, and another problem I found with the DS1388.

It's very sensitive to any crystal instability, so touching the contacts of the crystal while it's running is enough to upset it and make isRunning() return false.

Problem fixed by coating those pins and the short length of track between them and the ds1388 with hot glue. Solved :-)
Logged

Pages: [1] 2   Go Up
Jump to: