Another HMC6352 Question

Hi All, I am totally new to C programming so forgive my ignorance. I have one of the above mentioned compass sensor breakouts from SparkFun and I have looked over lots of code and have no problems using it, however, the device needs calibrating as it is out by somewhere around 20 degrees. I grabbed the code below and modified it (mostly spelling and statements). I have tried doing this numerous times and I it just stays the same so I suspect the code isn’t working properly. According to the data sheet for the HMC6352 You first send a “C” to start the calibration mode and rotate the device 2 times in succession anywhere between 6 seconds to 3 minutes, after that you send “E” to end the calibration mode then “L” to save the data. I don’t think the L command is necessary as looking in the data sheet from Honeywell it mentions that the data is automatically stored.

Here is the code I used to try and set the calibration:

#include <Wire.h>
int add = 0x42;   //Hmc6352 Address
void setup()
{
Serial.begin(9600);
Wire.begin();
}
void loop()
{
  delay(5000);
  Serial.println("Get Ready in 5");
  delay(5000);
Serial.println("start");
  Wire.beginTransmission(add);
  Wire.write("C");   
  Wire.endTransmission();
  delay(70);
  Serial.println("rotate 1 count to 20");
  delay(20000);
  Serial.println("rotate 2 count to 20");
  delay(20000);
  Serial.println("stop rotate");
  delay(150);
  Wire.beginTransmission(add);
  Wire.write("E");   
  Wire.endTransmission();
  delay(70);
  Wire.beginTransmission(add);
  Wire.write("L");   
  Wire.endTransmission();
  Serial.print("end. Finished, Restart in 5");
   delay(500000);
}

In the data sheet it also mentions to do 2 rotations in 20 seconds (not 40 as the above code is doing) so maybe that is an issue? Just maybe the reading code I am using could be in error? What I actually get is :

The left is the actual degrees and the right is the output of the HMC6352.

0 - 0 degrees (when facing north, this alone appears out by 20 degrees)
90 - 66 degrees
180 - 158 degrees
270 - 266 degrees

Strangely as you can see above from 270 - 0 degrees it appears correct!

Below is code I got also to check the compass headings just in case this is in error.

#include <Wire.h>
int HMC6352Address = 0x42;
// This is calculated in the setup() function
int slaveAddress;
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.write("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.read();
    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);
}

I hope someone can help me as the compass is pretty well useless as it is…

Regards Ismael

PS: Sorry forgot to mention I am using an ATMega 2560…

Hi Everyone, I actually got it working properly. I looked at the code for reading the compass and transposed some and it now works…

For those that want to calibrate the compass sensor here is the code I used. Remember it is more accurate the longer the period and very smooth rotations.

#include <Wire.h>
int add = 0x42;   //Hmc6352 Address
int slaveAddress;
void setup()
{
  slaveAddress = add >> 1;
Serial.begin(9600);
Wire.begin();
}
void loop()
{
  delay(5000);
  Serial.println("Get Ready in 5");
  delay(5000);
  Serial.println("start");
  delay(1000);
  Wire.beginTransmission(slaveAddress);
  Wire.write("C");   
  Wire.endTransmission();
  delay(10);
  Serial.println("rotate twice in 20 seconds NOW");
  delay(20000);
  Serial.println("stop rotate");
  delay(10);
  Wire.beginTransmission(slaveAddress);
  Wire.write("E");   
  Wire.endTransmission();
  delay(10);
  Wire.beginTransmission(slaveAddress);
  Wire.write("L");   
  Wire.endTransmission();
  Serial.print("end. Finished, Restart in 50 secs");// This gives you a chance to stop the loop returning 
  delay(500000); //and starting again before you disconnect or upload new sketch
}

… 8)

I Have updated the code to use a stepper motor. Go here: http://arduino.cc/forum/index.php/topic,117116.0.html