I was unable to get any of the examples (including the one in this thread) I found online to work either. In the end I ended up using the I2C bypass to access the magnetometer raw data.
First change the compass defines to point at the registers for the Compass instead of the MPU9150's registers:
//MPU9150 Compass
#define MPU9150_CMPS_XOUT_L 0x03 // R
#define MPU9150_CMPS_XOUT_H 0x04 // R
#define MPU9150_CMPS_YOUT_L 0x05 // R
#define MPU9150_CMPS_YOUT_H 0x06 // R
#define MPU9150_CMPS_ZOUT_L 0x07 // R
#define MPU9150_CMPS_ZOUT_H 0x08 // R
#define MPU9150_CMPS_CNTL 0x0A // R
Then setupCompass() gets simplified down to just:
void MPU9150_setupCompass(){
MPU9150_write(MPU9150_USER_CTRL, 0x00); //Disable Master Aux I2C mode
MPU9150_write(MPU9150_INT_PIN_CFG, 0x02); //Enable I2C Aux Bypass mode
MPU9150_I2C_ADDRESS = 0x0C; //change Address to Compass
writeSensor(MPU9150_CMPS_CNTL, 0x01); //Single Read Mode
delay(10);
MPU9150_I2C_ADDRESS = tempAddress; //new version to revert to original address
}
That sets up the Aux I2C to be connected directly to the main I2C. Then to read the values from the compass just do something along these lines:
void MPU9150Device::readCompassData(int &compassX, int &compassY, int &compassZ)
{
MPU9150_I2C_ADDRESS = MPU9150_CMPS_ADDRESS; //change Adress to Compass
writeSensor(MPU9150_CMPS_CNTL, 0x01); //trigger single read
delay(10);
compassX = MPU9150_read(MPU9150_CMPS_XOUT_L,MPU9150_CMPS_XOUT_H);
compassY = MPU9150_read(MPU9150_CMPS_YOUT_L,MPU9150_CMPS_YOUT_H);
compassZ = MPU9150_read(MPU9150_CMPS_ZOUT_L,MPU9150_CMPS_ZOUT_H);
MPU9150_I2C_ADDRESS = MPU9150_I2C_ADDRESS; //change Adress to MPU
}
The datasheet and register map documents here: https://www.invensense.com/products/motion-tracking/9-axis/mpu-9150/ Helped out a lot.