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.

CCS/TM4C123GH6PM: sample, accumulate, average function - CCS warning

Part Number: TM4C123GH6PM

Tool/software: Code Composer Studio

Hello,

I'm working with the mpu6050 sensor connected to my Launchpad board.

The readings are very noisy - so to improve the results I wanted write a function that does the following:

1. Takes a reading

2. Accumulates (adds the new reading to the sum of all the history readings.

3. Divides the accumulated sum by the number of readings.

This is what I wrote:

void sample_accumulate_average ( int number_of_samples , float *accelerometer_average[3] , float *gyro_average[3] ) // the function receives as an argument pointer to arrays of 3 elements
{
    float accelerometer_reading[3], gyro_reading[3];
    int sample_counter ;
    int axis_number ;
    tMPU6050 g_sMPU6050Inst; // MPU6050 sensor driver structure. "tMPU6050" is defined in the mpu6050.h file.
    for ( sample_counter = 0 ; sample_counter < number_of_samples ; sample_counter ++ )
    {
        MPU6050DataRead(&g_sMPU6050Inst, USER_MPU6050Callback, 0);
        while(!g_bMPU6050Done) { }
        MPU6050DataAccelGetFloat(&g_sMPU6050Inst, &accelerometer_reading[0], &accelerometer_reading[1], &accelerometer_reading[2]);
        MPU6050DataGyroGetFloat(&g_sMPU6050Inst, &gyro_reading[0], &gyro_reading[1], &gyro_reading[2]);
        for ( axis_number = 0 ; axis_number < 3 ; axis_number ++ )
        {
            *accelerometer_average [ axis_number ] = *accelerometer_average [ axis_number ] + accelerometer_reading [ axis_number ] ; // accumulate accelerometer readings
            *gyro_average [ axis_number ] = *accelerometer_average [ axis_number ] + accelerometer_reading [ axis_number ] ; // accumulate gyro readings
        }
    }
    for ( axis_number = 0 ; axis_number < 3 ; axis_number ++ )
    {
        *accelerometer_average [ axis_number ] = *accelerometer_average [ axis_number ] / number_of_samples ;
        *gyro_average [ axis_number ] = *gyro_average [ axis_number ] / number_of_samples ;
    }
}

And this is how I call the function in my code

 sample_accumulate_average ( 64 , &fAccel , &fGyro ) ;

I get the following warning:

Description Resource Path Location Type
#169-D argument of type "float (*)[3]" is incompatible with parameter of type "float **" main.c /PID line 186 C/C++ Problem

What did I do wrong ?

  • You are confusing arrays of floats with arrays of pointers to floats. I assume that both fAccel and fGyro are defined as:

      float fAccel[3];
      float fGyro[3];

    And i assume you want to pass pointers to these two arrays to your function and have the function fill the arrays with the average values read from the MPU-6050. First, when you call the function, the array name (without the []) is the pointer to the array. It is the same as &fAccel[0]. Passing &fAccel is creating a copy of the address and passing the address to the address (not what you want). 

    So in the routine:

    void sample_accumulate_average ( int number_of_samples , float *accelerometer_average , float *gyro_average) // the function receives as an argument pointer to arrays of 3 elements
    {
        float accelerometer_reading[3], gyro_reading[3];
        int sample_counter ;
        int axis_number ;
        tMPU6050 g_sMPU6050Inst; // MPU6050 sensor driver structure. "tMPU6050" is defined in the mpu6050.h file.
        for ( sample_counter = 0 ; sample_counter < number_of_samples ; sample_counter ++ )
        {
            MPU6050DataRead(&g_sMPU6050Inst, USER_MPU6050Callback, 0);
            while(!g_bMPU6050Done) { }
            MPU6050DataAccelGetFloat(&g_sMPU6050Inst, &accelerometer_reading[0], &accelerometer_reading[1], &accelerometer_reading[2]);
            MPU6050DataGyroGetFloat(&g_sMPU6050Inst, &gyro_reading[0], &gyro_reading[1], &gyro_reading[2]);
            for ( axis_number = 0 ; axis_number < 3 ; axis_number ++ )
            {
                accelerometer_average [ axis_number ] = accelerometer_average [ axis_number ] + accelerometer_reading [ axis_number ] ; // accumulate accelerometer readings
                gyro_average [ axis_number ] = gyro_average [ axis_number ] + gyro_reading [ axis_number ] ; // accumulate gyro readings
            }
        }
        for ( axis_number = 0 ; axis_number < 3 ; axis_number ++ )
        {
            accelerometer_average [ axis_number ] = accelerometer_average [ axis_number ] / number_of_samples ;
            gyro_average [ axis_number ] = gyro_average [ axis_number ] / number_of_samples ;
        }
    }
    

  • Just to add to Bob's comment, if you want to access an element of an array using the pointer then you do something like this:

      float fAccel[3];
      float fGyro[3];

    float *ptr;
    float x;

    ptr = fAccel; // ptr points to the first element of the fAccel array
    x = *(ptr+2); // move the content of the third element of fAccel which is equivalent to fAccel[2] to x.

  • Your assumptions are correct.

    And I should call the like this?

            sample_accumulate_average
            (
                64          ,
                &fAccel[0]  ,
                &fGyro[0]
            ) ;

  • Yes you can write like above. Or you can just write like below as an array is a pointer per C definition.

    sample_accumulate_average
    (
    64 ,
    fAccel ,
    fGyro
    ) ;
  • I want to solidify my understanding of what Bob wrote with a simple example of indirectly incrementing a variable via a function.
    //Case 1 - the external variable IS NOT an array element:

    int x ;

    void increment_indirectly ( int * pointer_to_non_array_elemet )
    {
    * pointer_to_non_array_element ++ ;
    ]

    increment_indirectly ( &x ) ;



    //Case 2 - the external variable IS an array element:

    // Incorrect form:
    int x[3] ;

    void increment_indirectly ( int * pointer_to_non_array_element )
    {
    * pointer_to_array_element [0] = * pointer_to_array_element [0] + 1 ;
    ]

    increment_indirectly ( & x [ 0 ] ) ;

    The reason why case 2 is incorrect is because in C the array name (x in this case) is implicitly defined as a pointer the moment we declare the array.
    So this:
    * pointer_to_array_element [0]
    Is actually a pointer to a pointer instead of a pointer to the array element.

    Am I correct ?
  • That is correct.

    unsigned int array[5];
    
    array[0] = 0;
    *array++;    // array[0] now equals 1
    array[0]++;  // array[0] now equals 2
    
    *array[0]++; // means increment the data stored at address 2

  • just don't get confused between pointer to array vs. array of pointers which was what you originally had before.

    This link may be helpful.
    www.tutorialspoint.com/.../c_array_of_pointers.htm