Software:

The software is working perfectly as I’ve already tested them thoroughly. Here’s what they are suppose to do:

Diagram 1: The logic flowchart for the software.

During the standby mode, when the person clicks the button, it will go into an ISR or interrupt service routine which tells the system to wake up from sleep and go to start the system. Some of the problems that we have faced are that the register wasn’t able to read the inputs right away so that if the motion sensor picks up some one, it won’t do anything until the values are written into the registers. There were two different causes for this problem; one was that the user has to set the pin 7 of the ADCON1 so that PORTA pins can be read as digital inputs instead of analog inputs.

The other major cause was using CMVRON register and CMCON register to activate comparator module. This module compares the analog input from PORTA1 with the set voltage reference on PORTA 2. The CMCON controls which comparator mode the user wants and reads the output from CMCON pin 7. When the current sensor picks up a spike, the voltage is suddenly increased. The comparator module checks PORTA1 and compares it to PORTA2. If the PORTA1 input has a higher voltage, the system will recognize that something is blocking the door’s path and automatically go to TIMER if the door was in opening process or goes to SLEEP mode if the door was in closing operation. However, for the PORTA pins to continue work as digital inputs, one needs to load B’00000111’ into the CMCON register so that the comparator module is turned off.

One of the more obscure problems involved with this particular program is that when the bits are loaded to CMCON register, even when the inputs are changed, the input registers do not record those changes inputs are changed, the input registers do not record those changes. The programmer solved this problem by setting up few extra unnecessary instructions. These changes can be spotted in the program easily.

The entire program was created in assembly. The reason for that is that it is easier to manipulate bit level with assembly and should keep the program simple compared to higher level language.

From here, I’ll explain the basics of the programming for the PIC16F876A. First, in order to get the program to work, one needs to find the f876atmpo.asm and then find the 16f876.lkr file. These are essential to get the programming started. There are also some sample codes that can help you program. The main information I used to program was the F876A manual, as it contained all the information about registers, timer, comparator module and other things. Now, onto the programming itself.

In the RESET_VECTOR section, one can see that it jumps to the MAIN label by first loading the address of the MAIN label into PCLATH. In the main label, I wanted to clear all the registers before I start the program to avoid any unwanted outputs and inputs. To do that, first select the bank of that register then use the clrf function to clear all the registers. PORTB, 4 is used for remote press (see comments), it is the only pin that can be used for interrupt the system while it’s in sleep mode. Here, basically it will start the system when the remote control button is pressed.

RESET_VECTORCODE0x000; processor reset vector

nop; nop required for icd

movlwhigh MAIN; load upper byte of 'MAIN' label

movwfPCLATH; initialize PCLATH

gotoMAIN; go to beginning of program

INT_VECTORCODE0x004; interrupt vector location

movwfw_temp; save off current W register contents

movfSTATUS,w; move status register into W register

movwfstatus_temp; save off contents of STATUS register

movfPCLATH,w; move pclath register into w register

movwfpclath_temp; save off contents of PCLATH register

bankselINTCON

bcfINTCON, RBIF;clear the flag in INTCON register that

disrupts the sleep mode

movfpclath_temp,w; retrieve copy of PCLATH register

movwfPCLATH; restore pre-isr PCLATH register contents

movfstatus_temp,w; retrieve copy of STATUS register

movwfSTATUS; restore pre-isr STATUS register contents

swapfw_temp,f

swapfw_temp,w; restore pre-isr W register contents

retfie; return from interrupt PAGE 500 in text book explains interrupt.

MAINCODE

MAIN

nop

bankselPORTB

clrfPORTB;disable outer motion sensor PORTB 5

;diable fan PORTB 1

bankselPORTC

clrfPORTC;disengage clutch PORTC 3

btfss PORTB,4;the pin should be high, start opening door if

RA4 is pressed (low)

goto MAIN;Go back to start

start_set_pins

banksel PORTA

clrfPORTA

bsfSTATUS,RP1;select Bank 1

bankselADCON1 ;select this bank

movlw0x06;configure all pins as digital inputs

movwfADCON1

bankselTRISA

bsfTRISA,0;PORTA0 is input for open optical sensor

bsfTRISA,1;PORTA1 is input for current sensor

bsfTRISA,2;PORTA2 is input for close optical sensor

bsfTRISA,3;PORTA3 is input for outer motion sensor

bcfTRISA,4;PORTA4 is output for inner motion

sensor enable

bsfTRISA,5;PORTA5 is input for inner motion sensor

bankselTRISB

bsfTRISB,0; make switch RB0 an input

bcfTRISB,1; make PORTB1 an output for fan enable

bcfTRISB,2; make PORTB2 an output to turn motor toopen

bcfTRISB,3; make PORTB3 an output to turn motor to close

bsfTRISB,4; make PORTB4 an input for receiver so that it

wakes from sleep mode with flag RBIF

bcfTRISB,5; make PORTB5 an output for outer motion

bankselTRISC

;bcfTRISC,0; make PORTC0 an output for Crystal oscillator

;bsfTRISC,1; make PORTC1 an input for Crystal oscillator

bcfTRISC,2; make PORTC2 an output for electromagnet

bcfTRISC,3; make PORTC3 an output for clutch

bcfTRISC,4; make PORTC4 an output for strike plate In the section start_set_pins, the pins are selected individually so that the reader can see clearly which pin is set for input or output. The way to set the pins into output or input is to set them clear the corresponding TRISA or by setting them, respectively. PORTA is special as it needs to configure the ADCON1 to make them able to accept digital inputs. The default is analog inputs.

Diagram 2: Pins of the PIC876A

start

bankselPORTA

bsfPORTA,4;inner motion sensor enable

bankselPORTB

bsfPORTB,5;outer motion sensor enable

bsfPORTB,1;fan enable

sensor2

bankselT1CON

movlw0x0F;move this value into W reg

movwfT1CON;initialize timer move this value into TICON

clrfseconds;clear register

bcfPIR1,TMR1IF;clear interrupt request flag

movlw0x80;move this value into W register

movwfTMR1H;load regs for 1 sec overflow

clrfTMR1L

increment_sec1

bankselPORTA;check this bank

btfscPORTA,5;inner sensor picks up something? high means YES, low means NO.

goto sensor2;No, move on.

incfseconds, 1;increment seconds

movfseconds, w

sublw.5;is it 5 seconds yet?

btfssSTATUS,Z;if overflowed go clear the seconds and check sensor 2

gotoincrement_sec1;go back to increment seconds if not overflowed

clrfseconds;clear seconds

The timer can be start by first selecting T1CON register and move the 0x0F value into that register. PicF876A has 3 timers but the TIMER 1 is chose as it can output seconds. Basically, this section resets the timer, then checks for the inner sensor. If the inner sensor picks up something, it will go back and reset the timer. This program checks for movement for 5 seconds. Within those 5 seconds, if movement is detected, it will reset the timer. If no object is detected for 5 seconds, it will start opening the door and ignore the inner sensor. The way to check for 5 seconds is to use sublw .5 and then check for the STATUS bit. When it opens the door, the values 0x1C can be loaded into PORTC all at once instead of using BCF or BSF instructions. The PIC876A manual warns the user of using those codes as it will turn on one pin but turn off the other pins.

open_door

bankselPORTC

movlw0x1C

movwfPORTC;push electromagnet

;engage clutch

;release strike plate

turn_motor

bankselPORTB

bsfPORTB,2;turn motor to open

bankselCMCON;select bank 1

movlw0x26;move these bits into the CMCON register

movwfCMCON;move values into this register

bankselCVRCON

movlwB'11001111';last for digits set the referenc voltage

movwf CVRCON;move this value into CVRCON register

btfscCMCON,7;check the output of comparator: if 1 go to

doortimer, if 0 check switch

gotodisable_CS;go to disable the current sensor

check_openswitch

bankselCMCON

movlw0x07;disable the comparator module

movwfCMCON

bankselCVRCON

clrfCVRCON;disable the comparator voltage reference module

gotoOOS;check open optical switch

In the turn_motor label, the programmer uses CMCON register to turn on the comparator module. The module, as seen in the data sheet, is 110 or 6. The default values of these last 3 bits are 111 or 7. The CVRCON register can be used to set the reference voltage. The voltage set here is 2.5V since the current sensor outputs 2.5 V when it doesn’t sense a spike. When the current sensor senses a spike, the voltage will spike and therefore, the output out of CMCON, 7th bit should be high. When this happens, it means that something is blocking the path of the door and it will automatically go into 45 second timer. Or else it will keep opening the door. After using the CMCON and CVRCON register, the user must disable the comparator module by restoring their default values. If this is not done correctly, the register PORTA will ignore all input changes and only function as a comparator module. In the mean time, it also checks for open optical switch which tells the system that the door is opened.

Diagram 3: CMCON register

Diagram 4: Comparator modes

Diagram 5: Comparator voltage reference block diagram

OOS

bankselPORTA

btfssPORTA,0;check open optical switch: if 1 go to

doortimer, if 0 continue turn motor

gototurn_motor

disable_CS

bankselCMCON

movlw0x07;disable the comparator module

movwfCMCON

bankselCVRCON

clrfCVRCON;disable the comparator voltage reference module

doortimer

bankselPORTB

bcfPORTB,2;turn off motor

bankselPORTC

bcfPORTC,4;lock strike plate

bcfPORTC,3;disengage clutch

bankselT1CON

movlw0x0F;move this value into W reg

movwfT1CON;initialize timer move this value into TICON

clrfseconds;clear variable

bcfPIR1,TMR1IF;clear interrupt request flag

movlw0x80;move this value into W register

movwfTMR1H;load regs for 1 sec overflow

clrfTMR1L

increment_sec2

bankselPORTB

btfsc PORTB,4;high means not pressed, start closing door ifRA4 is pressed (low)

goto start_closing;Go back to start

incfseconds,1;increment seconds

movfseconds,w

sublw.45;is it 45 seconds yet?

btfssSTATUS,Z;if overflowed go clear the seconds start closing door or else continue increment.

gotoincrement_sec2;go back to increment seconds

clrfseconds;clear seconds

In here, the program locks the strike plate and disengages the clutch. It sets the timer ready to count the seconds and then checks for whether someone has pressed the button. If some one presses the button, it will skip the 45 seconds count down and starts to close the door. Before the motor turns the door to close however, the system checks for closed switch, this is to make sure that someone has not already closed the door manually. Then it checks for both the inner sensor and the outer sensor for any motion for a duration of 5 seconds

start_closing

bankselINTCON

bcfINTCON, RBIF;Make sure this is off

btfscPORTA,2;if high: to sleep mode, if low continue

gotosleep_mode;door is already closed

sensor_1_2

bankselT1CON

movlw0x0F;move this value into W reg

movwfT1CON;initialize timer move this value into TICON

clrfseconds;clear register

bcfPIR1,TMR1IF;clear interrupt request flag

movlw0x80;move this value into W register

movwfTMR1H;load regs for 1 sec overflow

clrfTMR1L

increment_sec3

btfssPORTA,3;check outer sensor, if high reset time, if low check inner sensor

btfscPORTA,5;inner sensor picks up something? high means yes, low means no.

goto sensor_1_2;Yes, go reset time

incfseconds,1;increment seconds

movfseconds,w;move it to working register

sublw.5;is it 5 seconds yet?

btfssSTATUS,Z;if overflowed go clear the seconds and checksensor 2

gotoincrement_sec3;go back to increment seconds if not overflowed

clrfseconds;clear seconds

bankselPORTA

bcfPORTA,4;disable inner motion sensor

bankselPORTC

bsfPORTC,3;engage clutch

turn_motor1

bankselPORTB

bsfPORTB,2;turn motor to open

bankselCMCON;select bank 1

movlw0x26;move these bits into the CMCON register

movwfCMCON;move values into this register

movlwB'11001111';last four digits set the referenc voltage

bankselCVRCON

movwf CVRCON;move this value into CVRCON register

btfscCMCON,7;check the output of comparator: if 1 go to

doortimer, if 0 check switch

gotodisable_CS1;go to disable the current sensor

check_closeswitch

bankselCMCON

movlw0x07;disable the comparator module

movwfCMCON

bankselCVRCON

clrfCVRCON;disable the comparator voltage reference module

gotoOS;goto open switch

OS

bankselPORTA

btfscPORTA,3;outer sensor picks up something

goto reopen;reopen

btfssPORTA,2;check open optical switch:

gototurn_motor1

When the door is closing, it will check for outer motion sensor, the open switch and the current sensor. When the door hits something while it is closing, the program will recognize the event and tell the system to go to SLEEP. So that will the motor will not keep moving. The person will have to close the door manually or else it’ll be kept open. The programmer must make sure that there’s no glitch in this program or the system should produce random output. The job of the outer motion sensor is to keep track of people out of the door. If it detects movement during the closing operation, it will stop and reopen. Or else it will stop when the door is closed.

disable_CS1

bankselCMCON

movlw0x07;disable the comparator module

movwfCMCON

bankselCVRCON

clrfCVRCON;disable the comparator voltage reference module

goto sleep_mode;

reopen

bankselCMCON

movlw0x07;disable the comparator module

movwfCMCON

bankselCVRCON

clrfCVRCON

bankselPORTB

bcfPORTB,3;stop motor

gotostart;reopen

NOTE: the programmer must turn off the comparator module before they want to accept any digital inputs. Sometimes, the inputs in the register won’t take any input for few cycles, so I implemented dummy cycles such as OS and OOS labels.

sleep_mode

bankselPORTA

clrfPORTA

bankselPORTB

clrfPORTB;disable outer motion sensor PORTB 5

;disable fan PORTB 1

bankselPORTC

clrfPORTC;disengage clutch PORTC 3

;shut down electromagnet push PORTC 2

bankselINTCON

bcfINTCON, RBIF;Make sure this is off

sleep

nop

gotoMAIN;waken from interrupt? then go to MAIN

END ; directive 'end of program'

Figure 6: register file map

Output Ports / output voltage(V) / current(mA) / Power(mW)
PORTB,4 / 3.67 / 14.1 / 51.747
PORTB,5 / 2.341 / 28.3 / 66.2503
PORTA,4 / 1.825 / 2.56 / 4.672
PORTB,1 / 2.31 / 5.08 / 11.7348
PORTA,5 / 3.486 / 3.45 / 12.0267
PORTC,4 / 1.955 / 6.08 / 11.8864
PORTC,2 / 1.96 / 5.58 / 10.9368
PORTC,3 / 2.3 / 5.38 / 12.374
PORTB,2 / 2.26 / 5.25 / 11.865
PORTB,3 / 2.54 / 5.11 / 12.9794

Table 1: outputs of each pin, voltage, current measured using a green LED with 470 ohm resistor.

This table shows the voltage and current for each output pin using a LED and a 470 ohm resistor. Each pin is measure individually with other output pins disconnected. Values might be affected if more output pins are connected to ground.

Box design:

The enclosure uses a type of die cast aluminum alloy. It is ½ inch thick in the back piece of the box, which is also the side mounted on the wall, in order to handle the amount of stress from the 350 in-lb of torque produced by the motor. The top part of the box has about 2 inch diameter hole which supports a fan that cools the system. It is carefully placed close to the PCB’s which produce great amount of heat. It is placed on the top of the box since heat travels upward. The left side of the box supports the motor control PCB and the receiver PCB. The AC to DC power supply sits on the bottom piece of the box as it delivers power to the rest of the system. The motor itself sits on the back piece of the box. It is attached by threaded hex screws with half inch thread. The bottom of the clutch sits on a aluminum bushing which also connects to a metallic strip that functions as the optical switch breaker. The bushing is attached to the bottom rod by 2 set screws. The rod then extends down to the bottom of the box through a linear ball bearing and connects to the arms that open the door. The ball bearing is strategically located on the bottom piece of the box to reduce stress on the rod when it tries to open the door. The bearing will reduce tension and twist caused by the resistant torque by the 500 lb. door. The bottom piece also has 2 optical switches that actually tells the system when the door is opened or closed. The aluminum casing is chosen to increase heat dissipation and increase durability and robustness. It is an improvement in all aspects compared to the wooden casing designed by the previous design team.

The job of the next team is

1:find a wall paper to cover the inside so that the wires are insulated from the box.

2:The hole to the left sideof the box for the AC cable has yet to be determined.

3: The positions for the optical sensors have yet to be determined. The mounting have already been made so their job is to find the position of the hole where the mount sits on top of.

4: The length of the rod has already been determined, so they have to connect that rod to the arms that attach to the door. They should be carefully welded.