Fleming Family Farm Chicken Coop Automatic Door Opener Arduino Code

in Homesteading26 days ago

Here is the final working Arduino code for the automatic chicken coop door opener. It now resets the clock every morning at 12:01AM from an NTP server, provides a web page with many statistics, sets the open and close time automatically by season (you set the months), opens based on time and the light level, and provides the temperature and humidity. The LCD shows the IP address if you have DHCP so you can update the bookmark for the web page.

IMG_20240426_111718.jpg

The button is ornamental now since I removed the servo latch.

IMG_20240426_111739.jpg

IMG_20240426_111709.jpg

You can copy and paste the following code into the Arduino IDE and change to suit your needs. Ensure you make the arduino_secrets.h file (ctrl shift N).

/*
Fleming Family Farm Chicken Coop Automatic Door Opener 
Based on Time And Light Level
At 7am if the light level is under 600 the door opens and
at 8pm if the light level is above 600 the door closes

Parts Required:
 Uno R4 WiFi
 Shensor Shield
 Photoresistor with resistors to set value correct to your board
 DHT-11 Temperature and Hummidity sensor with resistor and capacitor
 20x4 LCD I2C Display
 Stepper Motor (I used Stepperonliine #23HS30-2804S)
 Motor mounting bracket
 TB6600 Stepper Motor Driver
 Jumper Wires
 Fine gauge steeel wire about 3ft/1m long
 Pulley to fit motor shaft (To hold the wire that opens and closes the door)
 2x4 to mount on and to install a bushing with washer on the end of for the wire to run over
 Wood sheet for door
 Hinges, Screws, Eye bolt, Wire clamp, 12v power supply

The LCD displays the current IP address in case you have DHCP so you can update the bookmark 
for the webpage which displays more info than the LCD can. 

The time is set on startup from an NTP server, then every night at 12:01 AM it resets the time from NTP
(I found that the RTC ran 20 minutes fast over a week with no battery attached to the R4 WiFi)

My door is hinged on top and I have a large magnet installed on the edge that locks the door to 
a metal piece attached to the coop wall. The wire winds onto the shaft of the motor and the door 
is pulled open off the magnet. At night the motor unspools the wire and the door closes shut thanks 
to the weight of and the magnet.

You need to set all of these suit:
  DOOR_OPEN time
  DOOR_CLOSE time
  The door opening and closing time is autoset seasonally in the very bottom code 
  timeZoneOffsetHours
  stepper.moveTo(-XXXXX)
  light <=/>= 600 - varies depending on your photoresistor

  Make new file arduino_secrets.h and paste this and fill in your info
    #define SECRET_SSID "YOUR SSID"
    #define SECRET_PASS "YOUR PASSWORD"

Make sure you have installed all the libraries below

*/

//Libraries included
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include "AccelStepper.h"
#include "RTC.h"
#include <NTPClient.h>
#include <WiFiS3.h>
#include <WiFiUdp.h>
#include "arduino_secrets.h" 

//Definitions
#define DHT11_PIN 7
#define DHTTYPE DHT11
#define motorInterfaceType 1
#define dirPin 4
#define stepPin 3
#define enPin 2

//Pins used: 2,3,4,7,A0,SDA/SCL

//Constants/Variables
const int pResistor = A0;     // Photoresistor at Arduino analog pin A0
int DOOR_OPEN_HH = 7;   // Is "int" so it can be changed seasonally
const int DOOR_OPEN_MM = 00; // Is "const" since minutes never change
int DOOR_CLOSE_HH = 20;  
const int DOOR_CLOSE_MM = 00;  
const int stepsPerRevolution = 200;
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS; 


//Object creation
DHT DHT11_Sensor(DHT11_PIN, DHTTYPE);
LiquidCrystal_I2C MyLCD(0x27, 20, 4);  // Creates I2C LCD Object With (Address=0x27, Cols=20, Rows=4)
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin, enPin);
WiFiUDP Udp; // A UDP instance to let us send and receive packets over UDP
NTPClient timeClient(Udp);
WiFiServer server(80);

//Variables
int light;       // Store value from photoresistor (0-1023)
int door_state;  // Door open or closed
float DHT11_TempF; //Declaration needed to display on webpage
float DHT11_Humidity; //Same as above

int wifiStatus = WL_IDLE_STATUS;

void connectToWiFi(){
   wifiStatus = WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network.
    delay(5000); // wait 5 seconds for connection:
  }

void setup() {
// Object initiation  
  Serial.begin(9600);
  connectToWiFi();
  RTC.begin();
  server.begin();
  timeClient.begin();
  timeClient.update();
  DHT11_Sensor.begin();
  MyLCD.init();

// Set stepper motor speed
  stepper.setMaxSpeed(3000);
  stepper.setAcceleration(500);

// Declare pins as output:
  pinMode(stepPin, OUTPUT);           // motor driver
  pinMode(dirPin, OUTPUT);            // motor driver
  pinMode(enPin, OUTPUT);             // motor driver
  pinMode(pResistor, INPUT);          // Set pResistor - A0 pin as an input
 
// Get the current date and time from an NTP server
  auto timeZoneOffsetHours = -7;
  auto unixTime = timeClient.getEpochTime() + (timeZoneOffsetHours * 3600);
  RTCTime timeToSet = RTCTime(unixTime);
  RTC.setTime(timeToSet);
}

void loop() {
  RTCTime currentTime;
  RTC.getTime(currentTime);
  light = analogRead(pResistor);

//Checks NTP Server time and sets board to correct time every night at 12:01 AM
  if (currentTime.getHour() == 0 &&
      currentTime.getMinutes() == 1) {
  // Get the current date and time from an NTP server
  auto timeZoneOffsetHours = -7;
  auto unixTime = timeClient.getEpochTime() + (timeZoneOffsetHours * 3600);
  RTCTime timeToSet = RTCTime(unixTime);
  RTC.setTime(timeToSet);
  }
   
//Temp & Humidity section
  float DHT11_Humidity = DHT11_Sensor.readHumidity();
  float DHT11_TempF = DHT11_Sensor.readTemperature(true);  // Read Temperature(°F)
  float hif = DHT11_Sensor.computeHeatIndex(DHT11_TempF, DHT11_Humidity); // Compute heat index in Fahrenheit

// Webpage Server Section  
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println();
            client.print("<div style=\"font-size:4em; text-align: center\">Fleming Family Farm Chicken Coop");
            client.println("<br />");
            client.print(Month2int(currentTime.getMonth()));
            client.print('/');
            client.print(currentTime.getDayOfMonth());
            client.print('/');
            client.print(currentTime.getYear());
            client.print(" ");
            client.print(currentTime.getHour());
            client.print(':');
            client.print(currentTime.getMinutes());
            client.println("<br />");
            client.print("THE DOOR OPENING TIME IS: ");
            client.print(DOOR_OPEN_HH);
            client.print(':');
            client.print(DOOR_OPEN_MM);
            client.println("<br />");
            client.print("THE DOOR CLOSING TIME IS: ");
            client.print(DOOR_CLOSE_HH);
            client.print(':');
            client.print(DOOR_CLOSE_MM);
            client.println("<br />");
            client.println("<br />");
            // output the state of the door
          if (door_state == 0) {
            client.print("THE DOOR IS CLOSED");
            } 
          else if (door_state == 1) {
            client.print("THE DOOR IS OPEN");
            }
            client.println("<br />");
            client.println("<br />");
            client.print("The Temperature is:  ");
            client.print(DHT11_TempF);
            client.print("°F");
            client.println("<br />");
            client.print("The Humidity is:  ");
            client.print(DHT11_Humidity);
            client.print(" %");
            client.println("<br />");
            client.print("The Heat Index is:  ");
            client.print(hif);
            client.print("°F");
            client.println("<br />");
            client.print("The Light Level is:  ");
            client.print(light);
            client.print("   (0 = Light to 1023 = Dark)");
            client.println("<br />");
            IPAddress ip = WiFi.localIP();
            client.print("IP Address: ");
            client.println(ip);    

            client.println("</div></html>");
          break;
            } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // close the connection:
    client.stop();
    }

//COOP DOOR OPENING SECTION

  // The door opens at the DOOR_OPEN_HR and MM when the light is brighter than 600 reading and not closing time
  if (currentTime.getHour() >= DOOR_OPEN_HH && 
       currentTime.getMinutes() >= DOOR_OPEN_MM &&
        currentTime.getHour() != DOOR_CLOSE_HH && //comment for testing <---------------
         stepper.currentPosition() != -51000 &&
          light <= 600) {
  //This opens the door and holds it open until close time
    digitalWrite(dirPin, LOW);  // Sets motor direction
    stepper.moveTo(-51000); // Set the target position = 8 rotations of shaft - Final position for open door <---------------
    //stepper.moveTo(-12000);     // Test - comment for normal operation <---------------
    stepper.runToPosition();  // Run to target position with set speed and acceleration/deceleration:
    door_state = 1;           //Sets door_state to 1 which = open
  }

// COOP DOOR CLOSING SECTION

  // the door closes when the time reaches the DOOR_CLOSE_HR and MM and the light is above the 600 reading
  if (currentTime.getHour() >= DOOR_CLOSE_HH && //<---------------
         currentTime.getMinutes() >= DOOR_CLOSE_MM && //<---------------
          stepper.currentPosition() != 0 &&
           light >= 600) {
    digitalWrite(dirPin, HIGH); // Sets motor direction
    stepper.moveTo(0);        // Set the target position:
    stepper.runToPosition();  // Run to target position with set speed and acceleration/deceleration:
    door_state = 0;           // Sets door_state to 0 which = closed
   }

// LCD DISPLAY SECTION
  MyLCD.backlight();
  MyLCD.setCursor(0, 0);
  MyLCD.print(Month2int(currentTime.getMonth()));
  MyLCD.print('/');
  MyLCD.print(currentTime.getDayOfMonth());
  MyLCD.print('/');
  MyLCD.print(currentTime.getYear());
  MyLCD.print(" ");
  MyLCD.print(currentTime.getHour());
  MyLCD.print(':');
  MyLCD.print(currentTime.getMinutes());
  MyLCD.print(':');
  MyLCD.println(currentTime.getSeconds());
  MyLCD.print(" ");
  MyLCD.setCursor(0, 1);
  MyLCD.print(DHT11_TempF);
  MyLCD.print(" °F   ");
  MyLCD.print(DHT11_Humidity);
  MyLCD.print(" %");
  MyLCD.setCursor(0, 2);
  MyLCD.print("Light ");
  MyLCD.print(light);
  MyLCD.print("  (0-1023)");
  IPAddress ip = WiFi.localIP();
  if (door_state == 0) {
    MyLCD.setCursor(0, 3);
    MyLCD.print("CLOSED -");
    MyLCD.print(ip);
  } 
  if (door_state == 1) {
    MyLCD.setCursor(0, 3);
    MyLCD.print("OPEN - ");
    MyLCD.print(ip);
    }

// Automatically set the door open and close time based on the month of the year
//    April 1 to September 30 the door opens at 7am and closes after 8pm based on light level
//    October 1 to March 31 the door opens at 8am and closes after 5pm based on light level
if (currentTime.getDayOfMonth(), DEC >= 4 &&
    currentTime.getDayOfMonth(), DEC < 10){
  int DOOR_OPEN_HH = 7; 
}
else if (currentTime.getDayOfMonth() < 4 && 
          currentTime.getDayOfMonth() >= 10) {
  int DOOR_OPEN_HH = 8; 
}
if (currentTime.getDayOfMonth(), DEC >= 4 &&
    currentTime.getDayOfMonth(), DEC < 10){
  int DOOR_CLOSE_HH = 20; 
}
else if (currentTime.getDayOfMonth() < 4 && 
          currentTime.getDayOfMonth() >= 10) {
  int DOOR_CLOSE_HH = 17; 
}
}



300x600-2
^Affiliate/Referral Link^


For more information about our farm:
Fleming Family Farm
FLEMING FAMILY FARM, LLC
Sustainable & Organic Methods | Heirloom Produce
All images are original works of Fleming Family Farm unless otherwise notated and credited.

If you find this post useful or entertaining, your support is greatly appreciated by upvoting, following, and sharing!

You can Also Find Me On:

nostr icon.jpg

Donations or Tips



Zap Me ⚡️ Alby Addy.JPG btc.jpg Sparrow.JPG LBTC LBTC.jpg

!

Veteran.jpg


FFF Runic.png

Sort:  

Yay! I have been waiting for this moment for quite a while. I was beginning to wonder if it would ever really work. I’m glad you finally won!

I'm super happy it works too. I thought something went awry but it seems some birds didn't go in on time last night so I will have to make the close time a bit later to make sure they are in. Thankfully it is only minor tuning required now.

Technology has advanced a lot and we see many such things now in the market and people like to buy them like automatic doors and many such things.