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: https://www.sparkfun.com/products/10846?. 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...