Weird behavior with onewire DS2417 RTC

Hi

I am working with a Maxim DS2417 RTC with interrupt. I thought that i had got the control of the chip all sorted and doing what i wanted but now the RTC seems to have other ideas.

I got a little test program together that would write the data to the RTC and then use the output from the interrupt pin to pluse every second on pin 2 of the uno.

The program should count the pulses and when the count gets to 10 turn the LED on for 2 seconds then turn it off and reset the count.

That all worked the first time i tried it.

Disconnected the uno left it a day then plugged the uno back in and now not getting anything on the interrupt pin.

#include <OneWire.h>

#define RTC_PIN A0
#define IRQ_PIN 2
#define LED_PIN 13



OneWire ds(RTC_PIN);

volatile int secondCount;

volatile boolean minuteTick = false;

uint8_t present = 0;
uint8_t addr[8];

void secondTickISR()
{
  static uint8_t secondCount = 0;
  
  secondCount++;
  if (secondCount == 10)
  {
    minuteTick = true;
    secondCount = 0;
  }
}

void setup() 
{
  present = ds.reset();
  ds.select(addr);
  ds.write(0x99, 1);
  ds.write(0x8C);
  present = ds.reset();
  
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  pinMode(IRQ_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(IRQ_PIN), secondTickISR, FALLING);
  
}



void loop()
{
  if (minuteTick)
  {
    minuteTick = false;
    digitalWrite(LED_PIN, HIGH);
    delay(2000);
    digitalWrite(LED_PIN, LOW);
  }
}

This is the code that worked and wont work even if I re upload the code to the uno.

I am confused as to why it worked once and not again

Where do you get the device's OneWire Address? How do you know you're talking to it? What do your Serial debug prints show?

The address to write the data too came from the datasheet.

When i had serial prints wrote in the code i got it to tell me the value of secondCount and i was getting what i expected

Count = 0
Count = 1
Count = 2
Etc

But now all i get is

Count = 0
Count = 0
Count = 0
Etc

When i probe the interrupt pin with oscilloscopes i could see the 5v to ov change every second.

Now there is no transition

This in your code initializes the address (a global array) to all 0's:

uint8_t addr[8];

I don't see any place in the code where it subsequently gets set to anything else.

I got the code i used from this code.

I thought addr was part of the onewire libary.

 #include <OneWire.h>

// DS1904 Real Time Clock iButton I/O
OneWire ds(10);  // on pin 10

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

void loop(void) {
 byte i;
 byte present = 0;
 byte data[8];
 byte addr[8];

 if ( !ds.search(addr)) {
     Serial.print("No more addresses found.\n");
     ds.reset_search();
     delay(500);  // for readability
     return;
 }

 Serial.print("ROM: ");
 for( i = 0; i < 8; i++) {
   Serial.print(addr[i], HEX);
   Serial.print(" ");
 }

 if ( OneWire::crc8( addr, 7) != addr[7]) {
     Serial.print("CRC is not valid!\n");
     return;
 }

 if ( addr[0] != 0x24) {
     Serial.print("\t\tDevice is not a DS1904 family device.\n");
     return;
 }

/*
 // write!
 Serial.println("writing to RTC...");
 present = ds.reset();
 ds.select(addr);
 ds.write(0x99,1);   // write RTC - this is the write code
 ds.write(0xAC);  //This is the control byte.  AC in hex = 10101100
                  //read the datasheet and you will see that this is important
                  //to start the internal osc's... Or to make the clock start
                  //counting seconds.  --ril3y
 ds.write(0x02);  //0x02 is a random time set it with your own
 ds.write(0x03);  //same with this
 ds.write(0x05);  //this
 ds.write(0x08);  //and this
 present = ds.reset();
 delay(1500);     // unknown if wait needed
*/

 // read!
 present = ds.reset();
 ds.select(addr);
 ds.write(0x66,1);   // read RTC

 Serial.print("PR: ");
 Serial.print(present, HEX);
 for ( i = 0; i < 5; i++) {
   data[i] = ds.read();
 }
 Serial.print(" CTRL BYTE:  ");
 Serial.print(data[0], BIN);
 Serial.print("\n\ttime:  ");
 for ( i = 1; i < 5; i++) {
   Serial.print(data[i], HEX);
   Serial.print(" ");
 }


 Serial.println();
 
}

What should i be doing different.

Where is the call to 'ds.search()' in your current code?

It is not in my code

My point exactly. That was a hint. It needs to be. That function scans the bus and picks up the OneWire addresses of connected devices. You can call it iteratively to discover all the devices. If you only have one device, then once will do it.

You can see how it works by looking at the examples that come with the OneWire library. But, they call it on every pass through loop(). You don't need to do that. Once in setup() will work. You should also open up the source code for the OneWire library and see how it works.

Alternatively, with only one device on the bus, you might be able to use the Skip ROM technique. This is all covered in the DS2417 Datasheet. You need to read it.

More Observations:
I'd avoid using parasitic power mode. I'm not sure if you're trying this, but it's implied by your call to:

ds.write(0x99,1);

with '1' as the second parameter.
Power the device with a real VDD at least until you get things working.

Also, you're not sending all the bytes required by the Write Clock command (i.e. 0x99). Again, this is all in the Datasheet.

I have change the code to this and it is now counting every time.

Is there anything i need to change to tidy up the main code or will just changing this in setup be enough

void setup() 
{
  present = ds.reset();
  ds.skip();
  ds.write(0x99);
  ds.write(0x8C);
  present = ds.reset();

The DS2417 datasheet states that when you issue the Write Clock command (0x99) you should follow it with 5 bytes: the Control Byte followed by 4 bytes for the clock setting. Finally, you should do a Bus Reset.

You're only sending the Control Byte and a then the reset. This may work, but you're using the device in an undocumented manner. You've essentially signed up to be an unpaid test pilot. Even though you're not actually using the clock part of the RTC, you should send it 4 dummy bytes (all zeros would probably work) after the Control Byte. Then send the reset.

Also, the 'ds.reset()' function returns a value that you're promptly ignoring. This return value provides useful information. You should read about it in OneWire.h. If a '1' is returned, all is well. But, a '0' signifies that a valid device was not found on the OneWire bus. If this happens, maybe you want your project to go into some kind of failure mode to let the user know that there's a problem? Maybe blink some lights or something.

Fix that stuff, put the code in 'setup()' and you should be good to go.

Is this better

void setup() 
{
  present = ds.reset(); // Sets present to 0
  ds.skip(); // Write to all addresses
  ds.write(0x99); // Command to start writing to RTC
  ds.write(0x8C); // Sets control bytes 1000 1100
  ds.write(0x00); // Write time byte (time not used)
  ds.write(0x00); // Same here
  ds.write(0x00); // And here
  ds.write(0x00); // And here
  present = ds.reset(); // sets present to 1 if all ok.
                        // if not remains as 0

Looks good. Is it working how you want?

It is working as i have expected.

Thank you for your help.

Now i just have to figure out my original problem and add the onewire code to my analog clock code