Trouble reading LSM303DLM compass/accelerometer data - SOLVED

I am working on an autonomous car based on an Arduino Uno with a GPS shield (http://www.sparkfun.com/products/10709). For guidance, I am using a compass (LSM303DLM http://www.pololu.com/catalog/product/1273) to read the heading. I have followed the wiring and code instructions in the guide (https://github.com/pololu/LSM303). However, when I try to read data from it, all I get is a blank Serial Monitor window.

In trying to fix the problem, I first made sure that the baud rate in Serial.begin matches that in the Serial monitor window, which it did.

I then poked around in the compass example and lsm303.cpp and found that the line that was causing it to fail was:

while (Wire.available() < 6);

For this line in context, see the selection of lsm303.cpp below.

When I comment out this line, it prints, but without sensor data:

Do you know why this line of code is broken? Might it be that the compass is incompatible with the GPS shield (e.g., because the GPS draws too much power)? Do you think I have a bad compass?

Serial.pde (https://github.com/pololu/LSM303/blob/master/LSM303/examples/Serial/Serial.pde)

#include <Wire.h>
#include <LSM303.h>

LSM303 compass;


void setup() {
  Serial.begin(9600);
  
  Wire.begin();
  compass.init();
  compass.enableDefault();
}

void loop() {
  
  compass.read();
  
  Serial.print("A ");
  Serial.print("X: ");

  Serial.print((int)compass.a.x);
  Serial.print(" Y: ");
  Serial.print((int)compass.a.y);
  Serial.print(" Z: ");
  Serial.print((int)compass.a.z);

  Serial.print(" M ");  
  Serial.print("X: ");
  Serial.print((int)compass.m.x);
  Serial.print(" Y: ");
  Serial.print((int)compass.m.y);
  Serial.print(" Z: ");
  Serial.println((int)compass.m.z);
  
  delay(100);
}

lsm303.cpp (https://github.com/pololu/LSM303/blob/master/LSM303/LSM303.cpp)

....
// Reads the 3 accelerometer channels and stores them in vector a
void LSM303::readAcc(void)
{

	Wire.beginTransmission(acc_address);
	// assert the MSB of the address to get the accelerometer 
	// to do slave-transmit subaddress updating.
	Wire.write(LSM303_OUT_X_L_A | (1 << 7)); 
	Wire.endTransmission();
	Wire.requestFrom(acc_address, (byte)6);

	while (Wire.available() < 6);  // ***** fails here *****

	byte xla = Wire.read();
	byte xha = Wire.read();
	byte yla = Wire.read();
	byte yha = Wire.read();
	byte zla = Wire.read();
	byte zha = Wire.read();

	a.x = (xha << 8 | xla) >> 4;
	a.y = (yha << 8 | yla) >> 4;
	a.z = (zha << 8 | zla) >> 4;

}

// Reads the 3 magnetometer channels and stores them in vector m
void LSM303::readMag(void)
{
	Wire.beginTransmission(MAG_ADDRESS);
	Wire.write(LSM303_OUT_X_H_M);
	Wire.endTransmission();
	Wire.requestFrom(MAG_ADDRESS, 6);

	while (Wire.available() < 6); // ***** fails here *****

	byte xhm = Wire.read();
	byte xlm = Wire.read();
	
	byte yhm, ylm, zhm, zlm;
	
	if (_device == LSM303DLH_DEVICE)
	{
		// DLH: register address for Y comes before Z
		yhm = Wire.read();
		ylm = Wire.read();
		zhm = Wire.read();
		zlm = Wire.read();
	}
	else
	{
		// DLM, DLHC: register address for Z comes before Y
		zhm = Wire.read();
		zlm = Wire.read();
		yhm = Wire.read();
		ylm = Wire.read();

	}

	m.x = (xhm << 8 | xlm);
	m.y = (yhm << 8 | ylm);
	m.z = (zhm << 8 | zlm);
}

// Reads all 6 channels of the LSM303 and stores them in the object variables
void LSM303::read(void)
{
	readAcc();
	readMag();
}
...
Wire.requestFrom(acc_address, (byte)6);

	while (Wire.available() < 6);  // ***** fails here *****

You don’t need the Wire.available() line at all. Wire.requestFrom blocks until it returns the requested number of bytes, or fails to do so. So a better approach would be:

if (Wire.requestFrom(acc_address, 6) != 6)
  {
  // handle error here
  return;
  }

// if we got here, we have data

The error could be the device isn’t there, isn’t on, has another address, and so on.

You can check the address of the device (and whether it is on, etc.) by running the I2C Scanner sketch on this page:

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

Another reading of the wiring instructions (https://github.com/pololu/LSM303) shows my mistake: I plugged SCL & SDA into digital 4 & 5 instead of analog 4 & 5. Embarrassing.

Suggested wiring:

Arduino Uno/Duemilanove LSM303 Carrier
5V → VIN
GND → GND
Analog Pin 5 → SCL
Analog Pin 4 → SDA

My original wiring:

Now that it’s wired correctly, it works fine.

I will keep in mind your suggestions when troubleshooting future I2C problems, Nick–thanks.