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.
Hello,
I am trying to get information (acceleration and angular rate) from the MPU 6050 sensor which is connected to the TMS570LC4357 micro.
I am able to obtain this information connecting this sensor to a Arduino Mega board. However, when I try to replicate the code in for the Hercules micro I do not obtain the same data (I get random numbers). I am doing the same operations in both cases and I am sure that the MPU 6050 is returning information. It is just that this information does not make sense. Just a couple of times I was able to get the right information, but when I tried a second time it returned random numbers again.
I have the Arduino mega, the MPU 6050 and the Hercules micro connected to the same bus. I have tried with interruptions, disabling the internal pull-up resistors and using external resistors, etc. but nothing seem to work. The connection Arduino-Hercules is totally fine (Hercules as master) and Arduino MPU6050 is also correct.
Do you have any idea what could be causing this strange behaviour?
Thanks for your time and consideration. Best regards,
Sergio
Hello,
To read the internal MPU6050 registers, the master sends a start condition, followed by the I2C slave address and a write bit, and then the register address that is going to be read. Upon receiving the ACK signal from the MPU6050, the master transmits a start signal followed by the slave address and read bit. As a result, the MPU6050 sends an ACK signal and the data. The communication ends with a not acknowledge (NACK) signal and a stop bit from master.
Can you share the I2C code on TMS570?
This is the example code to read data from slave:
///////////////////////////////////////////////////////////////
// Master Receive Functionality //
///////////////////////////////////////////////////////////////
/*****************************************/
//// Setup Slave to receving the data
/*****************************************/
/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cREG1) != true);
/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);
/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
/* Configure Data count */
/* Slave address + Word address write operation before reading */
i2cSetCount(i2cREG1, Receive_data_setup);
/* Set mode as Master */
i2cSetMode(i2cREG1, I2C_MASTER);
/* Set Stop after programmed Count */
i2cSetStop(i2cREG1);
/* Transmit Start Condition */
i2cSetStart(i2cREG1);
/* Send the Word Address */
i2cSendByte(i2cREG1, Slave_Word_address);
/* Wait until Bus Busy is cleared */
while(i2cIsBusBusy(i2cREG1) == true);
/* Wait until Stop is detected */
while(i2cIsStopDetected(i2cREG1) == 0);
/* Clear the Stop condition */
i2cClearSCD(i2cREG1);
/*****************************************/
//// Start receving the data From Slave
/*****************************************/
/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cREG1) != true);
/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);
/* Set direction to receiver */
i2cSetDirection(i2cREG1, I2C_RECEIVER);
/* Configure Data count */
/* Note: Optional - It is done in Init, unless user want to change */
i2cSetCount(i2cREG1, DATA_COUNT);
/* Set mode as Master */
i2cSetMode(i2cREG1, I2C_MASTER);
/* Set Stop after programmed Count */
i2cSetStop(i2cREG1);
/* Transmit Start Condition */
i2cSetStart(i2cREG1);
/* Tranmit DATA_COUNT number of data in Polling mode */
i2cReceive(i2cREG1, DATA_COUNT, RX_Data_Master);
/* Wait until Bus Busy is cleared */
while(i2cIsBusBusy(i2cREG1) == true);
/* Wait until Stop is detected */
while(i2cIsStopDetected(i2cREG1) == 0);
/* Clear the Stop condition */
i2cClearSCD(i2cREG1);
Hello QJ Wang,
Thank you for your help. I really appreciate it.
I have a similar code to the one that you posted. I want to recall that this code perfectly works when connecting the TMS570 with two Arduinos. It is the connection with the MPU6050 the one that fails.
Now, I am able to WRITE on the registers of the MPU6050 (I checked that the value is actually modified) but I am not capable of receiving the information. To test that, I am trying to write data to a register (0x6B) and then read the written data. This works using Arduino, the code for that case is very simple:
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(8); // Write 8
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr, 1, true);
This works perfectly. I must highlight here that I am writing Wire.endTransmission(false) when I want to receive because I do not want to send a Stop condition but a Restart condition.
I am doing the exact same thing with the TMS570LC43 micro (or at least I think I am). Here is the code that I am using:
///////////////////////////////////////////////////////////////
// Master Receive Functionality //
///////////////////////////////////////////////////////////////
/*****************************************/
//// Send data to Slave to write on the register 0x68
/*****************************************/
/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cModule) != true);
/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cModule, MPU6050address);
/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cModule, I2C_TRANSMITTER);
/* Configure Data count */
/* Slave address + Word address write operation before reading */
i2cSetCount(i2cModule, 2);
/* Set mode as Master */
i2cSetMode(i2cModule, I2C_MASTER);
/* Set Stop after programmed Count */
i2cSetStop(i2cModule);
/* Transmit Start Condition */
i2cSetStart(i2cModule);
/* Send the Word Address */
i2cSendByte(i2cModule, register_adress);
i2cSendByte(i2cModule, 8);
// Wait until Bus Busy is cleared
while(i2cIsBusBusy(i2cModule) == true);
//Wait until Stop is detected
while(i2cIsStopDetected(i2cModule) == 0);
// Clear the Stop condition
i2cClearSCD(i2cModule);
/*****************************************/
//// Received the data in 0x68 register that I have previously written
/*****************************************/
// Sending the Adress of the 0x68 register
/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cModule, MPU6050address);
/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cModule, I2C_TRANSMITTER);
/* Configure Data count */
// NOt necessary because I do not want to send a stop condition in this case
i2cSetCount(i2cModule, 1);
/* Set mode as Master */
i2cSetMode(i2cModule, I2C_MASTER);
/* Transmit Start Condition */
i2cSetStart(i2cModule); //No stop condition is set
/* Send the Word Address */
i2cSendByte(i2cModule, register_adress);
//Receiving data
// Configure address of Slave to talk to
i2cSetSlaveAdd(i2cModule, MPU6050address);
// Set direction to receiver
i2cSetDirection(i2cModule, I2C_RECEIVER);
// Configure Data count
// Note: Optional - It is done in Init, unless user want to change
i2cSetCount(i2cModule, 1);
// Set mode as Master
i2cSetMode(i2cModule, I2C_MASTER);
// Set Stop after programmed Count
i2cSetStop(i2cModule);
// Transmit Start Condition
i2cSetStart(i2cModule);
// Tranmit DATA_COUNT number of data in Polling mode
i2cReceive(i2cModule, 1, Rx_Data_Master);
// Wait until Bus Busy is cleared
while(i2cIsBusBusy(i2cModule) == true);
// Wait until Stop is detected
while(i2cIsStopDetected(i2cModule) == 0);
// Clear the Stop condition
i2cClearSCD(i2cModule);
printf("Reaches the end\n");
The content of the register is not 8 after the end of this sequence. I know that I have written 8 in that register because Arduino tells me that I am. Therefore, I am not doing the receive operation right. I think that the problem is in the Restart condition. After sending the Adress of the register that I want to read information.
Thank you for all your time and attention. Best wishes,
Sergio
-- Edit --
I have read that if the BB bit and STT bits are both set to 1 a start condition is generated. Using the previous code, I see that the BB bit is set to zero after the i2cSetStop statement when I try to receive. I would expect it to work if I move the i2csetStop condition after the i2csetStartCondition. However, I still do not see the 8 value in the register.
Please check whether I2C signals are enabled as outputs on the assigned terminals via configuration of the PINMUX registers (tab in HALCoGen).
Hello Sunil,
Within the PINMUX tab in Halcogen I have already enabled the SCL and SDA signals of the I2C2 module, which is the one that I am using. After your comment, I also enabled the Output direction on both signals in the I2C2 tab in Halcogen. But the result is the same as before. I can write but I cannot read.
Do you think it could be the repeated start condition?
Best regards,
Sergio
Hello QJ Wang,
Many thanks for your response. I changed the code to set the RM bit and the STP bit jus before receiving the byte (I just want to receive one byte) but it does not work. I also tried to set the STP bit after the i2cReceive statement, but I have the same result. Do you think that I should set the bits somewhere else?
/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cModule) != true);
// Sending the Adress of the 0x68 register
// Configure address of Slave to talk to
i2cSetSlaveAdd(i2cModule, MPU6050address);
// Set direction to Transmitter
i2cSetDirection(i2cModule, I2C_TRANSMITTER);
// Configure Data count
i2cSetCount(i2cModule, 1);
// Set mode as Master
i2cSetMode(i2cModule, I2C_MASTER);
//Enable Repeat Mode
i2cModule->MDR |= 0x80;
// Transmit Start Condition
i2cSetStart(i2cModule);
// Send the Word Address
i2cSendByte(i2cModule, register_adress);
//Receiving data
// Configure address of Slave to talk to
i2cSetSlaveAdd(i2cModule, MPU6050address);
// Set direction to receiver
i2cSetDirection(i2cModule, I2C_RECEIVER);
// Configure Data count
i2cSetCount(i2cModule, 1);
// Set mode as Master
i2cSetMode(i2cModule, I2C_MASTER);
// Transmit Start Condition
i2cSetStart(i2cModule);
// Set Stop after programmed Count
i2cSetStop(i2cModule);
// Tranmit DATA_COUNT number of data in Polling mode
i2cReceive(i2cModule, 1, &receivedDataArray[0]);
// Wait until Bus Busy is cleared
while(i2cIsBusBusy(i2cModule) == true);
// Wait until Stop is detected
while(i2cIsStopDetected(i2cModule) == 0);
// Clear the Stop condition
i2cClearSCD(i2cModule);
Thank you for your time. Best regards,
Sergio
I have realized (because I was in debug mode and put a breakpoint) that if a add
for(delay = 0; delay<10000; delay)
right after sending the byte with the address that I want to read it works, I can read the data that I have just written. Do you have some ideas about what could be the reason for this behavior?
If you use STOP condition, you need to check if the bus is free or not before the next transaction.
If you don't use STOP, please check the ARDY bit and NACK bit before starting next transmission:
For example:
while( ((i2cREG1->STR & I2C_NACK) == 0) && ((i2cREG1->STR & I2C_ARDY) == 0) );
Hello QJ Wang,
Indeed, substituting the delay loop by the sentence that you proposed ends up in the same correct result. I can read from the MPU 6050. However, I do not understand the logic here.
I do understand the ARDY bit (when it is 1 that means that we have sent the data to the slave), but why do we have to wait until the NACK bit is equal to 1? I would expect to receive an ACK from the slave right after sending the byte, therefore, the NACK bit should be 0.
I am obviously wrong because that line solves my problem, but I am still not sure why.
Thank you for all your time. This is really good support.