Three door opener

This project helps remote opening of electric doors. Three door algorithms are supported:

  1. Door 1 lock with coil
  2. Lamp in room 1 triggered at the same time as door 1 lock but with extended time
  3. Rolo door with up/down/stop and possible lamp
  4. Sectional door relais trigger

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-----|

PCB

Photo of PCB assembly on protoboard is avalable here.

Schematics


Click to enlarge

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.

Source code

/* 	$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.


© 2005, Leon Kos
Last modified: Thu Jun 8 13:34:47 CEST 2006