This project helps remote opening of electric doors. Three door algorithms are supported:
Remote control for this module is with three wires whith the following schematics for three buttons:
GND -------------- SW1 -------oTo----| SW2 -+-----oTo----| | | | V V | - - 1N4148 | | | | -----oTo-----|
Also available as PDF or gschem
Later I've realised that high sink current for port 1 in about 100μA and that 1mA drive current is needed. Pullup SIL resistor pack from 3k3 to 4k7 is required for reliable operation of port 1! ULN2001 would be a better solution than pullup resistors.
/* $Id: portus.c 1.1 2005/05/11 06:34:12 leon Exp leon $ (c) 2005, Leon Kos. Three door opener with three buttons on three wires. Each key works indenpendently of others. Thus multiple commands can be entered not interrupting the other states. AT89C2051 at 10.24 MHz with idle mode for power saving. \*/ #include <reg51.h> /* Port 3 INPUT control pins */ sbit SW1 = 0xB2; /* Interrupt pin 0 */ sbit SW2 = 0xB3; /* Interrupt pin 1 */ /* Port 1 OUTPUT */ sbit COIL = 0x92; /* Door 1 lock coil */ sbit LIGHT = 0x93; /* Room 1 light */ sbit ROLO = 0x94; /* Rolo door move */ sbit UPDOWN = 0x95; /* Rolo door direction */ sbit GARAGE = 0x96; /* Garage door trigger switch and light */ sbit LED = 0x97; /* debug LED */ /* Idle mode entered with PCON bit 0 */ #define IDLE() PCON |= 1; void ex0_isr (void) interrupt 0 { /* Wake UP the system */ } static unsigned char overflow_count; static unsigned char coil_timer; static unsigned char light_timer; static unsigned char rolo_timer; static unsigned char rolo_delay; static unsigned char garage_timer; void timer0_isr (void) interrupt 1 using 1 { /* Overflows every t=8192/f at f=10.240/12 MHz. 104 overflows in second. */ if (overflow_count++ == 104 ) /* Check this every second */ { overflow_count = 0; LED = ~LED; /* blink for fun */ if (coil_timer) { coil_timer --; if (!coil_timer) COIL = 0; } if (light_timer) { light_timer --; if (!light_timer) LIGHT = 0; } if (rolo_timer) { rolo_timer --; if (rolo_delay) { rolo_delay = 0; ROLO = 1; } if (!rolo_timer) { ROLO = 0; rolo_delay = 1; } } else if (rolo_delay) { rolo_delay = 0; UPDOWN = 0; } if (garage_timer) { garage_timer --; if (!garage_timer) GARAGE = 0; } if (!coil_timer && !rolo_timer && !garage_timer && !light_timer) { TR0 = 0; /* stop the timer */ LED = 0; } } } void ex1_isr (void) interrupt 2 { /* Wake UP the system */ } /* Coil is switched on for 10 seconds. Then it switches off */ void coil(void) { COIL = 1; LIGHT = 1; coil_timer = 10; light_timer = 70; /* Lamp is lit a little more */ TR0 = 1; /* Start the timer */ } /* rolo door changes direction at any time with up down and stop when running. With rolo also ligth is switched on. */ void rolo(void) { static bit up_down_status = 0; if (rolo_timer) /* door active -> stop */ { rolo_timer = 0; ROLO = 0; rolo_delay = 1; return; } up_down_status = ~up_down_status; UPDOWN = up_down_status; rolo_timer = 120; rolo_delay = 1; overflow_count = 50; TR0 = 1; } /* For garage door we need short pulse of 2s duration */ void garage(void) { GARAGE = 1; garage_timer = 2; TR0 = 1; } void main(void) { P3 = 0xff; /* initial input state */ P1 = 0x00; /* initial output state */ IT0 = 1; /* enable falling edge */ EX0 = 1; /* enable EX0 interrupt */ IT1 = 1; /* enable falling edge */ EX1 = 1; /* enable EX1 interrupt */ TMOD = (TMOD & 0xF0) | 0x00; /* Timer 0, mode 0 Set T/CO mode */ ET0 = 1; /* enable timer 0 interrupt */ TR0 = 0; /* stop timer for now */ TL0 = 0x00; TH0 = 0x00; overflow_count = 0; coil_timer = 0; rolo_timer = 0; garage_timer = 0; light_timer = 0; rolo_delay = 0; EA = 1; /* enable global interrupt flag */ while (1) { unsigned int i; IDLE(); /* wait for key (and other interrupt!)*/ if (!SW1 && !SW2) /* middle key */ rolo(); else if (!SW1) coil(); else if (!SW2) garage(); else if (TR0) /* wake up with timer interrupt */ continue; for(i = 0; i < 8000; i++) if (!SW1 || !SW2) /* depress wait*/ i = 0; } }
Hardware can be simplified throwing away functionality not needed. That's why HEX file is provided.