Go Down

Topic: TimeAlarms.h works for a few days and quits (Read 169 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

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.




Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy