Poll example
This commit is contained in:
@ -101,15 +101,15 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
let inputs = &*ANALOG_INPUTS.init(Inputs {
|
let inputs = &*ANALOG_INPUTS.init(Inputs {
|
||||||
ai1: StatefulPublisher::new(
|
ai1: StatefulPublisher::new(
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
PubSubChannel::new().into(),
|
PubSubChannel::new().into(),
|
||||||
),
|
),
|
||||||
ai2: StatefulPublisher::new(
|
ai2: StatefulPublisher::new(
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
PubSubChannel::new().into(),
|
PubSubChannel::new().into(),
|
||||||
),
|
),
|
||||||
ai3: StatefulPublisher::new(
|
ai3: StatefulPublisher::new(
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
PubSubChannel::new().into(),
|
PubSubChannel::new().into(),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
@ -10,12 +10,12 @@ use {defmt_rtt as _, panic_probe as _};
|
|||||||
|
|
||||||
use {embassy_executor as executor, embassy_stm32 as stm32};
|
use {embassy_executor as executor, embassy_stm32 as stm32};
|
||||||
|
|
||||||
|
use ads1256::standard::input::SingleEnded;
|
||||||
use ads1256::{
|
use ads1256::{
|
||||||
AdControl, Ads1256, AutoCal, BitOrder, BlockingDelay, Buffer, ClockOut, Config, DState,
|
AdControl, Ads1256, AutoCal, BitOrder, BlockingDelay, Buffer, ClockOut, Config, DState,
|
||||||
DataRate, DigitalIo, DigitalIoDirection, DigitalIoState, DioDirection, Gain, Multiplexer,
|
DataRate, DigitalIo, DigitalIoDirection, DigitalIoState, DioDirection, Gain, Multiplexer,
|
||||||
MuxInput, OutputPin, Sdcs, SpiBus, Status, Wait,
|
MuxInput, OutputPin, Sdcs, SpiBus, Status, Wait,
|
||||||
};
|
};
|
||||||
use ads1256::standard::input::SingleEnded;
|
|
||||||
use embassy_time::{Delay, Duration, Timer};
|
use embassy_time::{Delay, Duration, Timer};
|
||||||
use executor::Spawner;
|
use executor::Spawner;
|
||||||
use stm32::dma::NoDma;
|
use stm32::dma::NoDma;
|
||||||
@ -32,8 +32,12 @@ use defmt::{debug, error, info, trace, unwrap};
|
|||||||
use embassy_executor::_export::StaticCell;
|
use embassy_executor::_export::StaticCell;
|
||||||
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
|
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
|
||||||
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::pubsub::PubSubChannel;
|
use embassy_sync::pubsub::PubSubChannel;
|
||||||
use physical_node::transducer::{Publish, StatefulPublisher};
|
use physical_ads1256::standard::multiplexer::poll::{
|
||||||
|
AutocalPoll, AutocalPollStatePub, ModInputOnly,
|
||||||
|
};
|
||||||
|
use physical_node::transducer::{Publish, Publisher, StatefulPublisher};
|
||||||
|
|
||||||
const AUTOCAL_CONF: Config = Config {
|
const AUTOCAL_CONF: Config = Config {
|
||||||
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),
|
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),
|
||||||
@ -56,16 +60,31 @@ impl ads1256::BlockingDelay for Ads1256Delay {
|
|||||||
fn t11_2_delay(&mut self) {}
|
fn t11_2_delay(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExampleInput = AutocalPollStatePub<
|
||||||
|
'static,
|
||||||
|
NoopRawMutex,
|
||||||
|
NoopRawMutex,
|
||||||
|
ModInputOnly,
|
||||||
|
Ads1256Delay,
|
||||||
|
Output<'static, PF7>,
|
||||||
|
ExtiInput<'static, PF6>,
|
||||||
|
Spi<'static, SPI3, NoDma, NoDma>,
|
||||||
|
10,
|
||||||
|
1,
|
||||||
|
>;
|
||||||
|
|
||||||
struct Inputs {
|
struct Inputs {
|
||||||
ai1: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
ai1: ExampleInput,
|
||||||
ai2: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
ai2: ExampleInput,
|
||||||
ai3: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
|
ai3: ExampleInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
static ANALOG_INPUTS: StaticCell<Inputs> = StaticCell::new();
|
static ANALOG_INPUTS: StaticCell<Inputs> = StaticCell::new();
|
||||||
static ADS_1256: StaticCell<Ads1256<Ads1256Delay, Output<PF7>, ExtiInput<PF6>>> = StaticCell::new();
|
static ADS_1256: StaticCell<
|
||||||
static SPI: StaticCell<Spi<SPI3, NoDma, NoDma>> = StaticCell::new();
|
Mutex<NoopRawMutex, Ads1256<Ads1256Delay, Output<PF7>, ExtiInput<PF6>>>,
|
||||||
|
> = StaticCell::new();
|
||||||
|
static SPI: StaticCell<Mutex<NoopRawMutex, Spi<SPI3, NoDma, NoDma>>> = StaticCell::new();
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
@ -86,7 +105,7 @@ async fn main(spawner: Spawner) {
|
|||||||
let ads1256_data_ready = ExtiInput::new(Input::new(p.PF6, Pull::Up), p.EXTI6);
|
let ads1256_data_ready = ExtiInput::new(Input::new(p.PF6, Pull::Up), p.EXTI6);
|
||||||
let select_ads1256 = Output::new(p.PF7, Level::High, Speed::VeryHigh);
|
let select_ads1256 = Output::new(p.PF7, Level::High, Speed::VeryHigh);
|
||||||
|
|
||||||
let spi = SPI.init(Spi::new(
|
let spi = &*SPI.init(Mutex::new(Spi::new(
|
||||||
p.SPI3,
|
p.SPI3,
|
||||||
p.PC10,
|
p.PC10,
|
||||||
p.PC12,
|
p.PC12,
|
||||||
@ -95,86 +114,48 @@ async fn main(spawner: Spawner) {
|
|||||||
NoDma,
|
NoDma,
|
||||||
Hertz(ads1256::defaults::SPI_CLK_HZ),
|
Hertz(ads1256::defaults::SPI_CLK_HZ),
|
||||||
spi_conf,
|
spi_conf,
|
||||||
));
|
)));
|
||||||
|
|
||||||
let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready));
|
let ads_1256 =
|
||||||
|
&*ADS_1256.init(Mutex::new(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready)));
|
||||||
|
|
||||||
let inputs = &*ANALOG_INPUTS.init(Inputs {
|
let inputs = &*ANALOG_INPUTS.init(Inputs {
|
||||||
ai1: StatefulPublisher::new(
|
ai1: AutocalPollStatePub {
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
poll: AutocalPoll::new(
|
||||||
PubSubChannel::new().into(),
|
ModInputOnly {
|
||||||
|
gain: Gain::X2,
|
||||||
|
multiplexer: SingleEnded::AIn1.into(),
|
||||||
|
},
|
||||||
|
ads_1256,
|
||||||
|
spi,
|
||||||
),
|
),
|
||||||
ai2: StatefulPublisher::new(
|
publisher: PubSubChannel::new().into(),
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
state: Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
PubSubChannel::new().into(),
|
},
|
||||||
|
ai2: AutocalPollStatePub {
|
||||||
|
poll: AutocalPoll::new(
|
||||||
|
ModInputOnly {
|
||||||
|
gain: Gain::X2,
|
||||||
|
multiplexer: SingleEnded::AIn2.into(),
|
||||||
|
},
|
||||||
|
ads_1256,
|
||||||
|
spi,
|
||||||
),
|
),
|
||||||
ai3: StatefulPublisher::new(
|
publisher: PubSubChannel::new().into(),
|
||||||
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
|
state: Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
PubSubChannel::new().into(),
|
},
|
||||||
|
ai3: AutocalPollStatePub {
|
||||||
|
poll: AutocalPoll::new(
|
||||||
|
ModInputOnly {
|
||||||
|
gain: Gain::X2,
|
||||||
|
multiplexer: SingleEnded::AIn3.into(),
|
||||||
|
},
|
||||||
|
ads_1256,
|
||||||
|
spi,
|
||||||
),
|
),
|
||||||
|
publisher: PubSubChannel::new().into(),
|
||||||
|
state: Cell::new(f32::ElectricPotential::new::<volt>(f32::NAN)).into(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
spawner.spawn(log_task(inputs)).unwrap();
|
|
||||||
spawner
|
|
||||||
.spawn(drive_inputs_task(ads_1256, spi, inputs))
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[embassy_executor::task]
|
|
||||||
async fn drive_inputs_task(
|
|
||||||
ads_1256: &'static mut Ads1256<Ads1256Delay, Output<'static, PF7>, ExtiInput<'static, PF6>>,
|
|
||||||
spi: &'static mut Spi<'static, SPI3, NoDma, NoDma>,
|
|
||||||
inputs: &'static Inputs,
|
|
||||||
) {
|
|
||||||
let Inputs { ai1, ai2, ai3 } = inputs;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut accumulator = f32::ElectricPotential::new::<volt>(0.0);
|
|
||||||
|
|
||||||
let voltage = ads_1256
|
|
||||||
.autocal_convert(spi, SingleEnded::AIn0.into(), None, None, None, false)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
|
||||||
ai1.update(voltage);
|
|
||||||
accumulator += voltage;
|
|
||||||
|
|
||||||
let voltage = ads_1256
|
|
||||||
.autocal_convert(spi, SingleEnded::AIn1.into(), None, None, None, false)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
|
||||||
ai2.update(voltage);
|
|
||||||
accumulator += voltage;
|
|
||||||
|
|
||||||
let voltage = ads_1256
|
|
||||||
.autocal_convert(spi, SingleEnded::AIn2.into(), None, None, None, false)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.to_voltage(AUTOCAL_CONF.ad_control.gain());
|
|
||||||
ai3.update(voltage);
|
|
||||||
accumulator += voltage;
|
|
||||||
|
|
||||||
let accum_volts = accumulator.get::<volt>();
|
|
||||||
info!("Immediate loop iteration result, combined volts: {}", accum_volts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[embassy_executor::task]
|
|
||||||
async fn log_task(inputs: &'static Inputs) {
|
|
||||||
let Inputs { ai1, ai2, ai3 } = inputs;
|
|
||||||
let mut ai1_sub = ai1.subscribe().unwrap();
|
|
||||||
let mut ai2_sub = ai2.subscribe().unwrap();
|
|
||||||
let mut ai3_sub = ai3.subscribe().unwrap();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let msg = ai1_sub.next_message_pure().await.get::<volt>();
|
|
||||||
info!("Log task ai1: {}", msg);
|
|
||||||
|
|
||||||
let msg = ai2_sub.next_message_pure().await.get::<volt>();
|
|
||||||
info!("Log task ai2: {}", msg);
|
|
||||||
|
|
||||||
let msg = ai3_sub.next_message_pure().await.get::<volt>();
|
|
||||||
info!("Log task ai3: {}", msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#[cfg(feature = "standard-input")]
|
#[cfg(feature = "standard-multiplexer")]
|
||||||
pub mod multiplexer;
|
pub mod multiplexer;
|
@ -25,6 +25,30 @@ where
|
|||||||
spi: &'a Mutex<DeviceMutexT, SpiT>,
|
spi: &'a Mutex<DeviceMutexT, SpiT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT>
|
||||||
|
AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT>
|
||||||
|
where
|
||||||
|
DeviceMutexT: RawMutex,
|
||||||
|
ModInT: ModInput,
|
||||||
|
DelayerT: BlockingDelay,
|
||||||
|
SST: OutputPin,
|
||||||
|
DrdyT: Wait,
|
||||||
|
SpiT: SpiBus,
|
||||||
|
{
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new(
|
||||||
|
input_mod: ModInT,
|
||||||
|
ads1256: &'a Mutex<DeviceMutexT, Ads1256<DelayerT, SST, DrdyT>>,
|
||||||
|
spi: &'a Mutex<DeviceMutexT, SpiT>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
input_mod,
|
||||||
|
ads1256,
|
||||||
|
spi,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> Poll
|
impl<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT> Poll
|
||||||
for AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT>
|
for AutocalPoll<'a, DeviceMutexT, ModInT, DelayerT, SST, DrdyT, SpiT>
|
||||||
where
|
where
|
||||||
@ -40,6 +64,7 @@ where
|
|||||||
async fn poll(&self) -> Result<Self::Value, CriticalError> {
|
async fn poll(&self) -> Result<Self::Value, CriticalError> {
|
||||||
let mut ads1256_guard = self.ads1256.lock().await;
|
let mut ads1256_guard = self.ads1256.lock().await;
|
||||||
let ads1256 = ads1256_guard.deref_mut();
|
let ads1256 = ads1256_guard.deref_mut();
|
||||||
|
ads1256.data_ready.wait_for_low().await;
|
||||||
|
|
||||||
let result = ads1256
|
let result = ads1256
|
||||||
.autocal_convert_m(
|
.autocal_convert_m(
|
||||||
@ -71,6 +96,36 @@ pub trait ModInput: Copy {
|
|||||||
fn data_rate(self) -> Option<DataRate>;
|
fn data_rate(self) -> Option<DataRate>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub struct ModInputOnly {
|
||||||
|
pub multiplexer: Multiplexer,
|
||||||
|
/// Only used for converting to voltage, this value must match what is set on the ADS1256, it
|
||||||
|
/// will not *be* set unlike the other fields.
|
||||||
|
pub gain: Gain,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModInput for ModInputOnly {
|
||||||
|
fn multiplexer(self) -> Multiplexer {
|
||||||
|
self.multiplexer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gain(self) -> Gain {
|
||||||
|
self.gain
|
||||||
|
}
|
||||||
|
|
||||||
|
fn status(self) -> Option<Status> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ad_control(self) -> Option<AdControl> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_rate(self) -> Option<DataRate> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// buffer
|
/// buffer
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct ModInStatus {
|
pub struct ModInStatus {
|
||||||
|
Reference in New Issue
Block a user