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
'the last three Define directives set the values suitable for simulation; they should be omitted for a real device
Dim v_divider As Single
Dim i_divider As Single
Dim p_divider As Single
Dim display_value As Single
v_divider = 4.092 'scaled so 1023 = 250V
i_divider = 102.3 'scaled so 1023 = 10A
p_divider = 5.688 'scaled so 512 = 2.5V = 90 degrees
Dim voltage As Word
Dim current As Word
Dim phase As Word
Lcdinit 0 'initialize LCD module; cursor is blinking
TRISA = 0x07 'TRISA has bits 0,1 And 2 As inputs
ADCON1 = 0x0c
main:
ADCON0 = 1
loop:
Adcin 0, voltage '1023 = 5V at ADC input pins
Adcin 1, current
Adcin 2, phase
Lcdcmdout LcdLine1Home
Lcdout "Voltage="
display_value = voltage / v_divider
Lcdout #display_value
Lcdcmdout LcdLine2Home
Lcdout "Current="
display_value = current / i_divider
Lcdout #display_value
Lcdcmdout LcdLine3Home
Lcdout "Power="
display_value = (voltage / v_divider) * (current / i_divider)
Lcdout #display_value
Lcdcmdout LcdLine4Home
Lcdout "Phase="
display_value = phase / p_divider
Lcdout #display_value
Goto loop
End
Adcin 2, phase
Lcdout "Phase: ",#phase
The 74S86 has a maximum current consumption of 75mA which is very high, if you can find a 74AC86 it is typically 5uA, some 15,000 times less so I would guess your power source couldn't handle the extra load. The 'AC' version also has better output levels, with a light load it goes closer to 0V when low and nearer to 5V when high so it will give a better linearity in the phase measurement, especially near to 0 degrees.
The readings are encouraging, remember that there is an additional phase shift in both the voltage and current inputs caused by the transformers so it is reasonable to expect some residual readings. The transformers introduce a fixed shift so it is safe to remove it in software. If you change the phase calculation to subtract 21 it should compensate for the transformers and then give good results.
Your product is basically working but there is still one more issue you may want to look at - it doesn't tell you whether the phase shift is inductive or capacitive, it only shows there is a difference.
Brian.
ASM: org 0x800
Define LCD_LINES = 4
Define LCD_CHARS = 16
Define LCD_BITS = 8
Define LCD_DREG = PORTC
Define LCD_DBIT = 0
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 0
Define LCD_EREG = PORTD
Define LCD_EBIT = 2
Define LCD_RWREG = PORTD
Define LCD_RWBIT = 1
Define LCD_COMMANDUS = 2000
Define LCD_DATAUS = 100
Define LCD_INITMS = 100
Define ADC_SAMPLEUS = 255 //This command makes more samples per cycle, and without it no ADC will be accurate
Lcdinit 0
ADCON1 = 0
Dim volt As Word
Dim x As Single
Dim current As Word
Dim y 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 //So sorry for using TOOO much variables, I know this is a sign of stupidity
Dim fudgefactor As Single
Dim pf As Single
Dim vcounter As Word
Dim icounter As Word
icounter = 30
vcounter = 5
x = 0
y = 0
pf = 0
fudgefactor = 8.192 //When 74S86 is interfaced to the total system, even when no load is there, it showed a 0.035 as a maximum value for amperes, so I've to limit it by subtracting the current from this value; I got it from: 0.04*1024/5
phase = 0
main:
Lcdcmdout LcdClear
Lcdout "Processing..."
WaitMs 300
Lcdcmdout LcdLine2Home
Lcdout "Testing System"
WaitMs 300
Lcdcmdout LcdLine3Home
Lcdout "Checking Inputs"
While vcounter > 0
Adcin 3, volt
x = x + volt
vcounter = vcounter - 1 //This is to test the values for adc of measured voltage 5 times, for more accuracy
volt = 0
Wend
x = x / 5
x = x * 5 / 1024
x = x * (1510 / 510)
x = x + 1
x = x * 16.30 //I`m having trouble in outputting real input voltage value, I think that this is done due to two things: sometimes the supply voltage can reach to 230V instead of 220V, and the 220/12VAC transformer does not have a fixed turns ratio 'n' so the value "16.30" is often changed, and sometimes present; sometimes the supply voltage is 230VAC but it shows after this conversion on LCD a "255.5VAC" value. [I]HOW to eliminate this error, is it by hardware, or software implementation?[/I]
Lcdcmdout LcdClear
Lcdout "Vinput: ", #x, "V"
currentloop:
While icounter > 0 //Here starts the adc measurement of current, thirty times
Adcin 1, current
y = y + current
icounter = icounter - 1
current = 0
Wend
y = y / 30 //The results of current measurement are very acceptable!
WaitMs 1500
If fudgefactor > y Then //due to [I]fudge factor[/I] introduced by 74S86, I must check if no load is there by this comparision method, such that if there is any value below 0.04Amps in reality, consider it as no load.
Goto noload
Endif
currentan = y * 5 / 1024
If y = 0 Then
noload:
flag = 0
Lcdcmdout LcdLine2Home
Lcdout "I: 0 A"
Lcdcmdout LcdLine3Home
Lcdout "Power = 0W" //These are the results when having no load, and they're true
Lcdcmdout LcdLine4Home
Lcdout "Phase: NO LOAD"
Goto prog_end
Else
flag = 1
currentan2 = currentan + 0.063
allcurrent = currentan2 * 0.2
Lcdcmdout LcdLine2Home
Lcdout "I(load)= ", #allcurrent, "A"
Endif
WaitMs 1000
If flag = 1 Then
Lcdcmdout LcdLine3Home
pow = allcurrent * x
Lcdout "Power: ", #pow, "W" //These are the results when there is a load connected
WaitMs 1000
Adcin 2, phase //Here starts the adc measurement of XOR circuit output
Lcdcmdout LcdLine4Home
phasean = phase / 1.6 //I've got the number '1.6' when connecting the fan load, the phase angle showed was almost 82, and cos(82) is almost 0.14 which is not logical, instead, such loads have a typical 50degrees phase angle value, so 82/50 almost 1.6
Lcdout "Phase: ", #phasean
WaitMs 2000
phasean = phasean / 325.894
Lcdcmdout LcdLine4Clear
pf = Cos(phasean) //applying cosine for the radians to degrees transformed 'phasean'
Lcdout "pf: ", #pf
WaitMs 1000
Endif
prog_end:
End
First you have to discover where the error is. Can you see the instabilities with a DVM. Or is it stable?1. How to make voltage reading [whether by hardware/software/both more stable and accurate
Your product is basically working but there is still one more issue you may want to look at - it doesn't tell you whether the phase shift is inductive or capacitive, it only shows there is a difference..
y = 60
cosy = Cos(6)
Lcdout "Cos(60) = " , #cosy
vcounter = 30
While vcounter > 0
Adcin 3, volt
x = x + volt
vcounter = vcounter - 1
volt = 0
Wend
x = x / 30 //This is because the adc value is accumulated 30 times
x = x * 5 / 1024 //This is to get back the voltage corresponding to the 0-1024 10-bit digital input
x = x * (1510 / 510) //This is to get back the initial voltage, before resistive voltage divider value
x = x + 0.5 //This is due to diode voltage drop, in the rectifier after the transformer
x = x * 16.30 //This is the turns ratio 'n' of the voltage transformer that often changes from 16.25 to 16.4
and I think that this has a big portion of problem creation
Lcdcmdout LcdClear
Lcdout "Vinput: ", #x, "V" //This is to send the resultant voltage, to LCD
Adcin 2, phase
Lcdcmdout LcdLine4Home
phasean = phase / 1.6
Lcdout "Phase: ", #phasean
WaitMs 2000
phasedeg = phasean * 0.01745329
Lcdcmdout LcdLine4Clear
pf = Cos(phasedeg)
Lcdout "pf: ", #pf
WaitMs 1000
Endif
Well done!
You could try increasing the ADC sampling time to improve accuracy. I can't guarantee it will help but if you switch channels too quickly, some of the previous charge on the sample and hold capacitor can remain and cause a wrong reading. You can check it by increasing the "Define ADC_SAMPLEUS =" setting. Typically when the value is too low for the selected conversion speed, you start to see some interaction between the voltages measured at the inputs, for example, if AN0 increases and the next channel you select is AN1, you see an increase in that too.
The debounce may be adequate but I would increase the resistor to 10K and wire a 1uF capacitor across it, also add 100 Ohms in series with the switch so it's contacts are protected against charging and discharging current. The input pins of the PIC only need a tiny current so it is quite in order to use larger value resistors for pull-up and pull-down. How much debounce time you need will depend on how rapidly your software reads the switch input again and of course the actual contact bouncing time. You might be able to get away with just adding a delay of say 1mS after detecting the switch is closed or opened.
Brian.
if(PORTB.F0 == 1) {
Delay_ms(80);
while(PORTB.F0 == 1)asm clrwdt;
//do what you want on button press here
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?