archusvijay1
Member level 3
Hi,
I am trying to measure 50Hz AC RMS voltage using PIC18F4520 microcontroller. Schematic shows how I am giving the input to ADC. adding a DC offset of 2.5 to the transformer output. there is also a zero crossing detector to take the samples for just one complete cycle correctly. But the measured values are not constant. so I measured 50 cycles and took average.. still there is variation. Please find the code below as I've given only the necessary part of code.I got rms values 214,221,228,229,231,215,222 etc. Is there anything wrong with the code. I've attached the circuit also. in that VOLT IN1 goes to the microcontroller pin and the outputof Q1(BC547) goes to zero crossing detector pin.
Someone please help me out
thanks.
I am trying to measure 50Hz AC RMS voltage using PIC18F4520 microcontroller. Schematic shows how I am giving the input to ADC. adding a DC offset of 2.5 to the transformer output. there is also a zero crossing detector to take the samples for just one complete cycle correctly. But the measured values are not constant. so I measured 50 cycles and took average.. still there is variation. Please find the code below as I've given only the necessary part of code.I got rms values 214,221,228,229,231,215,222 etc. Is there anything wrong with the code. I've attached the circuit also. in that VOLT IN1 goes to the microcontroller pin and the outputof Q1(BC547) goes to zero crossing detector pin.
Code:
void adcInit(void){
ADCON0=0x00;
ADCON1=0X07; // SET ANALOG CHANNELS
TRISA=0xFF;
PSPMODE=0;
TRISEbits.TRISE0=1;
TRISEbits.TRISE1=1;
TRISEbits.TRISE2=1;
ADCON2=0b10001010; // SET COVERSION CLOCK //101=15 //010=32
ADCON0=0x01; // TURN ON ADC MODULE
}
unsigned int getAdcCount(unsigned char channel){
//unsigned int count;
if(channel>13) return 0; //Invalid Channel
ADCON0=0x00;
ADCON0=(channel<<2); //Select ADC Channel
ADON=1; //switch on the adc module
// DelayMs(3); // WAITING FOR THE ACQUISITION TIME
GODONE=1; //Start conversion
while(GODONE); //wait for the conversion to finish
ADON=0; //switch off adc
//count = ADRES;
return ((ADRESH<<8)+ADRESL);
}
void main() {
unsigned char uctemp = 0;
double U32Volt;
unsigned int i = 0;
CM0 = 1; //turn off comparator
CM1 = 1; // turn off comparator
CM2 = 1; // turn off comparator
adcInit();
gprs_set_flag = 0;
EB_ZC_PIN_DIR = INPUT_PIN;
OUT_ZC_PIN_DIR = INPUT_PIN;
INV_ZC_PIN_DIR = INPUT_PIN; //zero crossing pins as inputs
while (1) {
U32Volt = 0;
for (i = 0; i < 50; i++) { //50 times averaging
invVolt = Measure_Rms_value(INVVOLT_CHANNEL, 1); // taking rms value
U32Volt += invVolt;
}
U32Volt = (U32Volt * 3.24) / 50; //3.24 multiplicaion factor
DelayS(1);
}
}
double Measure_Rms_value(unsigned channel, double Mul_factor) {
unsigned int i;
unsigned int sample_Val;
float offset_Val = 533; //775;//512; // for 3.3v ref offset val=775; for 5v ref, offset value=512
double sum_Val = 0;
float filtered_Val = 0, sq_Val = 0, Rms_val = 0;
unsigned char neg_cycle_flag;
unsigned int adc_counts = 1000;
unsigned int timeout = 0;
if (channel == INVVOLT_CHANNEL) {
unsigned int invZC = 0;
timeout = 0;
if(INV_ZC_PIN==1) // if positive half cycle: wait here
{
while (INV_ZC_PIN == 1) {
timeout++;
if (timeout >= 1000) {
timeout = 0;
break;
}
}
}
while (INV_ZC_PIN == 0) { // wait until negative cycle is finished
timeout++;
if (timeout >= 1000) {
timeout = 0;
return 0;
}
}
while (adc_counts--) { // start taking measurement for one cycle
invZC++;
sample_Val = getAdcCount(channel);
offset_Val = (offset_Val + ((sample_Val - offset_Val) / 1024));
filtered_Val = sample_Val - offset_Val;
sq_Val = filtered_Val * filtered_Val;
sum_Val += sq_Val;
if (INV_ZC_PIN == 0) { // negative cylce: zero crossing pin becomes low
neg_cycle_flag = 1;
}
if (neg_cycle_flag == 1 && INV_ZC_PIN == 1) {
neg_cycle_flag = 0;
break;
}
}
Rms_val = Mul_factor * (sqrt(sum_Val / invZC)); //
sum_Val = 0;
return Rms_val;
}
return 0;
}
Someone please help me out
thanks.