HMC5883

I have Grove - 3-axis Compass v1.0b (HMC5883).
I connect this device to atmega32. And have as result from compass 0xFF as MSB and 0x00 as LSB in X,Y,Z registers. Why I have this problem? Voltage for compass pcb 3.3 volts.

seeedstudio.com/wiki/index.p … pass_v1.0b

It should be 0x03 - 0x08 in the datasheet. In the I2C program code, I just set the mode, and request receive. Wire.beginTransmission(HMC5883_WriteAddress); //Initiate a transmission with HMC5883 (Write address). Wire.requestFrom(HMC5883_WriteAddress,6); //Request 6 bytes of data from the address specified.How did you get the registers address ?

I use avr microcontroller without arduino. Sure I read registers 0x03…0x08.
Part of my code:

void HMC5883(void)
{		
	//unsigned char xh, xl, yh, yl, zh, zl;
	long xo, yo, zo;
    
	
	i2cSendStart();
	i2cWaitForComplete();
	i2cWrite_Address(0x3C);    //write to HMC
	i2cWaitForComplete(); 
	i2cWrite_Data(0x02);    //mode register 
	i2cWaitForComplete();
	i2cWrite_Data(0x00);    //continuous measurement mode
	i2cWaitForComplete();
    //status_er = i2cGetStatus();
    //i2cCheckForMT_SLA();
	i2cSendStop(); 
    delay_ms(10);
	
	//must read all six registers plus one to move the pointer back to 0x03
	i2cSendStart();
	i2cWaitForComplete();
	i2cRead_Address(0x3D);          //read from HMC
    i2cWaitForComplete();
	i2cReceiveByte(TRUE);
	//i2cWaitForComplete();
	xh = i2cRead_Data();	//x high byte
	i2cWaitForComplete();  
    
	i2cReceiveByte(TRUE);
	i2cWaitForComplete();
	xl = i2cRead_Data();	//x low byte
	i2cWaitForComplete();
	xo = xl|(xh << 8);
	
	i2cReceiveByte(TRUE);
	i2cWaitForComplete();
    
	yh = i2cRead_Data();	//y high byte
	i2cWaitForComplete();
	
	i2cReceiveByte(TRUE);
	i2cWaitForComplete();
	yl = i2cRead_Data();	//y low byte
	i2cWaitForComplete();
	yo = yl|(yh << 8);
	
	i2cReceiveByte(TRUE);
	i2cWaitForComplete();
	zh = i2cRead_Data();	
	i2cWaitForComplete();      //z high byte
	
	i2cReceiveByte(TRUE);
	i2cWaitForComplete();
	zl = i2cRead_Data();	//z low byte
	i2cWaitForComplete();
	zo = zl|(zh << 8);
	
	i2cRead_Data();         //must reach 0x09 to go back to 0x03
	i2cWaitForComplete();
    i2cReceiveByte(TRUE);
	i2cWaitForComplete();
    status_er = i2cGetStatus();
	
	i2cSendStop();	
}
i2cRead_Address(0x3D);          //read from HMC

It should be Ox3c.

Why? In datasheet address for reading is 0x3D. In status register of this compass i read value 0xff, it’s very strange. How set default setting for compass or realize reset all configurations of HMC5883?
HMC5883.pdf (480 KB)

I read status register of HMC5883 and i get 0xff, in configuration A register is 0xf0, in configuration B register is 0x20.

If you can,you can post your i2cRead_Address function how to achieve,also the i2cWrite_Data function.
here is the change of the code:

[code] //must read all six registers plus one to move the pointer back to 0x03
i2cSendStart();
i2cWaitForComplete();
i2cRead_Address(0x3D); //read from HMC
i2cWaitForComplete();
i2cReceiveByte(TRUE);

delay_ms(500);

//i2cWaitForComplete();
xh = i2cRead_Data(); //x high byte
i2cWaitForComplete();
[/code]

and you can try the 0x3D and 0x3C both.This is depanding on the function of the i2CRead_Address();if in the function you are already set the read bit “bit 0” to ‘1’,then use the ox3C,if not use the 0x3D.

Yes, I can.

void i2cRead_Address(unsigned char data)
{
	TWDR=data;	// Address and read instruction
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte received
	while((TWSR & 0xF8)!= 0x40);  // Check for the acknoledgement
}

unsigned char i2cRead_Data(void)
{
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x58); // Check for the acknoledgement
	recv_data=TWDR;
    return (TWDR);
}
void i2cWrite_Address(unsigned char data)
{
	TWDR=data;	// Address and write instruction
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8)!= 0x18);  // Check for the acknoledgement
}
void i2cWrite_Data(unsigned char data)
{
	TWDR=data;	// put data in TWDR
	TWCR=(1<<TWINT)|(1<<TWEN);    // Clear TWI interrupt flag,Enable TWI
	while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
	while((TWSR & 0xF8) != 0x28); // Check for the acknoledgement
}

I try to use example from datasheet on HMC5883L, but i don’t understand what mean “Send 0x3D 0x06”.
TWI_COMPASS.rar (51.2 KB)
punkt.JPG

The 0x3D 0x06 just for the arduino firmware,that mean is to read 6 datas from the HMC5883.
For the code,you can consult the arduino demo code.

Now all work good. I wrote code, where i move pointer to each data registers and read it.

But work illegal. I don’t understand formula for definition north direction. In datasheet i can’r find it.

Now i get normal values for angle, when i rotate compass from 0 to 270 degrees. There are region in 90 degrees(270-360), where compass have non stable and wrong data.
When i rotate compass i get negative value from 0 to -135 and it value i (angle*2) and i think that i have right value, but all value from 0 to 270 degrees is negative, but i use atan2 function.
TWI_COMPASS.rar (108 KB)