Skip to content

Commit

Permalink
fix(eclssd): attempt to fix inaccurate delays
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkw committed Jun 9, 2024
1 parent 7156f2e commit 996a325
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 14 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ reqwest = { version = "0.12.4", default-features = false }
scd4x = { version = "0.3.0", default-features = false }
sgp30 = { version = "0.4.0", default-features = false }
serde = { version = "1.0", default-features = false }
spin_sleep = { version = "1.2.0" }

[patch.crates-io]
bosch-bme680 = { git = "https://github.com/hawkw/bosch-bme680", branch = "eliza/async" }
Expand Down
1 change: 1 addition & 0 deletions eclssd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ hostname = { workspace = true, optional = true }
linux-embedded-hal = { workspace = true, features = ["i2c", "async-tokio"] }
local-ip-address = { workspace = true, optional = true }
mdns-sd = { workspace = true, optional = true }
spin_sleep = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }

Expand Down
37 changes: 23 additions & 14 deletions eclssd/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ use anyhow::Context;
use clap::Parser;
use eclss::sensor::{self};
use eclss_app::TraceArgs;
use embedded_hal::{
delay::DelayNs as BlockingDelayNs,
i2c::{self, I2c as BlockingI2c},
};
use embedded_hal::i2c::{self, I2c as BlockingI2c};
use embedded_hal_async::{delay::DelayNs, i2c::I2c};
use linux_embedded_hal::I2cdev;
use std::path::PathBuf;
use std::time::Duration;

#[cfg(feature = "mdns")]
mod mdns;
Expand Down Expand Up @@ -102,15 +100,15 @@ async fn main() -> anyhow::Result<()> {
async move {
tracing::info!("starting PMSA003I...");
eclss
.run_sensor(sensor, backoff, linux_embedded_hal::Delay)
.run_sensor(sensor, backoff, GoodDelay::default())
.await
.unwrap()
}
});

#[cfg(any(feature = "scd41", feature = "scd40"))]
sensors.spawn({
let sensor = sensor::Scd4x::new(eclss, AsyncBlockingDelayNs(linux_embedded_hal::Delay));
let sensor = sensor::Scd4x::new(eclss, GoodDelay::default());

let backoff = backoff.clone();
async move {
Expand All @@ -124,7 +122,7 @@ async fn main() -> anyhow::Result<()> {

#[cfg(feature = "sgp30")]
sensors.spawn({
let sensor = sensor::Sgp30::new(eclss, AsyncBlockingDelayNs(linux_embedded_hal::Delay));
let sensor = sensor::Sgp30::new(eclss, GoodDelay::default());

let backoff = backoff.clone();
async move {
Expand All @@ -138,26 +136,26 @@ async fn main() -> anyhow::Result<()> {

#[cfg(feature = "ens160")]
sensors.spawn({
let sensor = sensor::Ens160::new(eclss, linux_embedded_hal::Delay);
let sensor = sensor::Ens160::new(eclss, GoodDelay::default());

let backoff = backoff.clone();
async move {
tracing::info!("starting ENS160...");
eclss
.run_sensor(sensor, backoff.clone(), linux_embedded_hal::Delay)
.run_sensor(sensor, backoff.clone(), GoodDelay::default())
.await
.unwrap()
}
});

#[cfg(feature = "bme680")]
sensors.spawn({
let sensor = sensor::Bme680::new(eclss, AsyncBlockingDelayNs(linux_embedded_hal::Delay));
let sensor = sensor::Bme680::new(eclss, GoodDelay::default());
let backoff = backoff.clone();
async move {
tracing::info!("starting BME680...");
eclss
.run_sensor(sensor, backoff, linux_embedded_hal::Delay)
.run_sensor(sensor, backoff, GoodDelay::default())
.await
.unwrap()
}
Expand Down Expand Up @@ -213,10 +211,21 @@ where
/// type is not very precise. Use blocking delays for short sleeps in timing
/// critical sensor wire protocols, and use the async delay for longer sleeps
/// like in the poll loop.
struct AsyncBlockingDelayNs<D>(D);
#[derive(Default)]
struct GoodDelay(spin_sleep::SpinSleeper);
impl GoodDelay {
const ONE_MS_NANOS: u64 = Duration::from_millis(1).as_nanos() as u64;
}

impl<D: BlockingDelayNs> DelayNs for AsyncBlockingDelayNs<D> {
impl DelayNs for GoodDelay {
async fn delay_ns(&mut self, ns: u32) {
self.0.delay_ns(ns);
let mut ns = ns as u64;
let ms = ns % Self::ONE_MS_NANOS;
if ms > 0 {
tokio::time::sleep(Duration::from_millis(ms)).await;
ns -= ms * Self::ONE_MS_NANOS;
}

self.0.sleep_ns(ns);
}
}

0 comments on commit 996a325

Please sign in to comment.