This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

IQ math problem: Determining absolute shaft position using arctan

Other Parts Discussed in Thread: CCSTUDIO

I am encountering a problem with processing shaft sensor signals.

When I am using the IQ math, there is a highly repeatable error in the output for several calls into the library.

 

_IQatan2PU

_IQdiv

_IQmpy

 

The following software is an implementation where an average sampling is desired.

The average is normalized and passed into the IQ math calls to determine shaft position.

 

First, two sinusoidal signals in quadrature from a magnetic sensor is sampled via AD7 & 8.

Then, the sample is normalized by dividing by the sampling mean.

 

Next, the two signals, one sine, the other cosine, are passed into the IQ math library

 

_IQatan2PU()

 

The return should be a absolute signal from -1 to 1 IQ24 depicting the shaft position from 0⁰ to 360⁰.

 

For purposes of elimination, I tried different IQ math functions to get similar results.

The example depicted is a _IQmpy of the same signal.

 

I am using the CAN peripheral to output signal information as close to real time as possible.

The Vector Canoe CAN protocol analyzer output depicts some form of saturation that is not understood.

 

Here the cal_shaft_ShaftPosition signal data depicts a simple multiply of the normalized cosine shaft signal.

 

#define

SHAFT_LIMIT_SENSOR (0.01)
#define MAX_VELOCITY_SAMPLE_PWR (3)
#define MAX_VELOCITY_SAMPLE (1<<MAX_VELOCITY_SAMPLE_PWR)

    CalShaft.Sine.ShaftPositionAccum   += (long)ilg2_vdc1.ADC_conv8;
    CalShaft
.Cosine.ShaftPositionAccum += (long)ilg2_vdc1.ADC_conv7;

   
if ((CalShaft.NumVelocitySample++ % MAX_VELOCITY_SAMPLE) == 0)
   
{
        CalShaft
.Sine.DeltaShaftPosition      = _IQmpyI32(scaler, (CalShaft.Sine.ShaftPositionAccum)>>MAX_VELOCITY_SAMPLE_PWR ) - CalShaft.sensor_offset;

        CalShaft
.Cosine.DeltaShaftPosition    = _IQmpyI32(scaler, (CalShaft.Cosine.ShaftPositionAccum)>> MAX_VELOCITY_SAMPLE_PWR)- CalShaft.sensor_offset;


       
if ( (CalShaft.Cosine.DeltaShaftPosition < _IQ(SHAFT_LIMIT_SENSOR)) &&\
             (CalShaft
.Cosine.DeltaShaftPosition >= _IQ(0.0)))
       
{
            CalShaft
.Cosine.DeltaShaftPosition = _IQ(SHAFT_LIMIT_SENSOR);
       
}
       
else if ( (CalShaft.Cosine.DeltaShaftPosition > _IQ(-SHAFT_LIMIT_SENSOR)) &&\
                  (CalShaft
.Cosine.DeltaShaftPosition <= _IQ(0.0)))
       
{
            CalShaft
.Cosine.DeltaShaftPosition = _IQ(-SHAFT_LIMIT_SENSOR);
       
}
       
else
       
{
       
}

       
if ( (CalShaft.Sine.DeltaShaftPosition < _IQ(SHAFT_LIMIT_SENSOR)) &&\
             (CalShaft
.Sine.DeltaShaftPosition >= _IQ(0.0)))
       
{
            CalShaft
.Sine.DeltaShaftPosition = _IQ(SHAFT_LIMIT_SENSOR);
       
}
       
else if ( (CalShaft.Sine.DeltaShaftPosition > _IQ(-SHAFT_LIMIT_SENSOR)) &&\
                  (CalShaft
.Sine.DeltaShaftPosition <= _IQ(0.0)))
       
{
            CalShaft
.Sine.DeltaShaftPosition = _IQ(-SHAFT_LIMIT_SENSOR);
       
}
       
else
       
{
       
}

                                              
        CalShaft
.ShaftPosition = _IQmpy(CalShaft.Cosine.DeltaShaftPosition, CalShaft.Cosine.DeltaShaftPosition);

//        CalShaft.ShaftPosition = _IQmpy(CalShaft.Sine.DeltaShaftPosition, CalShaft.Sine.DeltaShaftPosition);

//        CalShaft.ShaftPosition = _IQmpy(CalShaft.Sine.DeltaShaftPosition, CalShaft.Sine.DeltaShaftPosition) +\
//                                 _IQmpy(CalShaft.Cosine.DeltaShaftPosition,CalShaft.Cosine.DeltaShaftPosition);

//        CalShaft.ShaftPosition                = _IQdiv(CalShaft.Sine.DeltaShaftPosition, CalShaft.Cosine.DeltaShaftPosition);
//        CalShaft.ShaftPosition                = _IQatan2PU((CalShaft.Sine.DeltaShaftPosition), \
//                                                             (CalShaft.Cosine.DeltaShaftPosition));

        CalShaft
.Sine.PriorAccum              = CalShaft.Sine.ShaftPositionAccum;
        CalShaft
.Cosine.PriorAccum            = CalShaft.Cosine.ShaftPositionAccum;

        CalShaft
.Sine.ShaftPositionAccum      = 0;
        CalShaft
.Cosine.ShaftPositionAccum    = 0;

Code Composer Studio 3.3.38.2

Integrated Development 5.98.0.219 Texas Instruments

Bios 5.31.02

Code Generation tools 5.2.3

IQ Math Library version: 15a

 

Linker/Cmd file configuration for IQ math:

 

   IQmath:      LOAD = FLASHC,

                       RUN = RAMH0,

                        LOAD_START(_IQmathLoadStart),

                       LOAD_END(_IQmathLoadEnd),

                       RUN_START(_IQmathRunStart),

                       PAGE = 0

 

   IQmathTables        : > ROM                                        PAGE = 0, TYPE = NOLOAD           /* Math Tables In ROM */

   IQmathTablesRam     : > FLASHC           PAGE = 0

 

Compiler Settings:

"C:\Program Files\Texas Instruments\C2000 Code Generation Tools 5.2.3\bin\cl2000" -g -pdsw225 -fr"../../CC_Build/Debug/obj" -i"../../src/include" -d"_DEBUG" -d"LARGE_MODEL" -ml -v28 -@"../../tools/code composer/Debug.lkf"

Linker Settings:

-z -a -c -m"../../CC_Build/Debug/DDM VW ProtoType.map" -o"../../CC_Build/Debug/DDM VW ProtoType.out" -stack0x100 -w -x -i"../../src/lib" -i"C:/CCStudio_v3.3.38.2/C2000/xdais/lib" -i"C:/CCStudio_v3.3.38.2/bios_5_31_02/packages/ti/bios/lib" -i"C:/CCStudio_v3.3.38.2/bios_5_31_02/packages/ti/rtdx/lib/c2000" -i"C:/Program Files/Texas Instruments/C2000 Code Generation Tools 5.2.3/lib" -l"Flash2808_API_V302.lib" -l"IQmath.lib"

  • Esmael Beydoun said:
    When I am using the IQ math, there is a highly repeatable error in the output for several calls into the library.
     
    _IQatan2PU
    _IQdiv
    _IQmpy
     

    Esmael,

    If I understand, you see incorrect behavior for each of these functions?  Can you provide

    • the exact input (hex value or IQ24 value)
    • the expected output and
    • the incorrect output for each of these functions.  

    Unfortunately I'm not able to easily figure this from the code listing.  

    Is it possible that the numbers are out of range for an IQ24?  For IQ24 the range is -128 to 129.9999

    These functions have been around for a while without any report of errors so I suspect something else might be going on.  The IQmpy is a compiler intrinsic that had a bug in one of the codegen versions but it was only with optimizations on, and it looks like you are not using optimizations.

    Regards,

    Lori

     

  • Here is my data.

    CalshaftCosineDeltaShaftPosition IQ24 CalshaftSineDeltaShaftPosition IQ24 cal_shaft_sensor_raw 32 bit unsigned cal_shaft_ShaftPosition IQ 24
    0.085903 1.081993 123803 0.007379
    0.085903 1.081993 123803 0.007379
    0.079159 1.081846 105129 0.006266
    0.079159 1.081846 105129 0.006266
    0.07095 1.0817 84455 0.005034
    0.07095 1.0817 84455 0.005034
    0.064061 1.08214 68849 0.004104
    0.064061 1.08214 68849 0.004104
    0.055998 1.080674 52609 0.003136
    0.055998 1.080674 52609 0.003136
    0.052333 1.083606 45948 0.002739
    0.052333 1.083606 24953073 1.489958
    0.052333 1.083606 24982586 1.489078
    0.046176 1.083312 24989964 1.489518
    0.046176 1.083312 24982586 1.489078
    0.039287 1.083752 24975207 1.488638
    0.039287 1.083752 24967829 1.488199
    0.033716 1.084778 24975207 1.488638
    0.033716 1.084778 24982586 1.489078
    0.02536 1.084485 24982586 1.489078
    0.02536 1.084485 24982586 1.489078
    0.019936 1.085658 24967829 1.488199
    0.019936 1.085658 24989964 1.489518
    0.011434 1.083752 25004720 1.490397
    0.011434 1.083752 25012098 1.490837
    0.01 1.085658 24989964 1.489518
    0.01 1.085658 24960451 1.487759
    -0.01 1.084632 24982586 1.489078
    -0.01 1.084632 25004720 1.488638
    -0.01 1.085071 24975207 1.488638
    -0.01 1.085071 24967829 1.488199
    -0.014806 1.084632 25004720 1.490397
    -0.014806 1.084632 24975207 1.488638
    -0.018324 1.086977 24975207 1.488638
    -0.018324 1.086977 24982586 1.489078
    -0.029465 1.084632 24989964 1.489518
    -0.029465 1.084632 24975207 1.488638
    -0.03357 1.084925 24997342 1.489958
    -0.03357 1.084925 24997342 1.489958
    -0.03958 1.084045 24997342 0.001567
    -0.03958 1.084045 26282 0.001567
    -0.046763 1.084925 36687 0.002187
    -0.046763 1.084925 36687 0.002187
    -0.051161 1.087124 43912 0.002617
    -0.051161 1.087124 43912 0.002617

     

  • I have resolved this issue.

    With the help from D3 engineering, I was able to use Code composer to to graph a temporary array within my routine.

    It was found that the return to the structure was being corrupted by an overrite in another routine.

    Thanks for every one's patience.

  • I'm trying to use the trig functions using the IQ math library.  Pid_Id.PreSatOut is on the x-axis, Pid_Iq.PreSatOut is on the y-axis and Filtered_PreSatVoltMag is the magnitude of the two.  I've tried finding the angle with respect to the x-axis and I seem to not get the correct answer for each.  everything is _IQ24 format.  Sometimes My answer for tan, cos and sin is greater than 2^24 but all three seem to be the same value but do not make sense in terms of angle.  For example.

    PID_Id = 6758233

    PID_Iq = 12597855

    Mag = 14296141

    and for each of the angles, I get approx 18000000 (in _iq24) which is greater than 2^24 and does not make sens for 0 to pi.  Below is my code

     

    cosAngle = _IQacos(_IQdiv(Pid_Id.PreSatOut,Filtered_PreSatVoltMag));
         sinAngle = _IQasin(_IQdiv(-Pid_Iq.PreSatOut,Filtered_PreSatVoltMag));
         tanAngle = _IQ24atan2(-Pid_Iq.PreSatOut,Pid_Id.PreSatOut);

    magnitude of unsaturated voltage vector and compare to limit */
      PreSatVoltMag = _IQmag(Pid_Iq.PreSatOut, Pid_Id.PreSatOut);