# 16F676 programming problem

Status
Not open for further replies.

#### swapan

##### Member
Hello friends,
I have taken up a project using 16F676 which will switch on a gadget to battery position when there is no AC Main supply. On resumption of AC Main supply the microcontroller will take some delay for stabilization of main supply then switch over to AC Main position. Also before switching over to ‘main’ position the microcontroller will check if the main supply is within permissible limit. When checking the stages one by one I face a problem in delay loop. Please see the code. When no delay is used the program works well. But on insertion of delay loop the BTFSC instruction has no effect and the relay operated from RA2 remains on even the RC5 bit is made ground. Please help.

Code:
config. bits. MCLR-OFF, PWRTE-OFF, CP-OFF, WDT-OFF, INTOSC

cblock 0x20
count1
count2
count3
endc

BSF STATUS, RP0
MOVLW 0X38
MOVWF TRISA
MOVLW 0X2C
MOVWF TRISC
MOVLW 0XC0
MOVWF ANSEL
MOVLW 0X87
MOVWF OPTION_REG
BCF STATUS, RP0
MOVLW 0X7
MOVWF CMCON
MOVLW 0X19
MOVLW b'00100000'
MOVWF INTCON

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BTFSS PORTC, 5 ; See if AC Main is present
GOTO AC_ON
INV_ON: MOVLW 0X4 ; If not, turn on Change Over Relay
MOVWF PORTA ; to inverter position.
CONT1: BTFSC PORTC,5
GOTO CONT1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

AC_ON:
MOVLW D’10’ ; D
MOVWF COUNT3 ;
CT_2: MOVLW D’255’ ; E
MOVWF COUNT2 ;
CT_1: MOVLW D’255’ ; L
MOVWF COUNT1 ;
WAIT_1: BCF INTCON,2 ; A
DLY_1: BTFSC PORTC, 5 ;
GOTO INV_ON ; Y
BTFSS INTCON,2 ;
GOTO DLY_1 ;
DECFSZ COUNT1,1 ;
GOTO WAIT_1 ;
DECFSZ COUNT2,1 ;
GOTO CT_1 ;
DECFSZ COUNT3,1 ;
GOTO CT_2 ;
MOVLW b'00000000'
MOVWF PORTC ; Turn off change over relay to switch
over to Main position.
CONT2: BTFSC PORTC, 5 ; Check if AC Main is present or not.
GOTO INV_ON ; If present continue here otherwise
GOTO CONT2 turn on relay .

END

#### ericgibbs

##### Well-Known Member
hi,
You are also using PORTC,5 in the Delay subr.!

Code:
config.	bits.	MCLR-OFF, PWRTE-OFF, CP-OFF, WDT-OFF, INTOSC

cblock	0x20
count1
count2
count3
endc

bsf	STATUS, RP0
movlw	0X38
movwf	TRISA
movlw	0X2C
movwf	TRISC
movlw	0XC0
movwf	ANSEL
movlw	0X87
movwf	OPTION_REG
bcf	STATUS, RP0
movlw	0X7
movwf	CMCON
movlw	0X19
movlw	b'00100000'
movwf	INTCON

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;
btfss	PORTC,5		; See if AC Main is present
goto	AC_ON
INV_ON:	movlw	0X4		; If not, turn on Change Over Relay
movwf	PORTA		; to inverter position.
CONT1:	btfsc	PORTC,5
goto	CONT1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;

AC_ON:
movlw	D’10’		; D
movwf	COUNT3		;
CT_2:	movlw	D’255’		; E
movwf	COUNT2		;
CT_1:	movlw	D’255’		; L
movwf	COUNT1		;
WAIT_1:	bcf	INTCON,2	; A
DLY_1:	[COLOR="Blue"]btfsc	PORTC,5[/COLOR]		;
goto	INV_ON		; Y
btfss	INTCON,2	;
goto	DLY_1		;
decfsz	COUNT1,1	;
goto	WAIT_1		;
decfsz	COUNT2,1	;
goto	CT_1		;
decfsz	COUNT3,1	;
goto	CT_2		;
movlw	b'00000000'
movwf	PORTC		; Turn off change over relay to switch
;over	to	Main position.
CONT2:	btfsc	PORTC,5		; Check if AC Main is present or not.
goto	INV_ON		; If present continue here otherwise
goto	CONT2 turn on relay .

end

Last edited:

#### kpatz

##### New Member
There's a few bugs...

First, after the delay, when you "turn off change over relay to switch over to Main position" near the bottom of the code, you're setting PORTC to all zeros. When you switched the relay on in INV_ON, you're setting PORTA. So, in the changed code below I changed the relay-off to PORTA.

Second of all, your delay routine is very long. The changes below give me a 3-4 second delay with a 20MHz clock (if you're using the internal oscillator it won't be more than 8 MHz). With your delay values the delay would be many hours or days!

When you post code on here, enclose it in [ CODE ] ... [ /CODE ] tags so the formatting isn't lost.

Code:
;config. bits. MCLR-OFF, PWRTE-OFF, CP-OFF, WDT-OFF, INTOSC
list      p=16F676            ; list directive to define processor
#include <p16F676.inc>        ; processor specific variable definitions

__CONFIG   _MCLRE_OFF & _PWRTE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT

cblock 0x20
COUNT1
COUNT2
COUNT3
endc

BSF STATUS, RP0
MOVLW 0X38
MOVWF TRISA
MOVLW 0X2C
MOVWF TRISC
MOVLW 0XC0
MOVWF ANSEL
MOVLW 0X87
MOVWF OPTION_REG
BCF STATUS, RP0
MOVLW 0X7
MOVWF CMCON
MOVLW 0X19
MOVLW b'00100000'
MOVWF INTCON

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;
BTFSS PORTC, 5 ; See if AC Main is present
GOTO AC_ON
INV_ON:
MOVLW 0X4 ; If not, turn on Change Over Relay
MOVWF PORTA ; to inverter position.
CONT1:
BTFSC PORTC,5
GOTO CONT1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;

AC_ON:
MOVLW D'1' ; D
MOVWF COUNT3 ;
CT_2:
MOVLW D'1' ; E
MOVWF COUNT2 ;
CT_1:
MOVLW D'255' ; L
MOVWF COUNT1 ;
WAIT_1:
BCF INTCON,2 ; A
DLY_1:
BTFSC PORTC, 5 ;
GOTO INV_ON ; Y
BTFSS INTCON,2 ;
GOTO DLY_1 ;
DECFSZ COUNT1,1 ;
GOTO WAIT_1 ;
DECFSZ COUNT2,1 ;
GOTO CT_1 ;
DECFSZ COUNT3,1 ;
GOTO CT_2 ;
MOVLW b'00000000'
MOVWF PORTA ; Turn off change over relay to switch over to Main position.
CONT2:
BTFSC PORTC, 5 ; Check if AC Main is present or not.
GOTO INV_ON ; If present continue here otherwise
GOTO CONT2  ;turn on relay .

END

#### swapan

##### Member
There's a few bugs...

First, after the delay, when you "turn off change over relay to switch over to Main position" near the bottom of the code, you're setting PORTC to all zeros. When you switched the relay on in INV_ON, you're setting PORTA. So, in the changed code below I changed the relay-off to PORTA.

Second of all, your delay routine is very long. The changes below give me a 3-4 second delay with a 20MHz clock (if you're using the internal oscillator it won't be more than 8 MHz). With your delay values the delay would be many hours or days!

When you post code on here, enclose it in [ CODE ] ... [ /CODE ] tags so the formatting isn't lost.

Code:
;config. bits. MCLR-OFF, PWRTE-OFF, CP-OFF, WDT-OFF, INTOSC
list      p=16F676            ; list directive to define processor
#include <p16F676.inc>        ; processor specific variable definitions

__CONFIG   _MCLRE_OFF & _PWRTE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT

cblock 0x20
COUNT1
COUNT2
COUNT3
endc

BSF STATUS, RP0
MOVLW 0X38
MOVWF TRISA
MOVLW 0X2C
MOVWF TRISC
MOVLW 0XC0
MOVWF ANSEL
MOVLW 0X87
MOVWF OPTION_REG
BCF STATUS, RP0
MOVLW 0X7
MOVWF CMCON
MOVLW 0X19
MOVLW b'00100000'
MOVWF INTCON

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;
BTFSS PORTC, 5 ; See if AC Main is present
GOTO AC_ON
INV_ON:
MOVLW 0X4 ; If not, turn on Change Over Relay
MOVWF PORTA ; to inverter position.
CONT1:
BTFSC PORTC,5
GOTO CONT1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;

AC_ON:
MOVLW D'1' ; D
MOVWF COUNT3 ;
CT_2:
MOVLW D'1' ; E
MOVWF COUNT2 ;
CT_1:
MOVLW D'255' ; L
MOVWF COUNT1 ;
WAIT_1:
BCF INTCON,2 ; A
DLY_1:
BTFSC PORTC, 5 ;
GOTO INV_ON ; Y
BTFSS INTCON,2 ;
GOTO DLY_1 ;
DECFSZ COUNT1,1 ;
GOTO WAIT_1 ;
DECFSZ COUNT2,1 ;
GOTO CT_1 ;
DECFSZ COUNT3,1 ;
GOTO CT_2 ;
MOVLW b'00000000'
MOVWF PORTA ; Turn off change over relay to switch over to Main position.
CONT2:
BTFSC PORTC, 5 ; Check if AC Main is present or not.
GOTO INV_ON ; If present continue here otherwise
GOTO CONT2  ;turn on relay .

END

Many thanks Mr. kpatz. The program is working fine. By mistake the PORTC was made clear instead of PORTA. Your pointing out the mistake in delay time helped me a lot. I think instead of using 2 counts loaded with D'1' each , if one count is loaded with D'2' the delay time will be the same. Please confirm.

#### swapan

##### Member
hi,
You are also using PORTC,5 in the Delay subr.!

Code:
config.	bits.	MCLR-OFF, PWRTE-OFF, CP-OFF, WDT-OFF, INTOSC

cblock	0x20
count1
count2
count3
endc

bsf	STATUS, RP0
movlw	0X38
movwf	TRISA
movlw	0X2C
movwf	TRISC
movlw	0XC0
movwf	ANSEL
movlw	0X87
movwf	OPTION_REG
bcf	STATUS, RP0
movlw	0X7
movwf	CMCON
movlw	0X19
movlw	b'00100000'
movwf	INTCON

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;
btfss	PORTC,5		; See if AC Main is present
goto	AC_ON
INV_ON:	movlw	0X4		; If not, turn on Change Over Relay
movwf	PORTA		; to inverter position.
CONT1:	btfsc	PORTC,5
goto	CONT1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;

AC_ON:
movlw	D’10’		; D
movwf	COUNT3		;
CT_2:	movlw	D’255’		; E
movwf	COUNT2		;
CT_1:	movlw	D’255’		; L
movwf	COUNT1		;
WAIT_1:	bcf	INTCON,2	; A
DLY_1:	[COLOR="Blue"]btfsc	PORTC,5[/COLOR]		;
goto	INV_ON		; Y
btfss	INTCON,2	;
goto	DLY_1		;
decfsz	COUNT1,1	;
goto	WAIT_1		;
decfsz	COUNT2,1	;
goto	CT_1		;
decfsz	COUNT3,1	;
goto	CT_2		;
movlw	b'00000000'
movwf	PORTC		; Turn off change over relay to switch
;over	to	Main position.
CONT2:	btfsc	PORTC,5		; Check if AC Main is present or not.
goto	INV_ON		; If present continue here otherwise
goto	CONT2 turn on relay .

end

Thanks Mr. ericgibbs for your reply. Actually I wanted to monitor the presence or absence of AC main supply frequently. Hence the instruction btfsc PORTC,5 has been used. Since TMR0 is used to count internal instruction cycle, I think it will make no difference if the said instruction is used. Your kind remark is solicited.

#### kpatz

##### New Member
I think instead of using 2 counts loaded with D'1' each , if one count is loaded with D'2' the delay time will be the same. Please confirm.
That should work fine. I just changed both to D'1' as a quick fix. You only need 2 delay counts (instead of 3) for the delay you need. You can use the stopwatch in the simulator in MPLAB to see how long your delay will be and then you can tweak the counts to get it the way you want. An even better way is to use one of the timers.

Last edited:

#### Mike - K8LH

##### Well-Known Member
How long of a delay are you trying to achieve? It's not clear in your source code.

#### Gayan Soyza

##### Active Member
A better method.

Get the transformer ratio & measure the output voltage of the transformer. This will indirectly measure the supply voltage.

A transformer rating of 230/12V has the following results. (The values may have slightly higher than the shown below after converting to DC)

230V it will show you 12.0V
240V it will show you 12.56V
220V it will show you 11.51V

Measure this voltage with AD ( after scaling to 5V) & check the line voltage is within the limits.

#### swapan

##### Member
That should work fine. I just changed both to D'1' as a quick fix. You only need 2 delay counts (instead of 3) for the delay you need. You can use the stopwatch in the simulator in MPLAB to see how long your delay will be and then you can tweak the counts to get it the way you want. An even better way is to use one of the timers.

Actuallu TMR0 has been used in the program by clearing bit 5 (T0CS) of POTION_REG. I could not got the idea of using one of the timers. Would you please throw some light?

#### swapan

##### Member
A better method.

Get the transformer ratio & measure the output voltage of the transformer. This will indirectly measure the supply voltage.

A transformer rating of 230/12V has the following results. (The values may have slightly higher than the shown below after converting to DC)

230V it will show you 12.0V
240V it will show you 12.56V
220V it will show you 11.51V

Measure this voltage with AD ( after scaling to 5V) & check the line voltage is within the limits.

I am thankful to you Mr. Gayan Soyza. Whenever I post any tag you have given your valuable comment. Actually, I shall employ the same idea as you have opined. Before proceeding further I have tested one part i.e. monitoring the presence or absence of AC Main. If there is no AC Main the circuit will immediately switch over to inverter position. On resumption of AC Main the circuit will switch over to AC Main position after some delay. During the delay period the circuit will continue checking the AC Main. Program for this has been tested successfully. Now I shall concentrate on checking the input AC Main voltage level. Certainly your idea will be employed.

#### Mr RB

##### Well-Known Member
(edit) my post removed, it was not relevant for an inverter.

Last edited:
Status
Not open for further replies.

Replies
1
Views
869
Replies
6
Views
3K
Replies
2
Views
1K
Replies
14
Views
1K
Replies
4
Views
1K