Pcf8523 RTC using with Arduino if else problem

I'm using Adafruit pcf8523 RTC to determine morning and afternoon using code below. It will pull arduino pin 10 high in the morning, and pull it low in the afternoon. Even though it's a straight forward and simple logic, the arduino seems to be not liking its pin 10 stay up high. RTC's output stuck and stop updating the time for some reasons that I cannot figure out. Could anyone please give me some advise on it?


#include "RTClib.h"

RTC_PCF8523 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int morning = 10;     //Assign the output pin to pin 10
//int state = 0;

void setup() {
  // put your setup code here, to run once:
Serial.begin(57600);
pinMode(morning, OUTPUT);
#ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1) delay(10);
  }

  if (! rtc.initialized() || rtc.lostPower()) {
    Serial.println("RTC is NOT initialized, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
    //
    // Note: allow 2 seconds after inserting battery or applying external power
    // without battery before calling adjust(). This gives the PCF8523's
    // crystal oscillator time to stabilize. If you call adjust() very quickly
    // after the RTC is powered, lostPower() may still return true.
  }

  // When time needs to be re-set on a previously configured device, the
  // following line sets the RTC to the date & time this sketch was compiled
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

  // When the RTC was stopped and stays connected to the battery, it has
  // to be restarted by clearing the STOP bit. Let's do this to ensure
  // the RTC is running.
       rtc.start();

   // The PCF8523 can be calibrated for:
  //        - Aging adjustment
  //        - Temperature compensation
  //        - Accuracy tuning
  // The offset mode to use, once every two hours or once every minute.
  // The offset Offset value from -64 to +63. See the Application Note for calculation of offset values.
  // https://www.nxp.com/docs/en/application-note/AN11247.pdf
  // The deviation in parts per million can be calculated over a period of observation. Both the drift (which can be negative)
  // and the observation period must be in seconds. For accuracy the variation should be observed over about 1 week.
  // Note: any previous calibration should cancelled prior to any new observation period.
  // Example - RTC gaining 43 seconds in 1 week
  float drift = 43; // seconds plus or minus over oservation period - set to 0 to cancel previous calibration.
  float period_sec = (7 * 86400);  // total obsevation period in seconds (86400 = seconds in 1 day:  7 days = (7 * 86400) seconds )
  float deviation_ppm = (drift / period_sec * 1000000); //  deviation in parts per million (μs)
  float drift_unit = 4.34; // use with offset mode PCF8523_TwoHours
  // float drift_unit = 4.069; //For corrections every min the drift_unit is 4.069 ppm (use with offset mode PCF8523_OneMinute)
  int offset = round(deviation_ppm / drift_unit);
  // rtc.calibrate(PCF8523_TwoHours, offset); // Un-comment to perform calibration once drift (seconds) and observation period (seconds) are correct
  // rtc.calibrate(PCF8523_TwoHours, 0); // Un-comment to cancel previous calibration

  Serial.print("Offset is "); Serial.println(offset); // Print to control offset
  
}

void loop() {
 DateTime now = rtc.now();
 if(now.hour()<13){            //Time before 1PM consider as 'Morning', otherwise, 'Afternoon'
   digitalWrite(morning,HIGH);
   Serial.println("Morning");
   delay(5);
 }
 else{
   Serial.println("Afternoon");
   digitalWrite(morning,LOW);
   delay(5);
 }
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
}


// switch (state) {
//  case 0:
//    Serial.println("Error");
//    break;
//  case 1:
//  RTC_Code_Morning();
//  Serial.println("Morning");
//    break;
//  case 2:
//  RTC_Code_Afternoon();
//Serial.println("Afternoon");
//    break;
//  default:
//    Serial.println("Error");
//    break;
//  }
//delay(1000);
//}
//void RTC_Code_Morning(){
//  digitalWrite(morning,HIGH);
//   delay(5);
//}
//
//void RTC_Code_Afternoon(){
//  digitalWrite(morning,LOW);
//  
//  delay(5);
//}


Did you try any of the pcf8523 example sketches from the Adafruit library, such as this one?

Do they work correctly?

Hi PaulRB,
Yes, I did. That works fine and I could get time correctly. My code is actually base on that example. The only thing I added is pull one pin high using if/ else.

What is connected to pin 10?

If you remove the digitalWrite() from loop() does the sketch show time correctly?

Does the output become more stable / time updating if you temporarily add a large delay to the end of your loop, maybe a delay(1000).

I'm not using a normal Arduino. I'm using a industrial arduino which is a 'Ardbox Relay HF+ RS485'. Pin 10 is one of relay output and is connected to another Ardbox as a digital input for further use. With this code here, if I comment digitalWrite (morning, HIGH), it works fine. And for the 'afternoon' part, where pin 10 is pulled low, using digitalWrite(morning, LOW), is working fine too. It simply doesn't like being HIGH.

Hi markd833,
I've tried increasing delay, it had no affect on it. The RTC stop working as always.

This would have been useful information to have included in your original post.

What if you choose another pin, a pin not connected to a relay. Does the code run correctly with that pin?

If so, you need to post a schematic showing all components and give links to the specs of each component.

Ok, what happens if you split the problem into 2 halves.

If you take the basic blink example and modify it to toggle the relay state with delays of seconds, does the relay stay in the correct state?

If you comment out the digitalWrite in your cide, does the RTC section work correctly?

Sorry mate. It's my first time posting in a forum. Due to time limit I'm stuck with this industrial arduino, which has no normal output pins but relay outputs. I don't have time to order a normal arduino in. I'll try to draw a schematic for this.

If you disconnect the output of relay on pin 10, does the code work then?

For the first question I need to double check that.

For the second one, if I comment out digitalWrite(morning,HIGH), and keep digitalWrite(morning,LOW), it works just fine. If I pull it high and then pull it back to low it works fine too. Once that pin stays high, I've tried different output pins, pin 9,10, or others, they all lead to rtc stop working.

It has the same result with when it was connected.

I am pretty sure from what you have told us so far, and the things you have tried, that there is no problem with the RTC and no problem with the if/else, which you were thinking.

What do you see on serial monitor, from the moment the code upload is completed?

I suspect this could be a power supply problem. How is the Arduino powered? I am thinking that the power supply could be inadequate, and when a relay is activated, the supply voltage drops and the circuit does not work correctly. The serial monitor output might confirm this.

Something else to throw into the mix just in case.

Your RTC is an I2C device. The user guide i found for your Ardbox says this:

The I2C protocol is meant to work in a pull-up configuration. The I2C pins in the Arduino
Leonardo are not pull-up, so in order to work with the I2C an external pull-up resistor is
required.

Do you have these resistors fitted on your RTC board?

Very good point mate! I never checked serial monitor using both usb and external psu. I only checked with the usb connection. Following is the screen shot of that. The first line should be correct current time, but I took the screen shot yesterday and I don't have the board with me right now. So basically, it got it correctly on first loop but stop working after that.

I don't think the rtc has build in pull-up resistors. This is one of the things I missed. I'll check that out later. Thank you Markd833!

So this problem occurs when powered by usb or from external PSU? You are using an ordinary desktop/laptop pc? Did you try a different USB cable? What is the spec of the power supply you used?

Please do not post images of serial monitor in future. Copy the text from serial monitor and paste into your post, between code tags.

1 Like

Just normal laptop, using miniusb to usb cable. Never tried other cables. For the psu, I was using 24vdc 3 or 5 amps psu.