espruino / Espruino

The Espruino JavaScript interpreter - Official Repo
http://www.espruino.com/
Other
2.77k stars 744 forks source link

Bangle Compass tilt compensation #1852

Open jeffmer opened 4 years ago

jeffmer commented 4 years ago

I have been working on a tilt compensated compass and I have discovered the following issues with the current Bangle compass implementation.

1) The heading gives 270 degrees when the Bangle points East and 90 degrees when pointed West - should be the other way round. The fix is to change line 1294 of jswrap_bangle.c which is currently: h = jswrap_math_atan2(dx,dy)*180/PI; to: h = jswrap_math_atan2(-dx,dy)*180/PI; i.e. dx should be negated.

2) You have implemented the standard Hard Iron calibration algorithm, however, after calibration, the max and min values continue to be adjusted.

So, for example, if you bring the bangle compass near a strong magnet the needle will move, however, when you move away from the magnet, the compass reading will be wrong as a new maximum has been recorded - I did the experiment:-) The fix is that after calibration, max and min should remain fixed until the next time you calibrate.

Not critical: it would be nice to give access to the max and min variable as then the user could implement the soft iron compensation as well. There is a neat delta algorithm see: https://appelsiini.net/2018/calibrate-magnetometer/

gfwilliams commented 4 years ago

Ahh - thanks. So even the heading reported by the compass app is actually wrong at the moment? You know I'm sure I flipped that around at some point in the past...

Changing this is a bit of a pain because suddenly all the apps using it will misbehave. If we change the apps then they'll break on old firmwares and vice-versa. Given the ease of fixing this (359-heading) it might just be better to document it?

For calibration, do you think that stopping updating min and max would actually be a net benefit? I feel like I can see more cases where calibration would go wrong than I could see cases where someone suddenly walks past a large magnetic field?

If we kept calibration then yes it'd be a pain, but as we clear it each time the compass is started I'm not sure it's such a big deal?

it would be nice to give access to the max and min variable

To be fair you can just look at the x,y and z values and do your own algorithm right now. No need to look at the Bangle's min and max?

jeffmer commented 4 years ago

Yes, the last version of the compass I checked - before you removed flicker - had the wrong headings. I agree that it’s a big legacy issue.

I think as you suggest it’s best to use the x,y and z values directly. I have implemented my own calibration algorithm which stores the compensation for reuse. It would be interesting to see if they change much between bangles. The dominant hard iron is the power docking magnets.

In answer to your questions, I think the best fix is documentation and the best solution for calibration would be to stop it after say 10 seconds. The problem is that a lot of everyday objects like tablets and phone cases have strong magnets included.

For information, the coefficients on my bangle are: ˋˋˋ var OFFSET = { x: -58, y: -3.5, z: -3.5}; var SCALE = { x: 1.01, y:1.05, z: 0.95}; ˋˋˋ Reliable calibration in 3 axis seems to require about-the 1 minute of waving about:-(

PS I have got tilt compensation to work using the accelerometer - will do PR when I tidy it up.

gfwilliams commented 1 year ago

The direction of headings has been fixed for a while now, and we do now have some slightly better calibration code.

I've spent quite a while looking into it though and have test-implemented a few different continuous calibration functions, and it's much harder than it seems to get something working nicely.

We currently have something that stores min/max with a maximum range, which seems to do a slightly better (but still not perfect) job of keeping calibration.

I have got tilt compensation to work using the accelerometer - will do PR when I tidy it up.

Any chance of digging that code out for a PR? That would be really handy.

jeffmer commented 1 year ago

Hi Gordon,

I am bobbing about in the Med for the next few weeks with minimal internet access.

The code for tilt compensation is in my Bangle compass app which is available in the Bangle app loader.

gfwilliams commented 1 year ago

Ok, no problem - thanks! Hope you have a good break!

I'll take a look when I get a moment and will see how easy it is to add. Looks like the code is at https://github.com/espruino/BangleApps/blob/master/apps/magnav/tilt.js