Kutluhan Aktar
Published © CC BY

RTC Bird Feeder

Set the feeding time and feed your birds without considering the time by using a DS3231 module. Display date, time and temperature as well.

AdvancedFull instructions provided3 hours9,743
RTC Bird Feeder

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
LCD Screen - 20x4
×1
DS3231M - ±5ppm, I2C Real-Time Clock
Maxim Integrated DS3231M - ±5ppm, I2C Real-Time Clock
×1
Pan-Tilt HAT
Pimoroni Pan-Tilt HAT
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×2
SparkFun Solder-able Breadboard - Mini
SparkFun Solder-able Breadboard - Mini
×2
Breadboard (generic)
Breadboard (generic)
×1
9V Battery Clip
9V Battery Clip
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×4
Resistor 1k ohm
Resistor 1k ohm
×4
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Custom parts and enclosures

Fritzing file

Schematics

Schematics

Code

RTC Bird Feeder

Arduino
         /////////////////////////////////////////////  
        //           RTC Bird Feeder               //
       //                                         //
      //             ---------------             //
     //              (Arduino Uno)              //           
    //             by Kutluhan Aktar           // 
   //                                         //
  /////////////////////////////////////////////

// Set the feeding time and feed your birds without considering the time by using a DS3231 module. Display date, time and temperature as well.
// By using buttons on the breadboard you can set the feeding time, defined as Left, Right, OK and END buttons.
// There are four different screens as menu options you switch using buttons:
// HomeScreen
// It is the interface of RTC Bird Feeder that shows date, time and temperature values.
// The Feeding Time Set Screen
// Set the feeding time in 24hr format.
// The Remaining Time Get Screen
// Get remaining time to the feeding time when it is activated.
// Status Check Screen
// It chacks whether the system is activated or not by using OK button.
//
// Connections
// Arduino Uno(CH340) :           
//                                20x4 LCD Screen
// D7  --------------------------- rs
// D6  --------------------------- en
// D5  --------------------------- D4
// D4  --------------------------- D5
// D3  --------------------------- D6
// D2  --------------------------- D7
//                                Servo SG-90 (Joint_1)
// D9  --------------------------- 
//                                Servo SG-90 (Joint_2)
// D10 ---------------------------
//                                DS3231
// SDA(or A4 )-------------------- SDA  
// SCL(or A5) -------------------- SCL
//                                Left Button
// A0  --------------------------- 
//                                OK Button
// A1  --------------------------- 
//                                Right Button
// A2  --------------------------- 
//                                End Button
// A3  --------------------------- 


// Include this library for DS3231 RTC module and init the DS3231 using SDA and SCL pins.
#include <DS3231.h>
DS3231  rtc(SDA, SCL);

// Define lcd screen pins(rs, en , D4, D5, D6, D7).
#include <LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2);

// Include servo library and define their names.
#include <Servo.h>
Servo Joint_1;
Servo Joint_2;

// Create lcd characters from bytes.
byte clocK[8] = {
0b01010,
0b01010,
0b11011,
0b10001,
0b10101,
0b10101,
0b10001,
0b11111,
};

byte X[8] = {
0b00000,
0b10001,
0b01010,
0b00100,
0b01010,
0b10001,
0b00000,
0b00000,
};

byte smile[8] = {
0b00000,
0b01010,
0b00000,
0b00100,
0b10001,
0b10001,
0b10001,
0b11111,  
};

byte celcius[8] = {
0b01111,
0b01001,
0b01001,
0b01111,
0b00000,
0b00000,
0b00000,
0b00000,  
};

// Define button pins.
#define Left_B A0
#define OK_B A1
#define Right_B A2
#define END A3

// Define button values.
int Left;
int OK;
int Right;
int End;

// Define menu options and variables to adjust the feeding time.
boolean Set_Feed_Time;
boolean Get_Remaining_Time;
boolean Status_Check;
// Check and test the feeding system.
boolean Activated = false;

// Define a time variable to get data from DS3231 properly.
Time t;

// Define feed hour and minute.
int feedHour;
int feedMin;

void setup(){
// Initial lcd library for a 20 to 4 lcd screen.
lcd.begin(20, 4);
  
// Initialize the rtc object
rtc.begin();

// Attach servo motors to pwm pins.
Joint_1.attach(10);
Joint_2.attach(9);

// Start pimMode();
  pinMode(Left_B, INPUT);
  pinMode(OK_B, INPUT);
  pinMode(Right_B, INPUT);

// The following lines can be uncommented to set the date and time
//  rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to Wednesday
//  rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
//  rtc.setDate(17, 10, 2018);   // Set the date to October 17st, 2018

} 

void loop(){
// Get the current hour and minute from DS3231. t.hour; and t.min;
t = rtc.getTime();

// Start servo motors.
Joint_1.write(0);
Joint_2.write(0);

 createLCD();

 ReadButtons();

 HomeScreen();

 Set_Feeding_Time(); // OK Button at the homescreen.

 Get_Remaining_Time_(); // Left Button at the homescreen.

 Status_Check_(); // Right Button at the homescreen.

 Feeding_Time();

}

void ReadButtons(){
  // Read button with anolog pins.
   Left = digitalRead(Left_B);
   OK = digitalRead(OK_B);
   Right = digitalRead(Right_B);
   End = digitalRead(END);
  }
  
void createLCD(){
  // Create lcd characters at the beginning of the code above.
  lcd.createChar(1, clocK);
  lcd.createChar(2, X);
  lcd.createChar(3, smile);
  lcd.createChar(4, celcius);
  }

 void HomeScreen(){
  // Code a homescreen for RTC Bird Feeder.
  lcd.setCursor(0, 0);
  lcd.print("Bird Feeder");
  // Write Dow
  lcd.setCursor(8, 3);
  lcd.print(rtc.getDOWStr(FORMAT_SHORT));
  // Write Date
  lcd.setCursor(12, 0);
  lcd.print(rtc.getDateStr(FORMAT_SHORT));
  // Write Time
  lcd.setCursor(12, 3);
  lcd.print(rtc.getTimeStr());
  // Write Temperature
  lcd.setCursor(0, 3);
  lcd.print(rtc.getTemp());
  lcd.write(4);
  lcd.print("C");
  }

 void Set_Feeding_Time(){
 if(OK == HIGH){
  Set_Feed_Time = true;
  // While OK is HIGH, it turns the homescreen to the feeding time set screen.
  if(Set_Feed_Time == true){
    lcd.clear();
    // Activate the feeding system.
    Activated = true;
    while(Set_Feed_Time == true){
      // Adjust the feeding time by either increasing or decreasing variables through the feeding time set screen.
      ReadButtons();
      lcd.setCursor(0, 0);
      lcd.print("Set Feeding Time");
      lcd.setCursor(0, 2);
      lcd.print("Left");
      lcd.setCursor(0, 3);
      lcd.print("F_Hour:");
      lcd.print(feedHour);
      lcd.setCursor(10, 2);
      lcd.print("Right");
      lcd.setCursor(10, 3);
      lcd.print("F_Min:");
      lcd.print(feedMin);

      // Change feedHour and feedMin bu using left and right buttons.
      if(Right == HIGH){
        feedMin++;
        delay(100);
          if(feedMin > 59){
          // It has to be bewtween 0 and 59 in 60 minutes.
          feedMin = 0;
          lcd.clear();
          }
        }
      if(Left == HIGH){
        feedHour++;
        delay(100);
        if(feedHour > 23){
          // It has to be bewtween 0 and 23 in 24hr format.
          feedHour = 0;
          lcd.clear();
          }
        }
      // Control OK button to turn the feeding time set screen to the homescreen.
      if(End == HIGH){
        // End task and turn back the homscreen.
        Set_Feed_Time = false;
        lcd.clear();
        }
      }
    }
  }
  }

 void Get_Remaining_Time_(){
  if(Left == HIGH){
    Get_Remaining_Time = true;
    // While Left is HIGH, it turns the homescreen to the get remaining time screen.
    if(Get_Remaining_Time == true){
      lcd.clear();
      while(Get_Remaining_Time == true){
        ReadButtons();
        // Get the remaining time for the feeding time.
        lcd.setCursor(0, 0);
        lcd.print("Remaining Time to ");
        lcd.write(1);
        lcd.setCursor(0, 2);
        if(Activated == false){
           lcd.print("Not Activated - ");
           lcd.write(2);
          }else if(Activated == true){
            if(t.hour > feedHour){
             lcd.print(24 - (t.hour - feedHour));
             }else if(t.hour <= feedHour){
              lcd.print(abs(t.hour - feedHour));
              }
          lcd.print(" hours ");
          if(t.min > feedMin){
            lcd.print(60 - (t.min - feedMin));
            }else if(t.min <= feedMin){
              lcd.print(abs(t.min - feedMin));
              }
          lcd.print(" minutes ");
         }
         
        // Control OK button to turn the feeding time set screen to the homescreen.
        if(End == HIGH){
         // End task and turn back the homscreen.
         Get_Remaining_Time = false;
         lcd.clear();
         } 
        }
      }
    }
  }

  void Status_Check_(){
    if(Right == HIGH){
      Status_Check = true;
      //  While Right is HIGH, it turns the homescreen to the status check screen.
      if(Status_Check == true){
        lcd.clear();
        while(Status_Check == true){
          ReadButtons();
          // Check the system whether it is activated or not.
          lcd.setCursor(0, 0);
          lcd.print("Status Check :");
          lcd.setCursor(0, 2);
          if(Activated == false){
            lcd.print("Not Activated - ");
            lcd.write(2);
            }else if(Activated == true){
              lcd.print("Running - ");
              lcd.write(3);
              }

          // Control OK button to turn the feeding time set screen to the homescreen.
          if(End == HIGH){
           // End task and turn back the homscreen.
           Status_Check = false;
           lcd.clear();
          } 
          }
        }
      }
    }

  void Feeding_Time(){
    // Check whether the feeding time is set or not.
    if(Activated == true){
      if(t.hour == feedHour && t.min == feedMin){
        // Activate the feeding systems by adjusting servos.
        Joint_1.write(0);
        Joint_2.write(180);
        delay(300);
        // Return system values after activation.
        Activated = false;
        }
      }
    
    }

Credits

Kutluhan Aktar

Kutluhan Aktar

82 projects • 307 followers
AI & Full-Stack Developer | @EdgeImpulse | @Particle | Maker | Independent Researcher

Comments