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