MAG3110 3-axis magnetometer

MAG3110

The MAG3110 from NXP/Freescale is a small, low-power, digital 3-axis magnetometer with a wide dynamic range to allow operation in PCBs with high extraneous magnetic fields. The MAG3110:

  • Features a standard I2C serial interface.
  • is capable of measuring local magnetic fields up to 10 Gauss with output data rates up to 80 Hz (12.5ms).
  • Measures the components of the local magnetic field, the sum of the geomagnetic field and the magnetic field created by components on the circuit board
  • Can be used in conjunction with a 3-axis accelerometer so that orientation-independent accurate compass heading information may be achieved

The sensor is build into the BBC micro:bit.

Use the MAG3110 (About Modules) module for it.

Wiring

You can use any I2C port, e.g. I2C1:

Device Pin Espruino
GND GND
VCC 3.3
SDA B7 Don't forget I²C pullup if not available on the breakout.
SCL B6 Don't forget I²C pullup if not available on the breakout.
INT A8 Any input pin (connection not required), see section Timing

It's not required to connect INT but is useful if you want to be notified when a new measurement value is available. A transition from 0 to 1 indicates the presence of new measurement data.

Usecases

Initialisiation

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

There exists a similar sensor with a different part number FXMS3110CDR1 with different I2C slave address 0x0f

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1, { address: 0x0f } );

Operation Modes

MAG3110 supports three operation modes:

  • 0 → Standby … very less power consumption; no measuring, but last measurement still readable
  • 1 → Active (RAW data) … measuring and getting the raw sensor values
  • 2 → Active (Offset-corrected data) … measuring and reading the raw sensor values subtracted be a previously configured offset
I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );
console.log( mag.getMode() ); // outputs 0 = standby (default after power-up)
mag.setMode( 1 ); // bring sensor in Active/Raw-mode → sensor begins to measure
console.log( mag.getMode() ); // outputs 1 (active/raw)

Reading magnetic value

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

// We are in standby mode → read() will return always the same value.
console.log( mag.read() ); // outputs { "x": 0, "y": 0, "z": 0 }
console.log( mag.read() ); // outputs { "x": 0, "y": 0, "z": 0 }

// Switching to raw mode → Rotating the sensor position will result in different measurement. 
mag.setMode( 1 );
console.log( mag.read() ); // outputs { "x": -130, "y": 346, "z": 743 }
console.log( mag.read() ); // outputs { "x": -125, "y": 334, "z": 735 }

// Offset-corrected mode will return nearly the same result because didn't configured any offset.
mag.setMode( 2 ); 
console.log( mag.read() ); // outputs { "x": -123, "y": 341, "z": 730 }

Using offset-corrected mode

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

// Configuring offset is only possible in standby mode!
mag.setOffset( { x : -123, y: 341, z: 730 } );
mag.setMode( 2 ); // offset-corrected mode

console.log( mag.read() ); // outputs { "x": -2, "y": 6, "z": 3 }

// For comparison
mag.setMode( 1 ); // raw mode
console.log( mag.read() ); // outputs { "x": -125, "y": 341, "z": 735 }

Measuring in standby mode

The sensor is not measuring in standby mode but you can trigger one explicit measurment cycle in standby mode.

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

// We are in standby mode after POR, otherwise use setMode(0)
console.log( mag.read() );    // outputs { "x": 0, "y": 0, "z": 0 }

mag.triggerMeasurement();
console.log( mag.read() );    // outputs { "x": -123, "y": 346, "z": 726 }
console.log( mag.getMode() ); // 0 - We are still in standby mode.

Customize sampling parameters

The sensor can work with different ADC Rate. More ADC Rate means higher power consumption but higher output rate. The Over Sample Ratio is the number of samples which will be averaged before a new measurement is available.

Sampling Output Rate Over Sample Ratio Current
0 80.00 Hz 16 900.0 µA
1 40.00 Hz 32 900.0 µA
2 20.00 Hz 64 900.0 µA
3 10.00 Hz 128 900.0 µA
4 40.00 Hz 16 550.0 µA
5 20.00 Hz 32 550.0 µA
6 10.00 Hz 64 550.0 µA
7 5.00 Hz 128 550.0 µA
8 20.00 Hz 16 275.0 µA
9 10.00 Hz 32 275.0 µA
10 5.00 Hz 64 275.0 µA
11 2.50 Hz 128 275.0 µA
12 10.00 Hz 16 137.5 µA
13 5.00 Hz 32 137.5 µA
14 2.50 Hz 64 137.5 µA
15 1.25 Hz 128 137.5 µA
16 5.00 Hz 16 68.8 µA
17 2.50 Hz 32 68.8 µA
18 1.25 Hz 64 68.8 µA
19 0.63 Hz 128 68.8 µA
20 2.50 Hz 16 34.4 µA
21 1.25 Hz 32 34.4 µA
22 0.63 Hz 64 34.4 µA
23 0.31 Hz 128 34.4 µA
24 1.25 Hz 16 17.2 µA
25 0.63 Hz 32 17.2 µA
26 0.31 Hz 64 17.2 µA
27 0.16 Hz 128 17.2 µA
28 0.63 Hz 16 8.6 µA
29 0.31 Hz 32 8.6 µA
30 0.16 Hz 64 8.6 µA
31 0.08 Hz 128 8.6 µA
I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

// Default is sample = 0
console.log( mag.getSamplingParams() ); // → 0

mag.setSamplingParams( 11 ); // 4 Measurements per second
console.log( mag.getSamplingParams() ); // → 11

mag.read(); // Over Sample Ratio = 128 → Results are smoother.

Timing

It's alway possible to read the last measured data but sometimes you want to know whether new data is available or not.

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

mag.setMode( 0 ); // standby mode
mag.setSamplingParams( 31 ); // low power consumption (8.6µA) but 12 seconds (0.08 Hz) per measurement 

console.log( mag.isNewDataAvailable() ); // → false
mag.setMode(1); // raw mode + start measuring
var start = getTime();
setInterval( function() {
    if (mag.isNewDataAvailable()) {
        mag.read(); // reading the measurement will reset the "new data available" flag
        console.log( "New data available after " + (getTime()-start).toFixed(1) + " seconds" );
    }
}, 300 );

This program snippet will output:

New data available after 1.8 seconds
New data available after 13.5 seconds
New data available after 25.2 seconds
New data available after 36.9 seconds
New data available after 48.6 seconds

Bug? The first availability after 1.8 seconds looks like a sensor bug. Maybe NXP/Freescale can explain the behavior?

Instead of pooling you can use the INT pin to detect new data. Assuming INT is connected with A8 the same program looks like:

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );

mag.setMode( 0 ); // standby mode
mag.setSamplingParams( 31 ); // low power consumption (8.6µA) but 12 seconds (0.08 Hz) per measurement 

console.log( mag.isNewDataAvailable() ); // → false
mag.setMode(1); // raw mode + start measuring
var start = getTime();

setWatch( function() {
    mag.read(); // reading the measurement will reset the "new data available" flag
    console.log( "New data available after " + (getTime()-start).toFixed(1) + " seconds" );
}, A8, { repeat: true, edge: 'rising' } );

A transition from 0 to 1 on INT indicates the presence of new measurement data.

Magnetic Reset

A magnetic reset is required after exposure to an excessive magnetic field which exceeds the Full Scale Range of +/-1000µT, e.g. near a speaker magnet. There are two possibilities: manual magnetic sensor reset (One-Shot) or automatic magnetic reset before each data acquisition.

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );
mag.magneticReset(); // one manual magnetic reset after por

Another option is to enable automatic magentic sensor reset:

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );
mag.setAutomaticMagneticReset( true );

Measuring Temperature

It's possible to measure the dia temperature of the MAG3110. This is used internally for removing temperature dependency. The sensitivity of the temperature is 1°C/LSB but the offset is not factory trimmed, e.g. my sensor say -7°C while 21°C in reality.

I2C1.setup( { scl: B6, sda: B7 } );
var mag = require('MAG3110').connect( I2C1 );
mag.setMode( 1 ); // Measuring only works in the active modes - also for temperature 

console.log( "Temperature = " + mag.readTemperature() + " °C" ); // → -7 °C

Buying

Alternatives

Reference

/* Read the current operation mode from the sensor
 * The sensor is in standby operation mode after power on reset.
 * 0 .. standby
 * 1 .. active (RAW data)
 * 2 .. active (offset-corrected data)
 * @returns {number}
 */
MAG3110.prototype.getMode = function () { ... }

/* Write the new operation mode to the sensor.
 * If you change into an active mode (raw or offset-corrected) then the automatic magnetic sensor reset will be disabled.
 * You have to enable this flag by calling setAutomaticMagneticReset(true) if required.
 * @param mode new operation mode
 *  0 .. standby
 *  1 .. active (RAW data)
 *  2 .. active (offset-corrected data)
 */
MAG3110.prototype.setMode = function (mode) { ... }

/* Read the last measurement value from the sensor
 * The complements x,y and z from the different axis are in the range of
 * -30000 to +30000.
 * If the operation mode is 2 (active/offset-corrected data) the result
 * is the raw sensor data minus the configured offset.
 * If the operation mode is 1 (active/raw data) the configured offset will be ignored.
 * @returns {{x: number, y: number, z: number}}
 */
MAG3110.prototype.read = function () { ... }

/* Read the user offsets of the x-,y- and z-axis which are automatically subtracted
 * by the MAG3110 if the sensor is in active-mode with offset-corrected data (mode = 2).
 * Possible values are in the range from -10000 to +10000.
 * After POR all values are 0.
 * @returns {{x: number, y: number, z: number}} offset vector
 */
MAG3110.prototype.getOffset = function () { ... }

/* Write new user offsets of the x, y and z-axis into the sensor
 * The values are not persistent (no EEPROM) and are lost after power down.
 * @param offset {{x: number, y: number, z: number}} new offset vector
 */
MAG3110.prototype.setOffset = function (offset) { ... }

/* Starts one measurement in standby operation mode.
 * In standby mode triggered measurement will occur immediately and part will return to standby mode
 * as soon as the measurement is complete. The method can only be call in standby operation mode.
 * The sampling parameters will be set to 0 (max. OutputRate).
 */
MAG3110.prototype.triggerMeasurement = function () { ... }

/* Returns whether a new measurement available
 * @returns {boolean}
 */
MAG3110.prototype.isNewDataAvailable = function () { ... }

/* Change the over-sampling ratio and the data rate of the sensor. Possible values are  in the range from 0 to 31.
 * 0: OutputRate: 80.00 Hz, Over Sample Ratio: 16, ADC Rate: 1280 Hz, Current: 900µA
 * 1: OutputRate: 40.00 Hz, ...
 * @param sampling Parameter index in the range from 0 to 31.
 */
MAG3110.prototype.setSamplingParams = function (sampling) { ... }

/* Read the configured over-sampling ratio and data rate
 * Possible values are in the range 0 to 31.
 * See setSamplingParams(..) for more details.
 * @returns {number}
 */
MAG3110.prototype.getSamplingParams = function () { ... }

/* Read the die temperature in °C in the range from -40°C to 125°C.
 * The temperature data is updated on every measurement cycle.
 * The sensitivity of the temperature sensor is factory trimmed to 1°C but the absolute offset is NOT calibrated.
 * It must be calibrated by the user software if absolute accuracy is required.
 * @returns {number} temperatur in °C
 */
MAG3110.prototype.readTemperature = function () { ... }

/* Performs a manual magnetic sensor reset (One-Shot).
 * Initiates a magnetic sensor reset cycle that will restore correct operation after exposure to an excessive magnetic
 * field wich exceeds the Full Scale Range of +/-1000µT, e.g. near a speaker magnet.
 */
MAG3110.prototype.magneticReset = function () { ... }

/* Set the automatic magentic reset flag.
 * If set the magnetic resets occur automatically before each data acquisition. If unset no automatic reset occurs.
 * The default value after power on reset is false (no automatic magnetic reset).
 * @param automatic true, if automatic magnetic reset before each measurement
 */
MAG3110.prototype.setAutomaticMagneticReset = function (automatic) { ... }

// Internal API: Read one byte from register reg
MAG3110.prototype.read8 = function (reg) { ... }

// Internal API: Write one byte value to register reg
MAG3110.prototype.write8 = function (reg, value) { ... }

exports.connect = function (i2c, options) { ... }

This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.