Wire.endTransmission() hangs sketch

Arduino board: Leonardo
IDE: v1.0.1
I2C hardware: MAG3110 magnetometer (https://www.sparkfun.com/products/10619)

Trying to set up the I2C sensor to take magnetic field data, but debugging is showing that Wire.endTransmission(); hangs the sketch (debug code below). Looking around online, I found others are having this problem as well:

Output always makes it to the line right before the first call to Wire.endTransmission(); in the config() function - In particular the output looks like:

Serial started.
Made it to the config fn.
Made it to the first CtrlReg.
Addressed CtrlReg1.
Enabled ACTIVE mode.

Based on internet research, it sounds like there’s either an obscure problem with the Wire library or I’m just not communicating with my I2C device (which sounds more likely). I’ve quadruple-checked my wiring and everything looks correct. [I’ve tried using both the Leonardo’s dedicated SCL/SDA pins and D2/D3, but there’s no difference, not surprisingly.]

Any thoughts on how to debug further? I’m at a bit of a loss, I’ll admit. Is it possible that my magnetometer is just fried? (Unfortunately, I don’t have another arduino to test it on. :frowning: )

Any suggestions welcomed.

/*
  MAG3110 Breakout Example Code
 
 by: Aaron Weiss, aaron at sparkfun dot com
 SparkFun Electronics 2011
 date: 9/6/11
 license: beerware, if you use this code and happen to meet me, you
 can by me a beer
 
 The code reads the raw 16-bit x, y, and z values and prints them 
 out. This sketch does not use the INT1 pin, nor does it poll for
 new data.
 
 */

#include <Wire.h>

#define MAG_ADDR  0x0E //7-bit address for the MAG3110, doesn't change

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println("Serial started.");
  config();            // turn the MAG3110 on
  Serial.println("Magnetometer config done.");
}

void loop()
{
  print_values();
  delay(100);
}

void config(void)
{
  Serial.println("Made it to the config fn.");
  int errorcode;
  
  Serial.println("Made it to the first CtrlReg.");
  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x10);              // cntrl register1
  Serial.println("Addressed CtrlReg1.");
  Wire.write(0x1);              // send 0x01, active mode
  Serial.println("Enabled ACTIVE mode.");
  errorcode = Wire.endTransmission();       // stop transmitting
  delay(1000);
  Serial.print("Error code:");
  Serial.println(errorcode);
  Serial.println("Ended transmission to CtrlReg1.");
  
  delay(15);
  
  Serial.println("Made it to the second CtrlReg.");
  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x11);              // cntrl register2
  Serial.println("Addressed CtrlReg2.");
  Wire.write(0x10);              // send 0x10, enable auto resets
  Serial.println("Enabled auto-reset.");
  errorcode = Wire.endTransmission();       // stop transmitting
  delay(1000);
  Serial.print("Error code: ");
  Serial.println(errorcode);
  Serial.println("Ended transmission to CtrlReg2.");
}

void print_values(void)
{
  Serial.print("x=");
  Serial.print(readx());
  Serial.print(", y=");    
  Serial.print(ready());      
  Serial.print(", z=");    
  Serial.println(readz());
}

int readx(void)
{
  int xl, xh;  //define the MSB and LSB

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x01);              // x MSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    xh = Wire.read(); // receive the byte
  }

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x02);              // x LSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    xl = Wire.read(); // receive the byte
  }

  int xout = (xl|(xh << 8)); //concatenate the MSB and LSB
  return xout;
}

int ready(void)
{
  int yl, yh;  //define the MSB and LSB

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x03);              // y MSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    yh = Wire.read(); // receive the byte
  }

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x04);              // y LSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    yl = Wire.read(); // receive the byte
  }

  int yout = (yl|(yh << 8)); //concatenate the MSB and LSB
  return yout;
}

int readz(void)
{
  int zl, zh;  //define the MSB and LSB

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x05);              // z MSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    zh = Wire.read(); // receive the byte
  }

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.beginTransmission(MAG_ADDR); // transmit to device 0x0E
  Wire.write(0x06);              // z LSB reg
  Wire.endTransmission();       // stop transmitting

  delayMicroseconds(2); //needs at least 1.3us free time between start and stop

  Wire.requestFrom(MAG_ADDR, 1); // request 1 byte
  while(Wire.available())    // slave may send less than requested
  { 
    zl = Wire.read(); // receive the byte
  }

  int zout = (zl|(zh << 8)); //concatenate the MSB and LSB
  return zout;
}
[\code]

Running your sketch on a Leonardo with no peripherals attached I get this:

Serial started.
Made it to the config fn.
Made it to the first CtrlReg.
Addressed CtrlReg1.
Enabled ACTIVE mode.
Error code:2
Ended transmission to CtrlReg1.
Made it to the second CtrlReg.
Addressed CtrlReg2.
Enabled auto-reset.
Error code: 2
Ended transmission to CtrlReg2.
Magnetometer config done.
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768
x=768, y=768, z=768

I would try my I2C scanner from this page:

http://www.gammon.com.au/i2c

That will tell you if it detects the I2C peripheral, and if so, on what address.

There is a problem with the stock I2C library that a mis-transmission may cause it to hang. This will generally happen on the Wire.endTransmission() line which is the one which actually sends the data. The other lines just put the data into a buffer. There is another library (link on the page above) which will time-out if it cannot communicate. You might want to check your wiring, the pull-up resistors, etc. Also try slowing down the I2C communications (how to do that is explained on my page).

Thank you so much for your I2C scanner Nick! It worked like a charm for me!

I have the same problem.

Wire.endTransmission causes a crash for me too, though I can see the device on the I2C Scanner.

Same problem here. I'm using a Mega2560 and sketch freeze at wire.endTransmission.

I tried use I2Cscanner sketch and MultispeedI2Cscanner, but Arduino hangs.

I got the same Wire.endTransmission() freeze problem too. And I solved this problem by replacing the "Wire.h" with "WSWire.h" from: https://github.com/steamfire/WSWireLib Then everything works fine. Hope this helps.

Tks. I'll check this code/lib.

But I solve this "bug" changing my Arduino (chinese version). With other protoboard works fine.

Ports 20 and 21 were working (I use a single LED to check output), but I2C not.

add Wire.begin(); just before Wire.beginTransmission I think it will work

Hi,I just want to offer some facts in case that happens to be ralativelly to the subject of this post.

I have a very simple arduino uno program.
An I2C LCD screen is attached to arduino.
But the Vcc (of LCD) is passing from a switch
that also this switch is pined on #2 of arduino.

So that when switch is on(closed) i have lcd-i2c working…

But i must have in my code the lcd.begin();
And this causes further calls to (from library)

void LiquidCrystal_I2C::expanderWrite(uint8_t _data){

  • Serial.println(“1.”);*
    Wire.beginTransmission(_addr);
  • Serial.println(“2.”);*
    Wire.write((int)(_data) | _backlightval);
  • Serial.println(“3.”);*
    Wire.endTransmission();
  • Serial.println(“4.”);*
    }

and hangs in 3…before endTransmisiion

here are the steps (assuming lcd is powered on startup)

a)We have LCD…and we are on lcd mode
b)We push the switch and going to the other mode

c)We again push switch …the lcd takes voltage and turns on
but the Wire.endTransmission(); of the library make it hung
(from mine code ->lcd.begin())

d)close switch …then the previus hang un-hangs…but again hungs

e)open again switch and finally all good.

Meaning i must make a further off-on action in order to UN- hang…

entering LCD mode
BEFORE expanderWrite(_backlightval);
1.
2.
3.
4.
AFTER expanderWrite
1.
2.
3.
4.
1.
2.
3.
4.
…many 1.2.3.4.here
1.
2.
3.
4.
LCD loopin 3910Starting loop …all good
entering SMS modeSwitch off …all good
SMS loopin 6917loop is working fine
entering LCD mode Here i press the switch again to ON but…
BEFORE expanderWrite(_backlightval);
1.
2.
3.… Hangs here
4.
AFTER expanderWrite
1.
2.
3.Unstack previus and hang again here when switrch is off (also lcd power off)

And as i ve said on the second switch on …all good…

Just in case someone have a simple idea how to fix…i am making this post.
(I know its an old thing the hanging of endTransmission…)

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
int was,is;
bool lcdmode(){
return is==HIGH;
}
void setup() {
Serial.begin(9600);
pinMode(2,INPUT);
is=digitalRead(2);
was=is+1;//to enter some mode on beginning
}
void loop() {
is=digitalRead(2);
if(is!=was){//if button pressed…no interrupts using
was=is;
if(lcdmode()){
Serial.println(“entering LCD mode”);
delay(500);
lcd.begin();
Serial.println(“begun()”);
lcd.print(“welcome”);
}
else{Serial.println(“entering SMS mode”);}
}
if(lcdmode()){Serial.print("LCD ");}
else{Serial.print("SMS ");}

Serial.print("loopin ");
Serial.println(millis());
delay(3000);
}