Reference Pages:
The next version is currently in development. It will use an Arduino and a Sparkfun Ardumotor to reduce the electronics build even further.
The picture below shows how the components will likely fit in the same enclosure as the enclosure used in the previous versions below.
However, one difference is that while this is the same enclosure, it is the version with a transparent lid, which should save the cost of drilling a hole for the chick coop door opener's photo-resistor light sensor.
Here's the Arduino code for this Ardumotor version. It's untested as yet. So if you find any bugs, let me know.
//**************************************************************** /* * Chicken Coop Door Controller * Includes auto chicken-feeder motor driver * Photoresistor on analog0 * Piezo Speaker on pin 13 * * By Lee Kimber * Based on 'Nightingale' by: * KHM 2008 / Lab3/ Martin Nawrath nawrath@khm.de * Kunsthochschule fuer Medien Koeln * Academy of Media Arts Cologne */ //**************************************************************** #include <avr/sleep.h> #include <avr/wdt.h> #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // sleep between runs int pause = 6000; int beeps = 250; int lightlevel = 830; int nint; int pinPiezoSpeaker=13; // make pin 13, was 10 volatile boolean f_wdt=1; // Lee adds // drive lines for the L298D motor driver //int pwm_a = 3; //PWM control for motor outputs 1 and 2 is on digital pin 3 //int pwm_b = 11; //PWM control for motor outputs 3 and 4 is on digital pin 11 //int dir_a = 12; //direction control for motor outputs 1 and 2 is on digital pin 12 //int dir_b = 13; //direction control for motor outputs 3 and 4 is on digital pin 13 int door_up=4; // becomes 5, was 11 int door_down=5; // becomes 4, was 12 // Set up chicken feeder driver int feeder1=7; // becomes 7, was 8 int feeder2=6; // becomes 6, was 9 void setup(){ delay(1000); { pinMode(pwm_a, OUTPUT); //Set control pins to be outputs pinMode(pwm_b, OUTPUT); pinMode(dir_a, OUTPUT); pinMode(dir_b, OUTPUT); analogWrite(pwm_a, 100); //set both motors to run at (100/255 = 39)% duty cycle (slow) analogWrite(pwm_b, 100); } Serial.begin(38400); // pinMode(pinLed,OUTPUT); pinMode(pinPiezoSpeaker,OUTPUT); // Lee adds pinMode(door_up,OUTPUT); pinMode(door_down,OUTPUT); pinMode(feeder1,OUTPUT); pinMode(feeder2,OUTPUT); delay(10000); Serial.println("Chicken coop door opener"); // CPU Sleep Modes // SM2 SM1 SM0 Sleep Mode // 0 0 0 Idle // 0 0 1 ADC Noise Reduction // 0 1 0 Power-down // 0 1 1 Power-save // 1 0 0 Reserved // 1 0 1 Reserved // 1 1 0 Standby(1) cbi( SMCR,SE ); // sleep enable, power down mode cbi( SMCR,SM0 ); // power down mode sbi( SMCR,SM1 ); // power down mode cbi( SMCR,SM2 ); // power down mode setup_watchdog(7); } byte del; int cnt; byte state=1; int light=0; // Lee adds int topswitch=2; // becomes 2, was 4 int bottomswitch=3; // becomes 3, was 5 int ts=0; int bs=0; //**************************************************************** //**************************************************************** //**************************************************************** void loop(){ { digitalWrite(dir_a, LOW); //Set motor direction, 1 low, 2 high digitalWrite(dir_b, LOW); //Set motor direction, 3 high, 4 low delay(1000); analogWrite(pwm_a, 255); //set both motors to run at 100% duty cycle (fast) analogWrite(pwm_b, 255) delay(1000); digitalWrite(dir_a, HIGH); //Reverse motor direction, 1 high, 2 low digitalWrite(dir_b, HIGH); //Reverse motor direction, 3 low, 4 high delay(1000); analogWrite(pwm_a, 100); //set both motors to run at (100/255 = 39)% duty cycle analogWrite(pwm_b, 100); delay(1000); // Set feed motor-driver line low to save power digitalWrite(feeder1,LOW); digitalWrite(feeder2,LOW); // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker, LOW); //digitalWrite(pinLed,LOW); if (f_wdt==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs f_wdt=0; // reset flag light=analogRead(0); // reading photoresistor // Lee adds ts=digitalRead(topswitch); // read the top reed switch bs=digitalRead(bottomswitch); // read the bottom reed switch Serial.print("light: " ); Serial.print(light ); Serial.print(" bs: "); Serial.print(bs); Serial.print(" ts: "); Serial.println(ts); // Lee add door-state reporting here if (ts == 1 && bs == 0) { Serial.println("Door is open"); } else if (ts == 0 && bs == 1) { Serial.println("Door is closed"); } else if (bs == 1 && ts == 1) { Serial.println("ALARM: Door state monitoring is faulty"); alarm(); } else { Serial.println("Door state is indeterminate (or possibly faulty)"); } switch (state){ case 0: // waiting for dawn if (light < lightlevel && ts == 0) { // light threshold high and door not open (ts open) state=1; Serial.println("Calling door-open function"); open(); // Door open, nothing to do for six hours delay(pause); } break; case 1: // waiting for dusk if (light > lightlevel && bs == 0) { // light threshold low and door not closed (bs open) state=0; //whistle(); beep(); Serial.println("Calling door-closer function"); close(); // Door closed, nothing to do for six hours delay(pause); } break; } nint++; // digitalWrite(pinLed,1); // let led blink Serial.print("Sleep " ); Serial.println(nint ); delay(2); // wait until the last serial character is send // digitalWrite(pinLed,0); // pinMode(pinLed,INPUT); // set all used ports to intput to save power pinMode(pinPiezoSpeaker,INPUT); // set all used port to intput to save power // Lee add: do as above with Lee's added pins pinMode(door_up,INPUT); pinMode(door_down,INPUT); pinMode(feeder1,INPUT); pinMode(feeder2,INPUT); system_sleep(); // pinMode(pinLed,OUTPUT); // set all ports into state before sleep pinMode(pinPiezoSpeaker,OUTPUT); // set all ports into state before sleep // Lee add: do as above with Lee's added pins pinMode(door_up,OUTPUT); pinMode(door_down,OUTPUT); pinMode(feeder1,OUTPUT); pinMode(feeder2,OUTPUT); } } //**************************************************************** // put some whistle sound on piezo void whistle() { for (int ii = 0; ii<= 20; ii++) { for (del=0; del <=254; del++) { digitalWrite(pinPiezoSpeaker,0); delayMicroseconds((ii*5)+(del * 2)); digitalWrite(pinPiezoSpeaker,1); delayMicroseconds((ii*5)+(del * 2)); } // PORTB ^= 32; // toggle pinLed } } //**************************************************************** // put some beep sound on buzzer void beep() { // Start the automatic chicken feeder motor Serial.println("Starting feed motor"); // Set feed motor-driver line high here digitalWrite(feeder1,HIGH); digitalWrite(feeder2,LOW); // Let the chickens know we're closing up // 1850 cycle-time / 1000 / 60 = 6.167 minutes warning Serial.println("Starting 200 beeps"); for (long i=0; i < beeps; i++) { Serial.println("Beep routine started"); digitalWrite(pinPiezoSpeaker, LOW); delay(1500); digitalWrite(pinPiezoSpeaker, HIGH); delay(300); } Serial.println("Stopping feed motor"); // Set feed motor-driver line low here digitalWrite(feeder1,LOW); digitalWrite(feeder2,LOW); // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker,LOW); // digitalWrite(pinLed,LOW); } //**************************************************************** // set system into the sleep state // system wakes up when watchdog is timed out void system_sleep() { cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here sleep_enable(); sleep_mode(); // System sleeps here sleep_disable(); // System continues execution here when watchdog timed out sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON } //**************************************************************** // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec void setup_watchdog(int ii) { byte bb; int ww; if (ii > 9 ) ii=9; bb=ii & 7; if (ii > 7) bb|= (1<<5); bb|= (1<<WDCE); ww=bb; Serial.println(ww); MCUSR &= ~(1<<WDRF); // start timed sequence WDTCSR |= (1<<WDCE) | (1<<WDE); // set new watchdog timeout value WDTCSR = bb; WDTCSR |= _BV(WDIE); } //**************************************************************** // Watchdog Interrupt Service / is executed when watchdog timed out ISR(WDT_vect) { f_wdt=1; // set global flag } //**************************************************************** // Door-opener function // It became day // open() void open() { // Photocell detected day-break // Door closed condition // Top sensor open (pin grounded) //Open door Serial.println("Open function called"); while (ts == 0) { digitalWrite(door_up,HIGH); digitalWrite(door_down,LOW); ts=digitalRead(topswitch); // re-read the top reed switch } // Door open, reset motor-driver lines digitalWrite(door_up,LOW); digitalWrite(door_down,LOW); // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker,LOW); // digitalWrite(pinLed,LOW); // now sleep for six hours //sleep 60; } //**************************************************************** // Door-closer function // It became night // nightingale sounded // close() void close() { // Photocell detected dusk // Door open condition // Bottom sensor open (pin grounded) // Close door Serial.println("Close function called"); while (bs == 0) { digitalWrite(door_up,LOW); digitalWrite(door_down,HIGH); bs=digitalRead(bottomswitch); // re-read the bottom reed switch } //Door closed, reset motor-driver lines digitalWrite(door_up,LOW); digitalWrite(door_down,LOW); // now sleep for six hours //sleep 60; } //**************************************************************** // Door-sensor fault alarm function void alarm() { for (int j=0; j<=600; j++) { whistle(); delay(6000); } } //**************************************************************** // Door-sensor test on start-up // Moves the door to whatever open/closed position it is not currently in // then moves it back void test() { if (bs == 1) { open(); close(); } else if (ts == 1) { close(); open(); } }
I almost finished the initial all-electronics version of the chicken coop door opener described in the section below. However, while testing and re-working the door-closing beeper circuit, I concluded that the circuit was physically too cumbersome to survive continually moving in an out of the enclosure.
So I built a L293 motor-driver on a piece of stripboard and replaced the light-sensing, door position-sensing, motor-driver, and beeper logic with an Arduino.
It took a weekend to prototype to working. That's a fraction of the time it took to prototype the all-electronics version.
Here's a video of the unit working at dusk:
This view of the case shows the Arduino stuffed in to the enclosure it the L293 driver stripboard on the right. With all the sensor wires and logic lines, there's a lot of wires heading to the stripboard.
Here's the Arduino code for that. This is a slightly improved version of the code running the door opener in the video link above and I haven't tested it yet. So, if you find any bugs, let me know.
//**************************************************************** /* * Chicken Coop Door Controller * Includes auto chicken-feeder motor driver * Photoresistor on analog0 * Piezo Speaker on pin 13 * * By Lee Kimber * Based on 'Nightingale' by: * KHM 2008 / Lab3/ Martin Nawrath nawrath@khm.de * Kunsthochschule fuer Medien Koeln * Academy of Media Arts Cologne */ //**************************************************************** #include <avr/sleep.h> #include <avr/wdt.h> #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // sleep between runs int pause = 6000; int beeps = 250; int lightlevel = 830; int nint; //int pinLed=13; // stop using, was 13 int pinPiezoSpeaker=13; // make pin 13, was 10 volatile boolean f_wdt=1; // Lee adds // drive lines for the L293D motor driver int door_up=4; // becomes 5, was 11 int door_down=5; // becomes 4, was 12 // Set up chicken feeder driver int feeder1=7; // becomes 7, was 8 int feeder2=6; // becomes 6, was 9 void setup(){ Serial.begin(38400); // pinMode(pinLed,OUTPUT); pinMode(pinPiezoSpeaker,OUTPUT); // Lee adds pinMode(door_up,OUTPUT); pinMode(door_down,OUTPUT); pinMode(feeder1,OUTPUT); pinMode(feeder2,OUTPUT); delay(10000); Serial.println("Chicken coop door opener"); // CPU Sleep Modes // SM2 SM1 SM0 Sleep Mode // 0 0 0 Idle // 0 0 1 ADC Noise Reduction // 0 1 0 Power-down // 0 1 1 Power-save // 1 0 0 Reserved // 1 0 1 Reserved // 1 1 0 Standby(1) cbi( SMCR,SE ); // sleep enable, power down mode cbi( SMCR,SM0 ); // power down mode sbi( SMCR,SM1 ); // power down mode cbi( SMCR,SM2 ); // power down mode setup_watchdog(7); } byte del; int cnt; byte state=1; int light=0; // Lee adds int topswitch=2; // becomes 2, was 4 int bottomswitch=3; // becomes 3, was 5 int ts=0; int bs=0; //**************************************************************** //**************************************************************** //**************************************************************** void loop(){ // Set feed motor-driver line low to save power digitalWrite(feeder1,LOW); digitalWrite(feeder2,LOW); // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker, LOW); //digitalWrite(pinLed,LOW); if (f_wdt==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs f_wdt=0; // reset flag light=analogRead(0); // reading photoresistor // Lee adds ts=digitalRead(topswitch); // read the top reed switch bs=digitalRead(bottomswitch); // read the bottom reed switch Serial.print("light: " ); Serial.print(light ); Serial.print(" bs: "); Serial.print(bs); Serial.print(" ts: "); Serial.println(ts); // Lee add door-state reporting here if (ts == 1 && bs == 0) { Serial.println("Door is open"); } else if (ts == 0 && bs == 1) { Serial.println("Door is closed"); } else if (bs == 1 && ts == 1) { Serial.println("ALARM: Door state monitoring is faulty"); alarm(); } else { Serial.println("Door state is indeterminate (or possibly faulty)"); } switch (state){ case 0: // waiting for dawn if (light < lightlevel && ts == 0) { // light threshold high and door not open (ts open) state=1; Serial.println("Calling door-open function"); open(); // Door open, nothing to do for 'pause' hours delay(pause); } break; case 1: // waiting for dusk if (light > lightlevel && bs == 0) { // light threshold low and door not closed (bs open) state=0; beep(); Serial.println("Calling door-closer function"); close(); // Door closed, nothing to do for 'pause' hours delay(pause); } break; } nint++; // digitalWrite(pinLed,1); // let led blink Serial.print("Sleep " ); Serial.println(nint ); delay(2); // wait until the last serial character is send // digitalWrite(pinLed,0); // pinMode(pinLed,INPUT); // set all used ports to intput to save power pinMode(pinPiezoSpeaker,INPUT); // set all used port to intput to save power // Lee add: do as above with Lee's added pins pinMode(door_up,INPUT); pinMode(door_down,INPUT); pinMode(feeder1,INPUT); pinMode(feeder2,INPUT); system_sleep(); // pinMode(pinLed,OUTPUT); // set all ports into OUTPUT state after sleep pinMode(pinPiezoSpeaker,OUTPUT); // set all ports into state after sleep // Lee add: do as above with Lee's added pins pinMode(door_up,OUTPUT); pinMode(door_down,OUTPUT); pinMode(feeder1,OUTPUT); pinMode(feeder2,OUTPUT); } } //**************************************************************** // put some whistle sound on piezo void whistle() { for (int ii = 0; ii<= 20; ii++) { for (del=0; del <=254; del++) { digitalWrite(pinPiezoSpeaker,0); delayMicroseconds((ii*5)+(del * 2)); digitalWrite(pinPiezoSpeaker,1); delayMicroseconds((ii*5)+(del * 2)); } // PORTB ^= 32; // toggle pinLed } } //**************************************************************** // put some beep sound on buzzer void beep() { // Let the chickens know we're closing up // 1850 cycle-time / 1000 / 60 = 6.167 minutes warning Serial.println("Starting 200 beeps"); for (long i=0; i < beeps; i++) { Serial.println("Beep routine started"); digitalWrite(pinPiezoSpeaker, LOW); delay(1500); digitalWrite(pinPiezoSpeaker, HIGH); delay(300); } // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker,LOW); // digitalWrite(pinLed,LOW); } //**************************************************************** // set system into the sleep state // system wakes up when watchdog is timed out void system_sleep() { cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here sleep_enable(); sleep_mode(); // System sleeps here sleep_disable(); // System continues execution here when watchdog timed out sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON } //**************************************************************** // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms // 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec void setup_watchdog(int ii) { byte bb; int ww; if (ii > 9 ) ii=9; bb=ii & 7; if (ii > 7) bb|= (1<<5); bb|= (1<<WDCE); ww=bb; Serial.println(ww); MCUSR &= ~(1<<WDRF); // start timed sequence WDTCSR |= (1<<WDCE) | (1<<WDE); // set new watchdog timeout value WDTCSR = bb; WDTCSR |= _BV(WDIE); } //**************************************************************** // Watchdog Interrupt Service / is executed when watchdog timed out ISR(WDT_vect) { f_wdt=1; // set global flag } //**************************************************************** // Door-opener function // It became day // open() void open() { // Photocell detected day-break // Door closed condition // Top sensor open (pin grounded) Serial.println("Open function called"); //Open door but as it opens so early, let's pause for an hour delay(3600000); while (ts == 0) { digitalWrite(door_up,HIGH); digitalWrite(door_down,LOW); ts=digitalRead(topswitch); // re-read the top reed switch } // Door open, reset motor-driver lines digitalWrite(door_up,LOW); digitalWrite(door_down,LOW); // Set piezoSpeaker output low to mute unwanted noises digitalWrite(pinPiezoSpeaker,LOW); // And provide chickens some feed // Start the automatic chicken feeder motor Serial.println("Starting feed motor"); // Set feed motor-driver line high here digitalWrite(feeder1,HIGH); digitalWrite(feeder2,LOW); // Assume feeder runs for ten minutes delay(600000); Serial.println("Stopping feed motor"); // Set feed motor-driver line low here digitalWrite(feeder1,LOW); digitalWrite(feeder2,LOW); // now sleep for six hours //sleep 60; } //**************************************************************** // Door-closer function // It became night // nightingale sounded // close() void close() { // Photocell detected dusk // Door open condition // Bottom sensor open (pin grounded) // Close door Serial.println("Close function called"); while (bs == 0) { digitalWrite(door_up,LOW); digitalWrite(door_down,HIGH); bs=digitalRead(bottomswitch); // re-read the bottom reed switch } //Door closed, reset motor-driver lines digitalWrite(door_up,LOW); digitalWrite(door_down,LOW); // now sleep for six hours //sleep 60; } //**************************************************************** // Door-sensor fault alarm function void alarm() { for (int j=0; j<=600; j++) { whistle(); delay(6000); } } //**************************************************************** // Door-sensor test on start-up // Moves the door to whatever open/closed position it is not currently in // then moves it back void test() { if (bs == 1) { open(); close(); } else if (ts == 1) { close(); open(); } }
Owners of chickens often wail about having to get up to let their loved ones out to forage - and about having to abandon dinner to round their loved ones up and into the safety of their coop at the end of the day.
After finding a couple of drawer runners abandoned by the verge and partnering them up with a small electric motor in my junk-box, I decided to noodle out an electronic circuit that would open and shut a coop door at dawn and dusk.
Testing the limit-switches that stop the coop door motor when the door is fully open or fully closed
In the above video, the door lifts as light falls on the light-dependent resistor, Simulating dawn. The door lifts until a magnet mounted on it closes a reed switch near the top of the vertical rails. When my hand covers the LDR again - simulating nightfall - the circuit waits five seconds before lowering the door until the magnet closes a reed switch mounted near the bottom of the vertical rails. The 'closing' delay is to sound an alert to warn the hens that the door is about to close, though, outside of this test, it would usually be set for ten minutes or so.
The exercise turned out to be a revelation in electronic design principles.
Here's how.
The dawn-dusk piece is pretty easy - just use an adjustable light-level detector. That part of the circuitry could be a standard combination of light-dependent resistor and op-amp comparator. More challenging was the problem of having the motor change direction depending on whether it is dawn or dusk; whether the door needs opening or closing and sensing where the door is in its travel.
Click here to read more
Click here to see less
The logic would need to prevent the motor running after the door reached the end of its travel - otherwise the motor would likely burn out. It seemed to me I'd need logic that would determine where the door is and to deliver the correct logic output pair until the door reached the correct location: fully open or fully closed.
The problems with that scenario are that there are any number of places the door can be between open and closed that are hard to sense cheaply and rather harder to design position-assessment logic around cheaply. Also, if we care about knowing which end-travel sensors are in which position all the time, then we are having to use three-input logic/truth tables, which are slightly newer to me than two-input logic/truth tables.
I batted that around for three days or so. One of the problems I considered was that building in logical fault sensing was much more complicated if we cared about the door's position. I spent some time considering if the H-bridge's 'enable/disable' pin could be hacked to help out with this.
The breakthrough came when I realised that it doesn't matter whether the system knows where the door is; what matters is where the door is *not* when the light level changes up (dawn) or down (dusk).
Click here to read more
Click here to see less
That revelation reveals that I only needed to create logic around two conditions:
Two reed switches - one at the top of the door's travel and one at the bottom - would provide the position sensing if the door was fitted with magnets that would trip the reed switches. The reed switches' *logic* output could be pre-set by biasing each switch with resistors.
Click here to read more
Click here to see less
With the revelation behind me, I started to look at the logic I'd need, focusing on the chips that are cheap or that I already had in my junk box. The comparator piece was easy: use a 741 or an LM393 along with three 1k resistors from the junkbox. I took an LDR from a discarded night-light.
After some scratching around I realised that the reed switch logic could be simplified if the logic conditions we look for were reduced to:
Light sensor = high + lower reed switch = high (1 + 1)
and
Light sensor = low + upper reed switch = low (0 + 0)
because the first (1 + 1) can be handled by an AND gate and the second (0 + 0) can be handled by an NOR gate. That is: if the reed switches and their voltage bias were judiciously arranged, the 1 + 1 AND condition could handle the 'door opening' condition and the 0 + 0 NOR condition could handle the 'door closing' condition.
Click here to read more
Click here to see less
This logic is shown in the truth tables below:
Door opens
| Light Sensor | Upper Switch | Action | Notes |
|---|---|---|---|
| 1 | 1 | Door opens | Light level went high; AND Gate triggers |
Door closes
| Light Sensor | Lower Switch | Action | Notes |
|---|---|---|---|
| 0 | 0 | Door closes | Light level went low; NOR Gate triggers |
Click here to see complete truth table
Click here to hid complete truth table
| Light Sensor | Upper Switch | Lower Switch | Action | Notes |
|---|---|---|---|---|
| 0 | 0 | 0 | Door close starts | Dusk, close starts after 555-determined delay |
| 0 | 0 | 1 | Door closing | Door has begun to close. Fault condition if prolonged |
| 0 | 1 | 1 | Door closed | This condition should last through night |
| 0 | 1 | 0 | Fault condition | |
| 1 | 1 | 1 | Door open starts | Dawn, open starts immediately |
| 1 | 0 | 1 | Door opening | Door has begun to open. Fault condition if prolonged |
| 1 | 0 | 0 | Door open | This condition should last through day |
| 1 | 1 | 0 | Fault condition | |
Click here to read more
Click here to see less
A little more scratching around revealed that I could use three NOR gates to create an AND gate, which meant that I could use the four NOR gates in the CMOS 4001 in my junkbox to handle all the logic. Two-input logic gates being more common than three-input logic gates, particularly in my junk-box.
So far, the cost of this project was nil.
Click here to read more
Click here to see less
The next step was to figure out how to give the chickens some warning that the door was going to close each night. After all, you don't want your agricultural assets clustered around a closed coop door as the foxes close in.
What I needed was to delay the operation of the H-bridge - and possibly the operation of the CMOS logic gates - when the light level was detected as changing from high to low. During the delay, a piezo-buzzer should sound to warn the hens of the coop door's imminent closure.
Click here to read more
Click here to see less
The difficulty with this trick is that we want to detect only low-going light level changes, not the high-going changes. That is, we only care to insert this delay at dusk, when the light level is falling, and not at dawn, when the light level is rising.
Fixing this proved easy: it's possible to configure a 555-based monostable like the Maplin kit to trigger only on low-going edges by sandwiching a capacitor between two pull-up resistors at the trigger pin (pin 2) of the 555. A couple of diodes inserted after the output stage of the light-level detector and the monostable isolated their respective outputs from each other so that only the 'high' output of either sub-circuit made its way to the inputs of the 4001's NOR gate.
Breadboard tests proved the viability of the design. However, I have since updated this circuit a little so contact me (bottom right of the page) to nudge me to retrieve the latest circuit diagram.
Click here to read more
Click here to see less
Careful simulation of lighting and switching showed that the logic and electronics through to the ping 3 and 4 outputs of U3 CMOS 4001 worked correctly.
Testing around U4 L293D showed that its logic power supply on pin 16 Vcc1 and Enable pin 1 was at 2.10 volts instead of the 5.1V theoretically delivered by the combination of 5.1V zener D3 and 1k resistor R14.
Given that this logic power supply had been tested delivering 5.1V before U4 L293D was inserted, it seemed likely that the issue was that the 1k resistor R14 was dropping too many volts at the current required by the L293D's logic power supply Vcc2.
So, let's work out what we need:
Logic Supply Voltage VCC1: 2.14V not 5.1V as it should be
Output Supply Voltage VCC2 in use: 12.5V
Voltage drop is:
6.39V
over 1kR
Logic supply current ICC1 is = 0.0064 6.4mA
According to TI's L293D datasheet, ICC1 is min: 13mA and max (in this application): 35mA
Calculate new R14 resistance:
12.5 - 5.1 = 7.4
At max I<subL</sub> current 7.4 / 0.035 = 211R
At min I<subL</sub> current 7.4 / 0.013 = 569R
Use 200R or close
Calculate resistor wattage rating: 7.4 * 0.035 = 0.26W
Click to read more
Click to see less
Case 1:
Night-time, door closed, 0 + 1 presented to the AND gate; 0 + 1 presented to the NOR gate
Light Sensor = 0 Upper Switch = 1 | | | || || Lower Switch = 1
Case 2:
Dawn breaks, light sensor output goes high, 1 + 1 presented to the AND gate; 1 + 1 presented to the NOR gate
Light Sensor = 1 Upper Switch = 1 | | | || || Lower Switch = 1
Case 3:
Day-time, light sensor output has gone high, AND gate high output has begun to pull door open, lower switch opens and goes low, 1 + 1 presented to the AND gate; 1 + 0 presented to the NOR gate
Light Sensor = 1 Upper Switch = 1 | | || || | Lower Switch = 0
Case 4: Day-time, light sensor output high, door fully open, upper switch closes and goes low, 1 + 0 presented to the AND gate; 1 + 0 presented to the NOR gate
Light Sensor = 1 Upper Switch = 0 || || | | | Lower Switch = 0
Case 5:
During daytime, light sensor output high, door fully open, 1 + 0 presented to the AND gate; 1 + 0 presented to the NOR gate
Light Sensor = 1 Upper Switch = 0 || || | | | Lower Switch = 0
Case 6:
Dusk, light sensor output goes low, door fully open, 0 + 0 presented to the AND gate; 0 + 0 presented to the NOR gate; NOR gate output goes high
Light Sensor = 0 Upper Switch = 0 || || | | | Lower Switch = 0
Case 7:
Dusk, light sensor output low, NOR gate beginning to close door, upper switch opens and goes high, 0 + 1 presented to the AND gate; 0 + 0 presented to the NOR gate; NOR gate output goes high and begins to close door
Light Sensor = 0 Upper Switch = 1 | || || | | Lower Switch = 0
Case 8:
Night-time, light sensor output low, NOR gate completes door-closing, lower switch closes at completion of door-closing and goes high, 0 + 1 presented to the AND gate; 0 + 1 presented to the NOR gate; NOR gate output goes low again as door closes. Same as case 1.
Light Sensor = 0 Upper Switch = 1 | | | || || Lower Switch = 1
Discussion