-
-
Save Slabity/feba4721928b557d5b117beec684d284 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use embassy_rp::peripherals; | |
use embassy_rp::i2c; | |
use embassy_rp::gpio; | |
use ads1x1x; | |
// These aliases make our tasks' function signatures simpler | |
// In the future this won't be necessary, as we won't need to pass the I2C0/I2C1 | |
// generics to the I2c struct and can just use it directly. | |
// See https://github.com/embassy-rs/embassy/pull/980 | |
#[allow(dead_code)] | |
pub type I2C0<'a, T> = i2c::I2c<'a, peripherals::I2C0, T>; | |
#[allow(dead_code)] | |
pub type I2C1<'a, T> = i2c::I2c<'a, peripherals::I2C1, T>; | |
pub struct AdcPeripherals { | |
pub i2c: I2C0<'static, i2c::Blocking>, | |
pub interrupt: gpio::Input<'static>, | |
} | |
// Number of values we want to read on a channel before switching. | |
const AVG_WINDOW: usize = 8; | |
// Number of extra values to read that will be cutoff. | |
const AVG_CUTOFF: usize = 2; | |
// Full size of the array to store readings in. | |
const AVG_LENGTH: usize = AVG_WINDOW + (AVG_CUTOFF * 2); | |
#[embassy_executor::task] | |
pub async fn adc_task(mut adc_p: AdcPeripherals) { | |
use ads1x1x; | |
// Initialize the ADS1115 driver | |
let mut adc = ads1x1x::Ads1x1x::new_ads1115(adc_p.i2c, ads1x1x::SlaveAddr::Gnd); | |
adc.set_full_scale_range(ads1x1x::FullScaleRange::Within6_144V).unwrap(); | |
adc.set_data_rate(ads1x1x::DataRate16Bit::Sps860).unwrap(); | |
let mut adc = match adc.into_continuous() { | |
Err(ads1x1x::ModeChangeError::I2C(e, _)) => { | |
panic!("{:?}", e); | |
}, | |
Ok(adc) => adc | |
}; | |
adc.use_alert_rdy_pin_as_ready().unwrap(); | |
adc.set_comparator_queue(ads1x1x::ComparatorQueue::One).unwrap(); | |
// Store the ADC readings into arrays | |
let mut readings_0 = [0i16; AVG_LENGTH]; | |
let mut readings_1 = [0i16; AVG_LENGTH]; | |
loop { | |
adc.select_channel(ads1x1x::channel::DifferentialA0A1).unwrap(); | |
adc_p.interrupt.wait_for_falling_edge().await; | |
adc.read().unwrap(); | |
for value in readings_0.iter_mut() { | |
*value = -adc.read().unwrap(); | |
} | |
adc.select_channel(ads1x1x::channel::DifferentialA2A3).unwrap(); | |
adc_p.interrupt.wait_for_falling_edge().await; | |
adc.read().unwrap(); | |
for value in readings_1.iter_mut() { | |
*value = -adc.read().unwrap(); | |
} | |
let avg_0 = average_readings(&mut readings_0); | |
let avg_1 = average_readings(&mut readings_1); | |
defmt::info!("A0A1: {}\tA0A3: {}", avg_0, avg_1); | |
} | |
} | |
fn average_readings(readings: &mut [i16]) -> i32 { | |
let mut avg = 0; | |
readings.sort_unstable(); | |
let window = &readings[AVG_CUTOFF..(AVG_LENGTH-AVG_CUTOFF)]; | |
for val in window { | |
avg += *val as i32; | |
} | |
avg /= window.len() as i32; | |
avg | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(impl_trait_in_assoc_type)] | |
#![no_std] | |
#![no_main] | |
#![feature(type_alias_impl_trait)] | |
use embassy_executor; | |
use embassy_futures; | |
use embassy_rp::bind_interrupts; | |
use embassy_rp::peripherals; | |
use embassy_rp::multicore; | |
use embassy_rp::usb; | |
use embassy_rp::i2c; | |
use embassy_rp::gpio; | |
use embassy_time::{Duration, Timer}; | |
use static_cell::StaticCell; | |
use {defmt_rtt as _, panic_probe as _}; | |
mod adc; | |
static mut CORE1_STACK: multicore::Stack<4096> = multicore::Stack::new(); | |
static mut CORE1_EXEC: StaticCell<embassy_executor::Executor> = StaticCell::new(); | |
bind_interrupts!(struct Irqs { | |
USBCTRL_IRQ => usb::InterruptHandler<peripherals::USB>; | |
}); | |
#[embassy_executor::main] | |
async fn main(_spawner: embassy_executor::Spawner) { | |
let p = embassy_rp::init(Default::default()); | |
let mut led = gpio::Output::new(p.PIN_25, gpio::Level::Low); | |
Timer::after_millis(3000).await; | |
defmt::info!("Starting program"); | |
// Set up i2c device | |
let sda = p.PIN_16; | |
let scl = p.PIN_17; | |
let i2c = i2c::I2c::new_blocking(p.I2C0, scl, sda, i2c::Config::default()); | |
// Use alert pulse to determine when new ADC value is available | |
let interrupt = gpio::Input::new(p.PIN_18, gpio::Pull::None); | |
// Outputs that send signal through potentiometers | |
let output_0 = gpio::Output::new(p.PIN_0, gpio::Level::Low); | |
let output_1 = gpio::Output::new(p.PIN_3, gpio::Level::Low); | |
let adc_p = adc::AdcPeripherals { | |
i2c, | |
interrupt, | |
}; | |
defmt::info!("Spawning ADC process"); | |
multicore::spawn_core1( | |
p.CORE1, | |
unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, | |
move || { | |
let executor = unsafe { | |
CORE1_EXEC.init(embassy_executor::Executor::new()) | |
}; | |
executor.run(|spawner| spawner.spawn(adc::adc_task(adc_p)).unwrap()); | |
} | |
); | |
defmt::info!("Entering main loop"); | |
loop { | |
led.set_high(); | |
Timer::after(Duration::from_millis(250)).await; | |
led.set_low(); | |
Timer::after(Duration::from_millis(750)).await; | |
embassy_futures::yield_now().await | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment