I2C working intermittently on ATMEGA32U4

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

Hello all,

I am using the MAX17043 Battery gauge on my custom ATMEGA32U4 board to log my battery usage. The communication with the device is done over the I2C/TWI interface.
I am using Peter Fleury's I2C driver. The ATMEGA32U4 runs at 1MHz and the I2C SCL frequency is 400kHz. I am using external pull-ups(4.7kOhms)
 

Here is the issue:
I am either completely not able to communicate with the device or the communication breaks-off randomly after a few bytes. Whatever data I am getting during those lucky transmissions are not garbage but actual voltage measurements of the battery.

 

Troubleshooting:

As the ATMEGA32U4 datasheet suggests, for a stable operation, the TWBR value should be greater than 10.

TWBR = ((F_CPU/SCL_CLOCK)-16)/(2 * 4^TWSR); 

Plugging in the above values in the equation(TWSR is 0), I am getting a value of -6.75 for the TWBR.

This clearly shows that the I2C will not operate in a stable manner.

I also tried different SCL frequencies ranging between 10kHz and sub-400kHz, but they don't even work as before.

This is equally strange because I interface the Bosch BNO055 IMU on the same bus and it works without any issues.

(I compared the datasheet of both devices and they have similar timing requirements for the I2C communication)

 

Solution?:

So, what could be the likely solution to the problem be?

Will operating the ATMEGA32U4 @ say 8MHz solve the issue?

Or is there something else I should take care of?

Thanks in advance.

 

[P.S.: Before anyone is suggesting me to sniff the I2C bus using a logic analyser/scope, I want to let you know that I don't have one :(]

This topic has a solution.

Regards,
Frederic Philips

Last Edited: Sun. Dec 23, 2018 - 04:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no point in attempting 400kHz
I2C can run at any speed e.g. 25kHz
.
Always check return value from i2c_start()
It is wise to read a known register e.g. an ID register.
Or write to a non-critical register and read it back.
.
David.

Last Edited: Sun. Dec 23, 2018 - 08:29 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hi,

The issue was indeed the low F_CPU speed. After changing the Clock Prescalar division factor to 1(which makes my F_CPU as 8MHz) from Chuck99's suggestion, I am able to communicate with the device without any issues.
Thanks, david.prentice and Chuck99

Regards,
Frederic Philips

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

Just one precision for thoose who "arrive" on this page looking for information about I2C on ATMega2560.

 

The specification is not clear about the TWBR formula.

 

It is writen: TWBR = ((F_CPU/SCL_CLOCK)-16)/(2 * 4^TWSR);

 

The 4^TWSR is to read "4 as value for the TWSR, as an example". indeed, the TWSR register description indicate: "The value of TWPS 1:0 is used in the equation"

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

Just do some maths.  e.g. for F_CPU = 16MHz and SCL_CLOCK = 100kHz

TWBR = ((160000000 / 100000) - 16) / (2 * 1); //4^0 = 1
TWBR = (160 - 16) / 2; // = 72

// it is unlikely that you will want bus speeds  < 100kHz
// but if you wanted 25kHz
TWBR = ((160000000 / 25000) - 16) / (2 * 4); //4^1 = 4 
TWBR = (640 - 16) / 8; // = 78

// but if you wanted 10kHz
TWBR = ((160000000 / 10000) - 16) / (2 * 4); //4^1 = 4
TWBR = (1600 - 16) / 8; // = 198

It is pretty unlikely that you would ever use a prescaler on TWBR.    The prescaler bits are almost always 0 (div1).  Sometimes 1 (div4)

Hey-ho.  Prescaler bits = 2 would be div16, bits = 3 would be div64

 

David.