got embassy compass outputting a heading number.
This commit is contained in:
parent
6f6660fd6a
commit
45578958a6
8 changed files with 103 additions and 76 deletions
|
@ -1,11 +1,4 @@
|
||||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=-Tlink.x",
|
|
||||||
"-C", "link-arg=-Tdefmt.x",
|
|
||||||
]
|
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "thumbv7em-none-eabihf"
|
target = "thumbv7em-none-eabihf"
|
||||||
|
|
||||||
[env]
|
|
||||||
DEFMT_LOG = "debug"
|
|
||||||
|
|
|
@ -8,3 +8,11 @@ opt-level = "z" # Optimize for size.
|
||||||
lto = true
|
lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
panic = "abort"
|
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" }
|
||||||
|
|
|
@ -5,16 +5,18 @@ authors = ["Gabriel Venberg"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[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"}
|
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"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/* NOTE K = KiBi = 1024 bytes */
|
/* NOTE K = KiBi = 1024 bytes */
|
||||||
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
|
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 16K
|
RAM : ORIGIN = 0x20000000, LENGTH = 16K
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,68 +2,87 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use core::cmp::max;
|
use core::f32::consts::PI;
|
||||||
use defmt::info;
|
use defmt::{debug, info};
|
||||||
use defmt_rtt as _;
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::join::join;
|
use embassy_time::Timer;
|
||||||
use embassy_nrf::{
|
use microbit_bsp::{
|
||||||
bind_interrupts,
|
Microbit,
|
||||||
gpio::{AnyPin, Input, Pin, Pull},
|
display::{Brightness, Frame},
|
||||||
temp::Temp,
|
embassy_nrf::{bind_interrupts, peripherals::TWISPI0, twim::InterruptHandler},
|
||||||
|
lsm303agr,
|
||||||
|
motion::new_lsm303agr,
|
||||||
};
|
};
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
use embassy_time::{Duration, Timer, WithTimeout};
|
|
||||||
use panic_probe as _;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
use independent_logic::{
|
||||||
enum Button {
|
heading_drawing::draw_constant_heading,
|
||||||
A,
|
line_drawing::{FourQuadrantMatrix, UPoint},
|
||||||
B,
|
tilt_compensation::{
|
||||||
}
|
Heading, NedMeasurement, calc_attitude, calc_tilt_calibrated_measurement,
|
||||||
|
heading_from_measurement,
|
||||||
static SIGNAL: Signal<CriticalSectionRawMutex, Button> = Signal::new();
|
},
|
||||||
|
};
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
TEMP => embassy_nrf::temp::InterruptHandler;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(_s: Spawner) {
|
||||||
info!("Starting");
|
let board = Microbit::default();
|
||||||
let p = embassy_nrf::init(Default::default());
|
defmt::info!("Application started!");
|
||||||
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 button(pin: AnyPin, id: &'static str, b: Button) {
|
let mut display = board.display;
|
||||||
let mut button = Input::new(pin, Pull::None);
|
display.set_brightness(Brightness::MAX);
|
||||||
loop {
|
|
||||||
button.wait_for_low().await;
|
|
||||||
info!("Button {} Pressed!", id);
|
|
||||||
SIGNAL.signal(b);
|
|
||||||
Timer::after_millis(200).await;
|
|
||||||
button.wait_for_high().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[embassy_executor::task]
|
// Bind interrupt to the TWI/SPI peripheral.
|
||||||
async fn temp_task(mut temp: Temp<'static>) {
|
bind_interrupts!(
|
||||||
const INTERVAL_MS: u64 = 500;
|
struct InterruptRequests {
|
||||||
let mut delay_ms = INTERVAL_MS;
|
TWISPI0 => InterruptHandler<TWISPI0>;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
independent_logic/.cargo/config.toml
Normal file
2
independent_logic/.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
target = "x86_64-unknown-linux-gnu"
|
|
@ -6,4 +6,5 @@ edition = "2024"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
defmt = "1.0.1"
|
||||||
libm = "0.2.1"
|
libm = "0.2.1"
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
use defmt::Format;
|
||||||
use libm::{atan2f, atanf, cosf, sinf};
|
use libm::{atan2f, atanf, cosf, sinf};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Format)]
|
||||||
pub struct Attitude {
|
pub struct Attitude {
|
||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
pub roll: f32,
|
pub roll: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Format)]
|
||||||
pub struct NedMeasurement {
|
pub struct NedMeasurement {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: 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
|
///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 struct Heading(pub f32);
|
||||||
|
|
||||||
pub fn calc_attitude(measurement: &NedMeasurement) -> Attitude {
|
pub fn calc_attitude(measurement: &NedMeasurement) -> Attitude {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue