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.

  • Resolved

EK-TM4C123GXL: MPU9150_init() returning false. Adapting DK-TM4C123G MPU9150 example to work on EK-TM4C123GXL + SENSHUB

Prodigy 170 points

Replies: 8

Views: 401

Part Number: EK-TM4C123GXL

I have recently bought a BOOSTXL-SENSHUB and had interest in using its MPU-9150 with my EK-TM4C123GXL. The example available in CCS that makes use of the MPU-9150 works as intended, but it's a non-rtos example. I am planning to use the MPU-9150 for a TI-RTOS application.

The closest example to what I've wanted has been found in a zip file, in the following link: http://processors.wiki.ti.com/index.php/TI-RTOS_MPU9150

I have noticed that there are some differences in that example with how, for example, TI-RTOS GPIO driver is used to configure pin PB2 as input and to issue interrupts at falling edges. I am aware some changes must be made in order to use convenient MPU9150 APIs found in MPU9150.h.

My current issue is that on my main, MPU9150_init() is returning false. I am not sure why, but I am thinking I need to do some changes to MPU9150.c, such as adding a transferMode, which seems absent from MPU9150.c found in the DK-TM4C123G TI-RTOS example. I have looked at the issue further and within MPU9150.c, the null is being returned due to I2C_transfer() returning false. I Will post parts of my code below, along with my project.

TI_RTOS_MPU9150.zip

MPU9150_Handle MPU9150_init(unsigned int mpu9105Index,
                            unsigned int i2cIndex,
                            uint8_t i2cAddr)
{
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;
    Error_Block     eb;
    bool			transferOK;
    uint8_t		    writeBuffer[5];
    uint8_t		    readBuffer[1];
    MPU9150_Handle	handle = &object[mpu9105Index];

    /* Check if the handle was already opened */
    if((mpu9105Index > MPU9150_COUNT) || (handle->i2c != NULL)) {




    	return (NULL);
    }

    /*
     * Create GateMutex to guarantee that data received from the MPU9150
     * retains its coherency.
     */
    Error_init(&eb);
    handle->dataAccess = GateMutex_create(NULL, &eb);

    if (!handle->dataAccess) {


    	return (NULL);
    }



    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    handle->i2c = I2C_open(i2cIndex, &i2cParams);
    handle->i2cAddr =  i2cAddr;

    /* If the I2C controller opened properly continue */
    if (handle->i2c) {

    	/* Used by all I2C transfers */
    	i2cTransaction.slaveAddress = i2cAddr;
    	i2cTransaction.writeBuf = writeBuffer;
    	i2cTransaction.readBuf = readBuffer;


    	/* Put the MPU9150 into reset state */
    	writeBuffer[0] = MPU9150_O_PWR_MGMT_1;
    	writeBuffer[1] = MPU9150_PWR_MGMT_1_DEVICE_RESET;
    	i2cTransaction.writeCount = 2;
		i2cTransaction.readCount = 0;

		//ISSUE is found in this if statement
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {

            //added
            System_printf("I2C_transfer() returned false \n Closing program\n");
            System_flush();

			return (NULL);
		}

       	/*
		 * Check the value read back from status to determine if device
		 * is still in reset or if it is ready.  Reset state for this
		 * register is 0x40, which has sleep bit set. Device may also
		 * respond with an address NACK during very early stages of the
		 * its internal reset.  Keep polling until we verify device is
		 * ready.
		 */
       	writeBuffer[0] = MPU9150_O_PWR_MGMT_1;
       	i2cTransaction.writeCount = 1;
    	i2cTransaction.readCount = 1;
    	do {
    		transferOK = I2C_transfer(handle->i2c, &i2cTransaction);
    	} while ((readBuffer[0] != MPU9150_PWR_MGMT_1_SLEEP) || (!transferOK));

    	/* Take the device out of reset and enable the clock */
       	writeBuffer[0] = MPU9150_O_PWR_MGMT_1;
       	writeBuffer[1] = MPU9150_PWR_MGMT_1_CLKSEL_XG;
       	i2cTransaction.writeCount = 2;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {
			return (NULL);
		}

    	/* Enable A I2C Master mode on the MPU9150 */
       	writeBuffer[0] = MPU9150_O_USER_CTRL;
       	writeBuffer[1] = MPU9150_USER_CTRL_I2C_MST_EN;
       	i2cTransaction.writeCount = 2;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {


            //added



			return (NULL);
		}

       	/*
       	 * Change to power mode complete, device is ready for configuration.
       	 * Set MPU9150's sampling rate
       	 * Set sample rate to 50 hertz.  1000 hz / (1 + 19)
       	 */
       	writeBuffer[0] = MPU9150_O_SMPLRT_DIV;
       	writeBuffer[1] = 19;
       	i2cTransaction.writeCount = 2;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {






			return (NULL);
		}

       	/*
		 * Write the I2C Master delay control so we only sample the AK
		 * every 5th time that we sample accel/gyro.  Delay Count itself
		 * handled in next state.
		 */
       	writeBuffer[0] = MPU9150_O_I2C_MST_DELAY_CTRL;
       	writeBuffer[1] = (MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV0_DLY_EN |
                          MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV4_DLY_EN);
       	i2cTransaction.writeCount = 2;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {



			return (NULL);
		}

       	/*
		 * Write the configuration for I2C master control clock 400khz
		 * and wait for external sensor before asserting data ready
		 */
       	writeBuffer[0] = MPU9150_O_I2C_MST_CTRL;
		writeBuffer[1] = (MPU9150_I2C_MST_CTRL_I2C_MST_CLK_400 |
                          MPU9150_I2C_MST_CTRL_WAIT_FOR_ES);

		/*
		 * Configure I2C Slave 0 for read of AK8975 (I2C Address 0x0C)
		 * Start at AK8975 register status 1 (0x02)
		 */
		writeBuffer[2] = MPU9150_I2C_SLV0_ADDR_RW | 0x0C;
		writeBuffer[3] = 0x02;
		writeBuffer[4] = MPU9150_I2C_SLV0_CTRL_EN | 0x08;
       	i2cTransaction.writeCount = 5;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {






			return (NULL);
		}

       	/*
		 * Write the configuration for I2C Slave 4 transaction to AK8975
		 * 0x0c is the AK8975 address on i2c bus.
		 * we want to write the control register with the value for a
		 * starting a single measurement.
		 */
       	writeBuffer[0] = MPU9150_O_I2C_SLV4_ADDR;
		writeBuffer[1] = 0x0C;
		writeBuffer[2] = 0x0A; //AK8975_O_CNTL
		writeBuffer[3] = 0x01; //AK8975_CNTL_MODE_SINGLE
		writeBuffer[4] = MPU9150_I2C_SLV4_CTRL_EN | 0x04;
       	i2cTransaction.writeCount = 5;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {





			return (NULL);
		}

        /*
         * Write application specific sensor configuration such as filter
         * settings and sensor range settings.
         */
       	writeBuffer[0] = MPU9150_O_CONFIG;
    	writeBuffer[1] = MPU9150_CONFIG_DLPF_CFG_94_98;
		writeBuffer[2] = MPU9150_GYRO_CONFIG_FS_SEL_250;
		writeBuffer[3] = (MPU9150_ACCEL_CONFIG_ACCEL_HPF_5HZ |
                          MPU9150_ACCEL_CONFIG_AFS_SEL_2G);
       	i2cTransaction.writeCount = 4;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {
			return (NULL);
		}

       	/*
		 * Configure the data ready interrupt pin output of the MPU9150.
		 */
       	writeBuffer[0] = MPU9150_O_INT_PIN_CFG;
    	writeBuffer[1] = MPU9150_INT_PIN_CFG_INT_LEVEL |
                         MPU9150_INT_PIN_CFG_INT_RD_CLEAR |
                         MPU9150_INT_PIN_CFG_LATCH_INT_EN;;
		writeBuffer[2] = MPU9150_INT_ENABLE_DATA_RDY_EN;
       	i2cTransaction.writeCount = 3;
    	i2cTransaction.readCount = 0;
       	if (!I2C_transfer(handle->i2c, &i2cTransaction)) {





			return (NULL);
		}

    	return (handle);
    }
    else {



    	return (NULL);
    }
}
  • The task that calls for MPU9150_init() after declaring a static MPU9150_Handle mpu variable:

    Void dataCollectionTaskFxn(UArg arg0, UArg arg1)
    {
    
       // mpu = MPU9150_init(0, Board_I2C_MPU9150, I2C_MPU9150_ADDR);
       // notes: I2C_MPU9150_ADDR defined in board.h
       // notes: Board_I2C1 corresponds to I2C3 module
        System_printf("Attempting to initalize mpu_handle \n");
        System_flush();
    
    
        mpu = MPU9150_init(0, Board_I2C1, I2C_MPU9150_ADDR );
        if (mpu == NULL) {
            System_abort("MPU9150 could not be initialized");
        }
        else{
    
            System_printf("SUCCESSFULLY INITIATED\n");
            /* SysMin will only print to the console when you call flush or exit */
            System_flush();
    
        }
    

  • In reply to Pablo Ambia Wang:

    Hi Pablo,

    An engineer will look at this on Monday.

    Todd

  • In reply to ToddMullanix:

    Hi ToddMullanix,

    I appreciate it.

    I left out the version of the software I am using. It is:

    TI-RTOS 2.16.00.08

    CCS 9.1.0

  • In reply to Pablo Ambia Wang:

    Hi Pablo,

    I don't have access to a BOOSTXL-SENSHUB, but could you put up a screenshot of the first I2C transfer with a logic analyzer?

    Jas

  • In reply to Jaskaran Atwal:

    Unfortunately lab equipment within my campus is not accessible at the moment. I have ordered a NOYITO USB Logic Analyzer Device with USB Cable. It will arrive this Saturday. I will provide a screenshot as soon as possible.

  • In reply to Jaskaran Atwal:

    Hi Jaskaran,

    Here is the screenshot of the first I2C transfer:

    PD0 corresponds to SCL

    PD1 corresponds to SDA

  • In reply to Pablo Ambia Wang:

    Hi Pablo,

    Thanks for the screenshot. It looks like the slave(MPU9150) is not responding to the I2C transaction as can be seen from the NACK after writing the slave address 0x69. Please make sure this is the correct slave address for the sensor and it is powered up correctly. I took a look at the MPU9150 datasheet and saw that the slave address could be either 0x68 or 0x69 depending on how a certain pin is configured so please take a look at that also.

    Jas

  • In reply to Jaskaran Atwal:

    Hi Jas,

    I followed your suggestions. The issue was solved when I changed the slave address from 0x69 to 0x68. The API call for initialization of the MPU9150 sensor does not return null now. Thanks for the help.

    Pablo

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.