Chicken Coop Controller

So I'm trying have a button override which will open or close the coop door based on bottom and top Reed switch values and implement a delay of about a 1/2 hour on docoopdoor() function. Any help would be appreciated.
My problem definitely lies in button override function in my functions. I have everthing working with no errors. Coop door opens and closes as expected based on photoresistor reading. Temp sensors work. The only thing I'm having trouble with is implementing this button override function to open and
close the coop door on demand when needed. I would like to be able to push it and either open it or close it based on the coop door status. Any help would be appreciated.
Thanks,
Chris D.
P.S. I posted about have the code the rest is in the attachment. Should be the entire sketch.

// ************************************** functions **************************************

// coop door button override                                     // So I'm trying have a button override which will open or close the coop door based on bottom and top 
void buttonOverride() {                                          // Reed switch values and implement a delay of about a 1/2 hour on docoopdoor() function. Any help would be appreciated.
  Serial.print(" Button State: ");
  Serial.println(buttonswitchval);
  buttonswitchval = digitalRead(buttonswitch);
  delay(10);
  buttonswitchval2 = digitalRead(buttonswitch);
  delay(10);
  if (buttonswitchval == buttonswitchval2) {
    if (buttonswitchval != buttonswitchstate) {
      if (buttonswitchval == LOW) {
        if (buttonmode == 0) {
          buttonmode = 1;
        } //else {
           // if
          // debounceTopReedSwitch();                    // read and debounce the switches
          // debounceBottomReedSwitch();
            if (buttonmode == 1 & topSwitchPinVal == 0 & bottomSwitchPinVal == 1) { // door closed
              openCoopDoorMotorB();              // Open the door
              delay(300000);
               doCoopDoor();
             }
              else {
              //debounceTopReedSwitch();
              //debounceBottomReedSwitch();
              if (buttonmode == 1 & topSwitchPinVal == 1 & bottomSwitchPinVal == 0) {
              closeCoopDoorMotorB();
              delay(300000);
               doCoopDoor();
        }
              }
      }
      buttonswitchstate = buttonswitchval;              // Save button switch state in buttonswitchval
    }
  }
}
          
          

// coop hvac
  
  
  
// operate the coop door

// photocel to read levels of exterior light

 void readPhotoCell() { // function to be called repeatedly - per cooptimer set in setup
  
    photocellReading = analogRead(photocellPin);
      Serial.print(" Photocel Analog Reading = ");
      Serial.println(photocellReading);


//  set photocel threshholds
        if (photocellReading >= 0 && photocellReading <= 3) {
        photocellReadingLevel = '1';
        Serial.print(" Photocel Reading Level:");
        Serial.println(" - Dark");
      }  else if (photocellReading  >= 4 && photocellReading <= 120){
         photocellReadingLevel = '2';
         Serial.print(" Photocel Reading Level:");
         Serial.println(" - Twilight");
      }  else if (photocellReading  >= 125 ) {
         photocellReadingLevel = '3';
         Serial.print(" Photocel Reading Level:");
         Serial.println(" - Light");
       }
     }

//debounce bottom reed switch

  void debounceBottomReedSwitch() { 

    //debounce bottom reed switch
    bottomSwitchPinVal = digitalRead(bottomSwitchPin);        // read input value and store it in val
    delay(10);
    bottomSwitchPinVal2 = digitalRead(bottomSwitchPin);       // read input value again to check or bounce
    
      if (bottomSwitchPinVal == bottomSwitchPinVal2) {        // make sure we got 2 consistant readings!
        if (bottomSwitchPinVal != bottomSwitchState) {        // the switch state has changed!
          bottomSwitchState = bottomSwitchPinVal;
        }
        Serial.print (" Bottom Switch Value: ");             // display "Bottom Switch Value:" 
        Serial.println(digitalRead(bottomSwitchPin));        // display current value of bottom switch;
      }
    }


 // debounce top reed switch
  void debounceTopReedSwitch() {

    topSwitchPinVal = digitalRead(topSwitchPin);               // read input value and store it in val
    delay(10);
    topSwitchPinVal2 = digitalRead(topSwitchPin);              // read input value again to check or bounce
    
      if (topSwitchPinVal == topSwitchPinVal2) {               // make sure we got 2 consistant readings!
        if (topSwitchPinVal != topSwitchState) {               // the button state has changed!
          topSwitchState = topSwitchPinVal;
        }
        Serial.print (" Top Switch Value: ");                // display "Bottom Switch Value:" 
        Serial.println(digitalRead(topSwitchPin));           // display current value of bottom switch;
      }
    }


// stop the coop door motor
  void stopCoopDoorMotorB(){
    digitalWrite (directionCloseCoopDoorMotorB, LOW);        // turn off motor close direction
    digitalWrite (directionOpenCoopDoorMotorB, LOW);         // turn on motor open direction
    analogWrite (enableCoopDoorMotorB, 0);                   // enable motor, 0 speed
  }

// close the coop door motor (motor dir close = clockwise) 
  void closeCoopDoorMotorB() {  
    delay(900);  // New delay  to keep motor running for locks
    digitalWrite (directionCloseCoopDoorMotorB, HIGH);       // turn on motor close direction
    digitalWrite (directionOpenCoopDoorMotorB, LOW);         // turn off motor open direction
    analogWrite (enableCoopDoorMotorB, 255);                 // enable motor, full speed 
      if (bottomSwitchPinVal == 0) {                         // if bottom reed switch circuit is closed
        stopCoopDoorMotorB();
        Serial.print(" Coop Door Closed - no danger");
      }
    }

  // open the coop door (motor dir open = counter-clockwise)
  void openCoopDoorMotorB() { 
    digitalWrite(directionCloseCoopDoorMotorB, LOW);    // turn off motor close direction
    digitalWrite(directionOpenCoopDoorMotorB, HIGH);    // turn on motor open direction
      analogWrite(enableCoopDoorMotorB, 255);           // enable motor, full speed
      if (topSwitchPinVal == 0) {                       // if top reed switch circuit is closed
          stopCoopDoorMotorB();
          Serial.print(" Coop Door open - danger!");
      }
    }
    

  void doCoopDoor(){

      
    if (photocellReadingLevel  == '1') {              // if it's dark
        if (photocellReadingLevel != '2') {             // if it's not twilight
          if (photocellReadingLevel != '3') {           // if it's not light 
            debounceTopReedSwitch();                    // read and debounce the switches
            debounceBottomReedSwitch();
            closeCoopDoorMotorB();                      // close the door
          }
        }
      } 
       if (photocellReadingLevel  == '3') {             // if it's light
        if (photocellReadingLevel != '2') {             // if it's not twilight
          if (photocellReadingLevel != '1') {           // if it's not dark 
            debounceTopReedSwitch();                    // read and debounce the switches
            debounceBottomReedSwitch();
            openCoopDoorMotorB();                       // Open the door
          }
        }
      }
    }

 // chickenCamServo
  void doChickenCamServo() {
    for (chickenCamServoPos = 0; chickenCamServoPos < 75; chickenCamServoPos += 1) {   // turns servo 0 to 75 degrees; 1 degree at a time
        chickenCamServo.write(chickenCamServoPos);                                    // read chickenCamServoPosition variable chickenCamServoPos
    }
    
    for(chickenCamServoPos = 75; chickenCamServoPos>=1; chickenCamServoPos-= 1){    // return from 75 degrees to 0 degrees; 1 degree at a time
        chickenCamServo.write(chickenCamServoPos);                                    // read chickenCamServoPosition variable chickenCamServoPos
      }
    }
 
  
//  lcd
 
// ************************************** the loop **************************************
  
  void loop() {
   
   coopTimer.run(); //    ( timers for doCoopHVAC & readPhotoCell)
 //  delay(1000);
   doCoopDoor();
   doChickenCamServo();
   doLcdMsg();
   buttonOverride();

  
}

Moderator edit: tags corrected

CoopController_mixed2.ino (20.3 KB)

Please re format the post so that only the code is in the separate window and it can be read without horizontal scrolling.

Weedpharma

cduryee:
The only thing I'm having trouble with is implementing this button override function to open and
close the coop door on demand when needed. I would like to be able to push it and either open it or close it based on the coop door status. Any help would be appreciated.

Perhaps you can describe the programming logic that you want.

If you have some automatic door open/close logic and you also want a manual open/close logic you must synchronize both.

Such like you have

  • a flip switch that switches: manual mode / automatic mode
  • a pushbutton switch that has no effect in automatic mode and toggles the door open/shut in manual mode

Or you might have:

  • just a single pushbutton
  • when pushbutton is pressed: program enters manual mode, door is toggled and the automatic mode is deactivated for x minutes, then reactivates after timeout

But you cannot have automatic mode (open/close controlled by light sensor) and manual mode (open/close controlled by pushbutton) at the same time.

First thing is to establish a programming logic that can work.

Kudos Jurs,
The programming logic I'm looking for is:

  • just a single pushbutton
  • when pushbutton is pressed: program enters manual mode, door is toggled and the automatic mode is deactivated for x minutes, then reactivates after timeout

cduryee:
The programming logic I'm looking for is:

  • just a single pushbutton
  • when pushbutton is pressed: program enters manual mode, door is toggled and the automatic mode is deactivated for x minutes, then reactivates after timeout

OK, then you want something called Finite State Machine (FSM) which can have four states:
#1. manual mode for x minutes, door is open
#2. manual mode for x minutes, door is closed
#3. automatic mode, door is open
#4. automatic mode, door is closed

The processing logic of your program must provide the transit between those four states in these cases:
a) if current state is #1 or #2 and and button pressed ==>
if #1 ==> new state is #2
if #2 ==> new state is #1
b) else if current state is #1 or #2 and x minutes have passed since the button was pressed ==>
if #1 ==> new state is #3
if #2 ==> new state is #4
c) else if current state is #3 or #4 and button pressed
if #3 ==> new state is #2
if #4 ==> new state is #1
d) else if current state is #3 or #4
if #3 and light sensor tells dark ==> new state is #4
if #4 and light sensor tells bright ==> new state is #3

The output logic then must act on the change: After a state change happened with a change from "door closed" to "door open" => open the door. And after a state change happened with a change from "door open" to door closed => close the door.

So now it's clear that you want a Finite State Machine, and the transit table with the conditions and changes is clear, you can start coding it.

Can you?

Well the honest answer is probably no. But I'll give it a hell of a whirl. I was trying to adopt and use examples on state change on a adafruit tutorial. I been able to see my button presses in serial monitor
But to no avail I'm currently stuck and asking for help. Thanks for the response Jurs. :-[

FSM is a powerful way of controlling things and thus worth learning, but you need not go all the way there for this.

I'd model it with two variables - desired door state and actual door state. I'd have a routine that is called from loop that acts if those states are different.

Then, let the button toggle desired state - don't forget to debounce it - a 20ms delay should accomplish that. Using millis, note the time that the button was pressed.

When one of the timer routines wants to change desired state, only allow it if thirty minutes have passed since a button push.

Hello I've started this thread and still am looking for some help. Can you please help find a door solution for my coop? Here's the link to the thread ----> How to open and close multiple doors at different times - Project Guidance - Arduino Forum

Thank you

Here is the new thread posted as a link for click access:

http://forum.arduino.cc/index.php?topic=311018.0

Hello, im following this thread. Did you find a way to do the manually override?

if (photocellReadingLevel  == '1') {              // if it's dark
        if (photocellReadingLevel != '2') {             // if it's not twilight
          if (photocellReadingLevel != '3') {           // if it's not light

This bit of code seems unnecessarily confusing and redundant. If photocellReadingLevel == '1', how can it be '2' or '3'?

You've already collected the value of a variable called buttonmode although I can't understand from your code if it is HIGH or Low when the button is depressed. If it is active LOW I think you could use it in your first 'if' control i.e.

if (photocellReadingLevel  == '1' && buttonmode){
  • Scotty