I2C NACK Despite Proper Address

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

Hi everyone! :)

 

a few weeks ago I started my adventure with AVR MC's. I am using Atmega8A and currently I was trying to establish I2C connection with MPU6050. General idea of the program is very simple. Read Data from Gyro Register through TWI, pack it to char arrays and send with USART via Bluetooth to COM port on PC where I can read this data through RealTerm.

 

As far as self-written RX/TX code is working perfectly fine I am having some hard time with I2C. I spent last 2 days of analyzing DS and different libraries on the internet to understand how does it work and so far I think it is clear for me.

At first I wanted to write my own lib for it but then somebody linked me Peter Fleury's I2C library which is simple and easy to debug I2C lib, and I know a lot of people around here use it... So I picked it.

 

Unfortunetely I cant connect to my MPU and I ahve no idea why it is not working.

 

Here is code of my main function:

#undef F_CPU
#define F_CPU 4000000UL // 4 MHz clock speed

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "i2cmaster.h"

BETWEEN includes AND int main(void) FILE I HAVE USART TRANSMISSION CODE WHICH ISN'T IMPORTANT IN THIS POST AS FAR AS IT WORKS.

int main(void)
{

	char gyroBuffer[64];		//ARRAY MADE FOR MICROCONTROLER SPACE EFFICENCY IN CONVERSION
	usart_Init();				//RX/TX INIT
	i2c_init();					//TWI INIT
	_delay_ms(200);

	int a = i2c_start(0x68);	//SAVING RETURN STATUS
	while(1){

		transmittData("ex ",2);		//transmit String in mode 2 which means, after sending it, there are not added any additional signs to UDR
		_delay_ms(5);				//break for atmega to finish some dirty business

		transmittData(intToString(gyroBuffer, a), 1);	//transmit String in mode 1 which means, after sending it, \r is sent to UDR
		_delay_ms(1000);

	}
}

 HERE IS RESULT: (realterm displays also the Carriage Return sign)

 

 

As you can see 

i2c_start(0x68)

returned 1 which is error(failed to access device). The body of the function is here(Peter Fleury's lib):

 

/*************************************************************************
  Issues a start condition and sends address and transfer direction.
  return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
    uint8_t   twst;

	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;

	// send device address
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));

	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;

	return 0;

}/* i2c_start */

I have checked it  and the line that is generating '1' is:

if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; 

which from my knowleadge means Not_Acknowledged

Adress I was sending was correct due to the MPU6050 Datasheet. (0x68 when PIN AD0 is L )

 

Here is how I pinned whole board: (sorry for ugly picture I am not used to doing such schematics. Also remember HC-05 is working correcly, thats why I didnt pay attention to its connection picture).

The MPU Board is connected to the VCC stabilized around 4V because Voltage supplying HC-05 and Atmega8a is a bit above 5V and I didnt want to damage the sensor as DS says that 5.0V is maximum it can get.

(perhaps small value above doesnt make difference, I dont know I am fresh to this so I prefer to be careful)

What could be the reason for MPU to not acknowleadging the connection ?

 

Chris

 

 

This topic has a solution.
Last Edited: Thu. Aug 31, 2017 - 07:38 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
	int a = i2c_start(0x68);	//SAVING RETURN STATUS

The MPU6050 has a 7-bit Slave address of 0x68 (0x69 if AD0=1)

You use 7-bit address with Wire.h

 

You use 8-bit address with Fleury e.g.

	int a = i2c_start((0x68 << 1) | I2C_WRITE);	//SAVING RETURN STATUS

i.e. it is 0xD0 for WRITE and 0xD1 for READ.

 

Congratulations.    Normally punters ignore the return value.

 

Your schematic implies n.c. for the AD0 pin.  I suggest that you tie to GND (AD0=0) or to VCC (AD0=1)
Oops. You have already tied AD0 to GND as suggested.

 

David.

Last Edited: Thu. Aug 31, 2017 - 06:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David, thank you!

it's working now!