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.
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)
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)