Problems with Arduino and HMC6352

hey there,

we are experiencing problems when we’re trying to interface sparkfuns HMC6352 compass module with an arduino board. check this thread on the arduino board for details: http://www.arduino.cc/cgi-bin/yabb2/YaB … 1170973485

any help would be greatly appreciated!

best regards,

garnitchique

I ran into a possibly similar issue - the HMC utilizes clock-stretching - aka, it will hold SCL low until its ready to respond. This is completely valid by the I2C spec, but you need to make sure your code takes this into account.

Cheers,

–David Carne

Dear David,

thank you for your information regarding clock-stretching on the HMC.

We tried with the stock Wire library on an Arduino NG board, but were

unsuccessful. Have you got HMC or similar clock-stretching chips to work

with Arduino Wire library or AVR in general?

We are in contact with Nicholas Zambretti, the author of the Wire

library and he is not sure whether clock-stretching is completely

transparent to his code or if it’s his duty to handle it. ("No advice

for how to implement it is given, just a hint that I2C could have

stretched clock cycles. Since the Wire library is entirely interrupt

driven (clock independent), I don’t understand why a lengthened clock

cycle should matter though.")

Any advise we could forward to him?

thanks

Hi David and garnitchique,

Any update to your efforts? I also am using this compass module with the Arduino and would like to know if you overcame your difficulties.

I posted some of this in an earlier reply that hasn’t shown up yet in the forum (stuck in moderation?).

Basically the problem is the address you need to use for the device. Instead of 0x42, you need to use 0x21 (only the most significant 7 bits). The TWI library left-shifts the address you supply by one bit, and then OR’s the read/write bit. To compensate, you need to shift the address one bit to the right. This is not specific to the HMC6352. You need to do this with any I2C device you try to interface with (at least with Arduino 0007). Maybe this will be fixed (or at least a little more friendly) in Arduino 0008.

Here’s some working code for an HMC6352 and a Arduino USB (rev. C) with an ATMega168 using Arduino 0007. Connect analog 4 to SDA, analog 5 to SCL. Don’t forget to put pull-up resistors on both lines! (I used 10K originally but was getting a little noise and switched to 4.7K).

#include <Wire.h>

int HMC6352Address = 0x42;
int slaveAddress;             // This is calculated in the setup() function

int ledPin = 13;
boolean ledState = false;

byte headingData[2];
int i, headingValue;

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);
  pinMode(ledPin, OUTPUT);      // Set the LED pin as output
  Wire.begin();
}

void loop()
{ 

  // Flash the LED on pin 13 just to show that something is happening
  // Also serves as an indication that we're not "stuck" waiting for TWI data

  ledState = !ledState;
  if (ledState) {
    digitalWrite(ledPin,HIGH);
  }
  else
  {
    digitalWrite(ledPin,LOW);
  }
  
  // Send a "A" command to the HMC6352
  // This requests the current heading data
  
  Wire.beginTransmission(slaveAddress);
  Wire.send("A");              // The "Get Data" command
  Wire.endTransmission(); 
  delay(10);                   // The HMC6352 needs at least a 70us (microsecond) delay 
                               // after this command.  Using 10ms just makes it safe
  
  // Read the 2 heading bytes, MSB first
  // The resulting 16bit word is the compass heading in 10th's of a degree
  // For example: a heading of 1345 would be 134.5 degrees

  Wire.requestFrom(slaveAddress, 2);        // Request the 2 byte heading (MSB comes first)
  i = 0;
  while(Wire.available() && i < 2) 
  {  
    headingData[i] = Wire.receive();
    i++;
  } 

  headingValue = headingData[0]*256 + headingData[1];  // Put the MSB and LSB together
  Serial.print("Current heading: ");
  Serial.print(int (headingValue / 10));     // The whole number part of the heading
  Serial.print(".");
  Serial.print(int (headingValue % 10));     // The fractional part of the heading
  Serial.println(" degrees");
  
  delay(500);
}

Hope this helps.

Instead of using slave address 0x42 for the HMC6352, use 0x21 and you should have no problems getting it going. This is due to the confusing way the TWI library is handling the slave address. It expects only the 7 most significant bits of the slave address. It then left-shifts the address you supply by one bit, and OR’s the R/W flag.

So if the slave address is 0x42, represented as:

0 0 1 0 1 0 1 0

Then TWI only wants the bold bits (with the MSb padded) as:

0 0 0 1 0 1 0 1 which is 0x21

I have in i2c device - the RN-Motor ST I2C stepper motor driver http://www.robotikhardware.de/download/rnmotor.pdf which uses the addresses 0x56 and 0x57. for the 0x56 i can apply this trick but not for the 0x57 the 1 gets lost. is there a way around this problem?

i just found out that my last post was nonesense. you explained it. it’s the read and write bit. sorry for the noise

It is a great job done by you. I think that it is very much helpful information. Is there any update to you effort?

micheal david:
It is a great job done by you. I think that it is very much helpful information. Is there any update to you effort?

Update what?

The working code I posted above should be enough to get any Arduino/HMC6352 project going. The HMC6352 is not a very complicated device so there’s not really a lot to add.

I also face this type of problem with sparkfuns HMC6352 compass module and i am waiting for new updates that is not held yet.