LIST P=PIC16F876A #include __CONFIG _CP_OFF & _DEBUG_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _HS_OSC ;******************************************************************* ;************ Defining Variables ************ ;******************************************************************* Buttons EQU h'20' Timer1 EQU h'21' Timer2 EQU h'22' Floor EQU h'23' RequestedLevel EQU h'24' CurrentLevel EQU h'25' Threshold EQU h'26' Teller3 EQU h'27' Teller4 EQU h'28' TIMER1 EQU h'29' TIMER2 EQU h'2A' Flags EQU h'2B' Temp EQU h'2C' UpperLimit EQU h'2D' LowerLimit EQU h'2E' Position EQU h'2F' Floor1 EQU h'30' Floor2 EQU h'31' Floor3 EQU h'32' Floor0 EQU h'33' Direction EQU h'34' Counter EQU h'35' Distance EQU h'36' DistanceMin EQU h'37' DutyCycle EQU h'38' DutyConstant1U EQU h'39' DutyConstant2U EQU h'3A' DutyConstant1D EQU h'3B' DutyConstant2D EQU h'3C' Temp2 EQU h'3D' RX EQU h'3E' CountSPI EQU h'3F' ;*********************************************** ; Naming Inputs and Outputs ;********************************************* GateA EQU PORTA Output2 EQU PORTB LED0 EQU h'00' LED1 EQU h'01' LED2 EQU h'02' LED3 EQU h'03' LED4 EQU h'04' LED5 EQU h'05' LED6 EQU h'06' Output EQU PORTC LED0 EQU h'00' PMW2 EQU h'01' PMW1 EQU h'02' LED3 EQU h'03' Motor1A EQU h'04' Motor2A EQU h'05' LED6 EQU h'06' LED7 EQU h'07' ;********************************************************************* ; START PROGRAM ;********************************************************************* ORG 0 GOTO RESET ORG 4 GOTO Interrupt ;********************************************************************* ; I/O configuration ;********************************************************************* RESET Bank1 MOVLW b'00000001' ; first pin is for the interrupts, the rest are outputs MOVWF TRISB MOVLW b'00000000' MOVWF TRISC MOVLW b'010001' ; signal from potentiometer and data from shift register are inputs MOVWF TRISA Bank0 CALL SetupPWM CALL SetupAnalog CALL Initialize ;*********************************************************************** ; Idle block ;*********************************************************************** Idle CALL SmallDelay CALL CheckButtons MOVF Flags,0 MOVWF Temp INCF Temp,1 DECFSZ Temp,1 GOTO Move GOTO Idle ;*********************************************************************** ; Moving block ;*********************************************************************** Move Update CALL CheckButtons ; update flag register CALL SmallDelay BSF ADCON0,GO ; start AD conversion TestConversie BTFSC ADCON0,GO ; once conversion finished, GO-bit is automatically reset GOTO TestConversie MOVF ADRESH,W ; 8 MSB are stored in W, 2 LSB are stored in ADRESL but not used MOVWF CurrentLevel ; current position of the elevator is now known CALL DetermineArea MOVWF Position GOTO DetermineRequestedLevel Loop1 CALL DisplayRequestedLevel GOTO DetermineMotion ; now that current and requested position are known, determine direction and speed of the motor ; **************************************************** ; * Determine Motion routine: * ; **************************************************** DetermineMotion MOVLW b'00001000' ; to define if elevator is close enough to destination MOVWF Threshold ADDWF RequestedLevel,W SUBWF CurrentLevel,W BTFSC STATUS,0 GOTO MoveDown ; CurrentLEvel > (reqlevel+threshold) , elevator needs to travel downwards MOVF Threshold,W ADDWF CurrentLevel,W SUBWF RequestedLevel,W BTFSC STATUS,0 GOTO MoveUp ; Currentlevel < (reqlevel-threshold), move elevator up GOTO StoppingProcedure ; else (reqlevel-threshold) < current level < (reqlevel+threshold), elevator has reached the destination ; **************************************************** ; * Setup PWM routine: * ; **************************************************** SetupPWM Bank1 MOVLW H'ff' ; determines period signal MOVWF PR2 Bank0 MOVLW D'0' MOVWF CCPR1L MOVLW D'0' MOVWF CCPR2L MOVLW B'00000100' MOVWF T2CON ; Timer2 is started , prescaler = 1 MOVLW B'00001100' MOVWF CCP1CON ; 1100 indicates PWM mode, two LSB of PMW are zero MOVWF CCP2CON RETURN ; **************************************************** ; * Setup Analog routine: * ; **************************************************** SetupAnalog Bank1 MOVLW B'00001110' MOVWF ADCON1 ; only first pin of port A is analogue, VDD and VSS are reference voltages, left justified for reading result Bank0 MOVLW B'01000001' MOVWF ADCON0 ; frequency Fosc/8 , channel RA0/AN0 selected, A/D converter is activated RETURN ; **************************************************** ; * Initialize routine ; **************************************************** Initialize BSF INTCON,7 ;GIE BSF INTCON,4 ;INTE - RB0 Interrupt Enable (1=enable) BCF INTCON,1 ; these three lines are to initialize the intterupt handler MOVLW b'00000100' ; third flag up, this way he will initially head for floor 3 MOVWF Flags MOVLW b'00000000' MOVWF Position MOVLW b'10011000' MOVWF UpperLimit MOVLW b'00001000' ; Upperlimit and Lowerlimit are used to determine the area ADDWF UpperLimit,1 MOVLW b'10011000' MOVWF LowerLimit MOVLW b'00001000' SUBWF LowerLimit,1 MOVLW b'00000001' ; initially flag three is set, thus elevator travelling upwards MOVWF Direction CLRWDT ; four different duty cycles constants. Determine respectively the accelaration and decelaration in upward and in downward sense MOVLW d'7' MOVLW d'7' MOVWF DutyConstant1U MOVLW d'7' MOVWF DutyConstant2U MOVLW d'5' MOVWF DutyConstant1D MOVLW d'10' MOVWF DutyConstant2D MOVLW d'170' MOVWF DutyCycle MOVLW b'00010100' MOVWF DistanceMin ; determines when to start decelerating during the approach of a floor MOVLW B'000010' ; PL=1 MOVWF PORTA ; needed for the shift register nop nop RETURN ; **************************************************** ; * SmallDelay: +- 100ms at 8MHz oscillator frequency * ; **************************************************** SmallDelay CLRWDT MOVLW D'255' MOVWF TIMER1 SmallDelayLoop2 MOVLW D'255' MOVWF TIMER2 DECFSZ TIMER2,F GOTO $-1 DECFSZ TIMER1,F GOTO SmallDelayLoop2 RETLW 0 ; **************************************************** ; * CheckButtons routine ; **************************************************** CheckButtons movlw D'7' movwf CountSPI clrf RX MOVLW B'000110' ; STCP ON MOVWF PORTA nop MOVLW B'000010' ; STCP OFF MOVWF PORTA nop MOVLW B'000000' ; PL OFF MOVWF PORTA nop MOVLW B'000010' ; PL ON MOVWF PORTA nop Read rlf RX,1 btfss PORTA,4 bcf RX,0 nop btfsc PORTA,4 bsf RX,0 nop MOVLW B'001010' ; SHCP ON MOVWF PORTA nop MOVLW B'000010' ; SHCP OFF MOVWF PORTA decfsz CountSPI,f GOTO Read movf RX,W ; W now contains current state of the buttons IORWF Flags,1 ; if necessary flags are set in the flag register nop nop RETURN ;**************************************************** ;* Determine Area ;**************************************************** DetermineArea MOVLW b'00000000' MOVWF Position MOVF CurrentLevel,0 SUBWF LowerLimit,0 BTFSC STATUS,0 RETLW b'00000001' MOVF CurrentLevel,0 SUBWF UpperLimit,0 BTFSS STATUS,0 RETLW b'00000100' RETLW b'00000010' ; **************************************************** ; * Determine requested level ; **************************************************** DetermineRequestedLevel BTFSC Position,0 GOTO Area1 BTFSC Position,1 GOTO Area2 GOTO Area3 Area1 BTFSS Direction,0 GOTO Area1bis CALL Area1Ascending MOVWF RequestedLevel GOTO Loop1 Area1bis CALL Area1Descending MOVWF RequestedLevel GOTO Loop1 Area1Ascending BTFSC Flags,1 RETLW b'10011000' BTFSC Flags,5 RETLW b'10011000' BTFSC Flags,2 RETLW b'11101110' BTFSC Flags,6 RETLW b'11101110' BTFSC Flags,4 RETLW b'10011000' RETLW b'00101001' Area1Descending RETLW b'00101001' Area2 BTFSS Direction,0 GOTO Area2bis CALL Area2Ascending MOVWF RequestedLevel GOTO Loop1 Area2bis CALL Area2Descending MOVWF RequestedLevel GOTO Loop1 Area2Ascending BTFSC Flags,1 RETLW b'10011000' BTFSC Flags,5 RETLW b'10011000' BTFSC Flags,2 RETLW b'11101110' BTFSC Flags,6 RETLW b'11101110' BCF Direction,0 ; now look in downward direction BTFSC Flags,4 RETLW b'10011000' RETLW b'00101001' Area2Descending BTFSC Flags,1 RETLW b'10011000' BTFSC Flags,4 RETLW b'10011000' BTFSC Flags,0 RETLW b'00101001' BTFSC Flags,3 RETLW b'00101001' BSF Direction,0 ; start looking in upward direction BTFSC Flags,5 RETLW b'10011000' RETLW b'11101110' Area3 BTFSS Direction,0 GOTO Area3bis CALL Area3Ascending MOVWF RequestedLevel GOTO Loop1 Area3bis CALL Area3Descending MOVWF RequestedLevel GOTO Loop1 Area3Ascending RETLW b'11101110' Area3Descending BTFSC Flags,1 RETLW b'10011000' BTFSC Flags,4 RETLW b'10011000' BTFSC Flags,0 RETLW b'00101001' BTFSC Flags,3 RETLW b'00101001' BTFSC Flags,5 RETLW b'10011000' RETLW b'11101110' ; **************************************************** ; * End determine requested level routine ; **************************************************** ; **************************************************** ; * Display requested level routine ; **************************************************** DisplayRequestedLevel nop nop CLRF Output2 BCF STATUS,2 MOVLW b'11101110' SUBWF RequestedLevel,0 BTFSS STATUS,2 GOTO Display2 BSF Output2,LED5 RETURN Display2 BCF STATUS,2 MOVLW b'10011000' SUBWF RequestedLevel,0 BTFSS STATUS,2 GOTO Display1 BSF Output2,LED4 RETURN Display1 BCF STATUS,2 MOVLW b'00101001' SUBWF RequestedLevel,0 BTFSS STATUS,2 RETURN BSF Output2,LED3 RETURN ; **************************************************** ; * Move Up routine ; **************************************************** MoveUp MOVWF Distance ; when this routine is called the value in W is exactly what we need to determine the Distance BCF Output,Motor1A BSF Output,Motor2A CALL AdjustAscendingSpeed MOVF DutyCycle,0 MOVWF CCPR1L BSF Direction,0 GOTO Update ;*********************************************************************** ; Move elevator down ;*********************************************************************** MoveDown MOVWF Distance BCF Output,Motor2A BSF Output,Motor1A CALL AdjustDescendingSpeed MOVF DutyCycle,0 MOVWF CCPR1L BCF Direction,0 GOTO Update ; **************************************************** ; * Stopping block ; **************************************************** StoppingProcedure MOVLW D'0' ; geen spanning meer aan de motor aanleggen door duty cycle nul te maken MOVWF CCPR1L MOVLW d'180' MOVWF DutyCycle CALL ClearFlags ANDWF Flags,1 nop CALL TimeOut GOTO CheckFloor1 LoopSx GOTO CheckFloor3 LoopSy GOTO CheckFloor2 LoopSz GOTO Idle CheckFloor1 BCF STATUS,2 MOVLW b'00101001' SUBWF RequestedLevel,0 BTFSS STATUS,2 GOTO LoopSx BSF Direction,0 ; lowest floor reached, now he needs to look up again for requests MOVLW b'00001001' ANDWF Flags,0 ; are flags 1 and 1 UP still set ? MOVWF Temp2 INCF Temp2,1 DECFSZ Temp2,1 GOTO StoppingProcedure ; they are still set, call stopping procedure again and wait GOTO LoopSz ; they are no longer set, the lift can continue its journey CheckFloor3 BCF STATUS,2 MOVLW b'11101110' SUBWF RequestedLevel,0 BTFSS STATUS,2 GOTO LoopSy BCF Direction,0 ; highest floor reached, now he needs to look down again for requests MOVLW b'01000100' ANDWF Flags,0 ; are flags 3 and 3 DOWN still set ? MOVWF Temp2 INCF Temp2,1 DECFSZ Temp2,1 GOTO StoppingProcedure GOTO LoopSz CheckFloor2 BTFSS Direction,0 MOVLW b'00010010' BTFSC Direction,0 MOVLW b'00100010' ANDWF Flags,0 ; are flags 2 and 2DOWN/2UP(depending on sweep) high ? MOVWF Temp2 INCF Temp2,1 DECFSZ Temp2,1 GOTO StoppingProcedure GOTO LoopSz ; **************************************************** ; * Clear Flags procedure ; **************************************************** ClearFlags BCF STATUS,2 MOVLW b'00101001' SUBWF RequestedLevel,0 BTFSC STATUS,2 RETLW b'01110110' ; we are on floor 1 , reset flag 1 and 1 UP BCF STATUS,2 MOVLW b'11101110' SUBWF RequestedLevel,0 BTFSC STATUS,2 RETLW b'00111011' ; floor 3, reset flag 3 and 3 DOWN BTFSC Direction,0 RETLW b'01011101' ; if set (moving up), clear flag 2 and flag 2 UP RETLW b'01101101' ; else clear 2 and 2 DOWN ; **************************************************** ; * TimeOut procedure : lasts about three seconds ; **************************************************** TimeOut MOVLW b'00100000' MOVWF Counter LoopTimeOut CALL SmallDelay CALL CheckButtons DECFSZ Counter,1 GOTO LoopTimeOut RETURN ;*********************************************************************** ; AdjustAscendingSpeed ;*********************************************************************** AdjustAscendingSpeed MOVF DistanceMin,0 SUBWF Distance,0 BTFSC STATUS,0 GOTO IncreaseDutyCycle GOTO DecreaseDutyCycle IncreaseDutyCycle MOVF DutyCycle,0 ADDWF DutyConstant1U,0 BTFSC STATUS,0 ; if this sum is > 255 , then carry bit will be set and this way we now if the DC needs to be limited MOVLW d'255' MOVWF DutyCycle RETURN DecreaseDutyCycle MOVF DutyConstant2U,0 SUBWF DutyCycle,1 MOVF DutyCycle,0 MOVWF Temp2 MOVLW d'180' SUBWF Temp2,1 BTFSS STATUS,0 MOVWF DutyCycle RETURN ;*********************************************************************** ; AdjustDescendingSpeed: bepaalt duty cycle tijdens het dalen ;*********************************************************************** AdjustDescendingSpeed MOVF DistanceMin,0 SUBWF Distance,0 BTFSC STATUS,0 GOTO IncreaseDutyCycle2 GOTO DecreaseDutyCycle2 IncreaseDutyCycle2 MOVF DutyConstant1D,0 ADDWF DutyCycle,1 MOVF DutyCycle,0 MOVWF Temp2 MOVLW d'235' SUBWF Temp2,1 ; chosen such that ascending speed and descending speed match (experimentally determined) BTFSC STATUS,0 MOVWF DutyCycle RETURN DecreaseDutyCycle2 MOVF DutyConstant2D,0 SUBWF DutyCycle,1 MOVF DutyCycle,0 MOVWF Temp2 MOVLW d'180' SUBWF Temp2,1 BTFSS STATUS,0 MOVWF DutyCycle RETURN ; **************************************************** ; * Interrupt Routine ; **************************************************** Interrupt MOVWF Temp CALL EmergencyProcedure BCF INTCON,1 ; CLEAREN if new interrupts are to be detected, not done automatically MOVF Temp,0 ; restore original value in W CALL SmallDelay CALL SmallDelay RETFIE ; **************************************************** ; * Emergency Routine ; **************************************************** EmergencyProcedure MOVLW D'0' MOVWF CCPR1L MOVLW b'10000000' ; just to see if it was a roof or bottom hit SUBWF CurrentLevel,0 BTFSC STATUS,0 GOTO EmergencyProcedure2 ; roof hit EmergencyProcedure1 BCF Output,Motor1A BSF Output,Motor2A MOVLW D'200' MOVWF CCPR1L BSF Direction,0 MOVLW b'00000001' MOVWF Flags ; all flags cleared, flag for level one is set MOVLW b'00101001' MOVWF RequestedLevel RETURN EmergencyProcedure2 BCF Output,Motor2A BSF Output,Motor1A MOVLW D'200' MOVWF CCPR1L BCF Direction,0 MOVLW b'00000100' MOVWF Flags ; all flags are cleard, flag for level three is set MOVLW b'11101110' MOVWF RequestedLevel RETURN ;*********************************************************************** ; Testroutines (instead of LEDS, used duty cycle PWM 2 ) ;*********************************************************************** TestLed MOVLW b'00001000' MOVWF Output CALL SmallDelay RETURN Testroutine1 MOVLW D'25' MOVWF CCPR2L CALL SmallDelay RETURN Testroutine2 MOVLW D'125' MOVWF CCPR2L CALL SmallDelay RETURN Testroutine3 MOVLW D'250' MOVWF CCPR2L CALL SmallDelay RETURN Testroutine0 MOVLW D'0' MOVWF CCPR2L CALL SmallDelay RETURN Errror MOVLW D'50' MOVWF CCPR2L CALL SmallDelay RETURN END