zero output of mpu9250 with atmega32 i2c [CodeVision]

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi

i used atmega32 for i2c communication with mpu9250 IMU module. i used i2c communication with eeprom and it works well. but when i use this code with mpu9250 it doesn't work. and it sends -0001 to serial port.

i used logic level converter 3.3 to 5 volt . imu module that i use has pull up resistor. and i use 10 k ohm pull up resistor for high level of logic converter ( atmega32 i2c). what is problem?

 

Last Edited: Thu. Apr 28, 2016 - 10:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

zk wrote:
what is problem?

A missing semi-colon on the end of line 47?

 

Seriously, how could anyone here possibly guess without seeing at least the relevant parts of the code and also a schematic to show how the electronics are wired together?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sorry this is my code :


#include <mega32.h>
#include <delay.h>
#include <stdio.h>
// I2C Bus functions
#include <i2c.h>

unsigned char address=0x68;
// accelleration
unsigned char acc_x=0x3b;
//unsigned char acc_x_l=0x3c;
unsigned char acc_y=0x3d;
//unsigned char acc_y_l=0x3e;
unsigned char acc_z=0x40;
//unsigned char acc_z_l=0x41;
//temp
unsigned char temp=0x42;
//unsigned char temp_l=0x43;
//gyro
unsigned char gyr_x=0x44;
//unsigned char gyr_x_l=0x45;
unsigned char gyr_y=0x46;
//unsigned char gyr_y_l=0x47;
unsigned char gyr_z=0x48;
//unsigned char gyr_z_l=0x49;
//mag
unsigned char mag_x=0x03;
//unsigned char mag_x_l=0x04;
unsigned char mag_y=0x05;
//unsigned char mag_y_l=0x06;
unsigned char mag_z=0x07;
//unsigned char mag_z_l=0x08;

int dataacc[3];
int datatemp;
int datagyr[3];
int datamag[3];
char str[3];

// Declare your global variables here
int imu_read(unsigned char regaddress)
{
unsigned char data;
int data2;
i2c_start();
i2c_write(address);
i2c_write(regaddress);
i2c_start();
i2c_write(address|1);
data=i2c_read(0);
i2c_stop();
data2=data;
data2=data2<<8;
regaddress+=1;
i2c_start();
i2c_write(address);
i2c_write(regaddress);
i2c_start();
i2c_write(address|1);
data=i2c_read(0);
i2c_stop();
data2|=data;
return data2;
}
void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=0xff;
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
 
  // USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x33;

// Bit-Banged I2C Bus initialization
// I2C Port: PORTB
// I2C SDA bit: 3
// I2C SCL bit: 4
// Bit Rate: 100 kHz
// Note: I2C settings are specified in the
// Project|Configure|C Compiler|Libraries|I2C menu.
i2c_init();

while (1)
      {
      // Place your code here   
      dataacc[0]=imu_read(acc_x);
      dataacc[1]=imu_read(acc_y);
        dataacc[2]=imu_read(acc_z);
      datatemp=imu_read(temp);  
        datagyr[0]=imu_read(gyr_x);
       datagyr[1]=imu_read(gyr_y);
        datagyr[2]=imu_read(gyr_z);
          datamag[0]=imu_read(mag_x);
      datamag[1]=imu_read(mag_y);
      datamag[2]=imu_read(mag_z); 
      sprintf(str,"xdot:%05u ,yawrate:%05u, temp:%05u ",dataacc[0],datagyr[2],datatemp);
      puts(str);
      delay_ms(1000);     
      }
}


 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clearly you are using Codevision (it helps to mention this kind of detail). When I look at the CV manual online and specifically the bit-bang I2C library I see this example:

#define I2C_7BIT_DEVICE_ADDRESS 0x50
#define EEPROM_BUS_ADDRESS (I2C_7BIT_DEVICE_ADDRESS << 1)
/* read a byte from the EEPROM */
unsigned char eeprom_read(unsigned int address)
{
unsigned char data;
i2c_start();
i2c_write(EEPROM_BUS_ADDRESS | 0);

Notice the <<1 in that? To me (at least) that suggests that the library takes 8 bit addresses so I wonder if your:

unsigned char address=0x68;

actually needs to be:

unsigned char address=0x68 << 1;

or, in other words:

unsigned char address=0xD0;

No doubt someone who know CV better than I do will be along in a minute to confirm whether this is the case.

 

Oh and I gotta ask. Given that a mega32 has a real I2C (that Atmel call TWI) why are you using bit-bang i2c rather than the real "twi" library?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From the data sheet:

The slave address of the MPU-9250 is b110100X which is 7 bits long. The LSB bit of the 7 bit address is determined by the logic level on pin AD0. This allows two MPU-9250s to be connected to the same I2C bus. When used in this configuration, the address of the one of the devices should be b1101000 (pin AD0 is logic low) and the address of the other should be b1101001 (pin AD0 is logic high).

So you are clearly using the wrong Slave address.

 

The Codevision bit-banged I2C uses 8-bit addresses.   e.g. Write 0xD0,  Read = 0xD1

Most Codevision functions have return values.    If you use them you would have seen that i2c_write(address) fails.

 

I also suggest that you format your code nicely.   It will make it easier for you to read.     As a side-effect,   it would make it more likely that your post is actually read by others.

 

I looked for your incorrect Slave value because it is the same mistake that always comes up.    I have not bothered to read the rest of your code.    You could spend 10 minutes of your life tidying it up by hand.    Then editing or re-posting.

 

David.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

 

Oh and I gotta ask. Given that a mega32 has a real I2C (that Atmel call TWI) why are you using bit-bang i2c rather than the real "twi" library?

but i  have been used bit-bang i2c with eeprom and it works well with a code like this.

and this is my schematic is it right.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, if Pins 23 and 22 are not used, it eats less flash and cycles using hardware I2C than software, bit banged one....

 

edited : some C beautifiers , like https://www.gnu.org/software/ind... http://gnuwin32.sourceforge.net/... or http://astyle.sourceforge.net/ might be useful for having programs automagically indented

Last Edited: Thu. Apr 28, 2016 - 11:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My eyesight is not so good.   Your pull-up resistors look like red-black-orange-gold.   i.e. 20k0 5%.   This is too high.

 

Yes,  the CV bit-banging works fine.    But the TWI works fine too.

And life is much easier if you just run at 3.3V instead of using level-shifters.

 

Incidentally,  the CV TWI library functions use 7-bit addresses.

The CV I2C library functions use 8-bit addresses.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

david.prentice wrote:
Incidentally, the CV TWI library functions use 7-bit addresses. The CV I2C library functions use 8-bit addresses.

therefore i should be use twi library instead of i2c library for read and write  for 7-bit address? i2c uses 0xD0 for write in mpu and it is wrong because mpu address is 0x68 from datasheet. if I use 0x34 for address it works well?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Codevision has built-in Help. Read the entries for i2c and twi functions.
.
I suggest that you read your MPU9250 datasheet. Especially the part that I have quoted for you.
.
Yes, you can use 0x68 with the twi functions or 0xD0 with the i2c functions.
Both libraries will report an error if you have the wrong Slave address.
.
You have successfully used 24Cxxx memories. Did you use 0xA0 (8-bit) 0x50 (7-bit) ?
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i read entire datasheet of mpu9250 and register map of it. i know that it has 0b110100x address. i connect ad0 to GND then it's address is 0b1101000. i used 24cxxx eeprom and it's address was 0xa0 and i could write and read  it. but i didn't know how i could read 7-bit address. i understand from your description that i should be use 0xD0 address for write to mpu9250. is that  right?

thank you for your help David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

zk wrote:
that i should be use 0xD0 address for write to mpu9250. is that right?

I thought David's answer was very clear. yes, that is the case.

 

If you ever see an I2C address (or range of addresses for read and write) quoted and the numbers are below 0x80 (0x00..0x7F) then what you have been given are 7 bit addresses. If the number is in the range 0x80..0xFF then it is an 8 bit address. If you use i2c_*() then it wants you to use 8bit addresses. If you use twi_*() it wants you to use 7 bit addresses. If you have a 7bit address (such as 0x68) and you need an 8 bit one then you double it (0xD0). if you have an 8 bit address (0xD0) and you need a 7 bit address then you half it (0x68). It really should be that simple.

 

The key thing, always, is knowing whether the library routines you are about to use require 7 or 8 bit addresses.

 

While not always true most I2C device datasheets will usually given the 7 bit address(es) so you may find yourself having to double them when using 8bit library code.

 

0xA0 (because it's in the range 0x80..0xFF) is, of course an 8bit address. The 7bit equivalent would be half that value: 0x50.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that is correct. If you connect ad0 to VCC, you could use 0xD2/0xD3 instead of 0xD0/0xD1.
Note that the DS1307 RTC chip has address 0xD0/0xD1.
.
It is a little confusing. But if you use the return values from the library functions, you always know what the problem is.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thank you very much for your help.