From 4db1abd887141c5194924fb8a8f648fc12b89985 Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 14 Sep 2021 22:52:42 +0200 Subject: [PATCH 1/6] WIP: nucleo changes --- firmware/.embed.toml | 3 ++- firmware/Cargo.toml | 3 ++- firmware/memory.x | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/firmware/.embed.toml b/firmware/.embed.toml index 1625676..fcfdebf 100644 --- a/firmware/.embed.toml +++ b/firmware/.embed.toml @@ -1,7 +1,8 @@ # Chip and probe config [default.general] -chip = "STM32L071KBTx" +# chip = "STM32L071KBTx" +chip = "STM32L031K6Tx" [default.probe] protocol = "Swd" diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 0947362..e186f4f 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -23,7 +23,8 @@ embedded-hal = { version = "0.2.2", features = ["unproven"] } one-wire-bus = "0.1.1" rn2xx3 = "0.2.1" stm32l0 = "0.10.0" -stm32l0xx-hal = { git = "ssh://git@github.com/stm32-rs/stm32l0xx-hal.git", branch = "master", features = ["rt", "mcu-STM32L071KBTx"] } +#stm32l0xx-hal = { git = "ssh://git@github.com/stm32-rs/stm32l0xx-hal.git", branch = "master", features = ["rt", "mcu-STM32L071KBTx"] } +stm32l0xx-hal = { git = "ssh://git@github.com/stm32-rs/stm32l0xx-hal.git", branch = "master", features = ["rt", "mcu-STM32L031K6Tx"] } shtcx = { git = "https://github.com/dbrgn/shtcx-rs", branch = "master" } [target.'cfg(target_arch = "arm")'.dependencies] diff --git a/firmware/memory.x b/firmware/memory.x index 01eee26..31f3704 100644 --- a/firmware/memory.x +++ b/firmware/memory.x @@ -1,8 +1,8 @@ MEMORY { /* NOTE K = KiBi = 1024 bytes */ - FLASH : ORIGIN = 0x08000000, LENGTH = 128K - RAM : ORIGIN = 0x20000000, LENGTH = 19K + FLASH : ORIGIN = 0x08000000, LENGTH = 32K + RAM : ORIGIN = 0x20000000, LENGTH = 8K PANDUMP : ORIGIN = 0x20004C00, LENGTH = 1K } From 918bb4c6470a2f0a2e878e5d29b1f695951801af Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 14 Sep 2021 22:53:40 +0200 Subject: [PATCH 2/6] Add supply monitor example --- firmware/examples/supply_monitor.rs | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 firmware/examples/supply_monitor.rs diff --git a/firmware/examples/supply_monitor.rs b/firmware/examples/supply_monitor.rs new file mode 100644 index 0000000..d3ed3dd --- /dev/null +++ b/firmware/examples/supply_monitor.rs @@ -0,0 +1,68 @@ +//! Prints the supply voltage monitor output to the serial port. +#![no_main] +#![no_std] + +use panic_persist as _; + +use core::fmt::Write; + +use cortex_m_rt::entry; +use stm32l0xx_hal as hal; +use stm32l0xx_hal::prelude::*; + +use gfroerli_firmware::supply_monitor; +use gfroerli_common::measurement::U12; + +#[entry] +fn main() -> ! { + let p = cortex_m::Peripherals::take().unwrap(); + let dp = stm32l0xx_hal::pac::Peripherals::take().unwrap(); + + + let syst = p.SYST; + let mut rcc = dp.RCC.freeze(hal::rcc::Config::hsi16()); + let mut delay = hal::delay::Delay::new(syst, rcc.clocks); + + let gpiob = dp.GPIOB.split(&mut rcc); + let mut led = gpiob.pb3.into_push_pull_output(); + + let gpioa = dp.GPIOA.split(&mut rcc); + let mut serial = hal::serial::Serial::usart2( + dp.USART2, + gpioa.pa2.into_floating_input(), + gpioa.pa3.into_floating_input(), + + //gpioa.pa9.into_floating_input(), + //gpioa.pa10.into_floating_input(), + + //gpiob.pb6.into_floating_input(), + //gpiob.pb7.into_floating_input(), + hal::serial::Config { + baudrate: hal::time::Bps(9600), + wordlength: hal::serial::WordLength::DataBits8, + parity: hal::serial::Parity::ParityNone, + stopbits: hal::serial::StopBits::STOP1, + }, + &mut rcc, + ) + .unwrap(); + + // Initialize supply monitor + let adc = dp.ADC.constrain(&mut rcc); + let a1 = gpioa.pa1.into_analog(); + let adc_enable_pin = gpioa.pa5.into_push_pull_output().downgrade(); + let mut supply_monitor = supply_monitor::SupplyMonitor::new(a1, adc, adc_enable_pin); + + + loop { + let v_supply = supply_monitor.read_supply_raw(); + writeln!(serial, "{:?}", v_supply); + + //serial.write_char('a').unwrap(); + + led.set_high().unwrap(); + delay.delay(hal::time::MicroSeconds(1_000_000)); + led.set_low().unwrap(); + delay.delay(hal::time::MicroSeconds(1_000_000)); + } +} From 06cfb6effc958deb420c25b4ef77d42b04cc3fd5 Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 5 Oct 2021 20:17:11 +0200 Subject: [PATCH 3/6] WIP: stuff --- firmware/examples/supply_monitor.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/firmware/examples/supply_monitor.rs b/firmware/examples/supply_monitor.rs index d3ed3dd..e7a196d 100644 --- a/firmware/examples/supply_monitor.rs +++ b/firmware/examples/supply_monitor.rs @@ -56,7 +56,15 @@ fn main() -> ! { loop { let v_supply = supply_monitor.read_supply_raw(); - writeln!(serial, "{:?}", v_supply); + if let Some(v) = v_supply { + writeln!(serial, "{:?}", v); + + // real ca. 0.7V@3.3V + let v_input = (v as f32) / 4095.0 * 3.3; + let v_supply_converted = (v as f32) / 4095.0 * 3.3 / 2.7 * (10.0 + 2.7); + + writeln!(serial, "{} -> {:?}", v_input, v_supply_converted); + } //serial.write_char('a').unwrap(); From 4de9adf10df2179d558859fef409c21040b6119a Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 5 Oct 2021 21:32:00 +0200 Subject: [PATCH 4/6] Compensate supply monitor reading with VREFINT Reading VREFINT allows us to measure the voltage at VDDA instead of just assuming that it is 3.3V. --- firmware/src/supply_monitor.rs | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/firmware/src/supply_monitor.rs b/firmware/src/supply_monitor.rs index 2278cc0..4321fef 100644 --- a/firmware/src/supply_monitor.rs +++ b/firmware/src/supply_monitor.rs @@ -1,6 +1,6 @@ use embedded_hal::adc::OneShot; use embedded_hal::digital::v2::OutputPin; -use stm32l0xx_hal::adc::{self, Adc, Align}; +use stm32l0xx_hal::adc::{self, Adc, Align, VRef}; use stm32l0xx_hal::gpio::gpioa::{PA, PA1}; use stm32l0xx_hal::gpio::{Analog, Output, PushPull}; @@ -14,6 +14,9 @@ pub struct SupplyMonitor { } impl SupplyMonitor { + const ADC_MAX: f32 = 4095.0; + const VREFINT_VOLTAGE: f32 = 1.224; + pub fn new( adc_pin: PA1, mut adc: Adc, @@ -50,6 +53,24 @@ impl SupplyMonitor { val } + /// Read the VREFINT value + pub fn read_vref_raw(&mut self) -> Option { + VRef.enable(&mut self.adc); + let val = self.adc.read(&mut VRef).ok(); + VRef.disable(&mut self.adc); + val + } + + /// Convert the raw VREFINT ADC value to VDDA + pub fn convert_vrefint_to_vdda(vrefint: u16) -> f32 { + Self::ADC_MAX * Self::VREFINT_VOLTAGE / (vrefint as f32) + } + + /// Read VREFINT and calculate VDDA from it + pub fn read_vdda(&mut self) -> Option { + self.read_vref_raw().map(Self::convert_vrefint_to_vdda) + } + /// Read the supply voltage (see `read_supply_raw` for details) and return /// the raw data as `U12`. pub fn read_supply_raw_u12(&mut self) -> Option { @@ -60,16 +81,15 @@ impl SupplyMonitor { /// the voltage in volts as `f32`. pub fn read_supply(&mut self) -> Option { let val = self.read_supply_raw()?; - Some(Self::convert_input(val)) + let vdda = self.read_vdda()?; + Some(Self::convert_input(val, vdda)) } /// Convert the raw ADC value to the resulting supply voltage - pub fn convert_input(input: u16) -> f32 { - const SUPPLY_VOLTAGE: f32 = 3.3; - const ADC_MAX: f32 = 4095.0; - const R_1: f32 = 9.31; - const R_2: f32 = 6.04; - (input as f32) / ADC_MAX * SUPPLY_VOLTAGE / R_1 * (R_1 + R_2) + pub fn convert_input(input: u16, vdda: f32) -> f32 { + const R_1: f32 = 2.7; + const R_2: f32 = 10.0; + (input as f32) / Self::ADC_MAX * vdda / R_1 * (R_1 + R_2) } } From 461e88020cfb962fbd567ddbd9ad4a227a85810a Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Tue, 5 Oct 2021 21:34:48 +0200 Subject: [PATCH 5/6] WIP: supply monitor example --- firmware/examples/supply_monitor.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/firmware/examples/supply_monitor.rs b/firmware/examples/supply_monitor.rs index e7a196d..e49bdf4 100644 --- a/firmware/examples/supply_monitor.rs +++ b/firmware/examples/supply_monitor.rs @@ -11,14 +11,12 @@ use stm32l0xx_hal as hal; use stm32l0xx_hal::prelude::*; use gfroerli_firmware::supply_monitor; -use gfroerli_common::measurement::U12; #[entry] fn main() -> ! { let p = cortex_m::Peripherals::take().unwrap(); let dp = stm32l0xx_hal::pac::Peripherals::take().unwrap(); - let syst = p.SYST; let mut rcc = dp.RCC.freeze(hal::rcc::Config::hsi16()); let mut delay = hal::delay::Delay::new(syst, rcc.clocks); @@ -31,10 +29,9 @@ fn main() -> ! { dp.USART2, gpioa.pa2.into_floating_input(), gpioa.pa3.into_floating_input(), - //gpioa.pa9.into_floating_input(), //gpioa.pa10.into_floating_input(), - + //gpiob.pb6.into_floating_input(), //gpiob.pb7.into_floating_input(), hal::serial::Config { @@ -49,21 +46,34 @@ fn main() -> ! { // Initialize supply monitor let adc = dp.ADC.constrain(&mut rcc); + let a1 = gpioa.pa1.into_analog(); let adc_enable_pin = gpioa.pa5.into_push_pull_output().downgrade(); let mut supply_monitor = supply_monitor::SupplyMonitor::new(a1, adc, adc_enable_pin); - loop { let v_supply = supply_monitor.read_supply_raw(); if let Some(v) = v_supply { - writeln!(serial, "{:?}", v); + writeln!(serial, "{}", v); // real ca. 0.7V@3.3V - let v_input = (v as f32) / 4095.0 * 3.3; - let v_supply_converted = (v as f32) / 4095.0 * 3.3 / 2.7 * (10.0 + 2.7); + let v_input = (v as f32) / 4095.0 * 3.3; + let v_supply_converted = (v as f32) / 4095.0 * 3.3 / 2.7 * (10.0 + 2.7); + + writeln!(serial, "{} -> {}", v_input, v_supply_converted).unwrap(); + } + + /* + if let Some(v) = supply_monitor.read_vref_raw() { + let v_input = (v as f32) / 4095.0 * 3.3; + let v_dda = supply_monitor::SupplyMonitor::convert_vrefint_to_vdda(v); + + writeln!(serial, "VDDA: {} ({}) -> {}", v, v_input, v_dda).unwrap(); + } + */ - writeln!(serial, "{} -> {:?}", v_input, v_supply_converted); + if let Some(vdd) = supply_monitor.read_supply() { + writeln!(serial, "VDD: {:?}", vdd); } //serial.write_char('a').unwrap(); From 3a928ab85ecc4dfce9bc11b1a7b541a182f4d3ef Mon Sep 17 00:00:00 2001 From: Raphael Nestler Date: Mon, 18 Oct 2021 09:05:35 +0200 Subject: [PATCH 6/6] WIP: Use VREFINT_CAL --- firmware/src/supply_monitor.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/firmware/src/supply_monitor.rs b/firmware/src/supply_monitor.rs index 4321fef..03d8650 100644 --- a/firmware/src/supply_monitor.rs +++ b/firmware/src/supply_monitor.rs @@ -3,6 +3,7 @@ use embedded_hal::digital::v2::OutputPin; use stm32l0xx_hal::adc::{self, Adc, Align, VRef}; use stm32l0xx_hal::gpio::gpioa::{PA, PA1}; use stm32l0xx_hal::gpio::{Analog, Output, PushPull}; +use stm32l0xx_hal::calibration::VrefintCal; use gfroerli_common::measurement::U12; @@ -61,9 +62,18 @@ impl SupplyMonitor { val } + /// Calcultate the VREFINT voltage from the calibrated value which was calibrated at 3.0V VDDA + pub fn calculate_vref_int_voltage() -> f32 { + 3.0 / Self::ADC_MAX * (VrefintCal::get().read() as f32) + } + /// Convert the raw VREFINT ADC value to VDDA pub fn convert_vrefint_to_vdda(vrefint: u16) -> f32 { - Self::ADC_MAX * Self::VREFINT_VOLTAGE / (vrefint as f32) + let vrefint_voltage = Self::calculate_vref_int_voltage(); + let vdda = Self::ADC_MAX * vrefint_voltage / (vrefint as f32); + + + let vdda = 3.0 * (VrefintCal::get().read() as f32) / (vrefint as f32); } /// Read VREFINT and calculate VDDA from it