CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

ac voltage and frequency measurement using clamping

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
zeroskj1988



Joined: 07 Jul 2011
Posts: 5
Location: kochi

View user's profile Send private message

ac voltage and frequency measurement using clamping
PostPosted: Mon Dec 26, 2011 6:10 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 26, 2011 8:29 am     Reply with quote

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: 19535

View user's profile Send private message

PostPosted: Mon Dec 26, 2011 9:17 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Dec 26, 2011 11:21 pm     Reply with quote

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: 19535

View user's profile Send private message

PostPosted: Tue Dec 27, 2011 2:36 am     Reply with quote

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

View user's profile Send private message

ac voltage and frequency measurement using clamping
PostPosted: Tue Dec 27, 2011 4:40 am     Reply with quote

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: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Dec 27, 2011 7:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 28, 2011 4:17 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

Please Share code for Voltmeter
PostPosted: Tue Jun 07, 2016 4:10 am     Reply with quote

Hi freesat,

Can u please share working code of voltmeter
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Jun 07, 2016 5:53 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue Jun 07, 2016 7:58 am     Reply with quote

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...
Code:


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

View user's profile Send private message

Warning: Zombie thread......
PostPosted: Tue Jun 07, 2016 8:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jun 09, 2016 8:52 am     Reply with quote

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 Very Happy

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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