简体   繁体   中英

Why does output shows constant values from MPU-6050 on Atmega8 via I2C?


Hi All!

I am trying to connect an MPU-6050(ITG/MPU breakout board) with ATmega8 (on a breadboard - non arduino) via I2C.

When I try to read one of the sensor values the TWSR values show perfect I2C communication,
like for example TWSR values for: Start, Slave+W, Address ACK, Register AddressACK, Slave+R, Data to TWDR, NACK by master, Stop, etc. all match with atmega8's data-sheet (I connected 8-pins of PORTD to 8 LEDS and set TWSR to display on this PORT every time a TWSR check operation is performed).

But the values I receive in TWDR are all constant and does not change by any movements of sensor (I tried displaying the sensed values on a 8-LEDS arrangement and also on an LCD).

I communicate on I2C in following manner:
Send Start,
Check TWSR,
Send Slave address with write bit,
Wait for N/ACK,
Check TWSR,
Send Sensor register address,
Wait for N/ACK,
Check TWSR,
Send START (repeated start)
Check TWSR,
Send Slave address with read,
Wait for N/ACK,
Check TWSR,
Copy TWDR data to an element of an Array,
Send "NACK",
Check TWSR
Stop.

I continuously monitor TWINT flag in all steps. And these steps are repeated again and again for different sensor registers.
Also I have enabled interrupt (by including sei();) but I have not put anything in the Interrupt vector.

My Question(s) is :

Why is this data constant?

Is there a problem with my I2C communication approach?

Or is the MPU operating on 3V3 and AVR on 5V killing the sensed data? (I use 4K7 pull-ups to 5V)

Or any other registers are to be configured (I tried PWR_MGMT_1, USER_CTRL, CONFIG, SMPRT_DIV, GYRO_CONFIG, ACCEL_CONFIG in this very order) before actual register addressing and data reading?

Or some other problem?

If similar experience had been discussed before or a discussion that might help, Please redirect.

Thanks.

Following is my code:

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "defandfunc4.c"    // contains I2C functions
#include "lcdincluder.c"    // contains LCD functions
#include "myheader.h"       // contains definitions and prototype decl.

int main (void)
{
//------------------ Variable initialisations
unsigned char SLA_W[10], SLA_R[10], RCVD_L[10], RCVD_M[10];
int INTRMDT[10], GYRO_Z[10], MSB[10], LSB[10];
int i = 0, j = 0;
sei();
DDRD = 0XFF;
DDRB = 0XFF;
//------------------ Clear LCD
Send_a_command (0X01);          // Clear screen
_delay_ms(2);               // takes 1.53 ms
//------------------ Address setting
SLA_W = ((SL_ADD<<1) | 0);      // Slave + Write bit (0)
SLA_R = ((SL_ADD<<1) | 1);      // Slave + Read bit (1)
//------------------------ Actual TWI communication begins
TWSR = 0X00;                // Set prescaler to be 0
TWBR = 0X0C;                // setting bit-rate division factor to be 12
_delay_us(10);
j = 1;
for (i=0;i<10;++i)
{
start_condn();              // start condition
//------------------------ First TWI : Send Register Addr
CHECK_TWSR_FOR (START);  // If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = SLA_W;               // Load TWDR with Slave + write
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MT_SLA_ACK);        // check TWSR for successful TXn of slave address. If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = GYRO_XOUT_H;         // Load TWDR with Data(register address)
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MT_DATA_ACK);       // check TWSR for successful TXn of Data and ACK RCVD. If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
//------------------------ Second TWI : Read data
start_condn();              // Repeated start condition
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (R_START);       // check TWSR for successful TXn of Repeated Start, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = SLA_R;               // Load TWDR with Slave + read
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MR_SLA_ACK);        // check TWSR for successful TXn of ADDr + R, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
wait_for_TWINT();           // Wait for TWINT
RCVD_M[i] =  TWDR;
TWCR = (1<<TWINT)|(1<<TWEN);        //send NACK
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (DATA_RCVD_NACK);    // check TWSR for Data RXd NACK sent, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
stop_condn ();              // Transmit STOP
//------------------------ Third TWI : Send Register Addr
start_condn();              // Repeated start condition
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (START);         // check value of TWSR for successful TXn of Start, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = SLA_W;               // Load TWDR with Slave + write
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MT_SLA_ACK);        // check TWSR for successful TXn of slave address, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = GYRO_XOUT_L;         // Load TWDR with Data(register address)
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MT_DATA_ACK);       // check TWSR for successful TXn of Data and ACK RCVD, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec

PORTD = 0X00;               // Switching off portD
//------------------------ Fourth TWI : Read data
start_condn();              // Repeated start condition
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (R_START);       // check TWSR for successful TXn of Repeated Start, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
TWDR = SLA_R;               // Load TWDR with Slave + read
charge ();              // Clear TWINT
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (MR_SLA_ACK);        // check TWSR for successful TXn of ADDr + R, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
wait_for_TWINT();           // Wait for TWINT
RCVD_L[i] =  TWDR;          
TWCR = (1<<TWINT)|(1<<TWEN);        //send NACK
wait_for_TWINT();           // Wait for TWINT
CHECK_TWSR_FOR (DATA_RCVD_NACK);    // check TWSR for Data RXd NACK sent, If status mismatches error routine is followed
clear_go(); //a prgram that glows an led for few milli sec
stop_condn ();              // Transmit STOP
//------------------ Making a word
LSB[i] = 0XFF & RCVD_L[i];
MSB[i] = 0XFF & RCVD_M[i];
INTRMDT[i] = ((MSB[i] << 8) | LSB[i]);
GYRO_Z[i] = INTRMDT[i];

// On to LCD
Send_a_character (GYRO_Z[i]);       // Displays it on LCD
_delay_us(50);              // takes 39 micro seconds
j++;
}
//------------------------ TWI complete ------------------------//
return 0;
}

I am using following breakout board:
http://playground.arduino.cc/Main/MPU-6050
(But I am not using Arduino)

Following is the MPU-6050 product page:
http://www.invensense.com/mems/gyro/mpu6050.html

Following is a link to MPU-6050 product specification and register map, respectively:
http://www.invensense.com/mems/gyro/documents/PS-MPU-6000A-00v3.4.pdf
http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A-00v4.2.pdf

Thanks!

The problem is in the sequence of accessing the TWDR register:

...
Send Slave address with read,
Wait for N/ACK,
Check TWSR,
Copy TWDR data to an element of an Array,
Send "NACK",
Check TWSR
...

Correct sequence is:

...
Send Slave address with read,
Wait for N/ACK,
Check TWSR,
Send "NACK",
Copy TWDR data to an element of an Array,
Check TWSR
...

The reason behind this is that by the time (N)ACK is not sent by the master, operation might still be in the state of receiving data from slave. And TWDR will be containing the value of last transmitted (or recieved) data, which in this case is slave address.

Hence data from the TWDR must be copied after sending (N)ACK making sure that data reception from slave is complete. But this copying should be done before sending a STOP or a Repeated Start.

One can also copy data after checking TWSR thus being 100% sure that operation is complete.

For general comments, the sequence of writes and reads to the device seem to be correct. I assume your functions would report if errors occurred.

You don't need an array to hold SLA_W and SLA_R. You are using the address of these arrays as bytes, which could be causing problems, but seems to be working somehow. Also, you could be doing burst reads to get both high and low bytes of the gyro reading at once. If you just keep sending acks, then the device will send back data in register order. In fact, you could get all the data from the device at once; start at 0x3B and read 14 bytes of data.

You are reading the device in a fast loop, but only have time to display the last reading, so the loop is pointless right now. (I assume you are going to do something with it later, perhaps?)

Also, note that the gyroscope register rotational movement. If the device is still, then is should read zero.

But I suspect your problem is in the writing to the LCD. The gyro reading is an integer, not an ascii character. You need to convert this number to a readable string, either with sprintf() or a handmade function. If you just send an integer, it will be truncated to a char, which is likely to be random or unprintable for the LCD, not the string of digits you are expecting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM