Using the Peter Fleury I2C library with Atmega32U4

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

Hi !

 

I'm quite new to AVR and I'm currently stuck with the I2c communication between my Atmega32U4 and my AD converter ADS1114.

I inspired myself with the basic example of Peter Fleury here as well with this other example.

The code builds just fine, but when it doesn't work. When I try debugging step by step, the  program get stuck at the

if ( ret ) {

statement.

twimaster.c and ic2master.h are added to my project.

If I also add ic2master.S, an error occurs because of multiple definitions of functions so it's not with the rest.

 

 

 

The relevant parts of the code are in blue.

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>		//bool type support
#include "i2cmaster.h"


//fast PWM output pin 5 & 6 port B -> to mosfet driver
#define HighSideMos DDB6
#define LowSideMos DDB5
//Switch between modes pin 2 & 6 port E
#define SwitchMode DDE6

// ADS1114 I2C Adresse 0x48
#define ADS1114 0x48


extern volatile bool TimerSet = false;
extern volatile bool IsCharging = true;//True -> Buck converter mode, using only High-side Mosfet. False -> Boost converter mode, using only Low-Side Mosfet

void PWM_Init()			//ok
{

	//fast PWM pins configured as output (timer 1)
	DDRB = (1<<HighSideMos)|(1<<LowSideMos);

	//InitTimer1
	TCNT1  = 0;
	TCCR1A = 0;
	TCCR1B = 0;

	// set to mode 14 fast PWM	see DatenBlatt S. 133
	// no prescaling
	// if inquiry to choose between buck or boost mode

	ICR1 = 159;   //Set Top Value, -> frequency 100 kHz 16 MHz/100kHz-1, 16 MHz internal clock

	if (IsCharging == true )	//buckmode, HSM with COM1B1
	{
		TCCR1A = 0b00100010;
		TCCR1B = 0b00011001;
	}
	else           //boostmode, LSM with COM1A1
	{
		TCCR1A = 0b10000010;
		TCCR1B = 0b00011001;
	}

	OCR1A = 50;   // init Wert 5 mikro sek
	OCR1B = 50;
}

void Get_current()
{
	unsigned char MSB;
	unsigned char LSB;

	i2c_rep_start(ADS1114+I2C_READ); // set device address and read mode
	MSB = i2c_readAck();			//read one byte from the I2C device, request more data from device
	LSB = i2c_readNak();			//read one byte from the I2C device, read is followed by a stop condition
	i2c_stop();						//Terminates the data transfer and releases the I2C bus.

}

int main(void)
{
	//switch interrupt pin configured as input
	//DDRE &= ~(1 << SwitchMode);
	unsigned char ret;
	DDRE &= ~(1 << SwitchMode);

	PWM_Init();

	//interrupt handling
	EICRB|= (1 << ISC60);  //any logical change should enable interrupt
	sei(); //enabling interrupts
	EIMSK |= (1 << INT6);	//Enabling ext Int6 (port bit 6)

	i2c_init();	 // initialize I2C library

	 ret = i2c_start(ADS1114+I2C_WRITE);       // set device address and write mode
	if ( ret ) {
		 /* failed to issue start condition, possibly no device found */
		 i2c_stop();
		 }else {
			 //Configure ADS1114 continuous conversion mode
			 i2c_write(0x90);
			 i2c_write(0x01);
			 i2c_write(0x84);
			 i2c_write(0x83);
		 }

	while (1) //loop. Waiting for interrupt to change mode
	{
		Get_current();
		//Buckmode
		if ((IsCharging == true) && (TimerSet == false)) {
			// Here Pin 9 stopped, Pin 10 enabled
			OCR1B = 100;
			TCCR1A &= ~(1 << COM1A1);		//PWM output is HighSideMos
			TCCR1A |= (1 << COM1B1);
			PORTB &= ~(1 << LowSideMos);		//LowSideMos connected to ground
			//warum immer gelsen selbst wenn kein interrupt ?
			TimerSet = true;
		}
		//Boostmode
		else if ((IsCharging == false) && (TimerSet == false)) {
			OCR1A = 70;
			TCCR1A &= ~(1 << COM1B1);			//PWM output is LowSideMos		//warum immer gelsen selbst wenn kein interrupt ?
			TCCR1A |= (1 << COM1A1);
			PORTB &= ~(1 << HighSideMos);		//HighSideMos connected to ground

			TimerSet = true;
		}

	}

}

//interrupt Routine
ISR(INT6_vect)
{
	if (PINE & 0x40)//Buckmode, highside Mosfet is working (bit 6 gesetzt?)
	{
		IsCharging = true;
		TimerSet = false;
	}
	else 	//Boostmode
	{
		IsCharging = false;
		TimerSet = false;
	}

}

 

 

I think that the ADC device is not found, but I cannot figure out why. Could someone please point out what I possibly did wrong ?

An other possible option is that I'm using the library wrong, but how wrong?

The ADDR pin is connected to ground, which means the ADS1114 adress is 1001000 btw

 

Thank you for your consideration.

Murmeltier

This topic has a solution.
Last Edited: Fri. Jan 5, 2018 - 01:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Murmeltier wrote:
I think that the ADC device is not found, but I cannot figure out why

Are you sure you have the I2C address correct and in the format expected by the library?

 

See: https://www.avrfreaks.net/comment...

 

And further detail at: https://www.avrfreaks.net/comment...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Right it seems I did this mistake.

For the address 1001000

 I typed 0x48 instead of 0x90 (which is the right one, I think)

 

But my problem is still there, and the debugging is stuck in exactly the same place either way. I also double-checked the connections of the elements and everything seems okay

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

Murmeltier wrote:
I'm quite new to AVR

Do you have experience with any other microcontroller(s) ?

 

What test equipment do you have to see what's actually happening on the wires?

 

Have you tried this on an Arduino?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please provide us with a schematic or a clear picture of your I2C setup..

What value of pull up resistors are you using on the I2C_SCL and SDA lines?

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

Well I learnt a little bit with 8051 Microcontrollers a few years ago (assembler). (I don't remember which one exactly). Otherwise not much, I can do basic functions with the atmega32U4 or the atmega8 through arduino nano, but that's it.

As for programing, I also had a C and a c++ course at about the same time, and I did a few projects in other languages (actionscript, ST, python) so I got a basic understanding of programming, but I am not used to microcontroller programming. 

 

I got a DMM and an osco for my tests.

 

I haven't tried this communication with arduino because I'm supposed to do this with the Atmega32u4 (didn't get to choose). However, I could try to make it work now with an arduino nano as an in-between step, just to check that it works at least that far. Seems easier, with the wire.h library, and there are a lot of examples. I'll still need to do it with Atmega in the end, though, so I really have to find this error.

 

Here is my schematic. The pull up are both 4,7kOhm.

 

Thanks, Murmeltier

 

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

Murmeltier wrote:
I got ... an osco for my tests.

You mean an oscilloscope?

 

The usual abbreviation is "scope"

 

So what have you learned from applying your 'scope ?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is a MAX616 - there is no such part number at https://www.maximintegrated.com

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As with any I2C project,   make sure that you use the correct Slave address.   And most importantly,   use return values.  e.g.


    i2c_init();	 // initialize I2C library

    ret = i2c_start(ADS1114+I2C_WRITE);       // set device address and write mode
    if ( ret ) {
         /* failed to issue start condition, possibly no device found */
         i2c_stop();
         PORTB |= (1<<LED); // e.g. light error LED
         while (1) ;        // and tread water
    }else {
         //Configure ADS1114 continuous conversion mode
         i2c_write(0x90);   // .kbv I do not understand this
         i2c_write(0x01);   // set address register to CONFIG
         i2c_write(0x84);   //
         i2c_write(0x83);   //
    }

The ADS1114 has a different Slave address according to the hardware pins.

And most IMPORTANTLY.   you must have external pullups e.g. 820R .. 10k

 

David.

 

Edit.   ADDR seems to be floating.   Connect to GND for (8-bit)Slave = 0x90

What is MAX616?   SDA, SCL should have proper pullup e.g. 3.3V   (or 5V in a 5V system)

 

Last Edited: Wed. Jan 3, 2018 - 02:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With the multimeter, I checked that everything is connected with what it should and not with what it shouldn't.

With the scope, I learned the same as with debugging: that the program doesn't work any farther: the PWM is initialized (so the PWM_init function is read), but not changed as it should be if the main function had been read at least once.

 

The MAX part is this one here: http://de.farnell.com/maxim-inte...

A voltage reference with 2.5 V (The ADS1114 supply range is from 2 V to 5 V)

My understanding of the connection diagram of the ADS111_ (attached) is that the pull up should be between the supply voltage (here 2,5 V) of the ADC and the SDA/SCL wires. Am I wrong ?

 

I added the

PORTB |= (1<<LED); // e.g. light error LED

line (replacing LED by PORT0), but the program doesn't go that far. It gets stuck by the if-line.

As for the floating addr pin, I'm really sorry, I just forgot to make the change in the plan when I decided to ground it, but it really is grounded, and the address I use is now 0x90

 

Edit: added the attachment

 

Attachment(s): 

Last Edited: Wed. Jan 3, 2018 - 03:25 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Murmeltier wrote:
With the scope, I learned the same as with debugging: that the program doesn't work any farther

But do you see a valid START condition, slave address, and an ACK from the slave?

 

The MAX part is this one here: http://de.farnell.com/maxim-inte...

So that's a MAX6166;  which is a voltage reference - why are you using it to power the ADS1114 ??

 

https://datasheets.maximintegrated.com/en/ds/MAX6161-MAX6168.pdf

 

A voltage reference with 2.5 V (The ADS1114 supply range is from 2 V to 5 V)

So why not use 5V ?

 

You have the microcontroller running at 5V; so it will be expecting 5V levels on the I2C - so probably won't work at 2.5V !

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I get from the scope on the SDA and SCL lines is below. Pink for SCL, yellow for SDA.

If I understand this well, there is a start condition, but then nothing else and the SCL is back to high, like it were some sort of instant start/stop?

 

 

 

 

About the 2,5 V reference:

 

I need to measure the output current of the battery. It can be up to 10 A. I need a precision as near as possible (given my means) to 0,2% (yep, I know it’s very high) for the 500 mA – 10 A range. Which means in the case of the 500 mA an accuracy of 1 mA (so, no more than 0,5 mA/bit, to be sure, ideally a tenth of that)

The 10 parallel resistors functions as a shunt of 0,3 Ohm with a precision of +/-0,1%  (10 because of high power + higher combined precision)

The MAX series elements have a very high precision too. (2 mV/2,5 V here)

Now if I take 5 V one bit represent: 5 V / 2^(16-1-1) = 304 uV (-1 because: imprecision of ADC (I was advised to discount this one, and another -1 because the current range is from -10 A to 10 A, so I need a bit for the direction change)

which divided by 0,3 Ohm is: 1,013 mA /bit which is two high for the desired precision.

Two ways to make it better: either make the shunt value higher (which is already higher than I’d like to. 0,3 Ohm with 10 A are 30 W loss and a huge voltage drop of 3 V), or make the voltage reference smaller, which is how I end up with 2,5 V and 3 Ohm as some sort of compromise.

 

I’m going to try to switch the MAX piece with a 5 V voltage reference, to check if this work. If that’s the case, I’ll have to think of some solution, maybe some sort of bi directional level converter on the SDA and SCL lines ?

Attachment(s): 

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

Murmeltier wrote:
Two ways to make it better

those aren't the only ways:

  • Use an ADC with separate reference input;
  • Use an amplifier on the input (there are parts specifically for this - Current-Sense Amplifiers)

 

Your microcontroller will work at 2.7V, won't it?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What speed are you trying to run your I2C at?

 

That pulse on SCL looks mighty narrow to me. According to the ADS1114 datasheet, in 'normal' I2C mode, it needs to be at least 1.3us wide.

"This forum helps those that help themselves."

"How have you proved that your chip is running at xxMHz?" - Me

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

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

You have a 5V system.  Connect pullups to 5V.   Connect ADS1114 VDD to 5V.    Connect ADDR to GND.

 

Paste or attach a buildable project.   Post an accurate schematic.   (or describe any changes to your earlier schematic)

Quite honestly,   I can't see how or why you have a nanosecond pulse on SCL or a 1us pulse on SDA,

After all,   a 100kHz bus has SCL pulses with 10us period.   5us low, 5us high.

 

Regardless of the ADC operation,   you should get good "I2C comms" between the ADS114 and the AVR.   e.g. good ACK for i2c_start(slave).   write data to the CONFIG register.   read the contents that you have just written.

 

What voltage is your battery?    AIN0, AIN1 must be in the permitted absolute range.   Even though you are only interested in the difference voltage.

 

David.

Last Edited: Wed. Jan 3, 2018 - 06:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I replaced the max voltage reference (2.5 V) with a connection to the 5 V Voltage reference already in the circuit (for the atmega). It seems to have solved my communication problem, see result below (yellow is the clock):

 

 

At least it is an improvement with which I can work further, so thank you very much people.

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

So you could mark that as the solution: https://www.avrfreaks.net/comment...

 

Do the comms work if you run the AVR and the ADC at 2.7V ... ?

(see #13)

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All right, I did the marking :)

And I just checked, the communication works for 2,8 V and higher !