This commit is contained in:
Zachary Sunforge
2023-06-23 20:32:01 -07:00
parent 2a0013481c
commit c46680247b
18 changed files with 193 additions and 133 deletions

View File

@ -7,7 +7,7 @@ members = [
"node",
"commander",
# Peripherals
"peripherals/standalone-ads1256/*",
# Peripheral components
"peripheral-components/ads1256/*",
# Macros

View File

@ -12,7 +12,7 @@ path = "../../node"
features = ["embassy-sync"]
[dependencies.physical-ads1256]
path = "../../peripheral-components/ads1256/node"
features = ["standard-input"]
features = ["poll"]
[dependencies.ads1256]
workspace = true
[dependencies.uom]

View File

@ -15,6 +15,7 @@ use ads1256::{
DataRate, DigitalIo, DigitalIoDirection, DigitalIoState, DioDirection, Gain, Multiplexer,
MuxInput, OutputPin, Sdcs, SpiBus, Status, Wait,
};
use ads1256::standard::input::SingleEnded;
use embassy_time::{Delay, Duration, Timer};
use executor::Spawner;
use stm32::dma::NoDma;
@ -32,9 +33,7 @@ use embassy_executor::_export::StaticCell;
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::pubsub::PubSubChannel;
use physical_ads1256::{standard_input, SingleEnded};
use physical_node::transducer::input::StatefulPublisher;
use physical_node::transducer::Publish;
use physical_node::transducer::{Publish, StatefulPublisher};
const AUTOCAL_CONF: Config = Config {
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),

View File

@ -0,0 +1,180 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait, async_fn_in_trait)]
use core::cell::Cell;
use cortex_m::prelude::{
_embedded_hal_blocking_delay_DelayMs, _embedded_hal_blocking_delay_DelayUs,
};
use {defmt_rtt as _, panic_probe as _};
use {embassy_executor as executor, embassy_stm32 as stm32};
use ads1256::{
AdControl, Ads1256, AutoCal, BitOrder, BlockingDelay, Buffer, ClockOut, Config, DState,
DataRate, DigitalIo, DigitalIoDirection, DigitalIoState, DioDirection, Gain, Multiplexer,
MuxInput, OutputPin, Sdcs, SpiBus, Status, Wait,
};
use ads1256::standard::input::SingleEnded;
use embassy_time::{Delay, Duration, Timer};
use executor::Spawner;
use stm32::dma::NoDma;
use stm32::exti::ExtiInput;
use stm32::gpio::{Input, Level, Output, Pull, Speed};
use stm32::spi::Spi;
use stm32::time::Hertz;
use stm32::{pac, spi};
use uom::si::electric_potential::volt;
use uom::si::f32;
use defmt::{debug, error, info, trace, unwrap};
use embassy_executor::_export::StaticCell;
use embassy_stm32::peripherals::{EXTI6, PF6, PF7, SPI3};
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::pubsub::PubSubChannel;
use physical_node::transducer::{Publish, StatefulPublisher};
const AUTOCAL_CONF: Config = Config {
status: Status::setting(Buffer::Enabled, AutoCal::Enabled, BitOrder::MostSigFirst),
multiplexer: Multiplexer::setting(MuxInput::AIn0, MuxInput::Common),
ad_control: AdControl::setting(Gain::X2, Sdcs::Off, ClockOut::Off),
data_rate: DataRate::Sps2_5,
digital_io: DigitalIo::setting(DigitalIoState::default(), DigitalIoDirection::default()),
};
struct Ads1256Delay;
impl ads1256::BlockingDelay for Ads1256Delay {
#[inline]
fn t6_delay(&mut self) {
Delay.delay_us(1u32);
}
fn t11_1_delay(&mut self) {}
fn t11_2_delay(&mut self) {}
}
struct Inputs {
ai1: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai2: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai3: StatefulPublisher<f32::ElectricPotential, NoopRawMutex, 10, 1>,
}
// Inputs
static ANALOG_INPUTS: StaticCell<Inputs> = StaticCell::new();
static ADS_1256: StaticCell<Ads1256<Ads1256Delay, Output<PF7>, ExtiInput<PF6>>> = StaticCell::new();
static SPI: StaticCell<Spi<SPI3, NoDma, NoDma>> = StaticCell::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
unsafe {
pac::FLASH.acr().modify(|v| {
v.set_prften(true);
v.set_icen(true);
v.set_dcen(true);
});
}
let p = embassy_stm32::init(Default::default());
let mut spi_conf = spi::Config::default();
spi_conf.mode = spi::MODE_1;
spi_conf.bit_order = spi::BitOrder::MsbFirst;
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 spi = SPI.init(Spi::new(
p.SPI3,
p.PC10,
p.PC12,
p.PC11,
NoDma,
NoDma,
Hertz(ads1256::defaults::SPI_CLK_HZ),
spi_conf,
));
let ads_1256 = ADS_1256.init(Ads1256::new(Ads1256Delay, select_ads1256, ads1256_data_ready));
let inputs = &*ANALOG_INPUTS.init(Inputs {
ai1: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new().into(),
),
ai2: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new().into(),
),
ai3: StatefulPublisher::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)).into(),
PubSubChannel::new().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);
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "physical-ads1256"
description = "Shared abstractions for ADS1256 components."
description = "Shared node abstractions for ADS1256 components."
version.workspace = true
edition.workspace = true
repository.workspace = true
@ -10,17 +10,12 @@ license.workspace = true
[features]
embassy-sync = ["dep:embassy-sync", "ads1256/embassy-sync", "physical-node/embassy-sync"]
poll = ["standard-multiplexer", "embassy-sync"]
config = ["physical-ads1256-types/config"]
standard-input = ["physical-ads1256-types/standard-input"]
standard-multiplexer = ["standard-input"]
standard-multiplexer = []
[dependencies.physical-node]
path = "../../../node"
[dependencies.node-poll-variants]
path = "../../../macros/node-poll-variants"
[dependencies.physical-ads1256-types]
path = "../types"
features = ["defmt"]
[dependencies.ads1256]
workspace = true
[dependencies.embedded-hal]

View File

@ -1,9 +1,4 @@
#![no_std]
#![feature(async_fn_in_trait, impl_trait_projections)]
#[cfg(feature = "standard-multiplexer")]
mod standard_multiplexer;
#[cfg(feature = "poll")]
mod poll;
pub use physical_ads1256_types::*;
pub mod standard;

View File

@ -0,0 +1,2 @@
#[cfg(feature = "standard-input")]
pub mod multiplexer;

View File

@ -38,11 +38,10 @@ where
type Value = f32::ElectricPotential;
async fn poll(&self) -> Result<Self::Value, CriticalError> {
let result = self
.ads1256
.lock()
.await
.deref_mut()
let mut ads1256_guard = self.ads1256.lock().await;
let ads1256 = ads1256_guard.deref_mut();
let result = ads1256
.autocal_convert_m(
self.spi,
self.input_mod.multiplexer(),

View File

@ -1,18 +0,0 @@
[package]
name = "physical-ads1256-types"
description = "ADS1256 Physical types."
version.workspace = true
edition.workspace = true
repository.workspace = true
readme.workspace = true
license.workspace = true
[features]
config = []
standard-input = []
[dependencies.ads1256-types]
workspace = true
[dependencies.defmt]
workspace = true
optional = true

View File

@ -1,2 +0,0 @@
use ads1256_types::{Buffer, Config, DataRate, Gain};

View File

@ -1,11 +0,0 @@
#![no_std]
#[cfg(feature = "standard-input")]
pub mod standard_input;
#[cfg(feature = "config")]
mod config;
#[cfg(feature = "config")]
pub use config::*;
#[cfg(feature = "standard-input")]
pub use standard_input::*;

View File

@ -1,39 +0,0 @@
use ads1256_types::{Buffer, Config, DataRate, Gain, Multiplexer, MuxInput};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum Differential {
AIn0 = Multiplexer::setting(MuxInput::AIn0, MuxInput::AIn1).0,
AIn1 = Multiplexer::setting(MuxInput::AIn2, MuxInput::AIn3).0,
AIn2 = Multiplexer::setting(MuxInput::AIn4, MuxInput::AIn5).0,
AIn3 = Multiplexer::setting(MuxInput::AIn6, MuxInput::AIn7).0,
}
impl Into<Multiplexer> for Differential {
#[inline(always)]
fn into(self) -> Multiplexer {
Multiplexer(self as u8)
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum SingleEnded {
AIn0 = Multiplexer::setting(MuxInput::AIn0, MuxInput::Common).0,
AIn1 = Multiplexer::setting(MuxInput::AIn1, MuxInput::Common).0,
AIn2 = Multiplexer::setting(MuxInput::AIn2, MuxInput::Common).0,
AIn3 = Multiplexer::setting(MuxInput::AIn3, MuxInput::Common).0,
AIn4 = Multiplexer::setting(MuxInput::AIn4, MuxInput::Common).0,
AIn5 = Multiplexer::setting(MuxInput::AIn5, MuxInput::Common).0,
AIn6 = Multiplexer::setting(MuxInput::AIn6, MuxInput::Common).0,
AIn7 = Multiplexer::setting(MuxInput::AIn7, MuxInput::Common).0,
}
impl Into<Multiplexer> for SingleEnded {
#[inline(always)]
fn into(self) -> Multiplexer {
Multiplexer(self as u8)
}
}

View File

@ -1,25 +0,0 @@
[package]
name = "physical-standalone-ads1256"
description = "Support for dedicated ADS1256 boards (i.e. boards that have no other functionality other than to expose the ADS1256)"
version.workspace = true
edition.workspace = true
repository.workspace = true
readme.workspace = true
license.workspace = true
[dependencies.physical-node]
path = "../../../node"
[dependencies.physical-standalone-ads1256-types]
path = "../types"
[dependencies.physical-ads1256]
path = "../../../peripheral-components/ads1256/node"
[dependencies.ads1256]
workspace = true
[dependencies.embedded-hal]
workspace = true
[dependencies.embedded-hal-async]
workspace = true
[dependencies.defmt]
workspace = true
[dependencies.uom]
workspace = true

View File

@ -1 +0,0 @@
#![no_std]

View File

@ -1,13 +0,0 @@
[package]
name = "physical-standalone-ads1256-types"
description = "Support for dedicated ADS1256 boards (i.e. boards that have no other functionality other than to expose the ADS1256)"
version.workspace = true
edition.workspace = true
repository.workspace = true
readme.workspace = true
license.workspace = true
[dependencies.ads1256-types]
workspace = true
[dependencies.physical-ads1256-types]
path = "../../../peripheral-components/ads1256/types"

View File

@ -1 +0,0 @@
#![no_std]