example adc
This commit is contained in:
parent
74c165ece0
commit
5af7aa190a
183
examples/rp/src/bin/adc_dma.rs
Normal file
183
examples/rp/src/bin/adc_dma.rs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_rp::adc::{Adc, Config, ContinuousAdc, InterruptHandler, SamplingSpeed};
|
||||||
|
use embassy_rp::{adc, bind_interrupts, Peripheral};
|
||||||
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
ADC_IRQ_FIFO => InterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_rp::init(Default::default());
|
||||||
|
let mut adc = Adc::new(p.ADC, Irqs, Config::default());
|
||||||
|
|
||||||
|
let mut p26 = p.PIN_26;
|
||||||
|
let mut p27 = p.PIN_27;
|
||||||
|
let mut p28 = p.PIN_28;
|
||||||
|
|
||||||
|
let mut dma0 = p.DMA_CH0.into_ref();
|
||||||
|
let mut dma1 = p.DMA_CH1.into_ref();
|
||||||
|
|
||||||
|
for _ in 0..3 {
|
||||||
|
for _ in 0..100 {
|
||||||
|
let bx26 = adc.blocking_read(&mut p26);
|
||||||
|
let bx27 = adc.blocking_read(&mut p27);
|
||||||
|
let bx28 = adc.blocking_read(&mut p28);
|
||||||
|
let bxt = adc.blocking_read_temperature();
|
||||||
|
let x26 = adc.read(&mut p26).await;
|
||||||
|
let x27 = adc.read(&mut p27).await;
|
||||||
|
let x28 = adc.read(&mut p28).await;
|
||||||
|
let xt = adc.read_temperature().await;
|
||||||
|
|
||||||
|
info!("{} {} {} {} {} {} {} {}", x26, x27, x28, xt, bx26, bx27, bx28, bxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = [0u16; 24];
|
||||||
|
adc.dma_read(
|
||||||
|
&mut adc::input_from_pin(&mut p26, true).add_temperature().add(&mut p28),
|
||||||
|
dma0.reborrow(),
|
||||||
|
&mut buffer,
|
||||||
|
SamplingSpeed::Fastest,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
info!("buffer {}", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("measuring with one dma channel at 10 microseconds per sample");
|
||||||
|
for _ in 0..10 {
|
||||||
|
// ordering of the input channels does not matter, only which one is the first one
|
||||||
|
// this particular input leads to adc measuring p27 p28 temp p26 p28 temp p26 p28 ....
|
||||||
|
let mut input = adc::input_from_pin(&mut p27, false)
|
||||||
|
.add(&mut p26)
|
||||||
|
.add_temperature()
|
||||||
|
.add(&mut p28);
|
||||||
|
|
||||||
|
let mut buffer = [0u16; 1000];
|
||||||
|
|
||||||
|
let speed = SamplingSpeed::Interval {
|
||||||
|
n: 48 * 10 - 1,
|
||||||
|
frac: 0,
|
||||||
|
};
|
||||||
|
let start_time = Instant::now();
|
||||||
|
adc.dma_read(&mut input, dma0.reborrow(), &mut buffer, speed).await;
|
||||||
|
let t = Instant::now().duration_since(start_time);
|
||||||
|
|
||||||
|
let mut sums = [0u32; 3]; // p26, p28, temp
|
||||||
|
let mut j = 1; // starting pin in [p26, p28, temp] is p28
|
||||||
|
for x in buffer[1..].into_iter() {
|
||||||
|
// ignoring first pin (p27), because it is not part of round robin
|
||||||
|
sums[j] += *x as u32;
|
||||||
|
j = (j + 1) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"t: {:?}, p26: {:?}, p28: {:?}, temp: {:?} (~{:?}°C)",
|
||||||
|
t.as_micros(),
|
||||||
|
mean(sums[0], 333),
|
||||||
|
mean(sums[1], 333),
|
||||||
|
mean(sums[2], 333),
|
||||||
|
convert_to_celsius(mean(sums[2], 333)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("measuring continuously with two dma channels at 2 microseconds per sample");
|
||||||
|
loop {
|
||||||
|
let mut buffer1 = [0u16; 1000];
|
||||||
|
let mut buffer2 = [0u16; 1000];
|
||||||
|
|
||||||
|
for l in 1..50 {
|
||||||
|
let data1 = &mut buffer1[..l];
|
||||||
|
let data2 = &mut buffer2[..l]; // same size is not required
|
||||||
|
|
||||||
|
// this particular input leads to adc measuring temp, p26, p27, p28, temp, p26, p27, p28, ...
|
||||||
|
let input = adc::input_temperature(true).add(&mut p28).add(&mut p27).add(&mut p26);
|
||||||
|
let mut control_input = [[0u32; 4]; 2];
|
||||||
|
let speed = SamplingSpeed::Fastest;
|
||||||
|
|
||||||
|
let mut sums = [0u32; 4]; // p26, p27, p28, temp
|
||||||
|
let mut counts = [0u32; 4];
|
||||||
|
let mut j = 3usize; // starting pin is temp
|
||||||
|
let mut corrupted = false;
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
let mut in_time = true;
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
let mut cadc = ContinuousAdc::start_new(
|
||||||
|
adc,
|
||||||
|
dma0.reborrow(),
|
||||||
|
dma1.reborrow(),
|
||||||
|
input,
|
||||||
|
speed,
|
||||||
|
&mut control_input,
|
||||||
|
data1,
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in 0..2499 {
|
||||||
|
(cadc, in_time) = cadc.next(data2).await;
|
||||||
|
evaluate(data1, &mut sums, &mut counts, &mut corrupted, &mut j, in_time);
|
||||||
|
|
||||||
|
(cadc, in_time) = cadc.next(data1).await;
|
||||||
|
evaluate(data2, &mut sums, &mut counts, &mut corrupted, &mut j, in_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to have exactly 5000 runs
|
||||||
|
(cadc, in_time) = cadc.next(data2).await;
|
||||||
|
evaluate(data1, &mut sums, &mut counts, &mut corrupted, &mut j, in_time);
|
||||||
|
|
||||||
|
// stop measurement, get adc back
|
||||||
|
adc = cadc.stop().await;
|
||||||
|
let t = Instant::now().duration_since(start).as_micros();
|
||||||
|
evaluate(data2, &mut sums, &mut counts, &mut corrupted, &mut j, true);
|
||||||
|
|
||||||
|
let mut c = heapless::String::<11>::new();
|
||||||
|
if corrupted {
|
||||||
|
c.push_str(", corrupted").unwrap();
|
||||||
|
}
|
||||||
|
info!(
|
||||||
|
"data length: {:?}, t: {:?} micros, p26: {:?}, p27: {:?}, p28: {:?}, temp: {:?}{}",
|
||||||
|
l,
|
||||||
|
t,
|
||||||
|
mean(sums[0], counts[0]),
|
||||||
|
mean(sums[1], counts[1]),
|
||||||
|
mean(sums[2], counts[2]),
|
||||||
|
mean(sums[3], counts[3]),
|
||||||
|
c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Timer::after(Duration::from_millis(1000)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_to_celsius(raw_temp: u16) -> f32 {
|
||||||
|
// According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet
|
||||||
|
27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mean(sum: u32, len: u32) -> u16 {
|
||||||
|
(0.5 + sum as f32 / len as f32) as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
data: &mut [u16],
|
||||||
|
sums: &mut [u32; 4],
|
||||||
|
counts: &mut [u32; 4],
|
||||||
|
corrupted: &mut bool,
|
||||||
|
j: &mut usize,
|
||||||
|
in_time: bool,
|
||||||
|
) {
|
||||||
|
*corrupted = *corrupted | !in_time;
|
||||||
|
for i in 0..data.len() {
|
||||||
|
sums[*j] += data[i] as u32;
|
||||||
|
data[i] = 0;
|
||||||
|
counts[*j] += 1;
|
||||||
|
*j = (*j + 1) % 4;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user