Created multiplexing publish / subscribe example.

This commit is contained in:
Zachary Sunforge
2023-06-16 18:23:43 -07:00
parent a143ad0e54
commit ad66d8e030
22 changed files with 419 additions and 67 deletions

View File

@ -0,0 +1,9 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# replace STM32F429ZITx with your chip as listed in `probe-run --list-chips`
runner = "probe-rs-cli run --chip STM32F429ZITx"
[build]
target = "thumbv7em-none-eabi"
[env]
DEFMT_LOG = "trace"

View File

@ -0,0 +1,42 @@
[package]
name = "ads1256-examples"
description = "Examples using the ads1256."
version.workspace = true
edition.workspace = true
repository.workspace = true
readme.workspace = true
license.workspace = true
[dependencies.physical-node]
path = "../../node"
features = ["embassy-sync"]
[dependencies.physical-ads1256]
path = "../../peripheral-components/ads1256/node"
features = ["standard-input"]
[dependencies.ads1256]
workspace = true
[dependencies.uom]
workspace = true
[dependencies.defmt]
workspace = true
[dependencies.defmt-rtt]
workspace = true
[dependencies.cortex-m]
workspace = true
features = ["critical-section-single-core"]
[dependencies.cortex-m-rt]
workspace = true
[dependencies.embassy-stm32]
workspace = true
features = ["stm32f429zi", "memory-x", "time", "exti", "time-driver-any"]
[dependencies.embassy-executor]
workspace = true
[dependencies.embassy-futures]
workspace = true
[dependencies.embassy-time]
workspace = true
features = ["tick-hz-16_000_000"]
[dependencies.embassy-sync]
workspace = true
[dependencies.panic-probe]
workspace = true

View File

@ -0,0 +1,5 @@
fn main() {
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}

View File

@ -0,0 +1,181 @@
#![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 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_ads1256::{standard_input, SingleEnded};
use physical_node::transducer::input::RawStatePubInput;
use physical_node::transducer::Publisher;
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: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai2: RawStatePubInput<f32::ElectricPotential, NoopRawMutex, 10, 1>,
ai3: RawStatePubInput<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: RawStatePubInput::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
PubSubChannel::new(),
),
ai2: RawStatePubInput::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
PubSubChannel::new(),
),
ai3: RawStatePubInput::new(
Cell::new(f32::ElectricPotential::new::<volt>(-1000.0)),
PubSubChannel::new(),
),
});
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);
}
}