Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Magnetometer x, y, z overflows in CALIBRATED_SAMPLE and BLE characteristics #472

Open
martinwork opened this issue Sep 30, 2020 · 1 comment
Assignees

Comments

@martinwork
Copy link
Contributor

As I understand it, the MAG3110 and LSM303 ranges are +/- 10 and nearly +/- 50 Gauss. They return 16bit signed integers with nominal units of 1 and 1.5 milliGauss. I think that's +/- 1000 and +/- 5000 microTesla with units 100 and 150 nanotesla.

The DAL normalises to nanotesla units in 32bit integers, with ranges +/- one and five million.

The magnetometer service assigns the 32bit numbers to its 16bit data characteristic buffers
https://github.com/lancaster-university/microbit-dal/blob/master/inc/bluetooth/MicroBitMagnetometerService.h#L96
https://github.com/lancaster-university/microbit-dal/blob/master/source/bluetooth/MicroBitMagnetometerService.cpp#L151

It looks like the data characteristics will overflow outside +/- 32 microtesla. Have I got my millis, micros, and nanos mixed up?!

@martinwork
Copy link
Contributor Author

It looks like there is also a problem in the CALIBRATED_SAMPLE calculation.

When passing a fridge magnet near the micro:bit, a small increase in the raw reading causes the result of CALIBRATED_SAMPLE to flip sign. It seems, because the raw readings are millions, multiplying by calibration.scale (1024) causes an overflow in the 32bit arithmetic.

With both micro:bits I tested, calibration.scale.y was 1024. Is that expected? If calibration.scale were another value, would the values still be nanotesla?

Test details...

I modified MicroBitCompass::update() to dump values to serial. My main.cpp calls uBit.compass.heading() to trigger the compass calibration routine, then uBit.compass.getX() in a while loop. I was concentrating on the final X reading which comes from the raw Y reading.

The readings below were from a micro:bit v1.5. When I tested a micro:bit 1.3 it also produced raw readings outside +/-2 million, so high enough to trigger the overflow.

First reading:
[ r = raw reading; c = calibrated sample; t = transformed values]

calY = (( 2007150 - -12424) * 1024) >> 10
calY = ( 2019574 * 1024) >> 10
calY = 2068043776 >> 10
calY = 2019574
r = 733050, 2007150, 469500
c = 747086, 2019574, 492218
t = -2019574, 747086, 492218

Next reading:

calY = (( 2103450 - -12424) * 1024) >> 10
calY = ( 2115874 * 1024) >> 10
calY = -2128312320 >> 10
calY = -2078430
r = 745950, 2103450, 518400
c = 759986, -2078430, 541118
t = 2078430, 759986, 541118

Added trace

int MicroBitCompass::update()
{
  SERIAL_DEBUG->printf( "calY = (( %d - %d) * %d) >> 10\n", sampleENU.y, calibration.centre.y, calibration.scale.y);
  int calY = sampleENU.y - calibration.centre.y;
  SERIAL_DEBUG->printf( "calY = ( %d * %d) >> 10\n", calY, calibration.scale.y);
  calY = calY * calibration.scale.y;
  SERIAL_DEBUG->printf( "calY = %d >> 10\n", calY);
  calY = calY >> 10;
  SERIAL_DEBUG->printf( "calY = %d\n", calY);

    SERIAL_DEBUG->printf( "r = %d, %d, %d\n", sampleENU.x, sampleENU.y, sampleENU.z);
  
    // Store the raw data, and apply any calibration data we have.
    sampleENU.x = CALIBRATED_SAMPLE(sampleENU, x);
    sampleENU.y = CALIBRATED_SAMPLE(sampleENU, y);
    sampleENU.z = CALIBRATED_SAMPLE(sampleENU, z);

    SERIAL_DEBUG->printf( "c = %d, %d, %d\n", sampleENU.x, sampleENU.y, sampleENU.z);
  
    // Store the user accessible data, in the requested coordinate space, and taking into account component placement of the sensor.
    sample = coordinateSpace.transform(sampleENU);

    SERIAL_DEBUG->printf( "t = %d, %d, %d\n", sample.x, sample.y, sample.z);

    // Indicate that a new sample is available
    MicroBitEvent e(id, MICROBIT_COMPASS_EVT_DATA_UPDATE);

    return MICROBIT_OK;
};

@martinwork martinwork changed the title MicroBitMagnetometer service x, y, z data characteristic overflows Magnetometer x, y, z overflows in CALIBRATED_SAMPLE and BLE characteristics Oct 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants