Hi All
I am working on an old project to make it more advanced (While in Lockdown here in NZ). It is an automatic chicken door that opens when it is light and closes 2 hours after the low light setting (to allow the chickens time to get in). Currently it has mechanical switches to set to manual and drive the door up with a DPDT relay. I want to do this via programming and learn more about subroutines as I have never used them before.
So far I have just added each component to the design at a time (first the LCD and buttons, then the latching relay to switch the motor direction), then tested the program then move on, hence there are a lot of unused pins and int's that are commented out. I am stuck trying to call a subroutine for a while loop the sets a max run time for the motor.
My problem is that I want the motor that drives the door to only run for 30 seconds (currently programmed a 3 secs for testing) the door will have limit switches so the max run time is a backup safety feature if the door gets jammed to prevent the motor burning out.
When I run the ManMode() subroutine and press a button which starts a while loop, the while loop then sets the time that is passed to the motor run subroutine. However this seems to pause the while loop for 3 seconds before then activating the latching the relay. It also doesn't cut the relay after 3 seconds, it just stays on. I assume the while is running over and over and I haven't got some form of break in the correct place. I thought of changing the void ManMode() to an int ManMode() and then passing a 1 or 0 back to whatever calls it but I don't know if that would work either.
I have tried several different ways but noting quite works.
I am looking for some examples to get me over this learning hurdle, anything would be appreciated
How do I
"While button is pressed"
- Activate latching relay coil to drive motor forward or backwards (got this bit going fine)
- Set a time the the motor has started from the time the button was pressed
- Only allow motor relay to run for 30 secs before switching off but continuing original while loop
- Print to LCD ERROR if 30 secs reached (I can probably work this out myself)
And lastly be able to call the Motorrun() subroutine from other parts of the sketch as it will be used in auto mode as well when the door is signaled to close or open.
Cheers
Al
#include <Wire.h> // Include Wire library (required for I2C devices)
#include <LiquidCrystal_I2C.h> // Include LiquidCrystal_I2C library
//Pins
//int LDRsensor = // LDR sensor used in auto mode
int Relayup = 5; // latching relay for coil 1
int Relaydn = 6; // latching relay for coil 2
//int Reedup = // switch to detect door has reached full heigh
//int Reeddn = // switch to detect door fully lowered
int Motorrelay = 7; // motor relay set to 30 seconds to prevent motor burning out in case of jam
//int RedLed = // Indicator light door up
//int GreenLed = // Indicator light door down
//int BlueLed = // Indicator light door in countdown process
int AutoManButton = 2; // button to set auto and manual
int Buttonup = 3; // button to drive door up in manual mode
int Buttondn = 4; // button to drive door down in manual mode
//Varibales
//int sunset = 400; // Low light threshold to close door
//int sunrise = 520; // upper light threshold to open door
//unsigned long Closedelay = 10000; // interval added to current time to close the door
//unsigned long sunsettime; // sets a varible to hold the time the light reached low threshold
//unsigned long doorclose; // sets a varible to hold the time to close the door after low light threshold
//int Doorposition; // Stores the current door position 0 open 1 closed
//int Lightvalue; // Sets the varible to hold the LDR level
int Mode = 0; // Set if auto or manual mode 0 is manual and 1 is auto
int ModeDisp; //Display the Mode as Text
int AutoManualMode = 0; // stores the mode - double up of mode int and possibly can be removed
unsigned long Motorstart; // sets the time the motor started used for max run
unsigned long Motorrunmax = 3000; // defines how long the motor can run
LiquidCrystal_I2C lcd(0x27, 16, 2); // Configure LiquidCrystal_I2C library with 0x27 address, 16 columns and 2 rows
void setup() {
Serial.begin(9600);
pinMode(Relayup, OUTPUT); // pin for latching rely up
pinMode(Relaydn, OUTPUT); // pin for latching relay down
// pinMode(Reedup, INPUT); // pin to detect when door has reached up
// pinMode(Reeddn, INPUT); // pin to detect when door has reached bottom
pinMode(Motorrelay, OUTPUT); // pin to isolate motor
// pinMode(RedLed, OUTPUT); // LED red output
// pinMode(GreenLed, OUTPUT); // LED green output
// pinMode(BlueLed, OUTPUT); // LED Blue output
pinMode(AutoManButton, INPUT_PULLUP); // Button to switch between auto and Manual
pinMode(Buttonup, INPUT_PULLUP); // Button to drive door up in manual
pinMode(Buttondn, INPUT_PULLUP); // Button to drive door down in manual
lcd.init(); // Initialize I2C LCD module
lcd.backlight(); // Turn backlight ON - need to add time out on backlight
}
int Setmode() // subroutine to set a global int to auto 1 or manual 0 via buttom press
{
int buttonpress = digitalRead(AutoManButton); // read button
delay(500); // pause so button only read once - look at other options to only read button a single time
if (buttonpress == LOW) { // if button pressed
if (AutoManualMode == 0) { // if in manual mode
AutoManualMode = 1; //switch to auto mode
}
else
{
AutoManualMode = 0; // switch to manual
}
}
return AutoManualMode; // return the result to Setmode
}
void loop() { // main loop
Mode = Setmode(); // set the mode - this int is a double up maybe consolidate
if (Mode == 1) { // if mode is auto
lcd.setCursor (0, 0);
lcd.print ("Auto ");
// AutoMode(); // run subroutine for automatic mode
}
if (Mode == 0) {
lcd.setCursor (0, 0);
lcd.print ("Manual");
ManMode(); // run subroutine for manual mode
}
}
void ManMode()
{
digitalWrite(Relayup, LOW); // default relay low so no power to relay coil
digitalWrite(Relaydn, LOW); // defealt relay low so no power to relay coil
digitalWrite (Motorrelay, LOW); // default motor relay to low - motor off
while (digitalRead (Buttonup) == LOW) { // while button up is pressed // need to add && digitalRead upswitch == LOW
Motorstart = millis(); // set motor start time - is this being constantly reset during while?
Motorrun(Motorstart); // subroutine to run motor for max 30 secs
digitalWrite (Relayup, HIGH); // latch coil on relay to switch motor to forward direction
lcd.setCursor (0, 1);
lcd.print ("Door Going UP"); // print to LCD door going up
}
while (digitalRead (Buttondn) == LOW) { //&& digitalRead upswitch == LOW
Motorstart = millis();
Motorrun(Motorstart);
digitalWrite (Relaydn, HIGH); // set latching coil to reverse motor contacts
lcd.setCursor (0, 1);
lcd.print ("Door Going DN");
}
if (digitalRead (Buttonup) == HIGH || digitalRead (Buttondn) == HIGH) { // if both buttons are open
lcd.setCursor (0, 1);
lcd.print (" "); // over type to clear LCD
}
}
void Motorrun(int Motorstart) // subroutine to switch relay to motor for 30 seconds, recieves start time used in manual and auto mode
{
//int Motorstart = millis();
int Motorruntime = Motorstart + Motorrunmax; // calculate max run time
digitalWrite (Motorrelay, LOW); // set default to low
while (millis() <= Motorruntime) { // while current time is less then motorruntime // need to add in door swith condition here also
digitalWrite (Motorrelay, HIGH); // turn on relay
if (millis() > Motorruntime) { // if current time is reached add in print LCD error
break; // break out of while loop motor relay should be low as defalut
}
}
}