HMC6352 Calibration using Stepper Motor

Hi All, I have refined the calibration method by using a stepper to control the rotation so it is even and smooth. I used a 0.9 degree 400 step/rev stepper same as this from Sparkfun: Stepper Motor - 68 oz.in (400 steps/rev) - ROB-10846 - SparkFun Electronics You will have to change the code for other steppers where marked. This rotates my compass twice in around 25 seconds. My compass is now accurate to within .5 degree. Make sure that you use a rod attached to the drive that is around 6-8" long and I just used blu-tak to fix it level and made sure the cable wouldn’t tangle.

Here is the code:

/* This program is for calibrating the HMC6352 compass sensor 
   from SparkFun. It uses a stepper motor to rotate the compass
   on a long rod (away from stepper) to do the calibration. 
   The stepper I used is a 3V 0.9 deg/step 400 step/per rev
   You will have to change the rotate deg and rotate calculation
   for other stepper motors.
   */

#include <Wire.h>
int add = 0x42;   //Hmc6352 Address
int slaveAddress;

#define DIR_PIN A7 // A9-A7
#define STEP_PIN A6 // A8-A6
#define DIRB_PIN A9
#define STEPB_PIN A8
void setup()
{
  slaveAddress = add >> 1;
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIRB_PIN, OUTPUT);
  pinMode(STEPB_PIN, OUTPUT);
  
  Serial.begin(9600);
  Wire.begin();
}
void loop()
{
  delay(1000);
  Serial.println("Get Ready in 5 seconds");
  delay(5000);
  Serial.println("start");
  delay(500);
  Wire.beginTransmission(slaveAddress);
  Wire.write("C");   
  Wire.endTransmission();
  delay(10);
  rotate(-12800, .05); //reverse Change this to suit stepper This is 2 revolutions
  delay(1000);
  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
} 
void rotate(int steps, float speed){
  //rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);

  digitalWrite(DIR_PIN,dir); 
  digitalWrite(DIRB_PIN,dir); 
  
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    digitalWrite(STEPB_PIN, HIGH);    
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    digitalWrite(STEPB_PIN, LOW);    
    delayMicroseconds(usDelay);
  }
} 

void rotateDeg(float deg, float speed){
  //rotate a specific number of degrees (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(DIR_PIN,dir); 
  digitalWrite(DIRB_PIN,dir);
// Set for 0.9 degree per step motors
  int steps = abs(deg)*(1/0.05625); // Change this to 0.225 for 1.8degree stepper motor
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);
    digitalWrite(STEPB_PIN, HIGH);
    delayMicroseconds(usDelay); 

    digitalWrite(STEP_PIN, LOW);
    digitalWrite(STEPB_PIN, LOW);
    delayMicroseconds(usDelay);
  }
}

Enjoy all.

PS: I am using a Big EasyDriver, it works with the same steppers with the EasyDriver also…