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.

TM4C123GE6PM: Incorrect (-) sign printing of angle values

Part Number: TM4C123GE6PM

Hello,

Following help from Ralph Jacobi regarding printing of floating point number over UART in this post:

e2e.ti.com/.../743882

I wrote the following code:

////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h>
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include <math.h>
#include <stddef.h> // For using the NULL pointer

#define PWM_FREQUENCY 55

////////////////////////////////////////////////////////////////////////////////////////////////////
// My I2C defines & includes
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "sensorlib/i2cm_drv.h"
#include "sensorlib/mpu6050.h"
#include "sensorlib/hw_mpu6050.h"
#define DEBUG


////////////////////////////////////////////////////////////////////////////////////////////////////
// My UART defines & includes
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
#include "definitions_mpu6050.h"

tI2CMInstance g_sI2CInst; // I2C master driver structure. "tI2CMInstance" is defined in the i2cm_drv.h file.
tMPU6050 g_sMPU6050Inst; // MPU6050 sensor driver structure. "tMPU6050" is defined in the mpu6050.h file.
volatile unsigned long g_vui8DataFlag; // Data ready flag
volatile unsigned long g_vui8ErrorFlag; // Error flag

void
ISL29023I2CIntHandler(void)
{
I2CMIntHandler(&g_sI2CInst);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
    float fAccel[3], fGyro[3] = {0.0} ;
    uint8_t register_mpu6050_o_pwr_mgmt_1 ; // Used for debug
    uint8_t register_mpu6050_o_who_am_i ; // Used for debug

    uint8_t index = 0 ;
    uint32_t counter = 0 ;
    int32_t i32IntegerPart = 0 ;
    int32_t i32FractionPart = 0 ;


    // Configure the clock
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

////////////////////////////////////////////////////////////////////////////////////////////////////
    // My I2C initialization code

    // Enable GPIO peripheral that contains I2C 2
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    // Enable I2C module 2
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);

    // Configure the pin muxing for I2C2 functions on port E4 and E5.
    GPIOPinConfigure(GPIO_PE4_I2C2SCL);
    GPIOPinConfigure(GPIO_PE5_I2C2SDA);

    // Select the I2C function for these pins.
    GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4);
    GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);

    IntMasterEnable();

//    USER_I2CMInit(&g_sI2CInst, I2C2_BASE, INT_I2C2, 0xFF, 0xFF, SysCtlClockGet()); // Set SCL to 100KHz instead of the original 400KHz.
    I2CMInit(&g_sI2CInst, I2C2_BASE, INT_I2C2, 0xFF, 0xFF, SysCtlClockGet());

    SysCtlDelay(SysCtlClockGet() / 3);

    // USER_MPU6050Callback will modify the g_bMPU6050Done variable to true if the functions that use it succeed.

    // Initialize the MPU6050
    g_bMPU6050Done = false;
    MPU6050Init(&g_sMPU6050Inst, &g_sI2CInst, MPU6050_I2C_ADDRESS, USER_MPU6050Callback, 0);
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
//    SysCtlDelay(SysCtlClockGet() / 3);

    g_bMPU6050Done = false;
    MPU6050Read(&g_sMPU6050Inst, MPU6050_O_WHO_AM_I , &register_mpu6050_o_who_am_i, 1 ,USER_MPU6050Callback , 0);
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
    SysCtlDelay(SysCtlClockGet() / 3);

    g_bMPU6050Done = false;
    MPU6050Read(&g_sMPU6050Inst, MPU6050_O_PWR_MGMT_1 , &register_mpu6050_o_pwr_mgmt_1, 1 ,USER_MPU6050Callback , 0); // Someone forgot to take the device out of sleep.
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
    SysCtlDelay(SysCtlClockGet() / 3);

    g_bMPU6050Done = false;

//  Writing 0x00 Wakes up the device from sleep.
//  Writing 0x01 wakes up the device from sleep and also makes the main clock PLL with X axis gyroscope reference.
//  MPU6050Write(&g_sMPU6050Inst, MPU6050_O_PWR_MGMT_1 , 0x00 , 1 , USER_MPU6050Callback , 0);
    MPU6050Write(&g_sMPU6050Inst, MPU6050_O_PWR_MGMT_1 , 0x01 , 1 , USER_MPU6050Callback , 0);
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
    SysCtlDelay(SysCtlClockGet() / 3);

    g_bMPU6050Done = false;
    MPU6050Read(&g_sMPU6050Inst, MPU6050_O_PWR_MGMT_1 , &register_mpu6050_o_pwr_mgmt_1 , 1 ,USER_MPU6050Callback , 0);
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
    SysCtlDelay(SysCtlClockGet() / 3);

    g_bMPU6050Done = false;
    // Configure the MPU6050 for +/- 4 g accelerometer range.
//    MPU6050ReadModifyWrite(&g_sMPU6050Inst, MPU6050_O_ACCEL_CONFIG, ~MPU6050_ACCEL_CONFIG_AFS_SEL_M, MPU6050_ACCEL_CONFIG_AFS_SEL_4G, USER_MPU6050Callback, 0);
    MPU6050ReadModifyWrite(&g_sMPU6050Inst, MPU6050_O_ACCEL_CONFIG, ~MPU6050_ACCEL_CONFIG_AFS_SEL_M, MPU6050_ACCEL_CONFIG_AFS_SEL_2G, USER_MPU6050Callback, 0);
    while(!g_bMPU6050Done) { }
    g_bMPU6050Done = false;
    SysCtlDelay(SysCtlClockGet() / 3);

////////////////////////////////////////////////////////////////////////////////////////////////////
    // My UART initialization code
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    UARTStdioConfig(0, 115200, 16000000);
    UARTprintf("The UART Works\n");
////////////////////////////////////////////////////////////////////////////////////////////////////


    while(1)
    {
        g_bMPU6050Done = false;

        while ( counter < 1000000 )
        {
            counter ++ ;
        }
        counter = 0 ;

        // Get the new accelerometer and gyroscope readings.
//        MPU6050DataAccelGetFloat(&g_sMPU6050Inst, &fAccel[0], &fAccel[1], &fAccel[2]);
//        MPU6050DataGyroGetFloat(&g_sMPU6050Inst, &fGyro[0], &fGyro[1], &fGyro[2]);


        sample_accumulate_average
        (
            &g_sMPU6050Inst ,
            256             ,
            fAccel          ,
            fGyro
        ) ;



        float angle = atan2 (fAccel[0],fAccel[2]) * ( 180.0 / PI ) ;

        i32IntegerPart = (int32_t)angle;
        i32FractionPart = (int32_t)(angle * 1000.0f);
        i32FractionPart = i32FractionPart - (i32IntegerPart * 1000);
        UARTprintf("angle: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);

        // Convert floating point to an integer and send it via UART

        for ( index = 0 ; index <= 2 ; index ++ )
        {
            i32IntegerPart = (int32_t)fAccel[index];
            i32FractionPart = (int32_t)(fAccel[index] * 1000.0f);
            i32FractionPart = i32FractionPart - (i32IntegerPart * 1000);

            if(i32FractionPart < 0)
            {
                i32FractionPart *= -1;
            }

            if ( index == 0 )
            {
                UARTprintf("Accelerometer X: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);
            }

            if ( index == 1 )
            {
                UARTprintf("Accelerometer Y: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);
            }

            if ( index == 2 )
            {
                UARTprintf("Accelerometer Z: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);
            }
        }

        for ( index = 0 ; index <= 2 ; index ++ )
        {
            i32IntegerPart = (int32_t)fGyro[index];
            i32FractionPart = (int32_t)(fGyro[index] * 1000.0f);
            i32FractionPart = i32FractionPart - (i32IntegerPart * 1000);

            if(i32FractionPart < 0)
            {
                i32FractionPart *= -1;
            }

            if ( index == 0 )
            {
                UARTprintf("Gyro X: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);
            }

            if ( index == 1 )
            {
                UARTprintf("Gyro Y: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);
            }

            if ( index == 2 )
            {
                UARTprintf("Gyro Z: %3d.%03d\t\n\n\n\n\n", i32IntegerPart, i32FractionPart);
            }
        }

        /*
        We're interested in:
        Accelerometer readings in the X axis ( perpendicular to the table ).
        Gyro readings in the Y axis ( the ball bearing axis ).
        */
        fAccel[0] = 0.0 ;
        fAccel[1] = 0.0 ;
        fAccel[2] = 0.0 ;
        fGyro[0] = 0.0 ;
        fGyro[1] = 0.0 ;
        fGyro[2] = 0.0 ;
    }
}


Everything works fine - except of on thing, 

When the values of "angle" assume a negative value - the print of the (-) sign doesn't work well (a screenshot is attached)

Please help me fix the code.

  • Hello Shai,

    It looks like for the Angle you are missing the code you used in other places:

    shai kon said:
    if(i32FractionPart < 0)
                {
                    i32FractionPart *= -1;
                }

    For angle you only do this:

            i32IntegerPart = (int32_t)angle;
            i32FractionPart = (int32_t)(angle * 1000.0f);
            i32FractionPart = i32FractionPart - (i32IntegerPart * 1000);
            UARTprintf("angle: %3d.%03d\t\n", i32IntegerPart, i32FractionPart);

    So the minus sign of your last i32FractionPart operation isn't being taken care of.