|
|
View previous topic :: View next topic |
Author |
Message |
PROMOD
Joined: 01 Feb 2018 Posts: 42
|
Average power measurement by PIC 18f4431 |
Posted: Fri Mar 30, 2018 9:37 am |
|
|
Code: | #include<18f4431.h>
#device adc=10
#fuses xt,nowdt,nolvp
#use delay(clock=20000000)
#include "flex.c"
float k=0,a=0,r=0,p=0,pav=0;int16 i=0;
#int_timer2
void pwm_interrupt()
{
i=i+1;
set_adc_channel(0);
k=read_adc(); //convert the instantaneous voltage value of a certain moment(let t1) in channel 0
k=((k/204)-2); //calibrating the decimal value of ADC output;here offset value is 2. 10bit ADC means maximum 1023 so 1023/5=204;
set_adc_channel(1);
a=read_adc(); //convert the instantaneous current value of the certain moment t1 in channel 1
a=((a/204)-2); //calibrating the decimal value of ADC output; here offset value is 2. 10bit ADC means maximum 1023 so 1023/5=204;
p=p+a*k; //a*k= instantaneous power of the certain moment t1. p storing the summation of power of 50 different moment like t1.
if(i==49)
{
pav=p/i; //pav is the average of 50 different moment instantaneous value.
printf(lcd_putc," Average=%f", pav);
i=0;pav=0;p=0;//setting all variable to 0.
}
}
void main()
{
lcd_init();
setup_timer_2(t2_div_by_16,125,1); //interrupt setting time (Here in every 4*10^-4 seconds interrupt occurs) for 50 Hz signal 50 interrupts makes one complete cycle.
enable_interrupts(global);
enable_interrupts(int_timer2);
setup_adc_ports(all_analog);
setup_adc(adc_clock_internal);
while(1)
{
}
} |
If I use 2 volt sine wave and 2 Ampere sine wave at channel 0 & 1 respectively then "pav" should be 0.637*2*0.637*2=1.623. But when I run the program it shows pav=1.9 in LCD display.
Could someone please tell me what is the problem in my coding? Thanks in advance!
Last edited by PROMOD on Fri Mar 30, 2018 11:02 am; edited 1 time in total |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Mar 30, 2018 11:00 am |
|
|
There are many things wrong here.
You've been shown how to do this in one of the parallel posts you're running.
One of the Mr T's has commented about your ADC setup.
I think you might need 50 samples assuming that you've got a 50Hz mains source.
Your expected average power calculation is flawed.
I suggest you draw a graph of the instantaneous power against time for one complete cycle.
It should show power as a sine wave going from 0W to 4W.
It should also be obvious from the symmetry what the average power is.
Mike
Is this real hardware or ISIS/proteus? |
|
|
PROMOD
Joined: 01 Feb 2018 Posts: 42
|
|
Posted: Fri Mar 30, 2018 11:36 am |
|
|
Mike Walne wrote: | One of the Mr T's has commented about your ADC setup. | I have seen it. And Now I understand.
Mike Walne wrote: | Your expected average power calculation is flawed. | You mean "average power=0.637*2*0.637*2=1.623" is wrong?
Mike Walne wrote: | Is this real hardware or ISIS/proteus? | It is ISIS/proteus. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Fri Mar 30, 2018 12:58 pm |
|
|
You should read the sticky called PIC101 up top.
Please note that ISIS/Proteus is NOT reliable or accurate. Think of it to PICs as what Windows (BSOD) is to PCs. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Mar 30, 2018 1:56 pm |
|
|
Mike Walne wrote: | Your expected average power calculation is flawed. | You mean "average power=0.637*2*0.637*2=1.623" is wrong?
Yes, it's seriously wrong.
You need to revisit your college notes.
Average REAL power is the mean time integral of instantaneous power.
What you've calculated is flawed in several ways
What you appear to have calculated is (roughly) mean_voltage * mean_current.
What you need are RMS voltage and current;
Then APPARENT power is RMS_voltage * RMS_current.
Most crude AC meters measure mean volts(or amps) and convert to RMS with a fudge factor.
If you want REAL power use the integral expression above, it gives the correct values for both sinusoidal and non-sinusoidal waveforms.
Do what I said before and plot the power/time graph.
Then you'll find the average power for your resistive load.
(For a resistive load REAL_power = APPARENT Power, resistive loads are a special case.)
Your expected power is ~20% out. As such is useless as a reference value.
Mike Walne wrote: | Is this real hardware or ISIS/proteus? | It is ISIS/proteus.
You should be using real hardware, ISIS is a complete waste of time for PICs.
Mike
I've looked through your previous posts.
You were told ~2 months ago, in no uncertain terms, to get rid of ISIS/proteus.
No one here can help you fix it.
The only proper test is to use REAL HARDWARE. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sat Mar 31, 2018 5:31 am |
|
|
re:
Code: |
if(i==49)
{
pav=p/i; //pav is the average of 50 different moment instantaneous value. |
Isn't 'pav' is the average of 49 values, since 'i' is 49 ?
also a and k can never be greater than .0098, if 2V is the max ADC input
though we don't know what Vref is (I'll assume VDD= 5V).
adc_clock_internal is still wrong.
Having FP math inside an ISR is wrong.
normally you sync to zero cross when doing anything with AC.....
the huge problem is that ISIS allows you to inject a PIC with AC voltage. Do that for real and POOF. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Apr 04, 2018 11:04 am |
|
|
I've had another look at your code
This line is wrong!
Code: | setup_timer_2(t2_div_by_16,125,1); //interrupt setting time (Here in every 4*10^-4 seconds interrupt occurs) for 50 Hz signal 50 interrupts makes one complete cycle. |
To get 0.4ms interrupt interval it needs to be:-
Code: | setup_timer_2(t2_div_by_16,124,1); //interrupt setting time (Here in every 4*10^-4 seconds interrupt occurs) for 50 Hz signal 50 interrupts makes one complete cycle. |
Replacing your 125 with 124 (it's in the data sheet).
Then I tried replacing your adc input with the expected data you should get.
i.e I introduced these arrays after your declarations (I've only used 32 value rather than your 50).
Code: |
float data_k[32] = {409,489,566,636,698,749,787,810,
818,810,787,749,698,636,566,489,
409,329,252,182,120, 69, 31, 8,
0, 8, 31, 69,120,182,252,329};
float data_a[32] = {409,489,566,636,698,749,787,810,
818,810,787,749,698,636,566,489,
409,329,252,182,120, 69, 31, 8,
0, 8, 31, 69,120,182,252,329}; |
In the ISR I:-
Moved the increment i.
Replaced the read adc lines.
Adjusted the pav calculation.
So the whole ISR now looks like this:-
Code: | #int_timer2
void pwm_interrupt()
{
k=data_k[i]; //Get effective adc value
k=((k/204)-2); //Convert to engineering units (volt).
a=data_a[i]; //Get effective adc value
a=((a/204)-2); //Convert to engineering units (ampere)
p=p+a*k; //a*k= instantaneous power of the certain moment t1. p storing the summation of power of 32 different moment like t1.
i+=1; // increment loop counter
if(i==32)
{
pav=p/i; //pav is the average of 32 different moment instantaneous value.
printf(lcd_putc," Average=%f", pav);
i=0;pav=0;p=0;//setting all variable to 0.
}
} |
Using your floating point method I'm now getting close to my expected value for the average power.
Which begs the question, why don't you? Your ISIS/Proteus generated value is in error by ~5%.
Which means you've got yet another fundamental problem!
I don't like to admit it, but, ISIS/Proteus is possibly giving you the correct answer for your flawed procedure.
BIG QUESTION (which might lead you to the correct conclusion):-
How does the time spent in your ISR compare to your expected ISR interval?
What you're measuring bears scant relation to your intention.
Mike
PS. You could increase the array sizes to 50.
You'll still find that your adc method and the array one disagree.
This will still apply when you get round to using REAL hardware.
There's a fundamental flaw in your procedure and MrT has told you what it is! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|