user2408205
user2408205

Reputation:

Overflow Error, RMS value shown wrong

I am measuring AC Voltage and I am calculating rms value for ADC.

I have an array which is having 128 samples of my signal. while squaring number I get an error.

unsigned long int calval=0;
unsigned int loop;
float adcbufval;
for(loop=0;loop<128;loop++)
{
    printf("adcval %d = %d\t ", loop, adc_temp[loop]);
    calval = (adc_temp[loop])*(adc_temp[loop]);
    printf("\t %ld \n", calval);

}

output:

adcval 1 = 168 28224
adcval 2 = 32 1024 
adcval 3 = -88 7744 
adcval 4 = -211 44521 // sqr(211) 44521 , it fine here
adcval 5 = -314 33060 // sqr(314) 98596-65536 = 33060 instead of 98596.
adcval 6 = -416 41984 
adcval 7 = -522 10340 
adcval 8 = -655 35809
adcval 9 = -773 7705 
adcval 10 = -889 3889 

Though I defined 'calval' as unsigned long int (range 0-4,294,967,295), it get over flowed at 65536 value. In normal C compiler its working fine. Any suggestions?

Hardware is dsPIC30f5011 / MPLAB 8.8x

Upvotes: 0

Views: 180

Answers (2)

sh1
sh1

Reputation: 4751

You haven't shown it (or I've overlooked it), but if adc_temp[] is an array of int, then to safely square the values you must cast at least one side of the multiplication to long before doing so. Otherwise the result of the multiplication will still be int, and it will only be converted to unsigned long for the assignment, after overflow has already occurred.

Like so:

calval = (long)(adc_temp[loop])*(adc_temp[loop]);

That cast may be unsigned long if adc_temp[] is also unsigned.

Upvotes: 3

Mgetz
Mgetz

Reputation: 5128

According to the datasheet the dsPIC30f5011 is a 16bit microcontroller, according to C99 you are correct unsigned long should be 2^32. However it appears that the compiler you are using treats long as an alias for int which is still compliant with C90 which simply required sizeof(short) <= sizeof(int) <= sizeof(long). You might have better luck if you really need 32bit math using unsigned long long.

Upvotes: 0

Related Questions