Compass

We will read the direction from an I2C compass, and log the readings to a serial port. If you have time, try displaying it on the LEDs somehow too, or use the buttons somehow.

Hints:

  • Check the documentation for the lsm303agr and microbit-v2 crates, as well as the micro:bit hardware.
  • The LSM303AGR Inertial Measurement Unit is connected to the internal I2C bus.
  • TWI is another name for I2C, so the I2C master peripheral is called TWIM.
  • The LSM303AGR driver needs something implementing the embedded_hal::blocking::i2c::WriteRead trait. The microbit::hal::Twim struct implements this.
  • You have a microbit::Board struct with fields for the various pins and peripherals.
  • You can also look at the nRF52833 datasheet if you want, but it shouldn’t be necessary for this exercise.

Download the exercise template and look in the compass directory for the following files.

src/main.rs:

#![no_main]
#![no_std]

extern crate panic_halt as _;

use core::fmt::Write;
use cortex_m_rt::entry;
use microbit::{hal::uarte::{Baudrate, Parity, Uarte}, Board};

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

    // Configure serial port.
    let mut serial = Uarte::new(
        board.UARTE0,
        board.uart.into(),
        Parity::EXCLUDED,
        Baudrate::BAUD115200,
    );

    // Use the system timer as a delay provider.
    let mut delay = Delay::new(board.SYST);

    // Set up the I2C controller and Inertial Measurement Unit.
    // TODO

    writeln!(serial, "Ready.").unwrap();

    loop {
        // Read compass data and log it to the serial port.
        // TODO
    }
}

Cargo.toml (you shouldn’t need to change this):

[workspace]

[package]
name = "compass"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
cortex-m-rt = "0.7.3"
embedded-hal = "1.0.0"
lsm303agr = "1.0.0"
microbit-v2 = "0.14.0"
panic-halt = "0.2.0"

Embed.toml (you shouldn’t need to change this):

[default.general]
chip = "nrf52833_xxAA"

[debug.gdb]
enabled = true

[debug.reset]
halt_afterwards = true

.cargo/config.toml (you shouldn’t need to change this):

[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = ["-C", "link-arg=-Tlink.x"]

See the serial output on Linux with:

picocom --baud 115200 --imap lfcrlf /dev/ttyACM0

Or on Mac OS something like (the device name may be slightly different):

picocom --baud 115200 --imap lfcrlf /dev/tty.usbmodem14502

Use Ctrl+A Ctrl+Q to quit picocom.