Rotating door automation

Just a small update. I've ordered a starter kit that includes a step motor, small servo and Light dependant resistors.

The kit also has an LCD and some buttons so the time can be changed as you suggested. I know I'll need a heavier servo/motor but my thinking is if I can get it working in principle first I can drop a bigger one into the circuit later.

There's also an IR remote, being able to operate the door using that would be quite handy. I could even get really fancy and have a buzzer go off 10 minutes before the door closes to tell the chickens it's bedtime. They're quite easy to train to that sort of thing. :smiley:

My UNO and accessories have arrived.

For testing I was wondering if I could connect a LDR to the prototype shield and have an LCD display its resistance to calibrate at what light intensity to operate the servo? If that's possible could anyone point me in the direction of a tutorial to output the reading from an LDR to an LCD?

I think I want to sketch to run along the lines of

Detect "night" or "day" every 5 minutes. If its day for 3 consecutive checks, open the door. If its night for 3 consequtive checks, close the door.

Then a button to toggle between Open, Close and Automatic.

I've never done any electronics before so I appreciate any help and advice.

I don't know of any tutes and probably I doubt you'll find one that does both, but there will be LDR tutes and LCD tutes that you can put together.

Start looking in the Arduino playground.

http://arduino.cc/playground/


Rob

Got the basic code started and tested.

Can anyone suggest an easy way to have the servo move more slowly?

#include <Servo.h> 

const int THRESHOLD = 680;   // an arbitrary threshold level that's in the range of the analog input
Servo myservo;  // create servo object to control a servo 
 
int LDRpin = 0;  // analog pin used to connect the potentiometer
int LDRval;    // variable to read the value from the analog pin 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
    // initialize serial communications:
  Serial.begin(9600);
} 
 
void loop() {
  // read the value of the LDR:
  int analogValue = analogRead(LDRpin);

  // if the analog value is high enough, turn on the Servo:
  if (analogValue > THRESHOLD) {
    myservo.write(180);
  } 
  else {
    myservo.write(0); //Reset the Servo if the value is too low
  }

  // print the analog value:
  Serial.println(analogValue);
  delay(150);        // delay in between reads for stability
}

One easy way to move the servo more slowly is a for loop that moves it a degree at a time, with whatever size delay you need on each iteration.

I have finished (I think) the code and hardware for this and I'm now at the stage where I want a permanent power solution.

Ideally I want to take a hard wired feed from the mains. Are there any recommendations for the easiest way to power an UNO board and servo in this way?

The Arduino can run on 5V at the +5V pin or on 7-12V on the Vin pin. The servo is probably designed to run at 6V so neither choice is ideal. Perhaps you could use a hefty 7+V supply and put a few big silicon diodes in the line going to power the servos. A silicon diode has a voltage drop of 0.6 to 0.7V so add drops to bring the voltage down to about 6V.

For simple servo setups, a 7805 regulating chip can have the output voltage increased using a small diode on the chip ground pin like below. There is a noticable servo performance improvement between 5v and 5.7v

I think I understood that.

I apologise if this is a stupid question but could I supply 12v to the arduino barrel connector and take the servo power from the VIN pin through a 7805 and diode as you suggested?

In fact considering the rating of the servo is 4.8v - 7.2v would a 7806 and no diode be better?

I just want to keep things are straight forward as possible and a 12v power brick should be easy to find.

This project would be well suited for a battery/solar panel application perhaps as a phase 2 of the project. Cheers, ChickenMechanic :wink:

could I supply 12v to the arduino barrel connector and take the servo power from the VIN pin through a 7805 and diode as you suggested?

Yep.

would a 7806 and no diode be better?

Same horse, different colour.

The diode trick is good if you have a 7805 lying around, you could use two diodes for that matter. But if you have to buy a regulator anyway the 7806 is fewer components.


Rob

They were so cheap I took a chance and went ahead and bought them. The proto board is all soldered up and working fine.

The only change I might make is to use a potentiometer to adjust the threshold value.

This is a great project. Please post a video when finished!

Out of curiosity, are there any concerns as far as the chickens being in the way of the door when it is being closed? If so, do you have any plans for handling that?

Thanks.

I Haven't got any sensors to detect obstruction if that's what you mean. I have added code to make the sweep of the servo adjustable so the door closes slowly. I'm hoping that should be enough.

At the minute I have the hardware mostly finished. The main thing I need is a replacement servo arm as I managed to strip the teeth from the plastic one that the servo came with. A metal one is ordered. The power baluns are done and the servo mounting enclosure.

What I would like to do is fine tune the starting and finishing position of the servo.

Is it possible to use a potentiometer to adjust a value BUT have the adjusted value saved even when the pot is removed?

ChickenMechanic:
Is it possible to use a potentiometer to adjust a value BUT have the adjusted value saved even when the pot is removed?

That is certainly doable. You could have something as simple as a button (could even use one already on the project) that, when held down for a while, begins a subroutine that lets you use the pot to set the starting position, press button again to save value to EEPROM, set finish position with pot, press button again to save to EEPROM.

You can also have the subroutine change the appropriate pins to an input instead of an output, that way you wouldn't have a pin set as an input all the time and not really doing anything, although I doubt it would have any unintended results anyway.

Your code would simply load the start and finish values from the EEPROM on power up. Note the first time the device powers up the contents of the EEPROM could be random values, so be mindful of that.

I suppose another way to do it would be 2 buttons, one to set the open value, one to set the closed value.

Press and hold to enter the subroutine ( maybe with an LED to show it was active) and press agin to save the setting.

What would the code for something like that look like?

Sorry, I've been off the forums for a few days.

Let's see, two buttons, a potentiometer, and saving the settings...

You can make two local Long variables to store when a button is first pressed. The button would wait a certain period of time before entering the subroutine (which wouldn't actually need to be a function). Some boolean values could be used to control when settings are saved and when settings should be read from the stored values...

I've attached some code that verifies OK, but I haven't actually tested whatsoever. I think it would run pretty well though, although it would be great if others would give it a glance. The code doesn't have to block whatsoever waiting on the buttons to be held down long enough.

The pin value constants are all set to 0, so that would need to be changed. The EEPROM locations would also need to be set according to your needs (not sure if you're storing anything else). Also there is no software debounce for the buttons, hardware debounce would be preferable or adding a "readPin(int pin)" type of method that could handle a software debounce.

The code should allow for a button to be held for five seconds, the value of the potentiometer adjusting the value for the position, and then having that value saved to EEPROM when the button is pressed again. An LED will glow indicating that a position is being adjusted, and then turn off when the position is stored.

I've tried to comment a bunch to explain things, but feel free to correct or ask about it!

EDIT: It was really annoying downloading the attachment so I included the code in the post

#include <EEPROM.h>

//These variables store the positions for open and closed
int positionOpen;
int positionClosed;
//These variables store the locations in EEPROM where the saved positions are stored
const int positionOpenLocation = 0;
const int positionClosedLocation = 0;
//These constants just store the pin values
const int setOpenValuePin = 0;
const int setClosedValuePin = 0;
const int potPin = 0;
const int LEDPin = 0;
//These values are used to store a button press and to check and see if it's still pressed for the required time
long buttonOpenTime = 0;
long buttonClosedTime = 0;
//These booleans keep track of when a button has been pressed, time stored, and we haven't registerred a low yet
boolean buttonOpenPressed = false;
boolean buttonClosedPressed = false;
//These booleans control what parts of the loop execute, ensuring we're not setting both at the same time, etc
boolean settingOpen = false;
boolean settingClosed = false;
//How long you want to have to hold the buttons down, in ms
const long buttonHoldTime = 5000;

void setup(){

pinMode(LEDPin, OUTPUT);  
  
//Read the stored values from memory, allows values to persist after power failure or reset
//You only want these next two lines after the values have been saved at least once
//or else your sevo might go to some random location
positionOpen = EEPROM.read(positionOpenLocation);
positionClosed = EEPROM.read(positionClosedLocation);
}

void loop(){

//If you're not currently setting the closed value, and the setOpen value is at HIGH
if(!settingClosed && digitalRead(setOpenValuePin) == HIGH){
  //if this is the first read of a high set the buttonOpenPressed to true and record the time
  if(!buttonOpenPressed){
    buttonOpenPressed = true;
    buttonOpenTime = millis();
    //if the button's been pressed and you've been held down longer than the buttonHoldTime, set settingOpen to true
  }else if(buttonOpenPressed && millis() - buttonOpenTime > buttonHoldTime){
    settingOpen = true;
    buttonOpenPressed = false;
    digitalWrite(LEDPin, HIGH);
  }
}

//if you've previously registered a press, but you now read low
if(buttonOpenPressed && digitalRead(setOpenValuePin) == LOW) buttonOpenPressed = false;

//if you're setting the open value and you've pressed the button to save it
if(settingOpen && digitalRead(setOpenValuePin == HIGH)){
  digitalWrite(LEDPin, LOW);
  EEPROM.write(positionOpenLocation, positionOpen);
  settingOpen = false;
}

//if you're setting the open position
if(settingOpen){
  //Read the potentiometer position and store it, dividing by 4 because of the EEPROM's storage size
  positionOpen = analogRead(potPin) / 4;
}


if(!settingOpen && digitalRead(setClosedValuePin) == HIGH){
  //if this is the first read of a high set the buttonClosedPressed to true and record the time
  if(!buttonClosedPressed){
    buttonClosedPressed = true;
    buttonClosedTime = millis();
    //if the button's been pressed and you've been held down longer than the buttonHoldTime, set settingClosed to true
  }else if(buttonClosedPressed && millis() - buttonClosedTime > buttonHoldTime){
    settingClosed = true;
    buttonClosedPressed = false;
    digitalWrite(LEDPin, HIGH);
  }
}

//if you've previously registered a press, but you now read low
if(buttonClosedPressed && digitalRead(setClosedValuePin) == LOW) buttonClosedPressed = false;

//if you're setting the closed value and you've pressed the button to save it
if(settingClosed && digitalRead(setClosedValuePin == HIGH)){
  digitalWrite(LEDPin, LOW);
  EEPROM.write(positionClosedLocation, positionClosed);
  settingClosed = false;
}

//if you're setting the closed position
if(settingClosed){
  //Read the potentiometer position and store it, dividing by 4 because of the EEPROM's storage size
  positionClosed = analogRead(potPin) / 4;
}

}

ChickenDoor.txt (3.72 KB)

No I'm not storing anything else... I think. I'm not at home at the minute but when I am I'll post the code I'm using. It's pretty basic compared to what's possible I'm sure but I've been learning as I go along. :slight_smile:

Thanks for taking the trouble to put that bit of code together. I already have a load of momentary buttons and a couple of pots so if we can get it working that makes it easier for anyone who wants to do something like this themselves.

Alright it's a bit niche but you never know. :wink:

No trouble at all, I love cool and practical projects like this!

Although your particular use may be niche, I could certainly envision someone doing something similar with blinds in a house that could be raised and lowered at the appropriate times to help block the sun. Who knows, it's always amazing the ways people adapt each other's ideas for their own projects.