Go Down

Topic: TimeAlarms.h works for a few days and quits (Read 389 times) previous topic - next topic

LionKing

Hi everyone,

I have some code below that uses TimeAlarms.h and an Adafruit RTC 1307 on an Uno to run a stepper motor to open and close a door at 6:00am and 6:30pm. The whole process was working great for weeks but then the was power shut off and since then the process has been working for a few cycles and then it fails and the door remains open.

Things I can confirm:
  • power is not being interrupted because Arduino is on when the alarm should run
  • the RTC is maintaining correct time. When I disconnect the Aruduino from its power supply and plug it into my computer to check the time on the serial monitor the time is correct. I am not recompiling the code, I'm simply checking the time
  • the door itself is working fine. I can push the open/close button (runs on pin 11) and the stepper runs and opens and closes the door


I really don't think I changed anything on the code but I wanted to see if you all could see if I'm missing something. Thank you for any help!

Code: [Select]
// Coop Door running on Real-time clock.

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Time.h>
#include <TimeAlarms.h>
#include "RTClib.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();

// Connect one stepper w/xxx steps to the bottom shield
Adafruit_StepperMotor *myMotor = AFMS.getStepper(2048, 1);

RTC_DS1307 RTC;

unsigned long DoorStatus = 0;     // 0 = open, 1 = closed
int LimitPin = 10;  // Limit switch
int ButtonPin = 11;  // Button

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

time_t syncProvider()     //
{
  return RTC.now().unixtime();
}

void setup()
{
  pinMode(A3, OUTPUT);    // set up pullup resistor for ground
  digitalWrite(A3, HIGH);    // turn on pullup resistor for ground
  pinMode(A2, OUTPUT);    // set up power for RTC
  digitalWrite(A2, LOW);    // turn on RTC
  pinMode(LimitPin, INPUT);    // limit as input
  digitalWrite(LimitPin, HIGH); // turns on pull-up resistor after input
  pinMode(ButtonPin, INPUT);    // button as input
  digitalWrite(ButtonPin, HIGH); // turns on pull-up resistor after input
  Wire.begin();
  RTC.begin();
  Serial.begin(9600);
  //  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
  // create the alarms
    if (! RTC.isrunning()) {
      Serial.println("RTC is NOT running!");
//   following line sets the RTC to the date & time this sketch was compiled
  RTC.adjust(DateTime(__DATE__, __TIME__));
    }
 
  setSyncProvider(syncProvider);
 
  AFMS.begin();  // create with the default frequency 1.6KHz
  myMotor->setSpeed(6);  // 10 rpm

  Alarm.alarmRepeat(6, 00, 0, OpenDoor); // 6:00am every day
  Alarm.alarmRepeat(18, 30, 0, CloseDoor); // 6:30pm every day

  DateTime now = RTC.now();
  Serial.print("Coop Door with Real-time Clock");
  Serial.println();
  Serial.print(year(), DEC);
  Serial.print('/');
  Serial.print(month(), DEC);
  Serial.print('/');
  Serial.print(day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(hour(), DEC);
  Serial.print(':');
  Serial.print(minute(), DEC);
  Serial.print(':');
  Serial.print(second(), DEC);
  Serial.println();
}


void  loop() {
  Alarm.delay(1); // mandatory check on the alarm/time status
 
  // CLOSE door if BUTTON is pushed and door is OPEN
  if (digitalRead(ButtonPin) == LOW && DoorStatus == 0) {
    {
      while (digitalRead(LimitPin) == HIGH)  // when pin goes HIGH/Switch is open
        myMotor->step(1, BACKWARD, SINGLE); //run the stepper
    }
    myMotor->release(); //power down the stepper
    DoorStatus = 1; // Door is CLOSED
  }
  // OPEN door if BUTTON is pushed and door is CLOSED
  if (digitalRead(ButtonPin) == LOW && DoorStatus == 1) {
    myMotor->step(8000, FORWARD, SINGLE); //run the stepper
    myMotor->release(); //power down the stepper
    DoorStatus = 0; // Door is OPEN
  }
}

void OpenDoor() {
  if (DoorStatus == 1)
  {
    myMotor->step(8000, FORWARD, SINGLE); //run the stepper
    myMotor->release(); //power down the stepper
    DoorStatus = 0; // Door is OPEN
  }
}

void CloseDoor() {
  if (DoorStatus == 0) {
    {
      while (digitalRead(LimitPin) == HIGH)  // when pin goes HIGH/Switch is open
        myMotor->step(1, BACKWARD, SINGLE); //run the stepper
    }
    myMotor->release(); //power down the stepper
    DoorStatus = 1; // Door is CLOSED
  }
}



J-M-L

Not your bug but

Code: [Select]
unsigned long DoorStatus = 0;     // 0 = open, 1 = closedis a lot of memory for a boolean type...

Your pins variables should be better off as const byte rather than int

daysOfTheWeek is overusing memory when you could declare it as
Code: [Select]
const char * daysOfTheWeek[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};


Besides that, Can you explain what you have on A2 and A3 and what your code in setup() is supposed to do?

This probably should be commented out RTC.adjust(DateTime(__DATE__, __TIME__)); if your arduino reboots you'll set the wrong date in your clock


Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages priv├ęs SVP

6v6gt

Which RTC you've got and how it is wired also interests me. I guess it has a battery backup so explicit control of the power to it (as you appear to be using) should be unnecessary.

LionKing

Thanks JML. I will review those efficiencies and test them out on the next round.

Quote
Besides that, Can you explain what you have on A2 and A3 and what your code in setup() is supposed to do?
A2 and A3 are providing power to the RTC to run when connected to the Uno. When A3 is high it is grounded on pullup resistor. When A2 is low it provides voltage to the 1307 RTC.

The other pin setups are for a limit switch to let the stepper know when the door is closed and a button that allows me to manually open the door.

I think the following is where I'm having my issues:
Quote
This probably should be commented out RTC.adjust(DateTime(__DATE__, __TIME__)); if your arduino reboots you'll set the wrong date in your clock
I am going to comment it out and see if that fixes it. I feel like I might have done that in the past when it was working well and maybe I took off the comments thinking that the RTC.adjust would only run if RTC was not running per the if statement part of the code:

Code: [Select]
  if (! RTC.isrunning()) {
      Serial.println("RTC is NOT running!");
//   following line sets the RTC to the date & time this sketch was compiled
  RTC.adjust(DateTime(__DATE__, __TIME__));
    }


What's strange is I compiled the code and confirmed the time on the serial monitor. I powered down the Uno for a few minutes, plugged it back into the serial monitor and the time was fine. Is there something that would make this work for a few hours but then after a few days it would fail?


PaulS

Since you have an RTC, the TimeAlarm library is not really necessary. On every pass through loop(), get the current time. See if it is time to open the door. If it is, open the door. See if it is time to close the door. If it is, close the door.
The art of getting good answers lies in asking good questions.

LionKing

Thanks, PaulS.

One thing I'm trying to understand is why the alarm works a few times and then quits. When I do a time check on the serial monitor my RTC is accurate. My code had been working successfully for months and then it stopped working. I'm afraid I accidentally changed something in the setup that is causing the issue. The setup code is very basic but I can't tell if something is amiss. Is there anything you notice that would cause an issue? Again, code was working fine for months, now it's not. Thanks again.

cattledog

Quote
Is there anything you notice that would cause an issue? Again, code was working fine for months, now it's not.
Quote
it fails and the door remains open.
First, I would check that the limit switch on pin 10 is not sticking closed and giving a LOW.

Second, I would use the pin 13 led indicator in the alarm function to see if you are entering or not entering the function. If the door fails open with the led lit, you know the problem is not anything to do with the time and the alarms.

Code: [Select]
void CloseDoor() {
   
   digitalWrite(13, HIGH);//declare pin 13 as an output in setup

  if (DoorStatus == 0) {
    {
      while (digitalRead(LimitPin) == HIGH)  // when pin goes HIGH/Switch is open
        myMotor->step(1, BACKWARD, SINGLE); //run the stepper
    }
    myMotor->release(); //power down the stepper
    DoorStatus = 1; // Door is CLOSED
  }
}

LionKing

Cattledog, thanks for the helpful response. Sorry for the delay in responding, I've been running the code for the last several days to test.

I commented out the RTC.adjust and the door opened and closed every day for 3 days with no issue. Then, the door stopped closing at night but would still open in the morning. Again, the door would open and close when I manually pushed the button, just for some reason it stopped closing. I would close it at night for a few days but it would still open in the morning no problem. Then, it wouldn't open or close. Again, the door would open manually with the button but it wouldn't work with the timer.

I'm going to add Cattledog's troubleshooting suggestion with pin 13 to let me know if the alarm triggers. I feel like it has something to do with how the RTC talks to the Arduino and somehow the connection gets lost or scrambled and the system loses track of time. In the past when the alarm stopped working I tested the time on the RTC in the serial monitor and it was still accurate.

Does anyone have any insights on how the RTC 1307 interacts with the Arduino and how communication might get dropped or scrambled?

PS - I will follow up with the pin 13 test in the next several days.

cattledog

Quote
Does anyone have any insights on how the RTC 1307 interacts with the Arduino and how communication might get dropped or scrambled?
Code: [Select]
setSyncProvider(syncProvider);

Code: [Select]
time_t syncProvider()     
{
  return RTC.now().unixtime();
}


setSyncProvider() coordinates the internal millis() clock with the real time clock. When the program starts, the time library will reference the millis() clock to the rtc time. Instead of millis() marking the time since the program started, the time library will use millis() to add to the time since the time on the rtc when the program started.

Then, every five minutes(the default synchronization period), the Arduino (time library) will get the time from the rtc, and if the millis() based time is different, it adjusts the millis() based time to match, thus keeping in synch.

All this is managed in the background by the time library.

Quote
I feel like it has something to do with how the RTC talks to the Arduino and somehow the connection gets lost or scrambled and the system loses track of time. In the past when the alarm stopped working I tested the time on the RTC in the serial monitor and it was still accurate.
If the time within the RTC is correct, but the reading of the RTC was scrambled and the arduino looses track of time on one reading, it should be corrected 5 minutes later.

If the led indicator experiment doesn't get you focused on something other than the time, you can use an SD card module to log the time.

Do you have an SD module and card you can use?

If you don't, they are very inexpensive (costs way less than a chicken  :) ), and pretty easy to use. If you get one, make sure it has the level shifter IC, and not the resistance network. The Catalex module for a micro sd card is good if there is only one device using SPI.




LionKing

Cattledog,

Thanks for all the suggestions. Here's what I have so far:
  • I added the 13 pin test to the alarm and the alarm triggered the pin along with the stepper motor.
  • The alarm never triggered the pin without running the stepper motor.
  • When I checked the RTC it was still accurate and reporting the correct time.


I tested several scenarios to see if something with the alarm or RTC might be wrong:
  • I set an alarm for less than 5 minutes out and the alarm worked as expected
  • I set an alarm for 15 minutes out and the alarm worked as expected
  • I set an alarm for 5 minutes out, removed and reconnected the RTC while the Arduino was running, and the alarm worked as expected


I was finally able to have the alarm fail when I stumbled across something I had not noticed before. I noticed that when I connect power to the Arduino, I don't always make a solid connection and sometimes the Arduino power light will turn off and on as I get the power connected. The reason is that I have a stepdown that takes the power from 12v to 5.2v and it isn't always easy to get the wires into the stepdown in a smooth, solid way. I always ended up with solid 5.2v power with plenty of amps behind it but the way that I connected the power seems to be a problem. I believe this is what was causing my issue.

When I made a poor initial power connection the alarm would fail. I would reset and make a solid initial power connection and everything worked fine. I setup the Arduino to run the door and made sure to make a solid initial connection. The door has worked fine for one of the alarms so far. I will keep you posted on whether this solves the problem long term.

I'm also wondering if this scenario could cause one alarm to fail before the other alarm does. Last time I had an alarm failure, the nightly alarm failed for a few days while the morning alarm worked fine. Then, the morning alarm finally failed. I don't know what goes on behind the scenes in these multiple time libraries but I'm wondering if the faulty initial connection could cause the issue.

PS - thanks to PaulS for the suggestion to remove the whole alarm function to begin with. I understand the concept and appreciate the simplicity. I just haven't taken the time to test and implement.

LionKing

Well, the second alarm did not work today. The morning alarm worked fine. I tested the evening alarm yesterday night under all the various circumstances listed above and it worked without issue except when I purposely caused a poor initial power connection. This time I made a solid connection so that should not be the issue.

Why would the morning alarm work but the evening alarm does not? The only guess I can make is the passage of time and some issue between the RTC and Arduino but the RTC checks out.

Or, there is some conflict between the various time libraries that causes intermittent issues. What's strange is the code worked for months until my primary battery died. Now it doesn't work and I didn't make any changes...

Code: [Select]
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Time.h>
#include <TimeAlarms.h>
#include "RTClib.h"


If anyone has any pointers on this I would greatly appreciate it. I am also going to try and write a sketch that only uses RTClib.h instead of all the other time libraries.

cattledog

Quote
Well, the second alarm did not work today.
What did the led test tell you? Did the program enter the alarm function but did not close the door?

You have to set up the led tell tale so that if the door opens or closes properly the led is turned off, and can indicate the failure mode on the next alarm action.

LionKing

The test told me that the alarm did not trigger. I have it set so that the LED turns on when the alarm triggers. When the door did not close the LED did not turn on. Strangely, the morning alarm has triggered and opened the door fine the last two days.

The open/close functions both use Alarm.alarmRepeat and simply run different but very similar pieces of code.

Code: [Select]
  Alarm.alarmRepeat(6, 00, 0, OpenDoor); // 6:00am every day
  Alarm.alarmRepeat(18, 30, 0, CloseDoor); // 6:30pm every day


Code: [Select]
void OpenDoor() {
  if (DoorStatus == 1)
  {
    myMotor->step(8000, FORWARD, SINGLE); //run the stepper
    myMotor->release(); //power down the stepper
    DoorStatus = 0; // Door is OPEN
  }
}

void CloseDoor() {
  digitalWrite(13, HIGH);//declare pin 13 as an output in setup
  if (DoorStatus == 0) {
    {
      while (digitalRead(LimitPin) == HIGH)  // when pin goes HIGH/Switch is open
        myMotor->step(1, BACKWARD, SINGLE); //run the stepper
    }
    myMotor->release(); //power down the stepper
    DoorStatus = 1; // Door is CLOSED
  }
}


Why would one alarm work and the other does not work when they use the same function to run?

It really makes me think there is some time glitch occurring at night that doesn't occur in the morning. At night, I can push the manual and the door closes, so I know it's not the door. And, as mentioned above, the test LED does not come on when the alarm is supposed to run so I know the alarm didn't run.

Thanks for any further advice!

cattledog

Quote
The test told me that the alarm did not trigger.
Excellent! You have indeed confirmed that the problem is with the time keeping.

One possibility is that when the system clock is running slow to the real world, and is updated with synchronization, it advances beyond the alarm time. The alarm will not trigger until the next cycle. It does not recognize that it is overdue.

Here's a suggestion, if your RTC is reasonably accurate, you may be able to synchronize once per day, at a time well away from any alarm.

Add this line to the sketch to create a once per day sync 24 hours after the program is restarted.

Code: [Select]
setSyncProvider(RTC.get);   // the function to get the time from the RTC
  setSyncInterval(86400);


Restart or reset the program some time after the evening alarm time.

Go Up