![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Can
Joined: 26 Feb 2012 Posts: 23
|
Power Meter ADC problems |
Posted: Mon Feb 25, 2013 2:32 pm |
|
|
I am trying to build a power meter with current and voltage measurements. The final circuit is going to be used to measure the power produced by a wind turbine. I am trying to build the power meter to work with 220Vac because it is the best AC source I can draw current and test my circuit. The setup is quite simple, a voltage divider (using 330k and 4.7k) for the voltmeter part and an ACS714 sensor for ammeter. As it is AC, I thought that the best solution to measure the voltage is to run it to the ADC of the PIC, have countless measures (20000 in my code), determine the peak value and calculate the RMS. As for the current, ACS714 has a 0 current output of 2.5V. Positive currents pull it up (say 3 V) and negative currents pull it down (say 2 V). While passing AC through the ACS714, the output fluctuates about 2.5V with an amplitude proportional to the current driven. I am using the following code to measure the current and voltage but the ADC channels seem to affect each other. For example when I pull the cable of ADC channel 1, both of the channels (channel 0 and channel 1) read 1023. Also, with a voltmeter i can see that there is like 2.5 Volts in the ADC0 but it reads 0 as the ADC value. As i can see the voltage by a voltmeter, I assume that the problem is not the hardware. Here is my code
Code: |
#include <16F876.H>
#DEVICE ADC=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, NOLVP
#use delay(clock=48000000)
#include "flex_lcd.c"
void main()
{
lcd_init(); // Always call this first.
int16 veri, veri2, counter, valADC, akimMin, akimMax, topAkim, topGerilim, gerilimMin, gerilimMax;
float gerilim,akim, guc, akimOrt, gerilimOrt;
setup_adc_ports(0); // ALL ANALOGS
setup_adc(ADC_CLOCK_DIV_32);
delay_ms(100);
while(1){
counter =0;
set_adc_channel(0); //Current Channel
veri=read_adc();
akimMax=veri;
akimMin=veri;
set_adc_channel(1); //Voltage Channel
veri2=read_adc();
gerilimMin=veri2;
gerilimMax=veri2;
for(counter=0;counter<20000;counter++){
set_adc_channel(0);
veri=read_adc();
if(veri>akimMax){ //determine the read max value
akimMax=veri;
}
if(veri<akimMin){ //determine the read min value
akimMin=veri;
}
delay_us(1);
set_adc_channel(1);
delay_us(1);
veri=read_adc();
if(veri>gerilimMax){ //determine the read max value
gerilimMax=veri;
}
if(veri<gerilimMin){ //determine the read min value
gerilimMin=veri;
}
delay_us(1);
}
akimOrt=(akimMax+akimMin)/2.; //verinin ortalama değeri denge gerilimini (2.5V) vermeli
gerilim=(gerilimMax*5./1024)*339.6/4.68; //R1=335.0k, R2=4,68k (Vadc*(R1+R2))/R2
akim=((akimMax-akimOrt)*5./1024)*(60/4); //The sensor outputs from 0.5V to 4.5V for -30A to 30A respectively. Lets take the steady state value (akimOrt) out of the max value of the current. That difference is caused by the current..
valADC=akimMax-akimMin;
//printf(lcd_putc,"\fI=%.3fA V=%.3fV\n",akim, gerilim);
printf(lcd_putc,"\fI=%.3fA V=%3.1fV",akim,gerilim);
printf(lcd_putc,"\nIM=%Lu VM=%Lu",akimMax,gerilimMax);
delay_ms(100);
output_toggle(PIN_C3);
}
}
|
Any pointers would be greatly appreciated. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Feb 25, 2013 3:06 pm |
|
|
Seems like you're trying to run before you can walk.
What do you mean by "pull the cable"?
The alternating voltage signal needs to be biased to half the reference voltage.
As you've described it you're going to be getting zero readings half the time.
Start by checking that the ADC gives the correct reading with DC inputs to first one channel, then both.
Then see what happens if you feed DC to one channel and AC to the other.
etc.............
Mike
EDIT Bear in mind that power is NOT the same as Vrms * Irms. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2013 3:18 pm |
|
|
1) safety first !!! 220 will KILL you, so you MUST follow proper wiring and isolation protocols !!
2) NO PIC can read AC, and you stand a good chance of frying it. Best to convert the AC to DC , then measure.
3) Nowadays, several manufacturers make a 'one chip' AFE (Analog Front End) to do all the 'dirty' work. Used in 'smart meters'..cheap,off the shelf solution.
hth
jay
be CAREFUL !!! |
|
![](templates/subSilver/images/spacer.gif) |
Can
Joined: 26 Feb 2012 Posts: 23
|
|
Posted: Mon Feb 25, 2013 3:27 pm |
|
|
Hello Mike,
Thank you for your reply. Well I know that I will be reading 0 half the time and that is fine with me. I want to build a working prototype as soon as I can and I will get the optimizations later. I hope you appreciate my situation, that I have to get some measurements soon or I will be, well, damned..
As for ADC of the current part reading zero, the ACS714 should not (and does not) give 0 Volts.
You asked me to feed DC to the channels in order to see the response. Well a battery seems to move the readings correctly.
I have chopped down my code, trying to achieve one thing at a time. So I cut the current reading part. Now I am just trying to read the 220Vac mains with the PIC. The results seem somewhat more reliable. But again, for example, even though the ADC channel 1 is not handled in the code, when I plug the ADC1 to ground and unplug it, it affects my ADC0 channel. Meaning that I am having some ambiguous readings on the ADC0.
Here is the code:
Code: | #include <16F876.H>
#DEVICE ADC=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, NOLVP
#use delay(clock=48000000)
#include "flex_lcd.c"
void main()
{
lcd_init(); // Always call this first.
int16 veri, counter, gerilimMin, gerilimMax;
float gerilim;
setup_adc_ports(0); // ALL ANALOGS
setup_adc(ADC_CLOCK_DIV_32);
delay_ms(100);
while(1){
counter =0;
set_adc_channel(0); //Current Channel
veri=read_adc();
gerilimMax=veri;
gerilimMin=veri;
for(counter=0;counter<20000;counter++){
set_adc_channel(0);
delay_us(1);
veri=read_adc();
if(veri>gerilimMax){ //determine the read max value
gerilimMax=veri;
}
if(veri<gerilimMin){ //determine the read min value
gerilimMin=veri;
}
delay_us(1);
}
gerilim=0.707*(gerilimMax*5./1024)*339.6/4.68; //R1=335.0k, R2=4,68k (Vadc*(R1+R2))/R2
printf(lcd_putc,"\fV=%3.1fV",gerilim);
printf(lcd_putc,"\nVM=%Lu",gerilimMax);
delay_ms(100);
output_toggle(PIN_C3);
}
} |
Hello Temtronic,
I know 220V will kill me, that is why now I am having back cramps, trying to put as much care as I can. But thank you for your concern. I really appreciate it. Well ACS714 is one of those chips doing the dirty work on the current side for me. But for the voltage part I had to come up with a solution quick so i didn't have time to wait for any samples of the kind of chips you mentioned. AD736 was one of the alternatives.
I took a quick look in the datasheet of the 16f876 but i could not see any mention of absolute maximum for reverse biasing (I guess that was the term). Maybe the look was so quick that it was inevitable to miss it. I am reading the datasheet again.
BTW I have a residual current circuit breaker installed in my mains. Actually I am counting on that to save me if by accident I touch the hot wire. I hope I am not wrong.
Last edited by Can on Mon Feb 25, 2013 3:32 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Feb 25, 2013 3:31 pm |
|
|
I think a posted schematic is in order.
How about it ?
the circuitry is just as important to your success as the code.
And IT is the real starting point. |
|
![](templates/subSilver/images/spacer.gif) |
Can
Joined: 26 Feb 2012 Posts: 23
|
|
Posted: Mon Feb 25, 2013 3:39 pm |
|
|
Hello asmboy,
The ISIS drawings are added. Sorry for the really quick drawing.
(Not exactly the same setup but the actual setup has an extension cable to draw current from it, I don't know how to model it in isis ;) )
Edit: Once again I arranged my code seeing that I can measure the AC voltage right. Using the following code, when I attach ADC1 to the output of ACS714, my voltage reading (the reading on my ADC0) goes to 200 Volts. When I detach the ACS714 from the ADC1, my ADC0 reading goes to 228V (which is almost the same as the voltmeter reading). I am going nuts.
Code: | #include <16F876.H>
#DEVICE ADC=10
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, NOLVP
#use delay(clock=48000000)
#include "flex_lcd.c"
void main()
{
lcd_init(); // Always call this first.
int16 veri, counter, gerilimMin, gerilimMax, akimMin, akimMax;
float gerilim, akim, akimOrt;
setup_adc_ports(0); // ALL ANALOGS
setup_adc(ADC_CLOCK_DIV_32);
delay_ms(100);
while(1){
counter =0;
set_adc_channel(0); //Current Channel
veri=read_adc();
gerilimMax=veri;
gerilimMin=veri;
delay_us(10);
set_adc_channel(1); //Current Channel
veri=read_adc();
akimMax=veri;
akimMin=veri;
delay_us(10);
for(counter=0;counter<20000;counter++){
set_adc_channel(0);
delay_us(1);
veri=read_adc();
if(veri>gerilimMax){ //determine the read max value
gerilimMax=veri;
}
if(veri<gerilimMin){ //determine the read min value
gerilimMin=veri;
}
delay_us(10);
set_adc_channel(1);
delay_us(1);
veri=read_adc();
if(veri>akimMax){ //determine the read max value
akimMax=veri;
}
if(veri<akimMin){ //determine the read min value
akimMin=veri;
}
delay_us(10);
}
akimOrt=(akimMax+akimMin)/2.; //verinin ortalama değeri denge gerilimini (2.5V) vermeli
gerilim=0.707*(gerilimMax*5./1024)*339.6/4.68; //R1=335.0k, R2=4,68k (Vadc*(R1+R2))/R2
akim=((akimMax-akimOrt)*5./1024)*(60/4); //The sensor outputs from 0.5V to 4.5V for -30A to 30A respectively. Lets take the steady state value (akimOrt) out of the max value of the current. That difference is caused by the current..
printf(lcd_putc,"\fV=%3.1fV I=%.2fA",gerilim,akim);
printf(lcd_putc,"\nVM=%Lu IM=%Lu",gerilimMax,akimMax);
delay_ms(100);
output_toggle(PIN_C3);
}
} |
Second Edit: I don't know what has changed but when I put the cable of ADC1 to the ground, ADC0 reads 172V (687 as ADC value) and ADC1 reads 0, when I unplug the ADC1 from the ground (thus it floats), both ADC0 and ADC1 reads 1023. In conclusion, there are ghosts in my PICs I suppose.. |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Feb 25, 2013 4:30 pm |
|
|
OMG .... i surely HOPE you are WELL isolated from this circuit!
FIRST - trying to digitize the AC directly is not going to be of much ( or ANY ) use. its RA0 i speak of here.
1- you need an isolated power supply - ala the LINK-SWITCH type of HF
switch mode ferrite core transformer isolated supplies .
2- if it is POWER you are speaking of ( then you want to consider power-factor/ phase angle ) - you need to sample load current as well as bridge the line voltage. a wholly different circuit with phase sensitive rectification is required for that and the Hall sensor chip alone won't do that.
you need to do more circuit design research if a genuine power meter is what you seek to build
is this for SCHOOL or for REAL ???
Last edited by asmboy on Mon Feb 25, 2013 5:03 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Feb 25, 2013 4:35 pm |
|
|
Quote: | As for ADC of the current part reading zero, the ACS714 should not (and does not) give 0 Volts. | Yes, I got that bit.
Quote: | You asked me to feed DC to the channels in order to see the response. Well a battery seems to move the readings correctly. |
What I was then suggesting was:-
1) Connect DC to channels 0 and 1. Check that both read OK.
2) Connect DC to say channel 0, AC to channel 1.
Read channels 0, and 1 in turn, but ignore the channel 1 readings and watch what happens to the channel 0 reading only.
3) Answer this question. Is the process of reading AC from channel 1 affecting the channel 0 value?
4) Proceed further when each stage produces satisfactory answers.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
Can
Joined: 26 Feb 2012 Posts: 23
|
|
Posted: Mon Feb 25, 2013 4:59 pm |
|
|
Asmboy:
I am afraid what you see in the schematics is basically what I am doing. So, my only isolation is the extreme caution I am paying. In that sense I understand the suggestion of isolated power supply.
My aim is to measure the voltage, current and power produced by the wind turbine and log the values in my datalogger (which I built thanks to you guys). Basically, these data (along with bunch of other data) will form my data set for my thesis. I would like to have the measurements close to real for sure.
Mike,
Ok, I got your suggestion. But if you saw my circuit, you must have noticed that it is not isolated. I've already made sure that the readings on channels 0 and 1 are accurate. But, I am afraid I can not connect any dc to a channel while the other channel is hot. To be honest, I am scared of the mains, yet I have to play with it. We have a discreet relationship with it and I aim to keep it that way. However, I can tell you this. The ADC0 stays stable (connected to the voltage divider, thus it is expected to read the same thing over and over again). When I unplug the ADC1 cable and it floats, ADC0 reads some value about 920 and ADC1 reads almost the same values. When I plug the ADC1 cable to the ground (well not actual ground but it is the neutral of the mains), ADC0 reads around 420 and ADC1 reads 0. When I connect ADC1 to the output of the ACS714 (which is around 2.28VDC), then the ADC0 reads around 800 and ADC1 reads around 490. I am not even touching the ADC0, I don't know why it keeps changing.. |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Feb 25, 2013 5:12 pm |
|
|
If I understand you correctly and you really are letting the PIC's ADC terminal float then you WILL get rubbish readings. A floating pin will pick up line frequency noise and read any value it wants between zero and 1023.
You've isolated your current measurement. So why not use a bog standard mains step down transformer to get a voltage signal?
I still think you need your voltage signal biassed to half Vref just like your current sensor.
And you're missing the point about POWER.
You calculate power from the time integral of current and voltage NOT Vrms * Irms. No need for phase angles etc.
Mike
EDIT Just for interest. What is the frequency of the output from your system? |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Feb 25, 2013 6:44 pm |
|
|
BTW: D1 REQUIRES a current limit resistor !!!
also PSU decoupling capacitors for the pic Vdd
even if you DO get dc on RA0 the input impedance is awfully high you know
hint read datasheet about ADC inputs |
|
![](templates/subSilver/images/spacer.gif) |
necati
Joined: 12 Sep 2003 Posts: 37 Location: istanbul
|
|
Posted: Mon Feb 25, 2013 8:17 pm |
|
|
http://coolcircuit.com/project/digital_amp_meter/picmicro_digital_amp_meter.html
Calculating volt to amp for Vcc 5V
From ACS712 data sheet we know :
0 A = Vcc/2 = 2.5V or 512 analog counts or 0x200.
Sensitivity 66mV/A for 30A version.
So
Volt at 30A = 2.5V + (66mV/A x 30A) = 4.48V or 917.504 analog counts
Volt at -30A = 2.5v - (66mV/A x 30A) = 0.52V or 106.5 analog counts
--------------------------------------------------------------------
Elenco 9440 Breadboard With JW-350 Jumper Wire Set
Extech EX330 Mini Multimeter with Built In Thermometer
--------------------------------------------------------------------
With basic math linear equation
y = mx + b ----------- Equ. 1
m = (y2 - y1) / (x2-x1) -------------Equ.2
So we get
m = (30-0) / (917 - 512) = 0.074
substitute m in Equ. 1 at output 0A, we will get b
0 = 0.074*512 + b
b = -37.888
thus, the final equation use in software is :
A = 0.074*(analog_counts) - 37.888
Example :
if analog counts = 512 we get 0 A
if analog counts = 917 we get about +30A
if analog counts = 106 we get about -30A |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Feb 26, 2013 5:07 am |
|
|
Your putting the cart before the horse.
Rushing to get something to show gets you nowhere.
You're not answering the questions that others and I are asking.
We're trying to help you by making you think about what's going on.
We've all been there before, so can see what's happening.
We're not going to give you the answers, because that won't help you become good at the job.
1) Isolate yourself from the killer volts.
2) Bias your volts measurement to half Vref.
3) Get each section to work correctly, BEFORE moving on to the next.
4) Tell me the frequency of the voltage output from your generator.
5) Tell me how much current your expecting at maximum output.
6) Suitably isolated you can hook a PC up to the UART and have a dialogue with the PIC.
7) What makes you think measuring peak volts and current allows you to measure power?
8) I'd be worried that you're still getting interaction between ADC channels.
9) Once isolated, it's easier to look at your ADC inputs with a 'scope.
Mike |
|
![](templates/subSilver/images/spacer.gif) |
Can
Joined: 26 Feb 2012 Posts: 23
|
|
Posted: Tue Feb 26, 2013 5:07 am |
|
|
Hello Mike, what I am understanding from your post is that I should pull down the analog pins with, say, 10k resistors, right?
About using a step down transformer, I thought about it but the turbine to which I am going to attach the circuit has an output frequency of 0-300Hz, 0-21.5A and 0-64Vac. So, I am not quite sure if the transformer will operate as expected with that frequency range.
About the power part, actually I was hoping to use Vrms*Irms for calculating the power however I don't know what is the total reactance of the overall circuit. You are right about that. Would using this formula help?
Asmboy:
The schematic I supplied has awful lot of small details missing. For example, the real circuit has a 330 ohm resistor connected to the led, also another 330 ohm is present between the voltage divider and the analog input. I am so sorry for skipping those details but I was trying to supply you guys with an idea of my setup. The real deal has a 100nf decoupling capacitor as well.
I was suspecting some impedance issues as well. For example, the voltage I read via a voltmeter at the voltage divider is higher when I unplug the ADC from the voltage divider. Right on to the datasheet now.
Necati:
Thank you as well for the reply. The calculations given are correct for a DC measurement. However, the ACS714 does not give a constant DC output when you run AC through it. It gives an AC signal biased to 2.5 volts. The amplitude of the signal changes proportionally with the current. Another problem with the sensor is that i can not always get the same 0A output at 2.5V. So, what I am basically doing is to get the max and min values of the sensor output and calculate the 0A output. Selamlar. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Tue Feb 26, 2013 5:28 am |
|
|
Take a deep breath....
If a student presented that as a part of a design, and I was marking him, I'd probably consider getting him beheaded, as an example to other students, and for the good of the human race as a whole!.....
Seriously, this is triply dangerous. Even if you must use a simple resistive divider, the design of this should be aimed at 'fail safe'. Are your resistors really rated for the full AC peak voltage?. How are they designed to fail?. What would happen if they fail 'short'?. At the very least, there should be two resistors, in series, and a high speed fuse in the detection wire, with the high voltage parts encapsulated or cased.
Far safer to use a measurement transformer, or opto coupler. You can (for instance) use an opto with a specified gain, and have this take the output from the voltage divider, or (cheaper and easier - getting accurate gains on an opto is not easy), just use a 100:1 voltage sensor transformer.
Do everyone (and yourself particularly) a favour, and isolate the mains. Otherwise you are asking to die.
Then, the ACS714 is a quite high frequency device. It'll respond to the little spikes always present on the supply. This is what the filter pin is for. This wants something like a 1nF capacitor to ground. You also talk about "a 100nf decoupling capacitor as well". You want one right by the legs of the ACS714, and at least one more right by the legs of the PIC. You also need to layout your ground with care when measuring signals. _One_ master ground point, that every ground connection runs back to. No 'daisy chaining' of ground connections.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|