Magnitude

How strong is the Earth's magnetic field? According to the documentation about the magnetic_field() method the x y z values we are getting are in nanoteslas. That means the only thing we have to compute in order to get the magnitude of the magnetic field in nanoteslas is the magnitude of the 3D vector that our x y z values describe. As you might remember from school this is simply:

#![allow(unused)]
fn main() {
use libm::sqrtf;
let magnitude = sqrtf(x * x + y * y + z * z);
}

Rust does not have floating-point math functions such as sqrtf() in core, so our no_std program has to get an implementation from somewhere. We use the libm crate for this.

Putting all this together in a program (examples/magnitude.rs):

#![deny(unsafe_code)]
#![no_main]
#![no_std]

use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};

use libm::sqrtf;

use microbit::{
    hal::{twim, Timer},
    pac::twim0::frequency::FREQUENCY_A,
};

use lsm303agr::{Lsm303agr, MagMode, MagOutputDataRate};

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let board = microbit::Board::take().unwrap();

    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };

    let mut timer0 = Timer::new(board.TIMER0);

    let mut sensor = Lsm303agr::new_with_i2c(i2c);
    sensor.init().unwrap();
    sensor
        .set_mag_mode_and_odr(
            &mut timer0,
            MagMode::HighResolution,
            MagOutputDataRate::Hz10,
        )
        .unwrap();
    let mut sensor = sensor.into_mag_continuous().ok().unwrap();

    loop {
        while !sensor.mag_status().unwrap().xyz_new_data() {
            timer0.delay_ms(1u32);
        }
        let (x, y, z) = sensor.magnetic_field().unwrap().xyz_nt();
        let (x, y, z) = (x as f32, y as f32, z as f32);
        let magnitude = sqrtf(x * x + y * y + z * z);
        rprintln!("{} mG", magnitude / 100.0);
    }
}

Run this with cargo run --example magnitude.

This program will report the magnitude (strength) of the magnetic field in nanotesla (nT) and milligauss (mG, where 1 mG = 100 nT). The magnitude of the Earth's magnetic field is in the range of 250 mG to 650 mG (the magnitude varies depending on your geographical location) so you ideally would see a value vaguely in that range. Your value will likely be off quite a bit because the sensor has not been calibrated: see appendix 3 for calibration. With calibration, I see a magnitude of around 340 mG.

Some questions:

  • Without moving the board, what value do you see? Do you always see the same value?

  • If you rotate the board, does the magnitude change? Should it change?