Erik de Ruiter
Published © CC BY-NC

Easy-to-Build Pet Feeder

This is an easy to build pet feeder with two timers. Delivers accurate portions each time.

BeginnerFull instructions provided41,703
Easy-to-Build Pet Feeder

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
Best to use a Arduino Nano if you want to use a compact housing
×1
Adafruit Real Time Clock
×1
Continuous Rotation Servo
×1
Cereal dispenser
×1
Hall sensor UNIPOLAR
×1
Rod Magnets 3mm dismeter, 5mm lenght
×6
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1
lcd i2c backpack
×1
Apem Push button momentary IP67
×1
Small push buttons momentary
×1
LED (generic)
LED (generic)
×6
Hammond Multi ABS housing with flange
×1

Software apps and online services

LCD character generator

Story

Read more

Schematics

Arduino Pet Feed-O-Matic

Arduino based Pet Feeder

ZIP files with all the files you need: .ino; .hex and all the libraries used

I used Arduino IDE 1.8.2. BE CAREFUL NOT TO HAVE TWO VERSIONS OF THE SAME LIBRARIES IN YOUR LIBRARIES FOLDER!!

Code

Pet Feed-O-Matic v 1.1 - 20-02-2018

Arduino
v 1.1: pressing the Cancel1 or 2 buttons will show a explanation
// c++ stuff...
//#include <Arduino.h>
//#line 1
//#line 1 "/Users/Erik/Documents/PlatformIO/Projects/180202-151127-uno/src/Pet_Feeder_1_1_ENG.cpp"
/*
                         _       _
           /\           | |     (_)
          /  \   _ __ __| |_   _ _ _ __   ___
         / /\ \ | '__/ _` | | | | | '_ \ / _ \
        / ____ \| | | (_| | |_| | | | | | (_) |
       /_/    \_\_|  \__,_|\__,_|_|_| |_|\___/
        _____     _     ______            _
       |  __ \   | |   |  ____|          | |
       | |__) |__| |_  | |__ ___  ___  __| | ___ _ __
       |  ___/ _ \ __| |  __/ _ \/ _ \/ _` |/ _ \ '__|
       | |  |  __/ |_  | | |  __/  __/ (_| |  __/ |
       |_|   \___|\__| |_|  \___|\___|\__,_|\___|_|



   Erik de Ruiter
   -----------------------------------------------------------------------------

   To do:
   - remote feeding?
   - feeder stop delay as menu editable item

  last change:
  dinsdag 20 februari 2018 - 17:20:28

   FEATURES:
   - *Accurate portions* each time! (by using a Hall sensor)
   - Two feeding times, once a day
   - *Extremely* accurate Real Time Clock (Only with genuine DS3231 chip)
   - Cancel upcoming feeding individually for both timers with
     display and Led indicator. Automatically reset after time has passed.
   - Manual feed function (one portion per button press)
   - Adjustable portions for each of the two feeding times (1-9 portions)
   - Overview of all set parameters in the main screen
   - Easy to navigate menu system
   - LED indication if feeding was successful
   - LCD backlight timer (off after 30 sec, on with any button press)
   - Backup in the event of a failing Hall sensor
   - Hass sensor LED will blink until midnight if the Hall sensor has failed
   - Time and other settings are safely stored in EEPROM

   WEBSITES:
   LCD HD44780 character generator website to make your own lcd symbols
   https://omerk.github.io/lcdchargen/

   Arduino sketch Large letter comment generator
   http://patorjk.com/software/taag/#p=display&c=c%2B%2B&f=Big&t=Comment


   Revisions:
   zondag 28 januari 2018 - 20:17:10

   
*/

////////////////////////////////////////////////////////////////////////////////
// USER CHANGEABLE VARIABLES
////////////////////////////////////////////////////////////////////////////////

// used for the Hall sensor fail backup function.
// the interval time should be somewhat larger than one 60 degree
// turn of the feeder (one portion)
#define HALL_SENSOR_BACKUP_VALUE 300

// delay before stopping the feeder servo after feeding. This way you can
// let the rotating peddle wheel stop at the right position
#define FEEDER_STOP_DELAY 100

// lcd backlight on time after pressing a button
#define LCD_BACKLIGHT_ON_TIME 30000

// exit menu without save after amanout of time set here in ms
#define MENU_TIMEOUT_VALUE 7000

////////////////////////////////////////////////////////////////////////////////

// https:// github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
#include <LiquidCrystal_I2C.h>
// https:// github.com/JChristensen/Button
#include <Button.h>
// http:// github.com/JChristensen/DS3232RTC
#include <DS3232RTC.h>
// http:// www.arduino.cc/playground/Code/Time
#include <Time.h>
// http:// arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include <Wire.h>
#include <EEPROM.h>

// CONNECTIONS:
//
// LCD (I2C module):
// SCL - A5
// SDA - A4
// VCC
// GND

// interrupt hal sensor pin
#define HALL_SENSOR_PIN 3

#define BUTTON_BACK_PIN     4
#define BUTTON_UP_PIN       5
#define BUTTON_DOWN_PIN     6
#define BUTTON_SELECT_PIN   7
#define BUTTON_CANCEL1_PIN  8
#define BUTTON_CANCEL2_PIN  9
#define BUTTON_MANUAL_PIN   10

#define LED_CANCEL1_PIN     A0
#define LED_CANCEL2_PIN     A1
#define LED_SUCCESS1_PIN    A2
#define LED_SUCCESS2_PIN    A3

// feeder Servo output Pin
#define SERVO_OUTPUT_PIN    12

// Hall sensor input Pin
#define LED_HALL_SENSOR_PIN 13

// address LCD(16x2) 0x27 or 0x3F
LiquidCrystal_I2C lcd(0x3F, 16, 2);

// define button library settings
// A debounce time of 20 milliseconds usually works well
// for tactile button switches.
#define DEBOUNCE_MS 20
// ms required before repeating on long press
#define REPEAT_FIRST 1000
// repeat interval for long press
#define REPEAT_INCR 200
// To keep things simple, we use the Arduino's internal pullup resistor.
#define PULLUP true
#define INVERT true

// Declare the buttons
Button buttonSelect  (BUTTON_SELECT_PIN,  PULLUP, INVERT, DEBOUNCE_MS);
Button buttonUp      (BUTTON_UP_PIN,      PULLUP, INVERT, DEBOUNCE_MS);
Button buttonDown    (BUTTON_DOWN_PIN,    PULLUP, INVERT, DEBOUNCE_MS);
Button buttonBack    (BUTTON_BACK_PIN,    PULLUP, INVERT, DEBOUNCE_MS);
Button buttonCancel1 (BUTTON_CANCEL1_PIN, PULLUP, INVERT, DEBOUNCE_MS);
Button buttonCancel2 (BUTTON_CANCEL2_PIN, PULLUP, INVERT, DEBOUNCE_MS);
Button buttonManual  (BUTTON_MANUAL_PIN,  PULLUP, INVERT, DEBOUNCE_MS);

// The number that is adjusted
int count;
// Previous value of count (initialized to ensure it's different when
// the sketch starts)
int lastCount = -1;
// A variable time that is used to drive the repeats for long presses
unsigned long rpt = REPEAT_FIRST;

// used for the menu time-out
unsigned long timeoutValue = 0;

// manual cancel feeding times variables
boolean manualCancelFeed1 = false;
boolean manualCancelFeed2 = false;

// Manaual feed option
boolean manualFeed = false;

// Feed amount (in portions)
int feedAmount1 = 1;
int feedAmount2 = 1;
bool feederSuccess = false;

// feeder portions
int portions = 0;
int turns = 0;

// input actions
enum {btnSELECT, btnUP, btnDOWN, btnBACK, btnCANCEL1, btnCANCEL2, btnMANUAL, trigTIMEOUT};

// States of the Finite State Machine (FSM)
enum STATES
{
  MAIN,
  MENU_EDIT_FEEDTIME1,
  MENU_EDIT_FEEDTIME2,
  MENU_EDIT_FEEDAMOUNT,
  MENU_EDIT_TIME,
  MENU_EDIT_DATE,
  MENU_EDIT_SETTINGS,

  EDIT_FEED_TIME1_HOUR,
  EDIT_FEED_TIME1_MINUTE,
  EDIT_FEED_TIME1_ON_OFF,

  EDIT_FEED_TIME2_HOUR,
  EDIT_FEED_TIME2_MINUTE,
  EDIT_FEED_TIME2_ON_OFF,

  EDIT_FEED_AMOUNT1,
  EDIT_FEED_AMOUNT2,

  EDIT_HOUR,
  EDIT_MINUTE,

  EDIT_DAY,
  EDIT_MONTH,
  EDIT_YEAR,

  EDIT_SERVO_STOP_DELAY,
  EDIT_SERVO_BACKUP_DELAY,
};
// Holds the current state of the system
STATES state;

int8_t userInput;
int8_t trigger;

int Second;
int Minute;
int Hour;
int Day;
int Month;
int Year;

int8_t DoW;
String day_of_week;
unsigned char address, data;

int testt = 0;

int feed_time1_hour;
int feed_time1_minute;
bool feed_time1_active = false;
bool alarm1Activated = false;

int feed_time2_hour;
int feed_time2_minute;
bool feed_time2_active = false;
bool alarm2Activated = false;


// used for the blink funtion when editing values
uint32_t blink_interval = 500;
uint32_t blink_previousMillis = 0;
uint32_t blink_currentMillis = 0;
boolean blink_state  = false;

// used for the blink funtion when editing values
uint32_t spinningWheel_interval = 170;
uint32_t spinningWheel_previousMillis = 0;
uint32_t spinningWheel_currentMillis = 0;
int spinningWheelSymbol = 0;

// used for the Hall sensor fail backup function
// the interval time should be somewhat larger than one 60 degree
// turn of the feeder (one portion).
uint32_t hallSensorBackup_interval = HALL_SENSOR_BACKUP_VALUE;
uint32_t hallSensorBackup_currentMillis = 0;
boolean hallSensorFail = false;

// used for the lcd backlight timer
uint32_t lcdBacklight_interval = LCD_BACKLIGHT_ON_TIME;
uint32_t lcdBacklight_currentMillis = 0;

boolean RTC_error = true;
boolean long_press_button = false;

// Define custom symbols for the LCD display
byte bell_symbol_Char[8] = {
  B00100,
  B01110,
  B01110,
  B01110,
  B11111,
  B00100,
  B00000,
  B00000
};

byte inverted_one_Char[8] = {
  0b11111,
  0b11011,
  0b10011,
  0b11011,
  0b11011,
  0b11011,
  0b10001,
  0b11111
};

byte inverted_two_Char[8] = {
  0b11111,
  0b11011,
  0b10101,
  0b11101,
  0b11011,
  0b10111,
  0b10001,
  0b11111
};

byte arrow_up_Char[8] = {
  0b00100,
  0b01110,
  0b11111,
  0b01110,
  0b01110,
  0b01110,
  0b01110,
  0b00000
};

byte arrow_down_Char[8] = {
  0b00000,
  0b01110,
  0b01110,
  0b01110,
  0b01110,
  0b11111,
  0b01110,
  0b00100
};

byte inverted_p_Char[8] = {
  0b11111,
  0b10001,
  0b10101,
  0b10001,
  0b10111,
  0b10111,
  0b11111,
  0b00000
};

byte backslash_Char[8] = {
  0b00000,
  0b10000,
  0b01000,
  0b00100,
  0b00010,
  0b00001,
  0b00000,
  0b00000
};

byte thickDash_Char[8] = {
  0b00000,
  0b00000,
  0b11111,
  0b11111,
  0b11111,
  0b00000,
  0b00000,
  0b00000
};

volatile boolean hallSensorActivated = false;

// Interrupt 1
void HallSensorIsr()
{
  hallSensorActivated = true;
  // turn on Hall sensor LED
  digitalWrite(LED_HALL_SENSOR_PIN, HIGH);
}
// These lines are needed to make this sketch a C++ file.
// I use it because I edit the code with the Atom
// text editor and the PlatformIO add-on
void HallSensorIsr();
void setup();
void loop();
void change_states();
void check_inputs();
void transition(int trigger);
void check_alarm();
void check_manual_feed();
void display_menu_option_set_feedtime1();
void display_menu_option_set_feedtime2();
void display_menu_option_set_feed_amount();
void display_menu_option_set_time();
void display_menu_option_set_date();
void midnight_reset();
void display_time();
void displayFeedingAmouts();
void displayFeedingTimes();
void set_feedAmount();
void set_time();
void set_date();
void set_feeding1_time();
void set_feeding2_time();
void get_time();
void get_date();
void write_time();
void write_date();
void write_feeding_time1();
void write_feeding_time2();
void write_feedamount();
void get_feedamount();
void get_feed_time1();
void get_feed_time2();
void check_RTC();
byte decToBcd(byte val);
byte bcdToDec(byte val);
void leading_zero(int digits);
void blinkFunction();
void displaySpinningWheel();
void startFeederServo();
void stopFeederServo();
void activateFeeder(int portions);
void check_LcdBacklight();
void lcd_backlight_ON();
void ledsAndLcdDisplayStartup();
void hallSensorCheck();
#line 355
// ******************************************************************************
// SETUP

void setup()
{
  // activate the lcd screen
  lcd.begin();
  // turn lcd backlight on and start backlight off-timer
  lcd_backlight_ON();

  // start I2C
  Wire.begin();

  // hall sensor input to detect rotation of the feeder/feed amount output check
  pinMode(HALL_SENSOR_PIN, INPUT_PULLUP);
  pinMode(LED_HALL_SENSOR_PIN, OUTPUT);
  pinMode(SERVO_OUTPUT_PIN, OUTPUT);
  pinMode(LED_CANCEL1_PIN, OUTPUT);
  pinMode(LED_CANCEL2_PIN, OUTPUT);
  pinMode(LED_SUCCESS1_PIN, OUTPUT);
  pinMode(LED_SUCCESS2_PIN, OUTPUT);

  // set default state of LED's to OFF
  digitalWrite(LED_CANCEL1_PIN, LOW);
  digitalWrite(LED_CANCEL2_PIN, LOW);
  digitalWrite(LED_SUCCESS1_PIN, LOW);
  digitalWrite(LED_SUCCESS2_PIN, LOW);
  digitalWrite(LED_HALL_SENSOR_PIN, LOW);

  lcd.createChar(0, thickDash_Char);
  lcd.createChar(1, bell_symbol_Char);
  lcd.createChar(2, backslash_Char);
  lcd.createChar(3, inverted_p_Char);
  lcd.createChar(4, inverted_one_Char);
  lcd.createChar(5, inverted_two_Char);
  lcd.createChar(6, arrow_up_Char);
  lcd.createChar(7, arrow_down_Char);

  // set feeder Servo to default state OFF
  stopFeederServo();

  Wire.begin();

  // set RTC as the Syncprovider
  setSyncProvider(RTC.get);
  // time in sec of resync with RTC
  setSyncInterval(60);

  // Disable the default square wave of the SQW pin.
  RTC.squareWave(SQWAVE_NONE);

  // Attach an interrupt on the Hall sensor (when unput turns LOW)
  // ever 60 degree turn of the feeder shaft, the hall sensor
  // should generate an interrupt
  attachInterrupt(INT1, HallSensorIsr, FALLING);

  // display test
  ledsAndLcdDisplayStartup();

  // Initial state of the FSM
  state = MAIN;

  // read the stored alarm value from the Arduino memory
  get_feed_time1();
  get_feed_time2();

}// End SETUP



// ******************************************************************************
// LOOP

void loop()
{
  // change states of FSM
  change_states();

  // check inputs (buttons)
  check_inputs();

  // check if alarm was called
  check_alarm();

  // check if manual feed was requsted
  check_manual_feed();

  // at midnight, reset some variables
  midnight_reset();

  // check connection RTC
  check_RTC();

  // Check the Hall sensor function
  hallSensorCheck();

  // check if lcd backlight must be turned off
  check_LcdBacklight();

}// End of LOOP


// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************



//******************************************************************************
// Finite State Machine
void change_states()
{
  // states
  switch (state)
  {
    //---------------------------------------
    case MAIN:
      display_time();
      displayFeedingAmouts();
      displayFeedingTimes();
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDTIME1:
      display_menu_option_set_feedtime1();
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDTIME2:
      display_menu_option_set_feedtime2();
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDAMOUNT:
      display_menu_option_set_feed_amount();
      break;
    //---------------------------------------
    case MENU_EDIT_TIME:
      display_menu_option_set_time();
      break;
    //---------------------------------------
    case MENU_EDIT_DATE:
      display_menu_option_set_date();
      break;

    //---------------------------------------
    case EDIT_FEED_TIME1_HOUR:
      set_feeding1_time();
      break;
    //---------------------------------------
    case EDIT_FEED_TIME1_MINUTE:
      set_feeding1_time();
      break;
    //---------------------------------------
    case EDIT_FEED_TIME1_ON_OFF:
      set_feeding1_time();
      break;

    //---------------------------------------
    case EDIT_FEED_TIME2_HOUR:
      set_feeding2_time();
      break;
    //---------------------------------------
    case EDIT_FEED_TIME2_MINUTE:
      set_feeding2_time();
      break;
    //---------------------------------------
    case EDIT_FEED_TIME2_ON_OFF:
      set_feeding2_time();
      break;

    //---------------------------------------
    case EDIT_FEED_AMOUNT1:
      set_feedAmount();
      break;
    //---------------------------------------
    case EDIT_FEED_AMOUNT2:
      set_feedAmount();
      break;

    //---------------------------------------
    case EDIT_HOUR:
      set_time();
      break;
    //---------------------------------------
    case EDIT_MINUTE:
      set_time();
      break;
    //---------------------------------------
    case EDIT_DAY:
      set_date();
      break;
    //---------------------------------------
    case EDIT_MONTH:
      set_date();
      break;
    //---------------------------------------
    case EDIT_YEAR:
      set_date();
      break;
      //---------------------------------------
  }
}


//******************************************************************************
// Check INPUTS

void check_inputs()
{
  // first check if timeout has occurred
  if ( millis() - timeoutValue > MENU_TIMEOUT_VALUE )
  {
    userInput = trigTIMEOUT;
    transition(userInput);
  }

  // check state of buttons
  buttonSelect.read();
  buttonUp.read();
  buttonDown.read();
  buttonBack.read();
  buttonManual.read();
  buttonCancel1.read();
  buttonCancel2.read();

  // check manual cancel Feed1 button
  switch (buttonCancel1.wasPressed())
  {
    case 1:
      // invert variable value (true to false and vise versa)
      manualCancelFeed1 = !manualCancelFeed1;
      //turn on lcd backlight manually
      lcd_backlight_ON();

      // message when Cancel1 button is pressed
      if (manualCancelFeed1 == 1)
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        //         0123456789012345 - LCD screen character counter
        lcd.print("Upcoming Feed #1");
        lcd.setCursor(0, 1);
        lcd.print("cancelled once  ");
        delay(2000);
        lcd.clear();
      }
      else if (manualCancelFeed1 == 0)
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        //         0123456789012345 - LCD screen character counter
        lcd.print("Upcoming Feed #1");
        lcd.setCursor(0, 1);
        lcd.print("canceling undone");
        delay(2000);
        lcd.clear();
      }
      break;
  }

  // check manual cancel Feed2 button
  switch (buttonCancel2.wasPressed())
  {
    case 1:
      // invert variable value (true to false and vise versa)
      manualCancelFeed2 = !manualCancelFeed2;
      //turn on lcd backlight manually
      lcd_backlight_ON();
      // message when Cancel1 button is pressed
      if (manualCancelFeed2 == 1)
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        //         0123456789012345 - LCD screen character counter
        lcd.print("Upcoming Feed #2");
        lcd.setCursor(0, 1);
        lcd.print("cancelled once  ");
        delay(2000);
        lcd.clear();
      }
      else if (manualCancelFeed2 == 0)
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        //         0123456789012345 - LCD screen character counter
        lcd.print("Upcoming Feed #2");
        lcd.setCursor(0, 1);
        lcd.print("canceling undone");
        delay(2000);
        lcd.clear();
      }
      break;
  }

  // check manual Feed button
  switch (buttonManual.wasPressed())
  {
    case 1:
      manualFeed = true;
      //turn on lcd backlight manually
      lcd_backlight_ON();
      break;
  }

  // check MENU/SELECT button
  switch (buttonSelect.wasPressed())
  {
    case 1:
      userInput = btnSELECT;
      //turn on lcd backlight manually
      lcd_backlight_ON();
      transition(userInput);
      break;
  }
  // check UP button
  switch (buttonUp.wasPressed())
  {
    case 1:
      userInput = btnUP;
      transition(userInput);
      //turn on lcd backlight manually
      lcd_backlight_ON();
      break;
  }
  // check long press UP button
  switch (buttonUp.wasReleased())
  {
    case 1:
      long_press_button = false;
      rpt = REPEAT_FIRST;
      break;
  }
  switch (buttonUp.pressedFor(rpt))
  {
    case 1:
      // increment the long press interval
      rpt += REPEAT_INCR;
      long_press_button = true;
      userInput = btnUP;
      transition(userInput);
      break;
  }
  // check  DOWN button
  switch (buttonDown.wasPressed())
  {
    case 1:
      userInput = btnDOWN;
      transition(userInput);
      //turn on lcd backlight manually
      lcd_backlight_ON();
      break;
  }
  // check long press DOWN button
  switch (buttonDown.wasReleased())
  {
    case 1:
      long_press_button = false;
      rpt = REPEAT_FIRST;
      break;
  }
  switch (buttonDown.pressedFor(rpt))
  {
    case 1:
      // increment the long press interval
      rpt += REPEAT_INCR;
      long_press_button = true;
      userInput = btnDOWN;
      transition(userInput);
      break;
  }
  // check btnBACK button
  switch (buttonBack.wasPressed())
  {
    case 1:
      userInput = btnBACK;
      transition(userInput);
      //turn on lcd backlight manually
      lcd_backlight_ON();
      break;
  }

}


//******************************************************************************
// Check for state transition trigger

void transition(int trigger)
{
  switch (state)
  {
    //---------------------------------------
    case MAIN:

      // set time-out timr
      timeoutValue = millis();

      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDTIME1;
      }
      else if (trigger == btnBACK)
      {
        //lcd.clear();
        //state = ALARM1_AND_2_TIME;
      }
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDTIME1:

      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
      if (trigger == btnUP)
      {
        //no action, this is the first menu
      }
      else if (trigger == btnDOWN)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDTIME2;
      }
      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = EDIT_FEED_TIME1_HOUR;
      }
      if (trigger == btnBACK)
      {
        lcd.clear();
        state = MAIN;
      }
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDTIME2:

      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
      if (trigger == btnUP)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDTIME1;
      }
      else if (trigger == btnDOWN)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDAMOUNT;
      }
      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = EDIT_FEED_TIME2_HOUR;
      }
      if (trigger == btnBACK)
      {
        lcd.clear();
        state = MAIN;
      }
      break;
    //---------------------------------------
    case MENU_EDIT_FEEDAMOUNT:

      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
      if (trigger == btnUP)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDTIME2;
      }
      else if (trigger == btnDOWN)
      {
        lcd.clear();
        state = MENU_EDIT_TIME;
      }
      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = EDIT_FEED_AMOUNT1;
      }
      if (trigger == btnBACK)
      {
        lcd.clear();
        state = MAIN;
      }
      break;
    //---------------------------------------
    case MENU_EDIT_TIME:

      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
      if (trigger == btnUP)
      {
        lcd.clear();
        state = MENU_EDIT_FEEDTIME2;
      }
      if (trigger == btnDOWN)
      {
        lcd.clear();
        state = MENU_EDIT_DATE;
      }
      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = EDIT_HOUR;
      }
      if (trigger == btnBACK)
      {
        lcd.clear();
        state = MAIN;
      }
      break;
    //---------------------------------------
    case MENU_EDIT_DATE:

      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
      if (trigger == btnUP)
      {
        lcd.clear();
        state = MENU_EDIT_TIME;
      }
      else if (trigger == btnDOWN)
      {
        //no action, end of menu items!
      }
      if (trigger == btnSELECT)
      {
        lcd.clear();
        state = EDIT_DAY;
      }
      if (trigger == btnBACK)
      {
        lcd.clear();
        state = MAIN;
      }
      break;

    //---------------------------------------
    case EDIT_FEED_TIME1_HOUR:
      // set time-out timer
      timeoutValue = millis();
      // check for time-out 'button' trigger
      if (trigger == trigTIMEOUT)
      {
        lcd.clear();
        state = MAIN;
      }

      // Now check for button triggers
...

This file has been truncated, please download it to see its full contents.

Credits

Erik de Ruiter
7 projects • 133 followers
No electronics education but enjoying my new found hobby. Never thought it would be possible to make things myself but here we are...
Contact

Comments

Please log in or sign up to comment.