Using the I2C PCF8563 Real Time Clock

Ok so I'm really getting desperate... I can't figure out what the hell I'm doing wrong :frowning:

Here's my latest code:

/* PROGRAM'S TITLE
* ---------------
      *
      * Comments
      *
      * (cleft) 2007 by Matthieu Lalonde
      * <http://smurfturf.net>
* <mailto:mlalonde(at)smurfturf(dot)net>
      *
*/
#include <Wire.h>

#define BAUD_RATE 19200
#define statusLED 12

// Addr. |Mode (162 + Read)
#define RTCAddressW 0xA2
#define RTCAddressR 0xA3

      volatile int blinkStatus = LOW;

void setup(void)
{
// initialize inputs/outputs

// start serial
      Serial.begin(BAUD_RATE);

      Wire.begin();

      Wire.beginTransmission(RTCAddressW);
      Wire.send(0);
      Wire.endTransmission();

// Registers

      Wire.beginTransmission(RTCAddressW);
      Wire.send(B00000000); // 00H      Test mode
      Wire.send(B00000000); // 01H      Alarm mode
      Wire.send(B00000001); // 02H      Seconds
      Wire.send(30);            // 03H      Minutes:p
      Wire.send(19);            // 04H      Hours
      Wire.send(11);            // 05H      Date
      Wire.send(2);                  // 06H      Day of the week
      Wire.send(B00000000); // 07H      Century bit 19XX = 1 | 20XX = 0
      Wire.send(7);                  // 08H      year
      Wire.send(B00000000); // 09H      Minute alarm
      Wire.send(B00000000); // 0AH      Hour alarm
      Wire.send(B10000000); // 0BH      Day alarm
      Wire.send(B10000000); // 0CH      Weekday alarm
      Wire.send(B10000011); // 0DH      CLKOUT control (00: 32.768Khz 11: 1Hz)
      Wire.send(B00000000); // 0EH      Timer control
      Wire.send(B00000000); // 0FH      Timer
      Wire.endTransmission();

      reportAVRState(3,0);
}

#define numberOfRegisters 16
char i = 0;
char c[numberOfRegisters];

void loop()
{
      Wire.beginTransmission(RTCAddressW);
      Wire.send(0);
      Wire.send(RTCAddressR);
        
      Wire.requestFrom(RTCAddressR, numberOfRegisters);
      
      i = 0;
      while(Wire.available())
      {
            c[i] = Wire.receive();
            i++;
      }
      Wire.endTransmission();
      
      for(i=0;i<numberOfRegisters;i++)
      {
            Serial.print(i, DEC);
            Serial.print(":\t");
            Serial.println(c[i], BIN);
      }
      
      Serial.println("Waiting a little");
      delay(2000);
}

// Reports the state of the controller via pin 13's led and serial
void reportAVRState(int howManyTimes, int leaveOn)
{
      int i;

      pinMode(statusLED, OUTPUT);

      for (i=0; i < howManyTimes; i++) {
            digitalWrite(statusLED, HIGH);
            delay(200);
            digitalWrite(statusLED, LOW);
            delay(200);       
      }

      if (leaveOn) { 
            digitalWrite(statusLED, HIGH); 
      }

      Serial.println();
      Serial.println("AVR Initialized");
}

check this post, the last post by libhart might help you. I didnt tried it yet, but i will soon, then I'm gonna post my results.

w

That's an old thread. Nothing relevant in my case.

I hope I'm not breaking any rules by dredging up this thread (:X) but I've had the same problems, and I think I've found the solution.

When using the Wire library, you only need to pass Wire.beginTransmission and Wire.requestfrom the 7-bit device address, less the read/write bit. Apparently, Wire takes care of the read/write bit for you, so if you pass it the full 8-bit address, your data is gonna get sent to the wrong place. This isn't mentioned anywhere in the documentation, and I had to find out about it from a blog. : |

Yeap, as I found out later, that's totally right!

Did you get the PCF8563 working? I am thinking of adding a Real time clock to my arduino project and so I was wondering if I should go with PCF8563. My project requires an RTC that gives me the current time... more or less accurately.

Are there other chips that I should think off?

I haven't really tried in a while. By now I've worked with a few other I2C devices like maxim's ds1337 RTC. I'm pretty sure the PCF8563 could work too. But for a safe bet use the ds1337 as there's a lib for it. Here's the code, config1 & config2 and usage doc. The only hitch is the 32.768Khz crystal needs to be a 6pF for accurate timing (12pF seems more common). From what I read in the datasheet at 12pF the skew could be ±1min/day. I'm not sure if that's also the case for the PCF8563.

Sorry for bringing this old thread up again but i really wan't to get my pcf8563 up and running...
I made som changes to your code, just to get it up and running but whit out success...:

#include <Wire.h>

void setup(void)
{
  Wire.begin();
  Serial.begin(9600);
  
  Wire.beginTransmission(0xA2);
  //Wire.send(B00000000);  
  Wire.send(B00000000);  // 00H      Test mode
  Wire.send(B00000000);  // 01H      Alarm mode
  Wire.send(B00000011);  // 02H      Seconds
  Wire.send(B01000101);  // 03H      Minutes:p
  Wire.send(B00010100);  // 04H      Hours
  Wire.send(B00010101);  // 05H      Date
  Wire.send(B00000101);  // 06H      Day of the week
  Wire.send(B10000111);  // 07H      Century bit 19XX = 1 | 20XX = 0
  Wire.send(B10011001);  // 08H      year
  Wire.send(B10000000);  // 09H      Minute alarm
  Wire.send(B10000000);  // 0AH      Hour alarm
  Wire.send(B10000000);  // 0BH      Day alarm
  Wire.send(B10000000);  // 0CH      Weekday alarm
  Wire.send(B10000011);  // 0DH      CLKOUT control (00: 32.768Khz 11: 1Hz)
  Wire.send(B00000000);  // 0EH      Timer control
  Wire.send(B00000000);  // 0FH      Timer
  Wire.endTransmission();
}

void loop()
{
  Wire.beginTransmission(0xA2);
  Wire.send(0x00);
  Wire.endTransmission();
  Wire.requestFrom(0xA2, 0x10);
  while(Wire.available())
  {
    Serial.println(Wire.receive() ,BIN);
  }
  Serial.println("Waiting a little");
  delay(2000);
}

And i get an response like this:

0
0
11
1000101
10100
10101
101
10000111
10011001
10000000
10000000
10000000
10000000
10000011
0
0
Waiting a little

Now, the strange thing is that when i RTC from my arduino I get the same response. Well, thats strange, if it's not connected you should not get any response right, but you do, it's the same when I try your code and remove the PCF8563...

Does anyone else experience the same thing or is it only me?

Thank You
/J

Yes, if the address is invalid you'll read back the buffer. Look on this forum, I have a post describing how to modify the TWI library to enable scanning of addresses. My bet is you need to shift your address by one to the right (>>1).

No, same result... :frowning: Really starting to get on my nervs....

Any suggestions?

Thanks
/J

What did the scanner say?

Scanner? if your refering to http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1192228140/1#1 I can't seem to get it right, I know the 312a313,324 markings indicates changes to some rows some how, but it makes no sence...
It would be really nice could take a moment and explain... I'm really nooby at this stuff....

Thanks

Got it to work now, thank you, as it turns out it was a bad wire that was the problem, the clock pin never got to the rtc... My current code is:

#include <Wire.h>

void setup(void)
{
  Wire.begin();
  Serial.begin(9600);
  Wire.beginTransmission(B1010001);
  Wire.send(B00000000);  
  Wire.send(B00000000);  // 00H      Test mode
  Wire.send(B00000000);  // 01H      Alarm mode
  Wire.send(B00000011);  // 02H      Seconds
  Wire.send(B01000101);  // 03H      Minutes:p
  Wire.send(B00010100);  // 04H      Hours
  Wire.send(B00010101);  // 05H      Date
  Wire.send(B00000101);  // 06H      Day of the week
  Wire.send(B10000111);  // 07H      Century bit 19XX = 1 | 20XX = 0
  Wire.send(B10011001);  // 08H      year
  Wire.send(B10000000);  // 09H      Minute alarm
  Wire.send(B10000000);  // 0AH      Hour alarm
  Wire.send(B10000000);  // 0BH      Day alarm
  Wire.send(B10000000);  // 0CH      Weekday alarm
  Wire.send(B10000011);  // 0DH      CLKOUT control (00: 32.768Khz 11: 1Hz)
  Wire.send(B00000000);  // 0EH      Timer control
  Wire.send(B00000000);  // 0FH      Timer
  Wire.endTransmission();
}
void loop()
{
  Wire.beginTransmission(B1010001);
  Wire.send(0x00);
  Wire.endTransmission();
  Wire.requestFrom(B1010001, 0x10);
  int i = 0;
  while(Wire.available())
  {
    Serial.print(i,HEX);
    Serial.print("\t");
    Serial.println(Wire.receive() ,BIN);
    i++;
  }
  Serial.println("Waiting a little");
  delay(1500);
}

It might help someone... The only problem now is that i don't get any clock out.. but thats probably some smal error...

/J
The scan function would be useful though....

Here's the post with the scanner http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1192228140/1#1. You can also look at the http://mlalonde.net/cral/ for the library used for handling the ds1337 RTC. You could possibly port it to the PCF8563.

I'm having a similar issue with an address > 127 but I'm just confused:

My address is 164, too large for Wire by default. So I truncate the LSbit and then I can use the address.
Wire will take care of the read / write bit.

Ok but still,
If my previous address was B10100100, how is wire going to differentiate my address with the LSBit dropped and an address of this value?

ie how does it know that my
B1010010 does not equal
B01010010

it just makes zero sense to me? There's gotta be some way to signal to the Wire library that it's getting a truncated address. I've successfully used the wire library on address 104, so it's not like it just ignores a bit by default? What I mean is the manufacturer said the address is 104, so I handed Wire 104, and it worked fine. I did not have to truncate the bit by default. If you don't truncate by default, how will Wire know you truncated a bit, or does it just not support addresses above 127?

Thanks for the help
Lucas

ok, if you have an address like you specified B10100100 the address that you give the wire library is B1010010, i.e you remove the last bit(the lsb). then when wire is going to use the address it will add ither an 1 or 0 to the end depending on if it's writing or reading to the device 0 for reading and 1 for writing if i'm not wrong... so it will be like this:
B10100100 (reading address)
B10100101 (writing address).
So to sum this up, when you specify an address to wire, you only give the first 7 bits and the library will add the last bit by it self depending on if its writing or reading from the device...

/J

But if I hand it a pure int, instead of 7 bits, it will just use that address directly? Because that seems to be what happens.

Thanks!

Conversion from integer to unsigned char will lose data. Aka, if you're trying to fit a 16 bit number inside 8 bit, the top 8 bit will be truncated. But that's in the best of world. Incompatible sing conversion will often result in unwanted/unpredictable behaviour. On another note. Yes a lot of datasheet mention the address as 8 bit, even when others from the same manufacturer give them as 7 bits. As such, if your address is over 127, it should be shifted to the right by one. As mentioned previous the Wire library already takes care of making it an 8bit address with the proper w/#r address.

Hope this helps.

Thank's a lot Jonen ! Now my clock is working ! :slight_smile: