Floating point division problems

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Floating point division problems

1,346件の閲覧回数
Ashkan
Contributor I

Hi,

In the following code, the simple division creat problems with the counter. It seems there is a spill over of the division into other parts of memory.  In other terms, there is a memory leak, and memory spill over.

 

I have had this problem many other times with the Codewarrior for HCS08 compiler. If you are lucky you can see the other non related variables change when a division is executed. (Spill over to other parts of memory)

In the following specific example, the line of    filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);  , changes the counter  n to zero ) So the loop never ends

 

I played with the code a bit, and increased the stack size. There is no spill over anymore, however the following line reset the MCU:  Vrms = VCAL*sqrt(sumV / numberOfSamples);

 

The code is a  good sample for ADC conversions...

 

Let me know if you guys have any insight to the problem....



//Calibration coeficients
//These need to be set in order to obtain accurate results
double VCAL = 1.0;
double ICAL = 1.0;
double PHASECAL = 2.3;

//Sample variables
int lastSampleV,lastSampleI,sampleV,sampleI;

//Filter variables
double lastFilteredV, lastFilteredI, filteredV, filteredI;
double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double calibratedV;

//Power calculation variables
double sqI,sqV,instP,sumI,sumV,sumP;

//Useful value variables
double realPower,
       apparentPower,
       powerFactor,
       Vrms,
       Irms;
       
int n;


//Setup variables
#define numberOfSamples  3000
 
void main(void)
{
  /* Write your local variable definition here */
  unsigned char i;
 
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  PE_low_level_init();
  /*** End of Processor Expert internal initialization.                    ***/

  /* Write your code here */
  /* For example: for( ; ; ) { } */
   
   
   //SendStr(Introduction);
  if ( xbee_SetCommandMode() != false )
  {
    xbeeResponse = xbee_SendCommand("ATPL4\r");
    xbee_ExitCommandMode();
  }
 
      
    
    for (n=0; n<numberOfSamples; n++)
    {

       //Used for offset removal
       lastSampleV=sampleV;
       lastSampleI=sampleI;
       
       //Read in voltage and current samples.   
        while ( AD1_Measure(TRUE) !=ERR_OK )
        {;}
        if (  AD1_GetValue16((unsigned int *) &ADC_Values) != ERR_OK )  
        continue;
      
       sampleV = ADC_Values[VAC_ADC];
       sampleI = ADC_Values[I1AC_ADC];
       
       //Used for offset removal
       lastFilteredV = filteredV;
       lastFilteredI = filteredI;
      
       //Digital high pass filters to remove 2.5V DC offset.
       filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
       filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
       
       //Phase calibration goes here.
       calibratedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
      
       //Root-mean-square method voltage
       //1) square voltage values
       sqV= calibratedV * calibratedV;
       //2) sum
       sumV += sqV;
       
       //Root-mean-square method current
       //1) square current values
       sqI = filteredI * filteredI;
       //2) sum
       sumI += sqI;

       //Instantaneous Power
       instP = calibratedV * filteredI;
       //Sum
       sumP +=instP;
    }
    

    //Calculation of the root of the mean of the voltage and current squared (rms)
    //Calibration coeficients applied.
    Vrms = VCAL*sqrt(sumV / numberOfSamples);
    Irms = ICAL*sqrt(sumI / numberOfSamples);

    //Calculation power values
    realPower = VCAL*ICAL*sumP / numberOfSamples;
    apparentPower = Vrms * Irms;
    powerFactor = realPower / apparentPower;
 
    sendStr("\r\n realPower:");
    SendWordValue(realPower );

 
 
  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(; ; ){}
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODI

ラベル(1)
0 件の賞賛
返信
3 返答(返信)

631件の閲覧回数
kef
Specialist I

Is math.h included? Missing function prototypes can be harmful.

 

Did you analyze the cause of reset? Was it COP, ILAF, ILOP? Please check your derivative datasheet what do these bits mean and where you can read them.

 

Code below requires not less than ~150bytes of stack. You may check that for example with simulator. Point data window to address you see in SP register, scroll data window up until you see area filled with 'uu' - undefined. After execution of your code you may see how what bytes in stack space were modified and calculate used stack space.

0 件の賞賛
返信

631件の閲覧回数
Ashkan
Contributor I

Hi,

Thanks for the reply. You were correct, some parts of the problem were due to the stack problems.

 

There were two major errors. First one was that I had created the project using different allocation sizes for float and double. Then, I changed them back to be the same in project setting. That was basically the source of the memory spill overs.

To solve it, I created a new clean project from scratch, added my source files to it.

 

The second problem was that I was running out of RAM in my HCS08QG microcontroller. For some reason, the compiler and linker didn't give me errors, however I believe there were problems with that. So, I just removed some parts unrelated code, and now its working like a charm.

 

0 件の賞賛
返信

631件の閲覧回数
bigmac
Specialist III

Hello,

 

The linker will show errors only if the defined global and static variables, plus the specified stack size cannot be allocated within the available RAM,  which does not usually include zero page RAM by default.  The linker does not estimate run time stack usage.

 

The determination of a suitable stack size is up to the programmer.  The stack size specified in the default PRM file is generally insufficient for floating point operations.

 

I would suggest that you check the allocation of the global and static variables within the map file for  the project, to determine the amount of RAM used.  The stack is normally allocated immediately above these variables.  The stack may usually be increased in size to occupy the remaining space.

 

It is possible that zero page RAM may not be used at all.  You might consider allocating some of the global variables to zero page RAM, to more fully utilize the RAM capacity.

 

It is possible that the last global variable defined will have the highest address (check this out in the map file).  This variable might be allocated as a dummy variable, and initialised to a specific value.  If the value contained in the variable were corrupted, this would inticate the prior occurrence of a stack overflow, and that other variables may have become corrupted.

 

Regards,

Mac

 

0 件の賞賛
返信