From e118b151a80dce02c07e72ac7d3264f642fd675f Mon Sep 17 00:00:00 2001 From: Benjamin Koch <bbbsnowball@gmail.com> Date: Wed, 24 May 2023 05:12:13 +0200 Subject: [PATCH] start adding ADC --- firmware/rust1/src/bin/heizung.rs | 69 +++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index fd5b2c9..91797c8 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -2,10 +2,13 @@ #![no_main] #![feature(type_alias_impl_trait)] +use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; + use defmt::*; use embassy_executor::Spawner; //use embassy_futures::join::join; use embassy_futures::select::*; +use embassy_rp::adc::{self, Adc}; use embassy_rp::peripherals::*; use embassy_time::{Duration, Timer}; use embassy_rp::gpio::{Input, Level, Output, Pull, Flex}; @@ -76,6 +79,46 @@ async fn uart_task(this: RS485<ModbusServer<ModBusRegs<'static>>>) { this.run_task().await; } +struct AdcData { + current1: AtomicU16, + current2: AtomicU16, + analog_in1_raw: AtomicU16, + analog_in1_millivolt: AtomicU16, + vcc: AtomicU16, +} + +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.0522 / 4096.0 - 0.706) / 0.001721 as f32 +} + +#[embassy_executor::task] +async fn adc_task(shared_data: &'static AdcData, adc: ADC, en_measure_current: Output<'static, PIN_3>, + mut analog_in1: PIN_26, mut current2: PIN_27, mut current1: PIN_28, mut measure_vcc: PIN_29) { + let irq = interrupt::take!(ADC_IRQ_FIFO); + let mut adc = Adc::new(adc, irq, adc::Config::default()); + + loop { + let level = adc.read(&mut analog_in1).await; + shared_data.analog_in1_raw.store(level, Ordering::Release); + let value = 3.05*level as f32/4096. * (10.+2.*5.1)/5.1; + shared_data.analog_in1_millivolt.store((value * 1000.) as u16, Ordering::Release); + info!("ADC analog_in1: {} -> {}", level, value); + + let level = adc.read(&mut current2).await; + info!("ADC current2: {}", level); + let level = adc.read(&mut current1).await; + info!("ADC current1: {}", level); + + let level = adc.read(&mut measure_vcc).await; + let vcc = 3.05 * level as f32 / 4096. * (100. + 10.)/10.; + info!("ADC measure_vcc: {} -> {}", level, vcc); + + let temp = adc.read_temperature().await; + info!("Temp: {} -> {} degrees", temp, convert_to_celsius(temp)); + Timer::after(Duration::from_secs(1)).await; + } +} struct ModBusRegs<'a> { led_g: Output<'a, PIN_5>, button_boot2: Input<'a, PIN_11>, @@ -83,6 +126,7 @@ struct ModBusRegs<'a> { reed4: Input<'a, PIN_20>, reed2: Input<'a, PIN_21>, reed1: Input<'a, PIN_22>, + adc_data: &'a AdcData, } impl<'a> ModbusRegisters for ModBusRegs<'a> { @@ -105,10 +149,12 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> { } fn read_input_register(self: &mut Self, addr: u16) -> Result<u16, ModbusErrorCode> { - if addr == 2 { - return Ok(42) + match addr { + 0 => Ok(42), + 1 => Ok(self.adc_data.analog_in1_raw.load(Ordering::Relaxed)), + 2 => Ok(self.adc_data.analog_in1_millivolt.load(Ordering::Relaxed)), + _ => Err(ModbusErrorCode::IllegalDataAddress) } - Err(ModbusErrorCode::IllegalDataAddress) } fn write_coil(self: &mut Self, addr: u16, value: bool) -> Result<(), ModbusErrorCode> { @@ -134,7 +180,7 @@ async fn main(spawner: Spawner) { //let LED_W = p.PIN_2; let _ws2812_display = p.PIN_2; //let LED_Y = p.PIN_3; - let mut _en_measure_current = Output::new(p.PIN_3, Level::Low); + let en_measure_current = Output::new(p.PIN_3, Level::Low); let mut led_b = Output::new(p.PIN_4, Level::Low); let led_g = Output::new(p.PIN_5, Level::Low); let led_r = p.PIN_6; @@ -157,16 +203,22 @@ async fn main(spawner: Spawner) { let _matrix_in3 = Input::new(p.PIN_23, Pull::Up); let _digout1 = p.PIN_24; let _digout2 = p.PIN_25; - let _analog_in1 = p.PIN_26; - let _current2 = p.PIN_27; - let _current1 = p.PIN_28; - let _measure_vcc = p.PIN_29; + let analog_in1 = p.PIN_26; + let current2 = p.PIN_27; + let current1 = p.PIN_28; + let measure_vcc = p.PIN_29; let i2c_irq = interrupt::take!(I2C0_IRQ); let mut i2c_config = i2c::Config::default(); i2c_config.frequency = 400_000; unwrap!(spawner.spawn(i2c_task(p.I2C0, scl, sda, i2c_irq, i2c_config))); + static ADC_DATA: AdcData = AdcData { + current1: AtomicU16::new(0), current2: AtomicU16::new(0), analog_in1_raw: AtomicU16::new(0), + analog_in1_millivolt: AtomicU16::new(0), vcc: AtomicU16::new(0) + }; + unwrap!(spawner.spawn(adc_task(&ADC_DATA, p.ADC, en_measure_current, analog_in1, current2, current1, measure_vcc))); + // use 19200 baud in 8E1 mode - not great but it's the Modbus default let mut uart_config = uart::Config::default(); uart_config.baudrate = 19200; @@ -178,6 +230,7 @@ async fn main(spawner: Spawner) { led_g, button_boot2, reed1, reed2, reed3, reed4, + adc_data: &ADC_DATA, }), ); unwrap!(spawner.spawn(uart_task(rs485))); -- GitLab