Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] Power factor measurement using PIC18f4520

Status
Not open for further replies.
Hi Klaus, thank you

You mean that I can use the LM7812?

I tried connecting it, its resultant output voltage was around 9V.
I supplied it from the rectified and capacitor filtered 12VAC.
 

A rectified and capacitor filtered 12 V AC signal can reach up to 17V DC. (12V x 1.414 ) ... subtract about 1.4V for full bridge rectifier.
So you should rather expect up to 20V DC.

There are two aspects:

first: 17 (peak value) - 1.5 (voltage drop) = 15.5 V (usable): not 20V DC

second: the peak value of 17V is available only for an instant in the half-cycle; this will drop even with a very small load. Whereas the capacitor remains charged to the peak voltage in absence of any load but for real load you should only take the factor as 1.2 or even 1.1.
 
LM7812.

If the transformer secondary is 12V RMS, the voltage after rectification and across the reservoir capacitor will be 1.414 times the RMS voltage (square root of 2) minus the drop in the two conducting diodes of the bridge rectifier (~0.7V) so even at 12V RMS you should have (12 * 1.414) - (2 * 0.7) = 15.6V, thats more than enough for a normal 12V linear regulator when the current is so low.

I haven't had chance to look at the flow chart yet - I will reply again later. Got the PM, thank you !

Brian.
 
Hello and thank you all!

Here is the full code, version 1. such that in within everything is working greatly, even if load is disconnected a buzzer and LCD notification is there to tell the user to connect load.
All ADC measurement are very acceptable.

Even if the user presses the button before calculations are done, the code does not get stuck at last program counter position.

The only problem is when every calculation is done, and the user is prompted to switch the button, after the Gosub setuppic statement the code gets stuck at last where it was, which is in this case the lcdout "Press Red Button" statement. Also if the user suddenly disconnects the load at any time after calculation are set, the code re-direct itself to capbankcalc function.

Code:
ASM:        org 0x800
Define LCD_LINES = 4
Define LCD_CHARS = 16
Define LCD_BITS = 8  'allowed values are 4 and 8 - the number of data interface lines
Define LCD_DREG = PORTC
Define LCD_DBIT = 0  '0 or 4 for 4-bit interface, ignored for 8-bit interface
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 0
Define LCD_EREG = PORTD
Define LCD_EBIT = 2
Define LCD_RWREG = PORTD  'set to 0 if not used, 0 is default
Define LCD_RWBIT = 1  'set to 0 if not used, 0 is default
Define LCD_COMMANDUS = 2000  'delay after LCDCMDOUT, default value is 5000
Define LCD_DATAUS = 100  'delay after LCDOUT, default value is 100
Define LCD_INITMS = 100  'delay used by LCDINIT, default value is 100
Define ADC_SAMPLEUS = 255

Lcdinit 0  'initialize LCD module; cursor is blinking



Dim volt As Word
Dim x As Single
Dim current As Word
Dim y As Single
Dim zz As Single
Dim pow As Single
Dim phase As Word
Dim phasean As Single
Dim currentan As Single
Dim currentan2 As Single
Dim allcurrent As Single
Dim flag As Word
Dim fudgefactor As Single
Dim phasedeg As Single
Dim pf As Single
Dim intflag As Byte
Dim curtest As Word

Dim vcounter As Word
Dim icounter As Word
Dim pcounter As Word
'icounter = 30
vcounter = 30
pcounter = 5
intflag = 0
x = 0
y = 0
zz = 0
pf = 0
fudgefactor = 28
phase = 0
phasean = 0

ConfigPin PORTD.3 = Output
Low PORTD.3


main:
INTCON.GIE = 0
Lcdcmdout LcdClear
Lcdout "Processing..."
WaitMs 300
Lcdcmdout LcdLine2Home
Lcdout "Testing System"
WaitMs 300
Lcdcmdout LcdLine3Home
Lcdout "Checking Inputs"

voltageloop:
While vcounter > 0
Adcin 3, volt

x = x + volt
vcounter = vcounter - 1
volt = 0
Wend

x = x / 30
x = x * 5 / 1024
x = x * (1510 / 510)
x = x + 0.5
x = x * 16.30

WaitMs 5000

Lcdcmdout LcdClear
Lcdout "Vinput: ", #x, "V"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
currentloop:
icounter = 30
While icounter > 0
Adcin 1, current
	
	y = y + current
	icounter = icounter - 1
	current = 0
	Wend

	y = y / 30
	WaitMs 2000
	
	If fudgefactor > y Then
		Goto noload
	Else
	If y > fudgefactor Then
		Goto load
	Endif
	Endif
	
	
noload:
	flag = 0
	Lcdcmdout LcdLine2Home
	Lcdout "I: 0 A"
	WaitMs 800
	Lcdcmdout LcdLine3Home
	Lcdout "Power = 0W"
	WaitMs 800
	Lcdcmdout LcdLine4Home
	Lcdout "CONNECT LOAD"
	WaitMs 500
	Lcdcmdout LcdLine4Clear
	High PORTD.3
	WaitMs 1000
	Low PORTD.3
	Goto currentloop
	
load:
	flag = 1
	currentan = y * 5 / 1024
	currentan2 = currentan + 0.063
	allcurrent = currentan2 * 0.2
Lcdcmdout LcdLine2Clear
Lcdcmdout LcdLine3Clear
Lcdcmdout LcdLine4Clear
Lcdcmdout LcdLine2Home
Lcdout "I(load)= ", #allcurrent, "A"

WaitMs 1000
'''''''''''''''''''''''''''''''''''''''''''		
If flag = 1 Then
	Lcdcmdout LcdLine3Home
	pow = allcurrent * x
	Lcdout "Power: ", #pow, "W"
	WaitMs 1000
	
	Lcdcmdout LcdLine4Home
	Lcdout "Calculating pf.."
	WaitMs 8000

	Adcin 2, phase
	
	
	Lcdcmdout LcdLine4Clear
	Lcdcmdout LcdLine4Home
	phasean = phase / 14.869
	phasean = phasean / 1.6
	Lcdout "Phase: ", #phasean
	WaitMs 4000
	phasedeg = phasean * 0.01745329
	Lcdcmdout LcdLine4Clear
	pf = Cos(phasedeg)
	Lcdout "pf: ", #pf
	WaitMs 1000
	Endif
	Gosub here
	
	
prog_end:
End                                               
setuppic:
	INTCON.GIE = 1
	TRISB = 0x03
	T1CON = 0x24
	INTCON = 0x10
	INTCON2 = 0xe0
	INTCON3 = 0x48
	ADCON1 = 0x0f
	Enable High
Return                                            

isr:
On High Interrupt
	If INTCON.INT0IF = 1 Then
			INTCON.INT0IF = 0
			Goto capbankcalc
	Endif
Resume                                            
here:
		
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Press Red Button"
	Lcdcmdout LcdLine2Home
	Lcdout "To Continue"
	WaitMs 1000
	
	Gosub setuppic
		
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Vinput: ", #x, "V"
	
	Lcdcmdout LcdLine2Home
	Lcdout "I(load)= ", #allcurrent, "A"
	Lcdcmdout LcdLine3Home
	Lcdout "Power: ", #pow, "W"
	
	Lcdcmdout LcdLine4Home
	Lcdout "pf: ", #pf
	
	WaitMs 1000
	
	Goto here
Return                                            
capbankcalc:
Lcdcmdout LcdClear
Lcdout "The input pf"
Lcdcmdout LcdLine2Home
Lcdout "is: ", #pf
If pf > 0.85 Then
	Lcdcmdout LcdLine3Home
	Lcdout "pf is optimal"
	WaitMs 1000
	Goto prog_end
Else
Lcdcmdout LcdLine3Home
Lcdout "Correcting..."
WaitMs 1000
Endif
Return

Thanks
 

Hopefully it's a simple fix:

You "Goto" capbankcalc but you "Return" from it. Try changing the "Goto" to "Gosub".

I'll explain the difference:

A "Goto" means simply jump to another place in the program, in technical terms, it loads the PIC program counter with the address you are going to and it carries on running from there.

A "Gosub" is similar but it expects your program to continue with the next instruction when the subroutine has finished. To do that, it first saves the address of the next instruction on the PIC 'stack' then does the same as a "Goto". At the end of a subrutine you use a "Return" instruction which picks up the return addess from the stack and loads it back in the program counter so the program continues from the instruction in the program after the "Gosub". Its rather like dropping a section of code (the subroutine) in-line with the program but gives you tha advantage of clearer to read code and the ability to use the same subroutine in several places.

If you look at the flow in your program, when the interrupt occurs, you "Goto capbankcalc" and start executing the code there but at it's end you try to recover the return address from the stack and jump back to it without the address ever being stored. It means the PIC would jump to whatever address corresponded with the number currently on the stack which could be almost anything as the stack is also used by internal compiler routines. A secondary problem is because you jumped out of the ISR it never reaches the "Resume" instruction to finsh the interrupt processing. Changing to "Gosub" should fix both problems.

Brian.
 
Thank you Brian!!

I did change the Goto in the ISR to a Gosub statement, but results were still the same:

The code gets stuck at
Code:
Gosub setuppic
after the
Code:
        Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Press Red Button"
	Lcdcmdout LcdLine2Home
	Lcdout "To Continue"
	WaitMs 1000

in the 'here' function



Thank you

P.s the system would automatically go to capbankcalc function if load is suddenly Disconnected
 

Move the line "Gosub setuppic" to just after 'main:'. You only need to initialize the PIC registers once, what you are doing is initializing them on every pass of the loop which upsets the interrupt bits. In particular, you enable the global interrupt which upsets the way the interrupt system works. When something triggers an interrupt, as well as jumping to the ISR, the PIC automatically disables GIE to prevent other interrupts until the ISR has finished. When the 'Resume' instruction is executed, the GIE bit is restored and the program flow continues from where it was before the interrupt. By enabling the GIE in your loop, you are defeating the automatic control when you enter the ISR.

Incidentally, there is no point in using the "ASM: org 0x800" line at all. It forces the code to start at address 0x800 instead of 0x000 and leaves 2K of memory unused. If you look at the memory usage graph, removing the line take the usage down from 29% to 22% without affecting how it works.

Brian.
 
Move the line "Gosub setuppic" to just after 'main:'. You only need to initialize the PIC registers once, what you are doing is initializing them on every pass of the loop which upsets the interrupt bits. In particular, you enable the global interrupt which upsets the way the interrupt system works. When something triggers an interrupt, as well as jumping to the ISR, the PIC automatically disables GIE to prevent other interrupts until the ISR has finished. When the 'Resume' instruction is executed, the GIE bit is restored and the program flow continues from where it was before the interrupt. By enabling the GIE in your loop, you are defeating the automatic control when you enter the ISR.

Incidentally, there is no point in using the "ASM: org 0x800" line at all. It forces the code to start at address 0x800 instead of 0x000 and leaves 2K of memory unused. If you look at the memory usage graph, removing the line take the usage down from 29% to 22% without affecting how it works.

Brian.


Hello Brian, thank you!

I tried from the beginning to put "Gosub setuppic" right after main, the program works totally efficiently, and the 'here' function completes itself but unfortunately, the only problem using this, is when user's presses the push-button before asked on LCD, the entire code stucks at last task it was operating.

Moreover, I also tried in the past, not writing any ASM statement at the beginning, orelse trying ASM 0X00 instead of ASM 0X800, the results were the same, as the .bas file compiles greatly, but the .hex file burned on PIC does not make it operates.
In the F1 manual of Oshonsoft software, Vlad'd written that when burning on real hardware, an ASM: 0X800 must be stated.

Due to reasons stated above, I thought that maybe a solution, is where I disable interrupts at the beginning of the code, in a way that if user presses te button whatever if intended or by mistake, the code won't react, unless got to a point where the press means something (in the 'here' function after all V, I, P, pf are calculated) the code must react to that press.

Also there is a weird problem, that is if user unplugs load after all calculations are made, and didn't press push-button, the code re-directs itself to 'capbankcalc' function.

Thanks
 

Hello,


Code:
ASM:        org 0x800
Define LCD_LINES = 4
Define LCD_CHARS = 16
Define LCD_BITS = 8  'allowed values are 4 and 8 - the number of data interface lines
Define LCD_DREG = PORTC
Define LCD_DBIT = 0  '0 or 4 for 4-bit interface, ignored for 8-bit interface
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 0
Define LCD_EREG = PORTD
Define LCD_EBIT = 2
Define LCD_RWREG = PORTD  'set to 0 if not used, 0 is default
Define LCD_RWBIT = 1  'set to 0 if not used, 0 is default
Define LCD_COMMANDUS = 2000  'delay after LCDCMDOUT, default value is 5000
Define LCD_DATAUS = 100  'delay after LCDOUT, default value is 100
Define LCD_INITMS = 100  'delay used by LCDINIT, default value is 100
Define ADC_SAMPLEUS = 255

Lcdinit 0


Dim volt As Word
Dim x As Single
Dim current As Word
Dim y As Single
Dim zz As Single
Dim pow As Single
Dim phase As Word
Dim phasean As Single
Dim currentan As Single
Dim currentan2 As Single
Dim allcurrent As Single
Dim flag As Word
Dim fudgefactor As Single
Dim phasedeg As Single
Dim pf As Single
Dim intflag As Byte


Dim vcounter As Word
Dim icounter As Word
Dim pcounter As Word
'icounter = 30
vcounter = 30
pcounter = 5
intflag = 0
x = 0
y = 0
zz = 0
pf = 0
fudgefactor = 37
phase = 0
phasean = 0

ConfigPin PORTD.3 = Output
Low PORTD.3


main:
intflag = 0
Lcdcmdout LcdClear
Lcdout "Processing..."
WaitMs 300
Lcdcmdout LcdLine2Home
Lcdout "Testing System"
WaitMs 300
Lcdcmdout LcdLine3Home
Lcdout "Checking Inputs"

voltageloop:
While vcounter > 0
Adcin 3, volt

x = x + volt
vcounter = vcounter - 1
volt = 0
Wend

x = x / 30
x = x * 5 / 1024
x = x * (1510 / 510)
x = x + 0.5
x = x * 16.30

WaitMs 5000

Lcdcmdout LcdClear
Lcdout "Vinput: ", #x, "V"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
currentloop:
icounter = 30
While icounter > 0
Adcin 1, current
	
	y = y + current
	icounter = icounter - 1
	current = 0
	Wend

	y = y / 30
	WaitMs 2000
	
	If fudgefactor > y Then
		Goto noload
	Else
	If y > fudgefactor Then
		Goto load
	Endif
	Endif
	
	
noload:
	flag = 0
	Lcdcmdout LcdLine2Home
	Lcdout "I: 0 A"
	WaitMs 800
	Lcdcmdout LcdLine3Home
	Lcdout "Power = 0W"
	WaitMs 800
	Lcdcmdout LcdLine4Home
	Lcdout "CONNECT LOAD"
	WaitMs 500
	Lcdcmdout LcdLine4Clear
	High PORTD.3
	WaitMs 1000
	Low PORTD.3
	Goto currentloop
	
load:
	flag = 1
	currentan = y * 5 / 1024
	currentan2 = currentan + 0.063
	allcurrent = currentan2 * 0.2
Lcdcmdout LcdLine2Clear
Lcdcmdout LcdLine3Clear
Lcdcmdout LcdLine4Clear
Lcdcmdout LcdLine2Home
Lcdout "I(load)= ", #allcurrent, "A"

WaitMs 1000
'''''''''''''''''''''''''''''''''''''''''''
If flag = 1 Then
	Lcdcmdout LcdLine3Home
	pow = allcurrent * x
	Lcdout "Power: ", #pow, "W"
	WaitMs 1000
	
	Lcdcmdout LcdLine4Home
	Lcdout "Calculating pf.."
	WaitMs 8000

	Adcin 2, phase
	
	
	Lcdcmdout LcdLine4Clear
	Lcdcmdout LcdLine4Home
	phasean = phase / 14.869
	phasean = phasean / 1.6
	Lcdout "Phase: ", #phasean
	WaitMs 4000
	phasedeg = phasean * 0.01745329
	Lcdcmdout LcdLine4Clear
	pf = Cos(phasedeg)
	Lcdout "pf: ", #pf
	WaitMs 1000
	Endif
	Gosub setuppic
	Gosub here
	
	
prog_end:
End                                               


isr:
On High Interrupt
	If INTCON.INT0IF = 1 Then
		If intflag = 1 Then
			INTCON.INT0IF = 0
			Gosub capbankcalc
		Endif
	Endif
Resume                                            
here:
	intflag = 1
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Press Red Button"
	Lcdcmdout LcdLine2Home
	Lcdout "To Continue"
	WaitMs 1000
	
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Vinput: ", #x, "V"
	
	Lcdcmdout LcdLine2Home
	Lcdout "I(load)= ", #allcurrent, "A"
	Lcdcmdout LcdLine3Home
	Lcdout "Power: ", #pow, "W"
	
	Lcdcmdout LcdLine4Home
	Lcdout "pf: ", #pf
	
	WaitMs 1000
	
	Goto here
Return                                            
capbankcalc:
Lcdcmdout LcdClear
Lcdout "The input pf"
Lcdcmdout LcdLine2Home
Lcdout "is: ", #pf
If pf > 0.85 Then
	Lcdcmdout LcdLine3Home
	Lcdout "pf is optimal"
	WaitMs 1000
	Goto prog_end
Else
Lcdcmdout LcdLine3Home
Lcdout "Correcting..."
WaitMs 1000
Endif
Return                                            

setuppic:
TRISB = 0x03
T1CON = 0x24
INTCON = 0x10
INTCON2 = 0xe0
INTCON3 = 0x48
ADCON1 = 0x0f
Enable High
Return

In the above code, as well as all other codes, the main problem arrive when "Gosub setuppic" in other words, the code starts acting weird, in whatever form it was written at the point when you define INTCON bits, and TRISB etc...

Whenever arrived to defining the setup of the PIC for interrupt and PORTB.0 as input, the whole code stucks.

Perhaps HEX values within these registers are causing this problem??

Thank you
 

The ASM line can be removed, it's purpose is to move the start of the program to 0x800 so room is left for Oshonsoft's bootloader code. If you are not using a serial link and pre-programmed bootloader it isn't needed and just wastes space.

The program flow still doesn't match your flow chart but I have tried to make it nearer with the code below. You will have to add a " ' " to the start of the second line to make it a comment before programming it in real hardware. Programming in BASIC is torture, it would be so easy to write the code in functional blocks but Oshonsofts compiler doesn't support returning values from subroutines, functions or procedures so all variables have to be global. It makes the code far more complicated than it needs to be.

Brian.
Code:
'comment out the following line before compiling for real hardware!!
Define SIMULATION_WAITMS_VALUE = 1

Define LCD_LINES = 4
Define LCD_CHARS = 16
Define LCD_BITS = 8  'allowed values are 4 and 8 - the number of data interface lines
Define LCD_DREG = PORTC
Define LCD_DBIT = 0  '0 or 4 for 4-bit interface, ignored for 8-bit interface
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 0
Define LCD_EREG = PORTD
Define LCD_EBIT = 2
Define LCD_RWREG = PORTD  'set to 0 if not used, 0 is default
Define LCD_RWBIT = 1  'set to 0 if not used, 0 is default
Define LCD_COMMANDUS = 2000  'delay after LCDCMDOUT, default value is 5000
Define LCD_DATAUS = 100  'delay after LCDOUT, default value is 100
Define LCD_INITMS = 100  'delay used by LCDINIT, default value is 100
Define ADC_SAMPLEUS = 255

Dim volt As Word
Dim x As Single
Dim current As Word
Dim y As Single
Dim zz As Single
Dim pow As Single
Dim phase As Word
Dim phasean As Single
Dim currentan As Single
Dim currentan2 As Single
Dim allcurrent As Single
Dim fudgefactor As Single
Dim phasedeg As Single
Dim pf As Single
Dim vcounter As Word
Dim icounter As Word
Dim pcounter As Word
Dim switch_pressed As Byte
Dim current_measured As Byte

'icounter = 30
vcounter = 30
pcounter = 5
current_measured = 0
x = 0
y = 0
zz = 0
pf = 0
fudgefactor = 37
phase = 0
phasean = 0

Lcdinit 0


ConfigPin PORTD.3 = Output
Low PORTD.3


main:
	Gosub setuppic

	Lcdcmdout LcdClear
	Lcdout "Processing..."
	WaitMs 300
	Lcdcmdout LcdLine2Home
	Lcdout "Testing System"
	WaitMs 300
	Lcdcmdout LcdLine3Home
	Lcdout "Checking Inputs"

	voltageloop:
	While vcounter > 0
		Adcin 3, volt
		x = x + volt
		vcounter = vcounter - 1
		volt = 0
	Wend

	x = x / 30
	x = x * 5 / 1024
	x = x * (1510 / 510)
	x = x + 0.5
	x = x * 16.30

	WaitMs 5000

	Lcdcmdout LcdClear
	Lcdout "Vinput: ", #x, "V"
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
	currentloop:
	icounter = 30
	While icounter > 0
		Adcin 1, current
		y = y + current
		icounter = icounter - 1
		current = 0
	Wend

	y = y / 30
	WaitMs 2000
	
	If fudgefactor >= y Then
		Goto noload
	Else
		Goto load
	Endif
	
	
	noload:
	Lcdcmdout LcdLine2Home
	Lcdout "I: 0 A"
	WaitMs 800
	Lcdcmdout LcdLine3Home
	Lcdout "Power = 0W"
	WaitMs 800
	Lcdcmdout LcdLine4Home
	Lcdout "CONNECT LOAD"
	WaitMs 500
	Lcdcmdout LcdLine4Clear
	High PORTD.3
	WaitMs 1000
	Low PORTD.3
	Goto currentloop
	
	load:
	current_measured = 1
	currentan = y * 5 / 1024
	currentan2 = currentan + 0.063
	allcurrent = currentan2 * 0.2
	Lcdcmdout LcdLine2Clear
	Lcdcmdout LcdLine3Clear
	Lcdcmdout LcdLine4Clear
	Lcdcmdout LcdLine2Home
	Lcdout "I(load)= ", #allcurrent, "A"

	WaitMs 1000
'''''''''''''''''''''''''''''''''''''''''''
	If current_measured = 1 Then
		Lcdcmdout LcdLine3Home
		pow = allcurrent * x
		Lcdout "Power: ", #pow, "W"
		WaitMs 1000
	
		Lcdcmdout LcdLine4Home
		Lcdout "Calculating pf.."
		WaitMs 8000

		Adcin 2, phase
	
	
		Lcdcmdout LcdLine4Clear
		Lcdcmdout LcdLine4Home
		phasean = phase / 14.869
		phasean = phasean / 1.6
		Lcdout "Phase: ", #phasean
		WaitMs 4000
		phasedeg = phasean * 0.01745329
		Lcdcmdout LcdLine4Clear
		pf = Cos(phasedeg)
		Lcdout "pf: ", #pf
		WaitMs 1000
	Endif
	
	Gosub here
	
	
'prog_end:
End                                               

isr:
On High Interrupt
	If INTCON.INT0IF = 1 Then
		switch_pressed = 1
		INTCON.INT0IF = 0
	Endif
Resume                                            

here:
	If switch_pressed = 1 And current_measured = 1 Then Goto capbankcalc
	switch_pressed = 0
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Press Red Button"
	Lcdcmdout LcdLine2Home
	Lcdout "To Continue"
	WaitMs 1000
	
	Lcdcmdout LcdClear
	Lcdcmdout LcdLine1Home
	Lcdout "Vinput: ", #x, "V"
	
	Lcdcmdout LcdLine2Home
	Lcdout "I(load)= ", #allcurrent, "A"
	Lcdcmdout LcdLine3Home
	Lcdout "Power: ", #pow, "W"
	
	Lcdcmdout LcdLine4Home
	Lcdout "pf: ", #pf
	
	WaitMs 1000
	
	Goto here
Return                                            

capbankcalc:
	switch_pressed = 0
	Lcdcmdout LcdClear
	Lcdout "The input pf"
	Lcdcmdout LcdLine2Home
	Lcdout "is: ", #pf
	If pf > 0.85 Then
		Lcdcmdout LcdLine3Home
		Lcdout "pf is optimal"
		WaitMs 1000
		Goto prog_end
	Else
		Lcdcmdout LcdLine3Home
		Lcdout "Correcting..."
		WaitMs 1000
	Endif
prog_end:
	Goto prog_end

setuppic:
TRISB = 0x03
T1CON = 0x24
INTCON = 0x10
INTCON2 = 0xc0
INTCON3 = 0x00
ADCON1 = 0x0c
Enable High
Return
 
Hello, Thank you Brian!

I tried the 'AND' function, in the ISR:

The problem is that, if user presses the button, at any time of code functioning without being asked from the system, the system won't react, until reached current_measured = 1, so it would automatically directs it self to 'capbankcalc' once got in the 'here' function.

To disable this, I've added current_measured = 0 at last point, after power factor is measured, such that after that point the code would ask the users if he wishes to continue or not:

If user presses button anywhere before asked, all his pushings will be set to zero, as if he never pushed once, until his push means something

Code:
current_measured = 0
Gosub here

This is a fair solution between all trials. Thank you!

After getting done with interrupt of push-button, there still a disturbing bug for the current code:

When you attend the 'here' function, that repeats itself until a push-button is pressed, if you disconnect load suddenly at that function, the code deals with it by going to 'capbankcalc' function even if no push button is pressed.

What does an ADC at pin #1 of MCU has to do with an interrupt at PORTB.0? Why does this code sees a 0 ADC as a high interrupt?

Thank you
 

When you attend the 'here' function, that repeats itself until a push-button is pressed, if you disconnect load suddenly at that function, the code deals with it by going to 'capbankcalc' function even if no push button is pressed.
I'll have to look at that more closely, it's difficult to simulate the condition without any hardware.

What does an ADC at pin #1 of MCU has to do with an interrupt at PORTB.0? Why does this code sees a 0 ADC as a high interrupt?
What package of 18F4520 are you using? None of the ones on the data sheet use pin #1 as an ADC input. If you are using a DIP package and put 0V on pin #1 it will force a reset condition.

Brian.
 
I ment by pin #1 the PORTA.1 (first pin of PORTA) not first pin of PIC18F4520.

Thank you
 

Nothing in the program reads the ADC in the 'here' loop and the ADC is not configured to generate interrupts so I can't see any software reason why it should do that.

Does it do it every time? I am thinking that disconnecting the load may produce an interference spike and it may be being picked up by the switch wiring. I'm not sure what debounce circuit you are using at the moment but if you have a capacitor between PORTB.0 (the switch input) and ground, try wiring it's ground side directly to the VSS pin so there are no wiring loops. Also ensure you have supply decoupling capacitors across both VSS/VDD pins and they have short wires. I think you are seeing an electrical rather than a software problem.

Brian.
 
Thank you Brian!

I already have decoupling capacitors between VDD and VSS directly connected on breadboard near PIC supply voltage pins.

I'm having a 10nF ceramic parallel with two 1uF electrolytic capacitors on two side of PIC for two VDD and VSS ports.

For the push-button, I've used according to your suggestions a 100k resistor parallel with a 10uF electrolytic capacitor whose ground is directly connected to PIC's ground.

Shall I increase VDD and VSS decoupling capacitors for a max of 10uF to be paralleled with 10nF ceramic capacitor?

Or should I add a resistive circuit at push-button terminals to prevent the spike caused by load disconnection to be considered as a a push?

Thank you
 

You seem to have everything wired as it should be. I'm still thinking it may be an electrical problem though. Try adding a resistor of ~10K in series with the switch input pin on the PIC.

I will be away for a while at a meeting so I might not be able to reply until tomorow - my return trip by train doesn't get me home until midnight!

Brian.
 
Thank you Brian, and take care at your trip!

I've tried to attach the push-button circuit via Edaboad "Add an Image" but it seems that its server is down.

Here's a link where you can see attached photo:

**broken link removed**

Have a safe trip!
 

Your resistor values are too off.

Replace 1M resistor to the 5V supply with 10K. Replace 1M resistor connecting to the portB with 100R. Replace 10K resistor to the ground with 10R and the capacitor with 0.1 or 0.01uF ceramic.

Let me try to explain in brief:

With switch off, the port B sees 0V through a 1M. 1M can make lots of noise.

With switch on, the capacitor charges only upto 50mV. Not good enough. Further the capacitor will take an eternity to charge.
 
Sorry I made the same mistake as you did! Put 10R to the 5V supply and 10K to the ground (in parallel to the capacitor).
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top