Go Down

Topic: DS3234 Alarms (Read 8641 times) previous topic - next topic

MobileWill

Okay I think I am convinced this RTC is bad.

It works after I configure it and set the time and all. But once I take power away and back again it starts not responding till I remove the battery to reset it. I will have to see if Sparkfun will send me another one.
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

Glad to (try to) help, too bad I don't have one of these critters to fool with, some things do seem fishy.  I suppose it is possible that the chip is bad, although that's usually my conclusion of last resort.


1. The RTC was acting up and becoming more and more unresponsive at times. Ended up pulling the battery until I figured out so that it would reset to defaults.

What do you mean by unresponsive, exactly?

Quote

2. Reading alarm and control/status values doesn't work right. Period. If I read 2 values they come out of the serial port in reverse order and some values are zero that shouldn't be. If you read one value its 0 regardless. So I gave up on reading the settings to verify.

Reverse order bit-wise, or byte-wise?

Quote

3. Despite the data sheet you can not have two transactions in 1 chip select session. You need to end it delay 10 or something and start another session.

The way I read it, CS has to be cycled for each read or write operation.  That is, (1) Drive CS low, (2) Read or write, (3) Drive CH high.  Each operation consists of one address byte, followed by one or more data bytes.  If more than one data byte, they are written to/read from the next sequential address(es).

Quote

8. It works better at 5v instead of 3.3 since Vcc needs to higher than Vbat and its too close.

"Better"?  The max spec on VPF is 2.70V, should be plenty of headroom there.  How is this powered?  Have you checked voltages with a meter?  If you've tried both 5V and 3.3V, is that just for the RTC, or for the MCU as well? 
[/quote]

Quote

I was able to use this as a reference and saw that each session only had 1 transaction. With a delay between each. I opted for a slightly longer delay of 10.

Datasheet says CS Inactive Time, tCWH has to be at least 400ns.  If the MCU clock is 16MHz, that's only seven instructions.  I'd think that if there is any processing at all between one read/write and the next, it'd be way more than that.  Heck, it probably takes more instructions than that to set up the next IO.  Bottom line, if you mean 10ms, that is orders of magnitude more than needed.  One microsecond is more than twice as much as needed.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MobileWill


Glad to (try to) help, too bad I don't have one of these critters to fool with, some things do seem fishy.  I suppose it is possible that the chip is bad, although that's usually my conclusion of last resort.


Quote


1. The RTC was acting up and becoming more and more unresponsive at times. Ended up pulling the battery until I figured out so that it would reset to defaults.

What do you mean by unresponsive, exactly?


I mean that if I request data from it, it doesn't respond and causes the Arduino to stop waiting for a response. At least that is what it looks like and now it is consistant on startup. Until I pull the battery and reset it.

Quote

Quote

2. Reading alarm and control/status values doesn't work right. Period. If I read 2 values they come out of the serial port in reverse order and some values are zero that shouldn't be. If you read one value its 0 regardless. So I gave up on reading the settings to verify.

Reverse order bit-wise, or byte-wise?


I mean that if I do 2 serial.print(spi.transfer(0x0e)); and then do another one with a different address it displays in the serial port in reverse order like i had reversed the print statements. But if i do reverse i will get 0 for both. Idk its really weird. I tired with multiple cs sessions. I guess I can try it again and try to narrow it down.

Quote

Quote

3. Despite the data sheet you can not have two transactions in 1 chip select session. You need to end it delay 10 or something and start another session.

The way I read it, CS has to be cycled for each read or write operation.  That is, (1) Drive CS low, (2) Read or write, (3) Drive CH high.  Each operation consists of one address byte, followed by one or more data bytes.  If more than one data byte, they are written to/read from the next sequential address(es).


Well I saw something in there that you can have multiple byte transfers per session.

Quote

Quote

8. It works better at 5v instead of 3.3 since Vcc needs to higher than Vbat and its too close.

"Better"?  The max spec on VPF is 2.70V, should be plenty of headroom there.  How is this powered?  Have you checked voltages with a meter?  If you've tried both 5V and 3.3V, is that just for the RTC, or for the MCU as well? 

[/quote]

Well I had thought the not responding was because the voltage was close to Vbat and causing it to shutdown SPI. But I guess not. I thought I saw in there Vcc had to be higher then Vbat and Vpf?


Quote


Quote

I was able to use this as a reference and saw that each session only had 1 transaction. With a delay between each. I opted for a slightly longer delay of 10.

Datasheet says CS Inactive Time, tCWH has to be at least 400ns.  If the MCU clock is 16MHz, that's only seven instructions.  I'd think that if there is any processing at all between one read/write and the next, it'd be way more than that.  Heck, it probably takes more instructions than that to set up the next IO.  Bottom line, if you mean 10ms, that is orders of magnitude more than needed.  One microsecond is more than twice as much as needed.
{/quote}

Now that you mention it I remember seeing something like that the first time i read it, but I guess I didn't go back to the beginning of it. I was doing a delay(10); The library uses delay(1); I can try it with that.  But I really need to fix this hanging not responding problem. Something is wrong though because it does it with the code example from sparkfun.

Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

Looking at the code you posted earlier, this is what you cannot do.  The code is copied from the earlier post, I've just added comments.

Code: [Select]
void SetAlarm(){

  digitalWrite(RTC_CS, LOW);

  //Set Alarm 2 to once per minute
 
  SPI.transfer(0x8B);  //first byte is always the address byte
  SPI.transfer(0x80);  //bytes 2-n are always data bytes.  So this writes 0x80 to register 0x8B.
 
  SPI.transfer(0x8C);  //and since CS is still low, this is interpreted as a data byte and written to 0x8C.
  SPI.transfer(0x80);  //ditto, this gets written to 0x8D.
 
  SPI.transfer(0x8D);  //and this to 0x8E,
  SPI.transfer(0x80);  //and this to 0x8F,
 
//Enable Alarm Interrupt 2
  SPI.transfer(0x8E);  //and since CS has never gone high, this writes 0x8E to 0x90, which is the Crystal Aging Offset

  SPI.transfer(0x1E); //and this attempts to write 0x1E to the Temperature MSB at 0x91, but that's a read-only register, so probably nothing happens.

 
  digitalWrite(RTC_CS, HIGH);

}


Now, if you could try this way:

Code: [Select]
void SetAlarm(){

  digitalWrite(RTC_CS, LOW);  //start a write operation

  //Set Alarm 2 to once per minute
 
  SPI.transfer(0x8B);  //send the address byte
  SPI.transfer(0x80);  //write 0x80 to register 0x8B
  SPI.transfer(0x80);  //and to 0x8C
  SPI.transfer(0x80);  //and to 0x8D
 
//Enable Alarm Interrupt 2
  SPI.transfer(0x1E);  //write 0x1E to the control register (0x8E) to enable Alarm 2 interrupts
 
  digitalWrite(RTC_CS, HIGH); //end of the data write

}


We could do all that in one operation because we were writing to four contiguous registers.  If they weren't contiguous, something like this would work (and this will still work even if they are contiguous):
Code: [Select]
void SetAlarm(){

  digitalWrite(RTC_CS, LOW);  //start the first write operation

  //Set Alarm 2 to once per minute
 
  SPI.transfer(0x8B);  //send the address byte
  SPI.transfer(0x80);  //write 0x80 to register 0x8B
  SPI.transfer(0x80);  //and to 0x8C
  SPI.transfer(0x80);  //and to 0x8D
  digitalWrite(RTC_CS, HIGH); //end the first write operation

//need to wait at least 400ns in between read/write operations, so we'll wait 1 microsecond, which is 1000ns.
  delayMicroseconds(1);
 
//Enable Alarm Interrupt 2
  digitalWrite(RTC_CS, LOW); //start the second write operation
  SPI.transfer(0x8E);  //this is the register address
  SPI.transfer(0x1E);  //write 0x1E to the control register (0x8E) to enable Alarm 2 interrupts
  digitalWrite(RTC_CS, HIGH); //end the second write operation

}


Hope that helps.  Again, I'd forget the interrupts for now, and just try to get it to work playing with the time registers.  Once you can read and write them, the others are just the same except for different addresses.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Jack Christensen

Meant to add, once I had this figured out, I'd check the Crystal Aging Offset register, and if it didn't contain a zero, I'd write a zero to it one time.  It's possible that it could have had something unintended written to it.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MobileWill


Meant to add, once I had this figured out, I'd check the Crystal Aging Offset register, and if it didn't contain a zero, I'd write a zero to it one time.  It's possible that it could have had something unintended written to it.



Wow, I didn't realize I would be writing to other registers, oops. So if I had pulled the battery would that reset everything? This would explain a lot and the time getting off before.
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

I'm not quite sure how to take the datasheet, when I read it before I thought it meant the aging register was reset only the first time the chip was powered up.  But now that I look at it again, I'm thinking that it may be every time it's powered up, so yes yanking the battery would reset it if that's the case.

But, the value in the aging register makes very, very little difference at room temperature (you're not operating the thing in a very hot or very cold environment, I assume) ... on the order of 5ppm max.  So it wouldn't throw off time keeping noticeably over short periods (where "short" could be a few months!)

So that's why I wouldn't worry about it right away.  For now, focus on just the basics, i.e. being able to set the time and read it back.  Once you've got that, check the aging register just for fun.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MobileWill

Well setting and reading the time is fine now. Plus I got the alarm set and the interrupt triggering. Now my only problem is it not responding after it switch's to battery and back.
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

Woohoo, excellent!  So if you pull the main power, so that it switches to the backup battery, leave it for a little while, then reapply power, it doesn't respond?  What does it take to get it to respond?  Do you have to pull the backup battery?
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MobileWill

Pretty much sums it up.  All I see from the serial is the text that I send to it to tell me a interrupt is triggered before I reset the flag and then that's it.

Its odd to see that on start up though.
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

Could you post the entire sketch as it is currently, please?
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MobileWill

Main File
Code: [Select]

#include <SPI.h>

//RTC
int TimeDate [7]; //second,minute,hour,null,day,month,year
int TimeStamp [7]; //Time stamp so compare against clock for items that do not need to be updated every cycle.
const int senIntervalMin = 1;
const int alarmPin = 2;
const int RTC_CS=10;

void setup()
{
Serial.begin(9600);

           RTC_init();
           
             //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
  //SetTimeDate(19,6,11,22,16,05);
}

void loop(){
 
  Serial.println("The time is: ");
  Serial.println(ReadTimeDate());
  delay(1000);
 
}


Init and Trigger functions
Code: [Select]
void RTC_init(){
 
//Turn on internal pullup for INT/SQW pin
         pinMode(alarmPin, INPUT);
         digitalWrite(alarmPin, HIGH);
         
         attachInterrupt(0, rtcAlarm, LOW); 

         pinMode(RTC_CS,OUTPUT); // chip select
// start the SPI library:
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1); // both mode 1 & 3 should work
//set control register
digitalWrite(RTC_CS, LOW); 
SPI.transfer(0x8E);
         SPI.transfer(0x06); //00000110 EOSC/BBSQW/TEMPCONV/RS1/RS2/INTCN/A2IE/A1IE
         //SPI.transfer(B00000110);
         digitalWrite(RTC_CS, HIGH);
         delay(10);
         digitalWrite(RTC_CS, LOW);
     
         SPI.transfer(0x8F);
         SPI.transfer(0x0);
digitalWrite(RTC_CS, HIGH);
delay(10);

    SetAlarm();
}


void rtcAlarm(){
 
  Serial.println("Alarm 2");
 


  digitalWrite(RTC_CS, LOW);

  SPI.transfer(0x8F);

  SPI.transfer(0x0);
 

  digitalWrite(RTC_CS, HIGH);

 
 

 
}


Set Alarm/Read/Write DateTime

Code: [Select]
void SetAlarm(){

delay(10);

digitalWrite(RTC_CS, LOW);

  //Set Alarm 2 to once per minute
       
  SPI.transfer(0x8B);
  SPI.transfer(0x80);
 
  digitalWrite(RTC_CS, HIGH);
  delay(10);
  digitalWrite(RTC_CS, LOW);

  SPI.transfer(0x8C);
  SPI.transfer(0x80);
   
   digitalWrite(RTC_CS, HIGH);
  delay(10);
  digitalWrite(RTC_CS, LOW);

  SPI.transfer(0x8D);
  SPI.transfer(0x80);
  delay(10);


  digitalWrite(RTC_CS, HIGH);

    Serial.println("Alarm 2 Set");

 
}




String ReadTimeDate(){
String strTD;
//int TimeDate [7]; //second,minute,hour,null,day,month,year
for(int i=0; i<=6;i++){
if(i==3)
i++;
digitalWrite(RTC_CS, LOW);
SPI.transfer(i+0x00);
unsigned int n = SPI.transfer(0x00);       
digitalWrite(RTC_CS, HIGH);
int a=n & B00001111;   
if(i==2){
int b=(n & B00110000)>>4; //24 hour mode
if(b==B00000010)
b=20;       
else if(b==B00000001)
b=10;
TimeDate[i]=a+b;
}
else if(i==4){
int b=(n & B00110000)>>4;
TimeDate[i]=a+b*10;
}
else if(i==5){
int b=(n & B00010000)>>4;
TimeDate[i]=a+b*10;
}
else if(i==6){
int b=(n & B11110000)>>4;
TimeDate[i]=a+b*10;
}
else{
int b=(n & B01110000)>>4;
TimeDate[i]=a+b*10;
}
}
strTD.concat(TimeDate[5]);
strTD.concat("/") ;
strTD.concat(TimeDate[4]);
strTD.concat("/") ;
strTD.concat(TimeDate[6]);
strTD.concat("     ") ;
strTD.concat(TimeDate[2]);
strTD.concat(":") ;
strTD.concat(TimeDate[1]);
strTD.concat(":") ;
strTD.concat(TimeDate[0]);
  return(strTD);
}






int SetTimeDate(int d, int mo, int y, int h, int mi, int s){
int TimeDate [7]={s,mi,h,0,d,mo,y};
for(int i=0; i<=6;i++){
if(i==3)
i++;
int b= TimeDate[i]/10;
int a= TimeDate[i]-b*10;
if(i==2){
if (b==2)
b=B00000010;
else if (b==1)
b=B00000001;
}
TimeDate[i]= a+(b<<4);
 
digitalWrite(RTC_CS, LOW);
SPI.transfer(i+0x80);
SPI.transfer(TimeDate[i]);       
digitalWrite(RTC_CS, HIGH);
  }
}

Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

MobileWill

Now it isn't doing it with the code example only my code. So it has to a code thing. Something with the interrupt.

Maybe attach the interrupt later in the code?
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

MobileWill

::Confused::

Now I set the time again and then with the example code from sparkfun it shows the time once and that's it.

http://www.sparkfun.com/datasheets/BreakoutBoards/DS3234_Example_Code.c
Current Projects:                    Arduinos:
Security Robot Tank               Uno
Security Robot II 4WD            Mega2560

http://mobilewill.blogspot.com

Jack Christensen

Still looking at it, but it looks like it (1) Sets up the ISR (attachInterrupt) on the Arduino, (2) Enables the interrupt on the RTC, and (3) Sets the RTC to interrupt once a minute.

If it were me, I'd (1) Set the RTC to interrupt once a minute, (2) Set up the Arduino ISR, then (3) Enable the interrupt on the RTC.

Not saying that's causing the trouble, but it's a more logical sequence in my mind.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Go Up