Automatic Chicken Door With RTC

Hi, my coworker and I built an automated chicken door for our chicken coop. We are using an Arduino Uno, though not genuine, an RTC (DS-3231) and two reed switches. The arduino is being powered by a 12v ps and that power is divided between the arduino and the motor, there is also a battery connected to the motor to give it some more juice and hopefully make sure there is no flicker (Not sure it works though). It gets really cold here at night but the arduino is also responsible for switching on a heat lamp and a light so it doesn't get below freezing in the coop.

Our problem is that everything will work perfectly for a few days and then something goes wrong, the door will either stay up or stay down. We wrote in a default position so if the door is ever confused it will just go down and reset the loop, but that doesn't seem to be working either.

If someone could read through our code that would be a great help as we are both newish to the arduino realm. I cannot decide if it is a power/flicker problem or something in the code. I live on the farm but would like to have this set up so I don't have to check on it every night/ morning and when no one is here it would be nice to know the chickens are ok. I have the code attached, it is tabbed so all 6 files are needed and I posted it here as well. Your help is greatly appreciated.

#include <Dusk2Dawn.h>
#include <RTClib.h>
#include <OneWire.h>
#include <Wire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

Dusk2Dawn Glenwood(39.51739, -107.328591, -7);

int SRise;
int SSet;
int TimeInMin;
float Temp = 0;
int UpSensor = 2;
int DownSensor = 3;
int MotorUp = 4;
int MotorDown = 5;
int Light = 6;
int Heat = 7;
bool HeatOn = false;
bool DoorUp;
bool DoorDown;
bool LightOn;

DateTime now;

int HeatOnAt = 45; //////Set to temp heater should turn on at
int HeatOffAt = 50; //////Set to temp heater should turn off at
int CloseDelay = 60; ///Set to min after sunset to close
int OpenDelay = 75; ///Set top min after sunrise to open



void setup() {
rtc.begin();
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  
pinMode(UpSensor, INPUT_PULLUP);
pinMode(DownSensor, INPUT_PULLUP);
pinMode(MotorUp, OUTPUT);
pinMode(MotorDown, OUTPUT);
pinMode(Light, OUTPUT);
pinMode(Heat, OUTPUT);
digitalWrite(MotorUp, HIGH);
digitalWrite(MotorDown, HIGH);
digitalWrite(Light, HIGH);
digitalWrite(Heat, HIGH);

sensors.begin(); ///Temp Senor
Serial.begin(9600);
}

void loop(){
//DateTime now = rtc.now(); ///////////////////RESET CLOCK
CLOCK();
SUNRISE_SUNSET();
DOORS();
HEATER();
LIGHT();


Serial.println();

delay(1000);

}
void CLOCK () {
 //Set now as RTC time
 now = rtc.now();
 //Print RTC time to Serial Monitor
 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);
 TimeInMin = (now.hour()*60+now.minute());
 //TimeInMin = 421; // Time Testing Line
 Serial.println();
 Serial.println(TimeInMin);
 delay(3000);
}
void DOORS(){
DoorUp = false;
DoorDown = false;
if(digitalRead(UpSensor) == 0) {
  DoorUp = true;
}
if(digitalRead(DownSensor) == 0) {
  DoorDown = true;
}

////////OPEN DOOR///////////////////
if (DoorDown == true && TimeInMin > (SRise+OpenDelay)){    // Conditions to open door
  if(TimeInMin < SSet){
  digitalWrite(MotorUp, LOW);
  do{
      if(digitalRead(UpSensor) == 0) {
        DoorUp = true;
      }
      delay(50);
      Serial.println("GOIN UP"); 
  }while(DoorUp == false);
  digitalWrite(MotorUp, HIGH);
  Serial.println("door up");
  }
}


//////////CLOSE DOOR//////////////////////////////
if (DoorUp == true && TimeInMin > (SSet+CloseDelay)){    // Conditions to close door
  digitalWrite(MotorDown, LOW);
  do{
      if(digitalRead(DownSensor) == 0) {
        DoorDown = true;
      }
      delay(50);
      Serial.println("GOING DOWN"); 
  }while(DoorDown == false);
  digitalWrite(MotorDown, HIGH);
  Serial.println("door down");
}

////////////CLOSE BY DEFAULT////////////////
if (DoorUp == false && DoorDown == false){
    digitalWrite(MotorDown, LOW);
    do{
      if(digitalRead(DownSensor) == 0) {
        DoorDown = true;
      }
      delay(50);
      Serial.println("GOING DOWN"); 
  }while(DoorDown == false);
  digitalWrite(MotorDown, HIGH);
}

}
void HEATER() {
  
sensors.requestTemperatures(); 
Temp=sensors.toFahrenheit(sensors.getTempCByIndex(0));
Serial.print("Temp =");
Serial.print(Temp);
Serial.println();
///////////////HEATER ON/OFF///////////////
if((Temp < HeatOnAt) && (HeatOn == false)){
  digitalWrite(Heat, LOW);
  HeatOn = true;
}
else if((Temp > HeatOffAt) && (HeatOn == true)){
  digitalWrite(Heat, HIGH);
  HeatOn = false;
}
Serial.print("HEAT ON =");
Serial.print(HeatOn);
Serial.println();
}
void LIGHT() {
if(TimeInMin > (SSet - 720))  {
  LightOn = true;
  if (TimeInMin > (SRise + 60)){
    LightOn = false;
  }
}
else{
  LightOn = false;
}

  if (LightOn == true){
    digitalWrite(Light, LOW);
    Serial.print("LIGHT ON =");
    Serial.println(LightOn);
  } else {
      digitalWrite(Light, HIGH);
  }
}
void SUNRISE_SUNSET(){
 SRise  = Glenwood.sunrise(now.year(), now.month(), now.day(), false);
 SSet = Glenwood.sunset(now.year(), now.month(), now.day(), false);
  

  /*  Time is returned in minutes elapsed since midnight. If no sunrises or
   *  sunsets are expected, a "-1" is returned.
   */
  Serial.println(SRise);
  Serial.println(SSet);

  }

CHICKEN_DOOR.ino (1.47 KB)

CLOCK.ino (631 Bytes)

DOORS.ino (1.3 KB)

HEATER.ino (470 Bytes)

LIGHT.ino (337 Bytes)

SUNRISE_SUNSET.ino (364 Bytes)

Haven’t read all your code but get rid of delay(xxx); lines, use blink without delay techniques instead.

Robin2 has a great discussion, see stickies at the top of the forums.

A glance through the code does not immediately reveal any of the usual crash-causing problems (use of Strings, array bound violations, etc.), so I suspect intermittent electrical disturbances in the power supply due to the motor (which can reset or damage the Arduino) and possibly the heater.

Try running the Arduino without the motor and heater to see if the crashes go away. If so, first separate the motor and Arduino power supplies completely, except that you must connect the grounds.

Please post a hand drawn (not Fritzing) wiring diagram, and post links to the motor, motor driver, heater and heater driver.

jremington, here is a quick hand drawn diagram linked. The motor is a 12v dc motor controlled by a relay. The heater and the light are also controlled by relays hooked up to an outdoor outlet. The relay controlling the motor is hooked up so that one relay makes the motor go down, and the other relay makes it go up by reversing the poles.

If you don’t get rid of delay() you can miss events.

FYI
These may be of interest.

No surge / spike suppression on the motor?

The images that are posted in #3/#4 are not wiring diagrams and are not useful to us.

Those posted in #5 are wiring diagrams, and they are useful.

I've never made my own circuit diagram, I could spend some time making one if truly needed though. I am going to convert the code to millis() based code as larryd suggested and go ahead and get another power supply to power the motor and arduino separately, as that seems like the most likely culprit to me. Thank you all for the help, I will update after the holidays when I complete everything.

The 1st schematic in #5 shows suppression across the motor.

FYI

After ! You have sorted this cause out and fixed it ..

With systems working remotely , where the life of a chicken may depend upon it , it’s worth including a watchdog routine , so that if anything unexpected locks the Arduino up, it will restart itself .
This isn’t a cure for poor programming but useful additional insurance .

hammy:
With systems working remotely , where the life of a chicken may depend upon it , it’s worth including a watchdog routine , so that if anything unexpected locks the Arduino up, it will restart itself .
This isn’t a cure for poor programming but useful additional insurance .

If the Arduino is to be restarted, then this line

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

should be removed from the code. (You know why, right?)