nonsense, nothing is fixed
This commit is contained in:
@@ -150,14 +150,23 @@ async fn main(spawner: Spawner) -> ! {
|
||||
match select3(
|
||||
mqtt_rx.receive(),
|
||||
imu_rx.receive(),
|
||||
Timer::after(Duration::from_secs(30)),
|
||||
Timer::after(Duration::from_secs(5)),
|
||||
).await {
|
||||
Either3::First(msg) => {
|
||||
mqtt_msg_count += 1;
|
||||
handle_mqtt_message(msg).await;
|
||||
display::api::set_mqtt_status(true, mqtt_msg_count).await;
|
||||
}
|
||||
Either3::Second(reading) => {
|
||||
Either3::Second(mut reading) => {
|
||||
// Drain any queued IMU messages and keep only the latest
|
||||
let mut drained = 0;
|
||||
while let Ok(next) = imu_rx.try_receive() {
|
||||
reading = next;
|
||||
drained += 1;
|
||||
}
|
||||
if drained > 0 {
|
||||
log::info!("IMU drained {} stale readings before display", drained);
|
||||
}
|
||||
imu_reading_count += 1;
|
||||
display::api::show_imu(reading).await;
|
||||
if imu_reading_count % MQTT_PUBLISH_DIVIDER == 0 {
|
||||
@@ -169,7 +178,9 @@ async fn main(spawner: Spawner) -> ! {
|
||||
}
|
||||
}
|
||||
Either3::Third(_) => {
|
||||
info!("Heartbeat: {} IMU readings", imu_reading_count);
|
||||
crate::mpu::api::IMU_CHANNEL.clear();
|
||||
info!("IMU heartbeat: force-cleared queue, {} readings total", imu_reading_count);
|
||||
// info!("Heartbeat: {} IMU readings", imu_reading_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,7 +270,6 @@ async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn button_detection_task(mut select_btn: Input<'static>, mut next_btn: Input<'static>) {
|
||||
use embassy_futures::select::Either;
|
||||
loop {
|
||||
match select(
|
||||
select_btn.wait_for_rising_edge(),
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// src/bus/mod.rs
|
||||
|
||||
use core::cell::RefCell;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embedded_hal_bus::i2c::RefCellDevice;
|
||||
use esp_hal::i2c::master::I2c;
|
||||
use esp_hal::Async;
|
||||
|
||||
@@ -136,8 +136,7 @@ impl Component for Screen {
|
||||
}
|
||||
}
|
||||
|
||||
// ============ PAGE ORDER ============
|
||||
|
||||
// PAGE ORDER
|
||||
const PAGE_ORDER: &[&str] = &["menu", "imu", "chat"];
|
||||
|
||||
pub fn next_page_id(current: &str) -> &'static str {
|
||||
@@ -150,9 +149,7 @@ pub fn prev_page_id(current: &str) -> &'static str {
|
||||
if idx == 0 { PAGE_ORDER[PAGE_ORDER.len() - 1] } else { PAGE_ORDER[idx - 1] }
|
||||
}
|
||||
|
||||
// ============ RENDERING - NO LAYOUT, DIRECT RECTS ============
|
||||
// 128x32 display = 21 chars x 4 rows (6x8 font)
|
||||
|
||||
// RENDERING
|
||||
/// Get row rect (0-3) for 128x32 display
|
||||
#[inline]
|
||||
fn row(area: Rect, n: u16) -> Rect {
|
||||
@@ -169,7 +166,7 @@ pub fn render_frame<B: ratatui::backend::Backend>(
|
||||
let area = f.area();
|
||||
|
||||
if let Some(ref err) = state.last_error {
|
||||
f.render_widget(Paragraph::new(format!("ERR:{}", err.as_str())).red().bold(), area);
|
||||
f.render_widget(Paragraph::new(format!("ERR:{}", err.as_str())).white().bold(), area);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -209,10 +206,10 @@ fn render_menu(f: &mut ratatui::Frame, area: Rect, focused: Option<&PageFocus>,
|
||||
fn render_imu(f: &mut ratatui::Frame, area: Rect, focused: Option<&PageFocus>, state: &DisplayState) {
|
||||
if let Some(ref imu) = state.last_imu {
|
||||
// Row 0 Gyro
|
||||
// f.render_widget(
|
||||
// Paragraph::new(format!("G:{:+5.0}{:+5.0}{:+5.0}", imu.gyro_dps[0], imu.gyro_dps[1], imu.gyro_dps[2])).cyan(),
|
||||
// row(area, 0),
|
||||
// );
|
||||
f.render_widget(
|
||||
Paragraph::new(format!("G:{:+5.0}{:+5.0}{:+5.0}", imu.gyro_dps[0], imu.gyro_dps[1], imu.gyro_dps[2])).cyan(),
|
||||
row(area, 0),
|
||||
);
|
||||
// Row 1 Accel
|
||||
f.render_widget(
|
||||
Paragraph::new(format!("A:{:+.1} {:+.1} {:+.1}", imu.accel_g[0], imu.accel_g[1], imu.accel_g[2])).green(),
|
||||
@@ -228,7 +225,7 @@ fn render_imu(f: &mut ratatui::Frame, area: Rect, focused: Option<&PageFocus>, s
|
||||
}
|
||||
|
||||
// Row 3 Nav bar
|
||||
render_nav_bar(f, row(area, 2), focused);
|
||||
// render_nav_bar(f, row(area, 3), focused);
|
||||
}
|
||||
|
||||
fn render_chat(f: &mut ratatui::Frame, area: Rect, focused: Option<&PageFocus>, state: &DisplayState) {
|
||||
@@ -245,7 +242,7 @@ fn render_chat(f: &mut ratatui::Frame, area: Rect, focused: Option<&PageFocus>,
|
||||
}
|
||||
|
||||
// Row 3 Nav bar
|
||||
render_nav_bar(f, row(area, 3), focused);
|
||||
render_nav_bar(f, row(area, 2), focused);
|
||||
}
|
||||
|
||||
/// Nav bar: --[<]-------[>]--
|
||||
|
||||
@@ -4,9 +4,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::channel::{Channel, Receiver, Sender};
|
||||
use crate::contracts::ImuReading;
|
||||
|
||||
const QUEUE_SIZE: usize = 4;
|
||||
const QUEUE_SIZE: usize = 16;
|
||||
|
||||
pub(crate) static IMU_CHANNEL: Channel<CriticalSectionRawMutex, ImuReading, QUEUE_SIZE> = Channel::new();
|
||||
pub static IMU_CHANNEL: Channel<CriticalSectionRawMutex, ImuReading, QUEUE_SIZE> = Channel::new();
|
||||
|
||||
pub fn events() -> Receiver<'static, CriticalSectionRawMutex, ImuReading, QUEUE_SIZE> {
|
||||
IMU_CHANNEL.receiver()
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::mpu::api::sender;
|
||||
use crate::mpu::driver::Mpu6050;
|
||||
|
||||
/// Sampling interval in milliseconds.
|
||||
/// 50ms = 20Hz, reasonable for display updates.
|
||||
/// 50ms = 20Hz
|
||||
const SAMPLE_INTERVAL_MS: u64 = 50;
|
||||
|
||||
/// MPU6050 I2C address (0x68 with AD0 low, 0x69 with AD0 high)
|
||||
@@ -52,7 +52,7 @@ pub async fn mpu_task(i2c: I2cDevice) {
|
||||
Timer::after(Duration::from_secs(2)).await;
|
||||
continue;
|
||||
}
|
||||
Err(_e) => {
|
||||
Err(_) => {
|
||||
warn!(
|
||||
"I2C error verifying MPU6050 (attempt {})",
|
||||
init_attempts
|
||||
@@ -68,7 +68,7 @@ pub async fn mpu_task(i2c: I2cDevice) {
|
||||
info!("MPU6050 initialized successfully");
|
||||
break;
|
||||
}
|
||||
Err(_e) => {
|
||||
Err(_) => {
|
||||
error!("MPU6050 init failed (attempt {})", init_attempts);
|
||||
Timer::after(Duration::from_secs(2)).await;
|
||||
continue;
|
||||
@@ -78,11 +78,14 @@ pub async fn mpu_task(i2c: I2cDevice) {
|
||||
|
||||
// Allow sensor to stabilize after wake-up
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
|
||||
info!("MPU task entering sampling loop ({}ms interval)", SAMPLE_INTERVAL_MS);
|
||||
info!(
|
||||
"MPU task entering sampling loop ({}ms interval)",
|
||||
SAMPLE_INTERVAL_MS
|
||||
);
|
||||
|
||||
let tx = sender();
|
||||
let mut consecutive_errors = 0u32;
|
||||
let mut sent_count: u32 = 0;
|
||||
|
||||
loop {
|
||||
let start = Instant::now();
|
||||
@@ -98,13 +101,20 @@ pub async fn mpu_task(i2c: I2cDevice) {
|
||||
timestamp_ms: start.as_millis(),
|
||||
};
|
||||
|
||||
// Try to send; if queue is full, drop oldest by using try_send
|
||||
// This ensures we never block the sampling loop
|
||||
if tx.try_send(reading).is_err() {
|
||||
// Queue full - that's okay, main will get the next one
|
||||
sent_count = sent_count.wrapping_add(1);
|
||||
if tx.try_send(reading).is_ok() {
|
||||
if sent_count % 20 == 0 {
|
||||
info!(
|
||||
"IMU send#{} ax:{:.2} ay:{:.2} az:{:.2} t:{:.1}",
|
||||
sent_count, accel_g[0], accel_g[1], accel_g[2], temp_c
|
||||
);
|
||||
}
|
||||
} else if sent_count % 20 == 0 {
|
||||
info!("IMU drop: channel full ({} sent)", sent_count);
|
||||
}
|
||||
}
|
||||
Err(_e) => {
|
||||
|
||||
Err(_) => {
|
||||
consecutive_errors += 1;
|
||||
if consecutive_errors == 1 || consecutive_errors % 10 == 0 {
|
||||
warn!("MPU read error (consecutive: {})", consecutive_errors);
|
||||
@@ -122,7 +132,7 @@ pub async fn mpu_task(i2c: I2cDevice) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sleep for remainder of interval
|
||||
// Maintain a steady period
|
||||
let elapsed = start.elapsed();
|
||||
let target = Duration::from_millis(SAMPLE_INTERVAL_MS);
|
||||
if elapsed < target {
|
||||
|
||||
Reference in New Issue
Block a user