got embassy compass outputting a heading number.

This commit is contained in:
Gabe Venberg 2025-07-08 17:22:26 +02:00
parent 6f6660fd6a
commit 45578958a6
8 changed files with 103 additions and 76 deletions

View file

@ -1,11 +1,4 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
]
[build]
target = "thumbv7em-none-eabihf"
[env]
DEFMT_LOG = "debug"

View file

@ -8,3 +8,11 @@ opt-level = "z" # Optimize for size.
lto = true
codegen-units = 1
panic = "abort"
[patch.crates-io]
embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }
embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }
embassy-nrf = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }
embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", rev = "f35aa4005a63e8d478b2b95aaa2bfb316b72dece" }

View file

@ -5,16 +5,18 @@ authors = ["Gabriel Venberg"]
edition = "2024"
[dependencies]
cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.5"
defmt = "1.0.1"
defmt-rtt = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["arch-cortex-m", "executor-thread", "defmt"] }
embassy-nrf = { version = "0.3.1", features = ["defmt", "nrf52833", "gpiote", "time-driver-rtc1", "time"] }
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime"] }
lsm303agr = { version = "1.1.0", features = ["async"] }
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
independent_logic = {path="../independent_logic"}
embassy-futures = { version = "0.1.1", features = ["defmt"] }
embassy-sync = { version = "0.7.0", features = ["defmt"] }
cortex-m = { version = "0.7", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "1.0"
defmt-rtt = "1.0"
panic-probe = { version = "1.0", features = ["print-defmt"] }
embassy-executor = { version = "0.7", features = ["arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.4", features = ["defmt", "defmt-timestamp-uptime"] }
embassy-futures = { version = "0.1", features = ["defmt"] }
embassy-sync = { version = "0.7", features = ["defmt"] }
microbit-bsp = { git = "https://github.com/lulf/microbit-bsp.git", rev = "19d555bfbbcfa39db6aac467673386662c39e299" }
libm = "0.2.15"

View file

@ -1,6 +1,6 @@
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 16K
}

View file

@ -2,68 +2,87 @@
#![no_main]
#![no_std]
use core::cmp::max;
use defmt::info;
use defmt_rtt as _;
use core::f32::consts::PI;
use defmt::{debug, info};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_nrf::{
bind_interrupts,
gpio::{AnyPin, Input, Pin, Pull},
temp::Temp,
use embassy_time::Timer;
use microbit_bsp::{
Microbit,
display::{Brightness, Frame},
embassy_nrf::{bind_interrupts, peripherals::TWISPI0, twim::InterruptHandler},
lsm303agr,
motion::new_lsm303agr,
};
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
use embassy_time::{Duration, Timer, WithTimeout};
use panic_probe as _;
use {defmt_rtt as _, panic_probe as _};
#[derive(Debug, Clone, Copy)]
enum Button {
A,
B,
}
static SIGNAL: Signal<CriticalSectionRawMutex, Button> = Signal::new();
bind_interrupts!(struct Irqs {
TEMP => embassy_nrf::temp::InterruptHandler;
});
use independent_logic::{
heading_drawing::draw_constant_heading,
line_drawing::{FourQuadrantMatrix, UPoint},
tilt_compensation::{
Heading, NedMeasurement, calc_attitude, calc_tilt_calibrated_measurement,
heading_from_measurement,
},
};
#[embassy_executor::main]
async fn main(spawner: Spawner) {
info!("Starting");
let p = embassy_nrf::init(Default::default());
let temp = Temp::new(p.TEMP, Irqs);
spawner.spawn(temp_task(temp)).unwrap();
let button_a = button(p.P0_14.degrade(), "A", Button::A);
let button_b = button(p.P0_23.degrade(), "B", Button::B);
join(button_a, button_b).await;
}
async fn main(_s: Spawner) {
let board = Microbit::default();
defmt::info!("Application started!");
async fn button(pin: AnyPin, id: &'static str, b: Button) {
let mut button = Input::new(pin, Pull::None);
loop {
button.wait_for_low().await;
info!("Button {} Pressed!", id);
SIGNAL.signal(b);
Timer::after_millis(200).await;
button.wait_for_high().await;
}
}
let mut display = board.display;
display.set_brightness(Brightness::MAX);
#[embassy_executor::task]
async fn temp_task(mut temp: Temp<'static>) {
const INTERVAL_MS: u64 = 500;
let mut delay_ms = INTERVAL_MS;
loop {
let value: u16 = temp.read().await.to_num();
info!("{} C", value);
let delay = Duration::from_millis(delay_ms);
if let Ok(v) = SIGNAL.wait().with_timeout(delay).await {
delay_ms = match v {
Button::A => max(INTERVAL_MS, delay_ms.saturating_sub(INTERVAL_MS)),
Button::B => delay_ms + INTERVAL_MS,
};
info!("Delay = {} ms", delay_ms);
// Bind interrupt to the TWI/SPI peripheral.
bind_interrupts!(
struct InterruptRequests {
TWISPI0 => InterruptHandler<TWISPI0>;
}
);
let irqs = InterruptRequests {};
let mut sensor = new_lsm303agr(board.twispi0, irqs, board.i2c_int_sda, board.i2c_int_scl);
sensor.init().await.unwrap();
sensor.enable_mag_offset_cancellation().await.unwrap();
sensor
.set_mag_mode_and_odr(
&mut embassy_time::Delay,
lsm303agr::MagMode::HighResolution,
lsm303agr::MagOutputDataRate::Hz50,
)
.await
.unwrap();
let Ok(mut sensor) = sensor.into_mag_continuous().await else {
panic!("Failed to set sensor to continuous mode");
};
sensor
.set_accel_mode_and_odr(
&mut embassy_time::Delay,
lsm303agr::AccelMode::Normal,
lsm303agr::AccelOutputDataRate::Hz50,
)
.await
.unwrap();
Timer::after_secs(2).await;
loop {
let (x, y, z) = sensor.magnetic_field().await.unwrap().xyz_nt();
let mag_measurement = to_ned(x, y, z);
let (x, y, z) = sensor.acceleration().await.unwrap().xyz_mg();
let accel_measurement = to_ned(x, y, z);
debug!("Mag: {}, Accel: {}", mag_measurement, accel_measurement);
Timer::after_millis(250).await;
let attitude = calc_attitude(&accel_measurement);
let mag_measurement = calc_tilt_calibrated_measurement(mag_measurement, &attitude);
let heading = heading_from_measurement(&mag_measurement);
debug!("Attitude: {}, Heading: {}", attitude, heading.0*(180.0/PI));
}
}
pub fn to_ned(x: i32, y: i32, z: i32) -> NedMeasurement {
NedMeasurement {
x: -y as f32,
y: x as f32,
z: -z as f32,
}
}

View file

@ -0,0 +1,2 @@
[build]
target = "x86_64-unknown-linux-gnu"

View file

@ -6,4 +6,5 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
defmt = "1.0.1"
libm = "0.2.1"

View file

@ -1,12 +1,13 @@
use defmt::Format;
use libm::{atan2f, atanf, cosf, sinf};
#[derive(Debug)]
#[derive(Debug, Format)]
pub struct Attitude {
pub pitch: f32,
pub roll: f32,
}
#[derive(Debug)]
#[derive(Debug, Format)]
pub struct NedMeasurement {
pub x: f32,
pub y: f32,
@ -14,6 +15,7 @@ pub struct NedMeasurement {
}
///theta=0 at north, pi/-pi at south, pi/2 at east, and -pi/2 at west
#[derive(Debug, Format)]
pub struct Heading(pub f32);
pub fn calc_attitude(measurement: &NedMeasurement) -> Attitude {