I have calculated the average of the min max and subtracted this from the raw. The calibration data now looks good. Now i can see when the puck is upside down as the z axis changes it sign. I am also calculating the heading and correcting for negative numbers .
Can you test on your device and see if the puck now works as a digital compass.
You will have to calibrate by holding down the button for 5 seconds then rotating the puck in all directions until the is only green flashes no blue. then press to go back to calibrated readings.
var Vec3 = require('Vec3');
var vMin = new Vec3();
var vMax = new Vec3();
var vAve = new Vec3();
var vZero = new Vec3();
var calibrating = false;
var calibrated = false;
var count = 0;
var h = 0;
var oldh = 0;
// call a function if button is held down for 4 seconds
function b4Seconds(callback) {
setWatch(function(e) {
if (calibrating) {return;}
console.log("Button down");
t4s = setTimeout(function() {
callback();
},4000);
setWatch(function(e) {
clearTimeout(t4s);
console.log("Button up");
}, BTN, { repeat: false, edge: 'falling', debounce: 50 });
}, BTN, { repeat: true, edge: 'rising', debounce: 50 });
}
function calibrate () {
if (calibrated) {
console.log('re-calibrating...');
} else {
console.log('calibrating...');
}
calibrated = false;
calibrating = true;
var xyz = Puck.mag();
var sMax = 0;
var sMin = 0;
count = 0;
vMin = new Vec3(xyz);
vMax = new Vec3(xyz);
Puck.magOn(10);
Puck.on('mag', function(xyz) {
if (calibrated) {return;}
var vMag = new Vec3(xyz);
vMin = vMin.min(vMag);
vMax = vMax.max(vMag);
if ((sMax != vMax.mag()) || (sMin != vMin.mag())) {
sMin = vMin.mag();
sMax = vMax.mag();
count++;
console.log('new min or max: ',count);
// flash the blue LED when calibrating
digitalWrite(LED3, count % 2 == 0);
} else {
// flash the green LED when not calibrating
digitalWrite(LED2, Math.random()>0.5);
digitalWrite(LED3, false);
}
});
//press the buton to stop calibrating
setWatch(function(e) {
Puck.magOn(5);
calibrating = false;
console.log("calibarion completed");
console.log('max: ',vMax);
console.log('min: ',vMin);
digitalWrite(LED3, false);
digitalWrite(LED2, false);
// calculate the average of vMin and vMax to get the nuteral position
vAve = new Vec3((vMin.x + vMax.x)/2,(vMin.y + vMax.y)/2,(vMin.z + vMax.z)/2);
console.log('ave: ',vAve);
// get the zero position when the end calibrate button was pressed
vZero = new Vec3(Puck.mag()).sub(vAve);
console.log('zero:',vZero);
calibrated = true;
}, BTN, { repeat: false, edge: 'rising', debounce: 50 });
}
function calibratedMag() {
Puck.magOn();
Puck.on('mag', function(xyz) {
if(calibrating) {return;}
var vMag = new Vec3(xyz).sub(vAve);
//console.log('mag: ',vMag);
h = (Math.atan2(vMag.y, vMag.x) * 180) / Math.PI;
if (h > 360) {
h = h - 360;
}
if (h < 0) {
h = h + 360;
}
if (Math.abs(Math.round(oldh) - Math.round(h)) >4) {
console.log('--------------------');
if (!calibrated) {console.log('uncalibrated!');}
console.log('heading: ',Math.round(h));
console.log('rotate: ', Math.round(oldh - h));
if (vMag.z > 0) {
console.log('upwards');
} else {
console.log('downwards');
}
}
oldh = h;
});
}
//calibrate by holding button down for 4 seconds
b4Seconds(calibrate);
calibratedMag();
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
I have calculated the average of the min max and subtracted this from the raw. The calibration data now looks good. Now i can see when the puck is upside down as the z axis changes it sign. I am also calculating the heading and correcting for negative numbers .
Can you test on your device and see if the puck now works as a digital compass.
You will have to calibrate by holding down the button for 5 seconds then rotating the puck in all directions until the is only green flashes no blue. then press to go back to calibrated readings.
The out
put after calibration