Hi everyone, I'm Matt, and this is my first post on this forum. It's also my first non-tutorial Arduino project, and I'm pleased to report good progress and many successes, along with several good lessons learned. Even though some of this might be obvious to many of you, I had a bit of a learning curve with it as a first-timer. I'm here to share what I found out, in order to help the next guy.
First, if you want to use the HMC6352 compass module with the Arduino, it's not hard, but it communicates using the Inter-Integrated Circuit (I2C) bus, which I learned is essentially a popular protocol ICs use to talk to each other. It uses a data line (SDA) and a clock line (SCL), and all devices on the bus share the same 2 pins on the board. SDA uses analog pin 4, and SCL uses analog pin 5 when the devices are connected to an Arduino (Duemillanove). Because all devices share the same physical connection, they are identified by their I2C Slave Address so that the data moves between the master (micro-controller) and it's various slave devices correctly. It's pretty easy to find a code sample that shows you how to get a heading out of the HMC6352 compass module with the Arduino using it's default I2C address, 0x42 (hexidecimal).
That worked pretty much right out of the box for me, but the device I'm building will use two different compass modules so that I can find the degrees of deviation between one compass heading and another (the direction my head is facing relative to my torso). Because of this, I cannot use the default address for one of the two devices... the two slave addresses on the bus have to be different. I have to find and change the address in one HMC6352. I didn't find much online about how to do that with the Arduino, but I found the data sheet http://www.sparkfun.com/datasheets/Components/HMC6352.pdf and found that it is possible to send commands that will read and write to the EEPROM (Electrically Erasable Programmable Read Only Memory) where the address is stored on the sensor.
I played around with the code, spent a while debugging it, and came up with the following, which allowed me to correctly read the address value from the EEPROM:
//Checking the I2C address of a HMC6352 Sparkfun Compass Module with Arduino
// By Matt Silvia 01/29/2012
#include <Wire.h>
int HMC6352Address = 0x42;
byte eepromAddress = 00; // the address in the HMC6352 EEPROM from which to request the value of the I2C Slave Address
int slaveAddress;
byte addressData[1];
int addressValue;
void setup()
{
// Shift the device's documented slave address (0x42) 1 bit right
// This compensates for how the TWI library only wants the
// 7 most significant bits (with the high bit padded with 0)
slaveAddress = HMC6352Address >> 1; // This results in 0x21 as the address to pass to TWI
Serial.begin(9600);
Wire.begin();
}
void loop()
{
// Send a "r" command to the HMC6352
// along with the EEPROM address to read
Wire.beginTransmission(slaveAddress);
Wire.send('r'); //read from EEPROM
Wire.send(eepromAddress); //argument to the 'r' command is sent seperately
Wire.endTransmission();
Wire.requestFrom(slaveAddress, 1); // Request the address
addressData[0] = Wire.receive();
Serial.print(addressData[0], HEX);
Serial.println(" is the address.");
delay(500);
}
Serial out reports that 42 is the address, so I believe I'm only a stone's throw from setting that to another value by using the "w" command with very similar code. When I get it working, I'll try to remember to come back and post the code for changing the value, as well as the final code for the degrees of variation between two compasses.