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.