Now to the problem at hand, I have discovered that the closing time is too early as the chickens are still out. So ideally I want to delay the closing time by a half hour. The way I see it, could try and only delay closing time or delay closing and opening time, to ensure opening is still about the present time I would decrease the LDR setting.
Now over to you what is the best way of achieving this? I presume using the millis function?
or is there better way?
Present code below.
Thanks in advance
Tony
// Chicken Coop Code 16/08/2017
// darkthreshold 2 (Really dark)
// Define pins & variables
const int EnMotorPin = 9; // enable motor - pin 9 PWM
const int CloseDoorPin = 8; // direction close motor - pin 8
const int OpenDoorPin = 7; // direction open motor - pin 7
const int photocellPin = A0; // photocell connected to analog 0
int photocellVal; // analog reading of the photocel
bool daylight = true; // daylight status
int darkthreshold = 2;
int daythreshold = 175; // sets hysteresis limits to stop door jittering
int systemState = 0;
int SPEED = 220;
// Reed switches top and bottom of coop door
int bottomSwitchPin = 2;
int topSwitchPin = 4;
bool topSwitchState; // true if door is up
bool bottomSwitchState; // true if door is down
void setup() {
Serial.begin(9600);
pinMode(bottomSwitchPin, INPUT);
pinMode(topSwitchPin, INPUT);
pinMode(EnMotorPin, OUTPUT);
pinMode(CloseDoorPin, OUTPUT);
pinMode(OpenDoorPin, OUTPUT);
}
void loop() {
systemState = 0;
photocellVal = analogRead(photocellPin); // read inputs
if (photocellVal > daythreshold)
{
daylight = true;
}
if (photocellVal < darkthreshold)
{
daylight = false;
}
topSwitchState = digitalRead(topSwitchPin);
bottomSwitchState = digitalRead(bottomSwitchPin);
// read system status
if (daylight == true && topSwitchState == true)
{
systemState = 0; // motor stop
}
if (daylight == true && topSwitchState == false)
{
systemState = 1; // drive door up
}
if (daylight == false && bottomSwitchState == true)
{
systemState = 0; // motor stop
}
if (daylight == false && bottomSwitchState == false)
{
systemState = 2; // drive door down
}
DispVals();
switch (systemState) {
case 0: // motor stop
digitalWrite(CloseDoorPin, LOW);
digitalWrite(OpenDoorPin, LOW);
analogWrite(EnMotorPin, 0);
break;
case 1: //drive door up
digitalWrite(CloseDoorPin, LOW);
digitalWrite(OpenDoorPin, HIGH);
analogWrite(EnMotorPin, SPEED);
break;
case 2: // drive door down
digitalWrite(CloseDoorPin, HIGH);
digitalWrite(OpenDoorPin, LOW);
analogWrite(EnMotorPin, SPEED);
break;
default:
digitalWrite(CloseDoorPin, LOW);
digitalWrite(OpenDoorPin, LOW);
analogWrite(EnMotorPin, 0);
break;
}
}
void DispVals()
{
Serial.print("topSW ");
Serial.print(topSwitchState);
Serial.print("\t");
Serial.print("botSW ");
Serial.print(bottomSwitchState);
Serial.print("\t");
Serial.print("PhotoVal ");
Serial.print(photocellVal);
Serial.print("\t");
Serial.print("daylight ");
Serial.print(daylight);
Serial.print("\t");
Serial.print("systemState ");
Serial.print(systemState);
Serial.print("\t");
if (systemState == 0)
{
Serial.println("\t door stopped");
}
if (systemState == 1)
{
Serial.println("\t door driving up");
}
if (systemState == 2)
{
Serial.println("\t door driving down");
}
}
You could set a flag when the LDR detects evening.
The code looks for this flag being set and the resets and starts the close timer ex: 30 minutes at which time the door is closed.
I don't know much about chickens but I do know roosters are up and about before what I would consider LDR distinguishable range from variances in moonlight.
I'd much sooner try counting chickens going in/out than try an LDR.
When the LDR code detects it is time to close the door, record millis() in a variable (type unsigned long).
When millis() - yourVariable >= 30601000ul you then close the door.
Could you not simply look at what the LDR reads when you do want it to close and just change your parameters? I'd've thought that'd be the most obvious answer. Just in case you've just copied someone's code in whole and were unaware of the parameters.
Change the trigger. Analogously- it's like setting an alarm clock at 5:00p but wanting it to wait until 5:30p to ring. Just set the alarm at 5:30p.
If light/dark thresholds have to be set that low, then the LDR pull up/down resistor has the wrong value.
Or... the LDR is already stuffed. There have been reports that they don't last very long outside (months).
People have succesfully replaced the LDR with a solar cell from a small garden light.
Better results, and they should last longer.
Connect between pin and ground, no pull up/down resistor.
It might be wise to add a (1-10k) resistor between solar+ and analogue pin, and a 100n cap from pin to ground.
Experiment with a short sketch that only displays the analogue value on the serial monitor.
Leo..
If you have a problem with your darkness value being too low (an analogRead() threshold of 2 is not the best imho, I'd want to bring it up to 10 or 20), you could replace the resistor wired with the LDR (I assume you wired this as voltage divider) to a much higher value. It'll of course also push higher the "day" value.
A second way of preventing jitter is to implement a delay before another change can be made to the door - e.g. can't open within 30 mins after closing and the other way around. That would give you more flexibility in the open/close darkness values.
Did you use the exact code in post #13 or did you change anything in it?
Do some testing, change the following line, then cover the sensor to see what happens.
if(millis() - delayMillis < 30 * 60 * 1000ul)
For testing, change to this for 30 second delay.
if(millis() - delayMillis < 30 * 1000ul)
darkthreshold = 2 <-----<<<< this is very very low, try ~10
You could add some code that, once darkness is triggered, only allow the door open if the sensor > ~60 for a period, but first check with 30 seconds.