|
|
View previous topic :: View next topic |
Author |
Message |
zeroskj1988
Joined: 07 Jul 2011 Posts: 5 Location: kochi
|
ac voltage and frequency measurement using clamping |
Posted: Mon Dec 26, 2011 6:10 am |
|
|
Dear friends,
I want to measure ac voltage and frequency using clamping principle. I used 2 1k resistor to clamp at vcc/2. I am using this program. As result I am getting correct ac value, some times. But sometime I am getting wrong result. Can anybody spot any error ?
I am using ccs compiler and pic18f452.
Code: |
void main()
{
int16 value,adc_val,adc_volt,count=0,freq;
int32 cum_adc=0;
float temp;
int8 a,b,c,d,e,data;
setup_adc_ports( ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); //26.2 ms overflow
//lcd_init();
//delay_ms(1000);
clear_interrupt(int_timer1);
set_timer1(0);
START:set_adc_channel(0);
delay_us(10);
adc_val=read_adc();
if((adc_val>512) & (adc_val<552))
{
adc_volt=read_adc();
if(adc_volt<adc_val)
goto START;
clear_interrupt(int_timer1);
set_timer1(0);
cum_adc=cum_adc+adc_val;
count++;
cum_adc=cum_adc+adc_volt;
count++;
while(adc_val>=512)
{
adc_val=read_adc();
cum_adc=cum_adc+adc_val;
count++;
if(interrupt_active(INT_TIMER1))
{
cum_adc=0;
d-0;
e=0;
goto skip;
}
}
freq=get_timer1();
temp=freq*.0000008;
freq=1/temp;
d=freq/10;
e=freq%10;
skip:lcd_display_char(2,4,'0'+d);
lcd_display_char(2,5,'0'+e);
value=cum_adc/count;
cum_adc=0;
count=0;
value=(value-506)*1.2550;
c=value/100;
lcd_display_char(3,4,'0'+c);
data=value%100;
b=data/10;
lcd_display_char(3,5,'0'+b);
a=data%10;
lcd_display_char(3,6,'0'+a);
}
goto START;
}
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Dec 26, 2011 8:29 am |
|
|
Honestly speaking, I don't know what the "clamping principle" is. At least it's not a commonly used technical term. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Dec 26, 2011 9:17 am |
|
|
Ditto....
Some comments on what you are doing might help!...
Also, use the code buttons when posting code.
I've modified the routine to use more normal coding style (goto's while sometimes necessary, generally should be avoided if you can), and commented on a couple of lines:
Code: |
void main(void) {
int16 value,adc_val,adc_volt,count=0,freq;
int32 cum_adc=0;
float temp;
int8 a,b,c,d,e,data;
int1 skip=FALSE;
setup_adc_ports( ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_32);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2); //26.2 ms overflow
clear_interrupt(int_timer1);
set_timer1(0);
set_adc_channel(0); //since you never change this do it once....
delay_us(10); //again the other code provides enough delay normally
do {
adc_val=read_adc();
if((adc_val>512) & (adc_val<552)) {
//However you do need a delay to re-acquire here, or you might
//as well just use the voltage already read....
adc_volt=read_adc();
if(adc_volt<adc_val)
continue; //Loop back
clear_interrupt(int_timer1);
set_timer1(0);
cum_adc=cum_adc+adc_val;
count++; //Why two increments?.
cum_adc=cum_adc+adc_volt;
count++; //Why not just add 2....
while(adc_val>=512) {
adc_val=read_adc();
cum_adc=cum_adc+adc_val;
count++;
if(interrupt_active(INT_TIMER1)) {
cum_adc=0;
d-0; //What does this do?
e=0;
skip=TRUE;
break;
}
}
if (!SKIP) {
freq=get_timer1();
temp=freq*.0000008;
freq=1/temp;
d=freq/10;
e=freq%10;
}
skip=FALSE;
//why not just use printf.
lcd_display_char(2,4,'0'+d);
lcd_display_char(2,5,'0'+e);
value=cum_adc/count;
cum_adc=0;
count=0;
value=(value-506)*1.2550;
//same comment here about using printf
c=value/100;
lcd_display_char(3,4,'0'+c);
data=value%100;
b=data/10;
lcd_display_char(3,5,'0'+b);
a=data%10;
lcd_display_char(3,6,'0'+a);
}
} while(TRUE);
}
|
Best Wishes |
|
|
zeroskj1988
Joined: 07 Jul 2011 Posts: 5 Location: kochi
|
|
Posted: Mon Dec 26, 2011 11:21 pm |
|
|
Thank you, Ttelmah
I want to measure ac signal of about range 230-300, 45-55hz.
Code: |
if(interrupt_active(INT_TIMER1)) {
cum_adc=0;
d-0; //What does this do?
e=0;
skip=TRUE;
break;
}
|
This part of code is designed to avoid infinite loop. Means timer is set to overflow at 26ms (well above my frequency). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Dec 27, 2011 2:36 am |
|
|
I was asking about the specific line. It should give a compiler warning 'code has no effect'. Think about it:
d-0;
What is this going to do?.
Best Wishes |
|
|
zeroskj1988
Joined: 07 Jul 2011 Posts: 5 Location: kochi
|
ac voltage and frequency measurement using clamping |
Posted: Tue Dec 27, 2011 4:40 am |
|
|
Code: |
int16 adc_volt,adc_volt_temp;
int16 value,count=0,freq;
int32 cum_adc=0;
float temp;
clear_interrupt(int_timer1);
set_timer1(0);
set_adc_channel(channel);
do
{
delay_us(20);
adc_volt_temp=read_adc();
if((adc_volt_temp>512) & (adc_volt_temp<552))
{
restart_wdt();
delay_us(20);
adc_volt=read_adc();
if(adc_volt<adc_volt_temp)
continue;
//clear_interrupt(int_timer1);
if(!channel)
set_timer1(0);
cum_adc=cum_adc+adc_volt_temp;
count++;
cum_adc=cum_adc+adc_volt;
count++;
while(adc_volt>=512)
{
delay_us(20);
adc_volt=read_adc();
cum_adc=cum_adc+adc_volt;
count++;
//if(interrupt_active(INT_TIMER1))
//{
//frl=0;
//frr=0;
//return(0);
//}
}
if(!channel)
{
freq=get_timer1();
temp=freq*.0000008;
freq=1/temp;
frl=freq/10;
frr=freq%10;
}
value=cum_adc/count;
cum_adc=0;
count=0;
value=(value-506)*1.2550;
return(value);
|
with the input from Ttel mah.i modified code like this.
but as output for 230v input
230v 023v 017v ....some random no: then again 230v ....some random no:
can any body know the problem. friends you don't have to worry about !channel. because it is provided to measure frequency when only Rphase measurement is taking
thank you in advance |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Dec 27, 2011 7:37 am |
|
|
I think it's time you took a few steps back and break the program down into managable functions. Right now you've got too much going on and can't see the flow...easy to make minor mistakes creating major headaches.
First I'd cut code to read the ADC and display the raw data on a local LCD or send to PC. Simple read, delay, display, pause (say 1/4 second ?), loop to read...
Observe the data to see if the readings are similar or 'bad'.
If they're all good (within say 2-3 bits) THEN do your math conversion and display that as well as the raw databits. Raw data on line 1 LCD, converted data on line 2 LCD. Again test for say 10-15 minutes, comparing the values.
If it looks good then proceed with the next function you want to attempt.
Overall, your Main program should 'call' your 'functions'(subroutines) in a logical order.
main()
setup..
do...
readadc-volts
math-volts
dispadc-volts
readadc-phase
math-phase
dispadc-phase
other stuff....
...forever
Done in this fashion you know every fuction (subroutine) you create is a working unit making it easier to concentrate on getting the overall flow of your main program to do what you want.
Start small, confirm the code, save as a function, build upon that. |
|
|
freesat
Joined: 08 Feb 2011 Posts: 32
|
|
Posted: Wed Dec 28, 2011 4:17 pm |
|
|
I have made a voltmeter working on 110v and 220v ac, reading two phases, to control a diesel power generator. It is not very accurate, sometimes give at least 1 volt error, but works great for me.
You must follow certain rules, on your program...
1: use external interrupt to get zero cross
2: delay... ( wait rising )
3: start adc
4: read adc
Same circuit used to detect zero cross can be used to measure with adc, but put an diode between zero cross pin and adc pin, then use an RC to reduce noise.
Without detect zero crossing, your measure will not be accurate.
Another thing, use good voltage regulator and filter on pic vcc, any noise or power variation will result on a bad acuracy.
You may want use a comparator, in this case use regulator with voltage below vcc, example, ( pic vcc 5v, use a 3v regulator connected on comparator pin ) and change your routines to calculate based on 3v.
Do not forget, ac may have a 90º and 120º phase, if you need measure 2 phases and display it separatedly and totalized use:
if 120º then
phase1 read: 127v
phase2 read: 129v
total = (( 127 + 129 ) /3 ) * 2 = 213 volts
F1:127v F2:129v T:213v
Wrong!!! 127 + 129 = 256v |
|
|
deepak0415
Joined: 07 Jun 2016 Posts: 1 Location: GOA
|
Please Share code for Voltmeter |
Posted: Tue Jun 07, 2016 4:10 am |
|
|
Hi freesat,
Can u please share working code of voltmeter |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Jun 07, 2016 5:53 am |
|
|
Please provide a schematic, then we can all see what you're working with. ASCII art will do.
Learn to use the code button, and indent to make program flow easy to follow.
I've had a quick look at your code, you appear to be doing this:-
1) Waiting for ADC_value to be between 512 and 522 as a cross-over detect.
2) Adding to a cumulative ADC_value until ADC_value falls below 512.
3) Then calculting your AC voltage.
A) How do you know the input voltage is rising when you start your measurement?
If the input voltage is falling you will get a few readings between 522 and 512 and a relatively low random final result!
B) Do you want a mean amplitude measurement or an RMS value?
A search on this forum will find ways of measuring RMS values using ADC readings over the whole waveform cycle.
You may even be able to extract a sufficiently accurate value without even bothering about zero crossing.
(Depends on the update rate required.)
Mike |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Jun 07, 2016 7:58 am |
|
|
YES.
Quote: | Please provide a schematic |
I'd like to see how this "clamping principle" is done in your circuit.
If the circuit is a bad design - you can't expect good data from the PIC..
and then there is this BAD comparison
Code: | if((adc_val>512) & (adc_val<552)) { |
don't you mean ?
Code: | if((adc_val>512) && (adc_val<552)) { |
then this Code: | value=(value-506)*1.2550; |
with value as an integer.., ? WHUT??
you have bad 'C code already. i'm worried your circuit is cut from the same cloth...
Last edited by asmboy on Tue Jun 07, 2016 8:04 am; edited 1 time in total |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
Warning: Zombie thread...... |
Posted: Tue Jun 07, 2016 8:02 am |
|
|
deepak0415,
Dude, this is five year old thread. Freesat is gone, so he's probably not going to provide any code..... _________________ John
If it's worth doing, it's worth doing in real hardware! |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Thu Jun 09, 2016 8:52 am |
|
|
We used to have a sign at work over our avionics design group that read "Garbage in Gold out" (seemed to be inspired by managements insistence that we come up with good hardware based on very nebulous requirements). My other favorite was the guy that had a cardboard "black cloud" about 2 feet long that he hung from the ceiling over his desk
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
|
|
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
|