commit d7e69aa47470080c4f28d57318af70ab10c75ba1
Author: Daniel Pérez <steew@psi.my.domain>
Date: Sun Jan 11 23:35:31 2026 +0000
diff --git a/fw/RustFM/src/main.rs b/fw/RustFM/src/main.rs
index 1499c5a..91aaeec 100644
--- a/fw/RustFM/src/main.rs
+++ b/fw/RustFM/src/main.rs
@@ -47 +411 @@
mod mpu;
mod rf;
+use embassy_sync::{blocking_mutex::raw::{CriticalSectionRawMutex, ThreadModeRawMutex}, rwlock::RwLock};
+use heapless::pool::arc::Arc;
use mpu::read_mpu;
+use mpu::BUFFERED_QUATERNIONS;
+use mpu6050_dmp::quaternion::Quaternion;
use rf::transmit;
use embassy_executor::Spawner;
@@ -177 +2112 @@ use embassy_stm32::{
};
+use embassy_sync::channel::Channel;
+use embassy_sync::blocking_mutex::raw::NoopRawMutex;
+
use embassy_time::Timer;
+use crate::mpu::{QuaternionDataBuffer, telemetry_sender};
+
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
@@ -616 +709 @@ async fn main(spawner: Spawner) {
+ // create shared channel between the MPU polling thread and the UART sender for the quaternion data buffer.
+ static QUATERNION_CHANNEL: Channel::<ThreadModeRawMutex, Quaternion, BUFFERED_QUATERNIONS> = Channel::<ThreadModeRawMutex, Quaternion, BUFFERED_QUATERNIONS>::new();
+
@@ -7311 +8516 @@ async fn main(spawner: Spawner) {
+ // dedicated task for the RF transmitter
+ // dedicated task for MPU data readings
- .spawn(read_mpu(iic, imu_int.into(), tmtry_uart.into()))
+ .spawn(read_mpu(iic, imu_int.into(), QUATERNION_CHANNEL.sender()))
-
+ // dedicated task for UART telemetry
+ spawner.spawn(telemetry_sender(tmtry_uart, QUATERNION_CHANNEL.receiver()));
+ // dedicated task for physical status leds
+ // TODO: replace with timer interrupt
diff --git a/fw/RustFM/src/mpu.rs b/fw/RustFM/src/mpu.rs
index dd6536a..05416f8 100644
--- a/fw/RustFM/src/mpu.rs
+++ b/fw/RustFM/src/mpu.rs
@@ -110 +113 @@
+use cortex_m::prelude::_embedded_hal_blocking_serial_Write;
use embassy_stm32::{
};
-use embassy_time::Delay;
+use embassy_sync::{blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex, ThreadModeRawMutex}, channel::{Channel, Receiver, Sender}, rwlock::RwLock};
+use embassy_time::{Delay, WithTimeout};
+use heapless::pool::arc::Arc;
use mpu6050_dmp::{
@@ -2631 +2951 @@ struct MotionState {
}
+pub const BUFFERED_QUATERNIONS: usize = 5;
+
+#[embassy_executor::task]
+pub async fn telemetry_sender(
+ mut telemetry_port: Uart<'static, Async>,
+ channel: Receiver<'static, ThreadModeRawMutex, Quaternion, BUFFERED_QUATERNIONS>,
+) {
+ loop {
+ // await until we receive a new quaternion packet from the sync channel
+ let next_quaternion_value = channel.receive().await;
+ // write the received values in the telemetry UART
+ // TODO: data synchronization for the receiver
+ telemetry_port.write(&next_quaternion_value.w.to_le_bytes()).await;
+ telemetry_port.write(&next_quaternion_value.x.to_le_bytes()).await;
+ telemetry_port.write(&next_quaternion_value.y.to_le_bytes()).await;
+ telemetry_port.write(&next_quaternion_value.z.to_le_bytes()).await;
+ }
+}
+
#[embassy_executor::task]
pub async fn read_mpu(
- tmtry: Uart<'static, Async>,
+ channel: Sender<'static, ThreadModeRawMutex, Quaternion, BUFFERED_QUATERNIONS>,
) {
+ // initialize the DMP processor for the MPU
+
- let calibration_params = CalibrationParameters::new(
- mpu6050_dmp::accel::AccelFullScale::G2,
- mpu6050_dmp::gyro::GyroFullScale::Deg2000,
- mpu6050_dmp::calibration::ReferenceGravity::ZN,
- );
-
+ // let _calibration_params = CalibrationParameters::new(
+ // mpu6050_dmp::accel::AccelFullScale::G2,
+ // mpu6050_dmp::gyro::GyroFullScale::Deg2000,
+ // mpu6050_dmp::calibration::ReferenceGravity::ZN,
+ // );
-
+
@@ -6148 +8425 @@ pub async fn read_mpu(
- let mut databuf_yaw: [f32; 10] = [0.0; 10];
- let mut databuf_pitch: [f32; 10] = [0.0; 10];
- let mut databuf_roll: [f32; 10] = [0.0; 10];
- let mut i = 0;
- mpu.interrupt_fifo_oflow_en().await.unwrap();
+ mpu.interrupt_data_ready_en().await.unwrap();
+
+ // block until we get an interrupt from the MPU line
- // info!("Received new data");
+ // read the combined data from the MPU fifo. It sends 28 byte packets, of which the first
+ // 16 are the quaternion data.
- // let accel = mpu.gyro().unwrap();
- // trace!("X: {}, Y: {}, Z: {}" , accel.x(), accel.y(),accel.z());
- // trace!("{}", fifo);
- let quat = Quaternion::from_bytes(&fifo[..16]).unwrap().normalize();
- let ypr = YawPitchRoll::from(quat);
- let yaw_deg = ypr.yaw * 180.0 / core::f32::consts::PI;
- let pitch_deg = ypr.pitch * 180.0 / core::f32::consts::PI;
- let roll_deg = ypr.roll * 180.0 / core::f32::consts::PI;
- // write the big endian repr of the sensor angles to UART for
- // plot representation in the telemetry receiving device.
- // let yaw_bytes = yaw_deg.to_ne_bytes();
- // let pitch_bytes = pitch_deg.to_ne_bytes();
- // let roll_bytes = roll_deg.to_ne_bytes();
-
- // tmtry.blocking_write(&yaw_bytes).unwrap();
- // tmtry.blocking_write(&pitch_bytes).unwrap();
- // tmtry.blocking_write(&roll_bytes).unwrap();
- // tmtry.write(&[255]).await.unwrap();
+ // obtain the first 16 quaternion packets
+ let quaternion_packet = Quaternion::from_bytes(&fifo[..16]).unwrap().normalize();
+ // send quaternion value to sync channel
+ channel.send(quaternion_packet);
- // info!(
- // " Angles [deg]: yaw={}, pitch={}, roll={}",
- // yaw_deg, pitch_deg, roll_deg
- // );
- info!(
- " Angles [quat]: w={}, x={}, y={}, z={}",
- quat.w, quat.x, quat.y, quat.z
- );
-
- mpu.interrupt_read_clear().await.unwrap();
+ // clear the pending interrupt and wait for the next
+ mpu.interrupt_read_clear().await.unwrap();
}