0

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

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

2 Answers2

3

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.

sh1
  • 4,324
  • 17
  • 30
  • that is a really good point... what is the point of fixing a storage specifier for a single variable if the damage is already done, depending on how it is declared I may remove my answer. – Mgetz Jul 05 '13 at 14:07
0

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.

Mgetz
  • 5,108
  • 2
  • 33
  • 51
  • 1
    Doesn't C90 (or something pre-dating C99, at least) also have constraints for LONG_MAX and LONG_MIN which suggest that it must be at least 32 bits? – sh1 Jul 05 '13 at 13:51
  • @sh1 I thought so too... [and we would both appear to be correct on that](http://stackoverflow.com/questions/589575/size-of-int-long-etc), however older implementations may not be conformant to C90... or even C89. My K&R book doesn't mention how big `unsigned long int` should be, which is why I suggested `unsigned long long` which I know should be 32bit at miniumn. – Mgetz Jul 05 '13 at 13:54