From 0f2db7e6e0303abef9deb29c4e4243e56a54c795 Mon Sep 17 00:00:00 2001 From: Sachymetsu Date: Thu, 27 Aug 2026 08:49:34 +0200 Subject: [PATCH] Use ADC oversampling --- src/adc.rs | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index 5e30d18..fc5697b 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,9 +1,9 @@ +use embassy_futures::join::join; use embassy_nrf::{ Peri, gpio::{Level, Output, OutputDrive}, - peripherals, - pwm::{self, DutyCycle, SimpleConfig, SimplePwm}, - saadc::{self, ChannelConfig, Config, Resolution, Saadc}, + peripherals, pwm, + saadc::{self, ChannelConfig, Saadc}, }; use embassy_time::Timer; use sachy_battery::BatteryDischargeProfile; @@ -52,10 +52,10 @@ fn to_volts(sample: i16, reference: f32) -> f32 { fn init_pwm<'scope>( pwm: Peri<'scope, peripherals::PWM0>, ch0: Peri<'scope, peripherals::P0_05>, -) -> SimplePwm<'scope> { - let mut config = SimpleConfig::default(); +) -> pwm::SimplePwm<'scope> { + let mut config = pwm::SimpleConfig::default(); config.prescaler = pwm::Prescaler::Div1; - let pwm_ctrl = SimplePwm::new_1ch(pwm, ch0, &config); + let pwm_ctrl = pwm::SimplePwm::new_1ch(pwm, ch0, &config); pwm_ctrl.set_period(2_000_000); pwm_ctrl @@ -73,8 +73,9 @@ fn init_saadc<'scope>( let bat_config = ChannelConfig::single_ended(saadc::VddInput); - let mut saadc_config = Config::default(); - saadc_config.resolution = Resolution::_10bit; + let mut saadc_config = saadc::Config::default(); + saadc_config.resolution = saadc::Resolution::_10bit; + saadc_config.oversample = saadc::Oversample::Over16x; Saadc::new( saadc, @@ -93,9 +94,9 @@ pub async fn task( mut pwm: Peri<'static, peripherals::PWM0>, mut pin5: Peri<'static, peripherals::P0_05>, ) { - static ADC_BUFFER: ConstStaticCell<[i16; 3]> = ConstStaticCell::new([0; 3]); - let adc_buf = ADC_BUFFER.take(); + static ADC_SAMPLE_BUFFER: ConstStaticCell<[i16; 3]> = ConstStaticCell::new([0; 3]); + let sample_buf = ADC_SAMPLE_BUFFER.take(); let mut measure = unwrap!(START_MEASUREMENTS.receiver()); loop { @@ -107,36 +108,22 @@ pub async fn task( photo_ctrl.set_high(); pwm_ctrl.enable(); - pwm_ctrl.set_duty(0, DutyCycle::normal(4)); - saadc.calibrate().await; + pwm_ctrl.set_duty(0, pwm::DutyCycle::normal(4)); - Timer::after_millis(30).await; + join(saadc.calibrate(), Timer::after_millis(30)).await; - let mut acc_buf = [0; 3]; - let divisor = 4; - - for _ in 0..divisor { - saadc.sample(adc_buf).await; - acc_buf - .iter_mut() - .zip(adc_buf.iter()) - .for_each(|(slot, &value)| *slot += value); - Timer::after_millis(5).await; - } + saadc.sample(sample_buf).await; photo_ctrl.set_low(); - pwm_ctrl.set_duty(0, DutyCycle::normal(0)); - pwm_ctrl.disable(); + pwm_ctrl.set_duty(0, pwm::DutyCycle::normal(0)); drop((pwm_ctrl, saadc, photo_ctrl)); - acc_buf.iter_mut().for_each(|acc| *acc /= divisor); - - let [soil, light, bat] = acc_buf; + let [soil, light, bat] = *sample_buf; let bat_volt = to_volts(bat, VREF); - let (soil, light, bat) = ( + let (soil, light, bat_pct) = ( calculate_soil_moisture(bat_volt, soil), calculate_lux(to_volts(light, VREF)).max(0.0), BatteryDischargeProfile::calc_pct_from_profile_range( @@ -145,9 +132,9 @@ pub async fn task( ), ); - let measurements = AdcMeasurements::new(bat, bat_volt, soil, light); + let measurements = AdcMeasurements::new(bat_pct, bat_volt, soil, light); - info!("Soil {}, Light {}, Bat {}", soil, light, bat); + info!("Soil {}, Light {}, Bat {}", soil, light, bat_pct); ADC_MEASUREMENT.signal(measurements); } -- 2.51.2