From eaf16de33e3189523ef95034b34b05d874021a51 Mon Sep 17 00:00:00 2001 From: Oleg Lazari Date: Tue, 30 Sep 2025 07:08:16 -0400 Subject: [PATCH 1/6] added vref passing --- include/core/io/ADC.hpp | 14 +++ include/core/io/platform/f3xx/ADCf3xx.hpp | 17 +++- include/core/io/platform/f4xx/ADCf4xx.hpp | 17 +++- samples/adc/CMakeLists.txt | 1 + samples/adc/multi_adc.cpp | 7 ++ samples/adc/single_adc.cpp | 49 +++++++--- samples/adc/vref_demo.cpp | 110 ++++++++++++++++++++++ src/core/io/platform/f3xx/ADCf3xx.cpp | 23 ++++- src/core/io/platform/f4xx/ADCf4xx.cpp | 20 +++- 9 files changed, 239 insertions(+), 19 deletions(-) create mode 100644 samples/adc/vref_demo.cpp diff --git a/include/core/io/ADC.hpp b/include/core/io/ADC.hpp index b43f7f875..1d076c6b6 100644 --- a/include/core/io/ADC.hpp +++ b/include/core/io/ADC.hpp @@ -44,6 +44,20 @@ class ADC { */ virtual float readPercentage() = 0; + /** + * Set the reference voltage for the ADC + * + * @param[in] vref The reference voltage in volts (e.g., 3.3, 5.0) + */ + virtual void setVref(float vref) = 0; + + /** + * Get the current reference voltage for the ADC + * + * @return The reference voltage in volts + */ + virtual float getVref() const = 0; + protected: /// The pin the ADC is attached to Pin pin; diff --git a/include/core/io/platform/f3xx/ADCf3xx.hpp b/include/core/io/platform/f3xx/ADCf3xx.hpp index 783a7d472..c47cd5ca8 100644 --- a/include/core/io/platform/f3xx/ADCf3xx.hpp +++ b/include/core/io/platform/f3xx/ADCf3xx.hpp @@ -27,13 +27,26 @@ class ADCf3xx : public ADC { float readPercentage(); + void setVref(float vref); + + float getVref() const; + + /** + * Perform ADC calibration for improved accuracy + * + * @return true if calibration was successful, false otherwise + */ + static bool calibrate(); + private: // Max number of channels supported by the ADC static constexpr uint8_t MAX_CHANNELS = 15; - // Positive reference voltage of the ADC. Needs to be updated based on the hardware configuration - static constexpr float VREF_POS = 3.3; + // Default positive reference voltage of the ADC. Can be updated via setVref() + static constexpr float DEFAULT_VREF_POS = 3.3; // Max value for a 12 bit ADC reading (2^12 - 1) static constexpr uint32_t MAX_RAW = 4095; + // Current reference voltage (can be modified at runtime) + static float vref_voltage; /// This is static since the STM32F3xx only has a single ADC which /// supports multiple channels. The ADC will be initialized once then /// each channel will be added on. diff --git a/include/core/io/platform/f4xx/ADCf4xx.hpp b/include/core/io/platform/f4xx/ADCf4xx.hpp index b9f50accd..b012d8810 100644 --- a/include/core/io/platform/f4xx/ADCf4xx.hpp +++ b/include/core/io/platform/f4xx/ADCf4xx.hpp @@ -30,15 +30,21 @@ class ADCf4xx : public ADC { float readPercentage(); + void setVref(float vref); + + float getVref() const; + private: // Max number of channels supported by the ADC static constexpr uint8_t MAX_CHANNELS = 16; // Number of supported ADC Peripherals static constexpr uint8_t NUM_ADCS = 3; - // Positive reference voltage of the ADC. Needs to be updated based on the hardware configuration - static constexpr float VREF_POS = 3.3; + // Default positive reference voltage of the ADC. Can be updated via setVref() + static constexpr float DEFAULT_VREF_POS = 3.3; // Max value for a 12 bit ADC reading (2^12 - 1) static constexpr uint32_t MAX_RAW = 4095; + // Current reference voltage (can be modified at runtime) + static float vref_voltage; // Flag to indicate if the timer has been initialized static bool timerInit; // Timer handle for TIM8, used to configure and control the timer instance @@ -144,6 +150,13 @@ class ADCf4xx : public ADC { * aka controls ADC conversion frequency */ static void initTimer(); + + /** + * Perform ADC calibration for improved accuracy + * + * @return true if calibration was successful, false otherwise + */ + static bool calibrate(); }; } // namespace core::io diff --git a/samples/adc/CMakeLists.txt b/samples/adc/CMakeLists.txt index 5000f0174..bc1c9f103 100644 --- a/samples/adc/CMakeLists.txt +++ b/samples/adc/CMakeLists.txt @@ -2,3 +2,4 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/evt-core_build.cmake) make_exe(single_adc single_adc.cpp) make_exe(multi_adc multi_adc.cpp) +make_exe(vref_demo vref_demo.cpp) diff --git a/samples/adc/multi_adc.cpp b/samples/adc/multi_adc.cpp index 8bec279a4..bcf5e0e46 100644 --- a/samples/adc/multi_adc.cpp +++ b/samples/adc/multi_adc.cpp @@ -29,6 +29,13 @@ int main() { io::ADC& adc0 = io::getADC(); io::ADC& adc1 = io::getADC(); + // Optional: Set custom VREF voltage (default is 3.3V) + // adc0.setVref(5.0f); // For 5V reference + // adc1.setVref(1.8f); // For 1.8V reference + + // Optional: Perform ADC calibration for improved accuracy + // adc0.calibrate(); + while (1) { core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); core::log::LOGGER.log( diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index 10d96fc85..dc7cd7d4c 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -4,9 +4,9 @@ * UART. */ #include +#include #include #include -#include #include namespace io = core::io; @@ -18,9 +18,7 @@ int main() { io::UART& uart = io::getUART(9600); - // Set up the logger to catch errors in ADC creation - core::log::LOGGER.setUART(&uart); - core::log::LOGGER.setLogLevel(core::log::Logger::LogLevel::INFO); + // Logger setup removed - using direct UART prints instead uart.printf("Starting ADC test\r\n"); @@ -28,14 +26,43 @@ int main() { io::ADC& adc0 = io::getADC(); + // Optional: Set custom VREF voltage (default is 3.3V) + + + + // Optional: Perform ADC calibration for improved accuracy + // Cast to F3xx specific ADC to access calibrate method + static_cast(adc0).calibrate(); + while (1) { - core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); - core::log::LOGGER.log( - core::log::Logger::LogLevel::INFO, "ADC0 : %d mV", static_cast(adc0.read() * 1000)); - core::log::LOGGER.log( - core::log::Logger::LogLevel::INFO, "ADC0: %d%%", static_cast(adc0.readPercentage() * 100)); - core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "ADC0 raw: %d", adc0.readRaw()); - core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------\r\n"); + adc0.setVref(1.8f); // For 1.8V reference + uart.printf("1.8V ADC Reference\r\n"); + uint32_t voltage_mv = static_cast(adc0.read() * 1000); + uint32_t percentage = static_cast(adc0.readPercentage() * 100); + uart.printf("ADC0 : %d mV\r\n", voltage_mv); + uart.printf("ADC0: %d%%\r\n", percentage); + uart.printf("ADC0 raw: %d\r\n", adc0.readRaw()); + uart.printf("--------------------\r\n"); + time::wait(500); + + adc0.setVref(5.0f); // For 5V reference + uart.printf("5V ADC Reference\r\n"); + voltage_mv = static_cast(adc0.read() * 1000); + percentage = static_cast(adc0.readPercentage() * 100); + uart.printf("ADC0 : %d mV\r\n", voltage_mv); + uart.printf("ADC0: %d%%\r\n", percentage); + uart.printf("ADC0 raw: %d\r\n", adc0.readRaw()); + uart.printf("--------------------\r\n"); + time::wait(500); + + adc0.setVref(3.3f); // For 3.3V reference + uart.printf("3.3V ADC Reference\r\n"); + voltage_mv = static_cast(adc0.read() * 1000); + percentage = static_cast(adc0.readPercentage() * 100); + uart.printf("ADC0 : %d mV\r\n", voltage_mv); + uart.printf("ADC0: %d%%\r\n", percentage); + uart.printf("ADC0 raw: %d\r\n", adc0.readRaw()); + uart.printf("--------------------\r\n"); time::wait(500); } } diff --git a/samples/adc/vref_demo.cpp b/samples/adc/vref_demo.cpp new file mode 100644 index 000000000..d18fb36aa --- /dev/null +++ b/samples/adc/vref_demo.cpp @@ -0,0 +1,110 @@ +/** + * This example demonstrates the VREF functionality of the ADC. + * It shows how to set a custom reference voltage and how it affects + * the voltage readings. It also demonstrates ADC calibration for + * improved accuracy. + */ +#include +#include +#include +#include +#include + +namespace io = core::io; +namespace time = core::time; + +int main() { + // Initialize system + core::platform::init(); + + io::UART& uart = io::getUART(9600); + + // Set up the logger to catch errors in ADC creation + core::log::LOGGER.setUART(&uart); + core::log::LOGGER.setLogLevel(core::log::Logger::LogLevel::INFO); + + uart.printf("Starting ADC VREF Demo\r\n"); + + time::wait(500); + + io::ADC& adc0 = io::getADC(); + + // Display initial VREF setting + uint32_t vref_mv = static_cast(adc0.getVref() * 1000); + uart.printf("Initial VREF: %d mV\r\n", vref_mv); + + // Note: ADC calibration is available in platform-specific implementations + // For STM32F3xx: ADCf3xx::calibrate() + // For STM32F4xx: ADCf4xx::calibrate() + uart.printf("Note: ADC calibration is available via platform-specific methods\r\n"); + + time::wait(1000); + + // Test with default VREF (3.3V) + uart.printf("\r\n=== Testing with default VREF (3.3V) ===\r\n"); + for (int i = 0; i < 5; i++) { + float voltage = adc0.read(); + float percentage = adc0.readPercentage(); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", + i+1, voltage, percentage * 100, raw); + time::wait(200); + } + + // Change VREF to 5.0V (common for many sensors) + uart.printf("\r\n=== Changing VREF to 5.0V ===\r\n"); + adc0.setVref(5.0f); + uart.printf("New VREF: %.2f V\r\n", adc0.getVref()); + + // Test with new VREF + uart.printf("\r\n=== Testing with new VREF (5.0V) ===\r\n"); + for (int i = 0; i < 5; i++) { + float voltage = adc0.read(); + float percentage = adc0.readPercentage(); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", + i+1, voltage, percentage * 100, raw); + time::wait(200); + } + + // Change VREF to 1.8V (common for low-voltage systems) + uart.printf("\r\n=== Changing VREF to 1.8V ===\r\n"); + adc0.setVref(1.8f); + uart.printf("New VREF: %.2f V\r\n", adc0.getVref()); + + // Test with new VREF + uart.printf("\r\n=== Testing with new VREF (1.8V) ===\r\n"); + for (int i = 0; i < 5; i++) { + float voltage = adc0.read(); + float percentage = adc0.readPercentage(); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", + i+1, voltage, percentage * 100, raw); + time::wait(200); + } + + // Demonstrate that raw values don't change, only voltage calculations do + uart.printf("\r\n=== Demonstrating that raw values are independent of VREF ===\r\n"); + uart.printf("Note: Raw ADC values should remain the same regardless of VREF setting\r\n"); + + float test_vrefs[] = {1.0f, 2.5f, 3.3f, 5.0f}; + for (float vref : test_vrefs) { + adc0.setVref(vref); + uint32_t raw = adc0.readRaw(); + float voltage = adc0.read(); + uart.printf("VREF: %.1fV -> Raw: %d, Voltage: %.3fV\r\n", vref, raw, voltage); + time::wait(100); + } + + uart.printf("\r\n=== VREF Demo Complete ===\r\n"); + uart.printf("The same raw ADC value produces different voltage readings\r\n"); + uart.printf("based on the VREF setting, allowing for accurate measurements\r\n"); + uart.printf("with different reference voltages.\r\n"); + + while (1) { + time::wait(1000); + } +} diff --git a/src/core/io/platform/f3xx/ADCf3xx.cpp b/src/core/io/platform/f3xx/ADCf3xx.cpp index dbf8d8f4f..677c0566e 100644 --- a/src/core/io/platform/f3xx/ADCf3xx.cpp +++ b/src/core/io/platform/f3xx/ADCf3xx.cpp @@ -26,6 +26,7 @@ ADC_HandleTypeDef ADCf3xx::halADC = {0}; Pin ADCf3xx::channels[MAX_CHANNELS]; uint16_t ADCf3xx::buffer[MAX_CHANNELS]; DMA_HandleTypeDef ADCf3xx::halDMA = {0}; +float ADCf3xx::vref_voltage = DEFAULT_VREF_POS; ADCf3xx::ADCf3xx(Pin pin, ADCPeriph adcPeriph) : ADC(pin, adcPeriph) { // Flag representing if the ADC has been configured yet @@ -64,7 +65,7 @@ ADCf3xx::ADCf3xx(Pin pin, ADCPeriph adcPeriph) : ADC(pin, adcPeriph) { float ADCf3xx::read() { float percentage = readPercentage(); - return percentage * VREF_POS; + return percentage * vref_voltage; } uint32_t ADCf3xx::readRaw() { @@ -81,11 +82,25 @@ float ADCf3xx::readPercentage() { return static_cast(raw / MAX_RAW); } +void ADCf3xx::setVref(float vref) { + if (vref > 0.0f) { + vref_voltage = vref; + } +} + +float ADCf3xx::getVref() const { + return vref_voltage; +} + +bool ADCf3xx::calibrate() { + // Perform ADC calibration for improved accuracy + HAL_StatusTypeDef status = HAL_ADCEx_Calibration_Start(&halADC, ADC_SINGLE_ENDED); + return (status == HAL_OK); +} + void ADCf3xx::initADC(uint8_t num_channels) { halADC.Instance = ADC1; // Only ADC the F3 supports - // TODO: Figure out ADC calibration - halADC.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // Use AHB clock (8MHz) w/ division for ADC clock halADC.Init.Resolution = ADC_RESOLUTION_12B; halADC.Init.DataAlign = ADC_DATAALIGN_RIGHT; @@ -213,6 +228,8 @@ bool ADCf3xx::checkSupport(ADCPeriph periph, Channel_Support channelStruct) { switch (periph) { case ADCPeriph::ONE: return channelStruct.adc1; + default: + return false; } } diff --git a/src/core/io/platform/f4xx/ADCf4xx.cpp b/src/core/io/platform/f4xx/ADCf4xx.cpp index fb86f5894..123fe1250 100644 --- a/src/core/io/platform/f4xx/ADCf4xx.cpp +++ b/src/core/io/platform/f4xx/ADCf4xx.cpp @@ -55,6 +55,7 @@ constexpr uint8_t ADC3_SLOT = 2; ADCf4xx::ADC_State core::io::ADCf4xx::adcArray[NUM_ADCS]; bool core::io::ADCf4xx::timerInit = false; TIM_HandleTypeDef core::io::ADCf4xx::htim8; +float core::io::ADCf4xx::vref_voltage = DEFAULT_VREF_POS; ADCf4xx::ADCf4xx(Pin pin, ADCPeriph adcPeriph) : ADC(pin, adcPeriph), adcState(ADCf4xx::adcArray[getADCNum(adcPeriph)]), adcNum(getADCNum(adcPeriph)) { @@ -96,7 +97,7 @@ ADCf4xx::ADCf4xx(Pin pin, ADCPeriph adcPeriph) float ADCf4xx::read() { float percentage = readPercentage(); - return percentage * VREF_POS; + return percentage * vref_voltage; } uint32_t ADCf4xx::readRaw() { @@ -113,6 +114,23 @@ float ADCf4xx::readPercentage() { return static_cast(raw / MAX_RAW); } +void ADCf4xx::setVref(float vref) { + if (vref > 0.0f) { + vref_voltage = vref; + } +} + +float ADCf4xx::getVref() const { + return vref_voltage; +} + +bool ADCf4xx::calibrate() { + // Note: STM32F4xx doesn't have the same calibration functions as F3xx + // For F4xx, we would need to implement a different calibration approach + // For now, return true as a placeholder + return true; +} + void ADCf4xx::initADC(uint8_t num_channels) { /** Configure the global features of the ADC (Clock, Resolution, Data * Alignment and number of conversion) From 637cf07fd41534e3d5a291cbad86c00268164bbd Mon Sep 17 00:00:00 2001 From: Oleg Lazari Date: Tue, 30 Sep 2025 07:11:11 -0400 Subject: [PATCH 2/6] got rid of calibration (not needed) --- include/core/io/platform/f3xx/ADCf3xx.hpp | 7 ------- include/core/io/platform/f4xx/ADCf4xx.hpp | 7 ------- samples/adc/multi_adc.cpp | 3 +-- samples/adc/single_adc.cpp | 5 +---- src/core/io/platform/f3xx/ADCf3xx.cpp | 5 ----- src/core/io/platform/f4xx/ADCf4xx.cpp | 6 ------ 6 files changed, 2 insertions(+), 31 deletions(-) diff --git a/include/core/io/platform/f3xx/ADCf3xx.hpp b/include/core/io/platform/f3xx/ADCf3xx.hpp index c47cd5ca8..3bcea8e98 100644 --- a/include/core/io/platform/f3xx/ADCf3xx.hpp +++ b/include/core/io/platform/f3xx/ADCf3xx.hpp @@ -31,13 +31,6 @@ class ADCf3xx : public ADC { float getVref() const; - /** - * Perform ADC calibration for improved accuracy - * - * @return true if calibration was successful, false otherwise - */ - static bool calibrate(); - private: // Max number of channels supported by the ADC static constexpr uint8_t MAX_CHANNELS = 15; diff --git a/include/core/io/platform/f4xx/ADCf4xx.hpp b/include/core/io/platform/f4xx/ADCf4xx.hpp index b012d8810..355e11336 100644 --- a/include/core/io/platform/f4xx/ADCf4xx.hpp +++ b/include/core/io/platform/f4xx/ADCf4xx.hpp @@ -150,13 +150,6 @@ class ADCf4xx : public ADC { * aka controls ADC conversion frequency */ static void initTimer(); - - /** - * Perform ADC calibration for improved accuracy - * - * @return true if calibration was successful, false otherwise - */ - static bool calibrate(); }; } // namespace core::io diff --git a/samples/adc/multi_adc.cpp b/samples/adc/multi_adc.cpp index bcf5e0e46..82dfb9152 100644 --- a/samples/adc/multi_adc.cpp +++ b/samples/adc/multi_adc.cpp @@ -33,8 +33,7 @@ int main() { // adc0.setVref(5.0f); // For 5V reference // adc1.setVref(1.8f); // For 1.8V reference - // Optional: Perform ADC calibration for improved accuracy - // adc0.calibrate(); + // ADC calibration removed - not needed for this application while (1) { core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index dc7cd7d4c..596dd590d 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -4,7 +4,6 @@ * UART. */ #include -#include #include #include #include @@ -30,9 +29,7 @@ int main() { - // Optional: Perform ADC calibration for improved accuracy - // Cast to F3xx specific ADC to access calibrate method - static_cast(adc0).calibrate(); + // ADC calibration removed - not needed for this application while (1) { adc0.setVref(1.8f); // For 1.8V reference diff --git a/src/core/io/platform/f3xx/ADCf3xx.cpp b/src/core/io/platform/f3xx/ADCf3xx.cpp index 677c0566e..e7f5b32ab 100644 --- a/src/core/io/platform/f3xx/ADCf3xx.cpp +++ b/src/core/io/platform/f3xx/ADCf3xx.cpp @@ -92,11 +92,6 @@ float ADCf3xx::getVref() const { return vref_voltage; } -bool ADCf3xx::calibrate() { - // Perform ADC calibration for improved accuracy - HAL_StatusTypeDef status = HAL_ADCEx_Calibration_Start(&halADC, ADC_SINGLE_ENDED); - return (status == HAL_OK); -} void ADCf3xx::initADC(uint8_t num_channels) { halADC.Instance = ADC1; // Only ADC the F3 supports diff --git a/src/core/io/platform/f4xx/ADCf4xx.cpp b/src/core/io/platform/f4xx/ADCf4xx.cpp index 123fe1250..f9bb60013 100644 --- a/src/core/io/platform/f4xx/ADCf4xx.cpp +++ b/src/core/io/platform/f4xx/ADCf4xx.cpp @@ -124,12 +124,6 @@ float ADCf4xx::getVref() const { return vref_voltage; } -bool ADCf4xx::calibrate() { - // Note: STM32F4xx doesn't have the same calibration functions as F3xx - // For F4xx, we would need to implement a different calibration approach - // For now, return true as a placeholder - return true; -} void ADCf4xx::initADC(uint8_t num_channels) { /** Configure the global features of the ADC (Clock, Resolution, Data From 3cdf4e9ed320e79082ba77938ce93b626de0ef13 Mon Sep 17 00:00:00 2001 From: Oleg Lazari Date: Tue, 30 Sep 2025 07:11:52 -0400 Subject: [PATCH 3/6] added comments --- samples/adc/multi_adc.cpp | 2 -- samples/adc/single_adc.cpp | 4 ---- samples/adc/vref_demo.cpp | 5 ----- 3 files changed, 11 deletions(-) diff --git a/samples/adc/multi_adc.cpp b/samples/adc/multi_adc.cpp index 82dfb9152..361369362 100644 --- a/samples/adc/multi_adc.cpp +++ b/samples/adc/multi_adc.cpp @@ -33,8 +33,6 @@ int main() { // adc0.setVref(5.0f); // For 5V reference // adc1.setVref(1.8f); // For 1.8V reference - // ADC calibration removed - not needed for this application - while (1) { core::log::LOGGER.log(core::log::Logger::LogLevel::INFO, "--------------------"); core::log::LOGGER.log( diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index 596dd590d..799626c1b 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -27,10 +27,6 @@ int main() { // Optional: Set custom VREF voltage (default is 3.3V) - - - // ADC calibration removed - not needed for this application - while (1) { adc0.setVref(1.8f); // For 1.8V reference uart.printf("1.8V ADC Reference\r\n"); diff --git a/samples/adc/vref_demo.cpp b/samples/adc/vref_demo.cpp index d18fb36aa..371a5220c 100644 --- a/samples/adc/vref_demo.cpp +++ b/samples/adc/vref_demo.cpp @@ -33,11 +33,6 @@ int main() { uint32_t vref_mv = static_cast(adc0.getVref() * 1000); uart.printf("Initial VREF: %d mV\r\n", vref_mv); - // Note: ADC calibration is available in platform-specific implementations - // For STM32F3xx: ADCf3xx::calibrate() - // For STM32F4xx: ADCf4xx::calibrate() - uart.printf("Note: ADC calibration is available via platform-specific methods\r\n"); - time::wait(1000); // Test with default VREF (3.3V) From 47d01368e257fb1a6a80adafc92a7ac2fd22168f Mon Sep 17 00:00:00 2001 From: GitHub Build Date: Tue, 30 Sep 2025 11:23:00 +0000 Subject: [PATCH 4/6] Applied Formatting Changes During GitHub Build --- include/core/io/ADC.hpp | 4 ++-- samples/adc/single_adc.cpp | 6 +++--- samples/adc/vref_demo.cpp | 31 ++++++++++++--------------- src/core/io/platform/f3xx/ADCf3xx.cpp | 3 +-- src/core/io/platform/f4xx/ADCf4xx.cpp | 1 - 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/include/core/io/ADC.hpp b/include/core/io/ADC.hpp index 1d076c6b6..5df9432f4 100644 --- a/include/core/io/ADC.hpp +++ b/include/core/io/ADC.hpp @@ -46,14 +46,14 @@ class ADC { /** * Set the reference voltage for the ADC - * + * * @param[in] vref The reference voltage in volts (e.g., 3.3, 5.0) */ virtual void setVref(float vref) = 0; /** * Get the current reference voltage for the ADC - * + * * @return The reference voltage in volts */ virtual float getVref() const = 0; diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index 799626c1b..405647713 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -28,7 +28,7 @@ int main() { // Optional: Set custom VREF voltage (default is 3.3V) while (1) { - adc0.setVref(1.8f); // For 1.8V reference + adc0.setVref(1.8f); // For 1.8V reference uart.printf("1.8V ADC Reference\r\n"); uint32_t voltage_mv = static_cast(adc0.read() * 1000); uint32_t percentage = static_cast(adc0.readPercentage() * 100); @@ -38,7 +38,7 @@ int main() { uart.printf("--------------------\r\n"); time::wait(500); - adc0.setVref(5.0f); // For 5V reference + adc0.setVref(5.0f); // For 5V reference uart.printf("5V ADC Reference\r\n"); voltage_mv = static_cast(adc0.read() * 1000); percentage = static_cast(adc0.readPercentage() * 100); @@ -48,7 +48,7 @@ int main() { uart.printf("--------------------\r\n"); time::wait(500); - adc0.setVref(3.3f); // For 3.3V reference + adc0.setVref(3.3f); // For 3.3V reference uart.printf("3.3V ADC Reference\r\n"); voltage_mv = static_cast(adc0.read() * 1000); percentage = static_cast(adc0.readPercentage() * 100); diff --git a/samples/adc/vref_demo.cpp b/samples/adc/vref_demo.cpp index 371a5220c..61e1ec124 100644 --- a/samples/adc/vref_demo.cpp +++ b/samples/adc/vref_demo.cpp @@ -38,12 +38,11 @@ int main() { // Test with default VREF (3.3V) uart.printf("\r\n=== Testing with default VREF (3.3V) ===\r\n"); for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); + float voltage = adc0.read(); float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); - - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", - i+1, voltage, percentage * 100, raw); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); time::wait(200); } @@ -55,12 +54,11 @@ int main() { // Test with new VREF uart.printf("\r\n=== Testing with new VREF (5.0V) ===\r\n"); for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); + float voltage = adc0.read(); float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); - - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", - i+1, voltage, percentage * 100, raw); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); time::wait(200); } @@ -72,23 +70,22 @@ int main() { // Test with new VREF uart.printf("\r\n=== Testing with new VREF (1.8V) ===\r\n"); for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); + float voltage = adc0.read(); float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); - - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", - i+1, voltage, percentage * 100, raw); + uint32_t raw = adc0.readRaw(); + + uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); time::wait(200); } // Demonstrate that raw values don't change, only voltage calculations do uart.printf("\r\n=== Demonstrating that raw values are independent of VREF ===\r\n"); uart.printf("Note: Raw ADC values should remain the same regardless of VREF setting\r\n"); - + float test_vrefs[] = {1.0f, 2.5f, 3.3f, 5.0f}; for (float vref : test_vrefs) { adc0.setVref(vref); - uint32_t raw = adc0.readRaw(); + uint32_t raw = adc0.readRaw(); float voltage = adc0.read(); uart.printf("VREF: %.1fV -> Raw: %d, Voltage: %.3fV\r\n", vref, raw, voltage); time::wait(100); diff --git a/src/core/io/platform/f3xx/ADCf3xx.cpp b/src/core/io/platform/f3xx/ADCf3xx.cpp index e7f5b32ab..babdf15d7 100644 --- a/src/core/io/platform/f3xx/ADCf3xx.cpp +++ b/src/core/io/platform/f3xx/ADCf3xx.cpp @@ -26,7 +26,7 @@ ADC_HandleTypeDef ADCf3xx::halADC = {0}; Pin ADCf3xx::channels[MAX_CHANNELS]; uint16_t ADCf3xx::buffer[MAX_CHANNELS]; DMA_HandleTypeDef ADCf3xx::halDMA = {0}; -float ADCf3xx::vref_voltage = DEFAULT_VREF_POS; +float ADCf3xx::vref_voltage = DEFAULT_VREF_POS; ADCf3xx::ADCf3xx(Pin pin, ADCPeriph adcPeriph) : ADC(pin, adcPeriph) { // Flag representing if the ADC has been configured yet @@ -92,7 +92,6 @@ float ADCf3xx::getVref() const { return vref_voltage; } - void ADCf3xx::initADC(uint8_t num_channels) { halADC.Instance = ADC1; // Only ADC the F3 supports diff --git a/src/core/io/platform/f4xx/ADCf4xx.cpp b/src/core/io/platform/f4xx/ADCf4xx.cpp index f9bb60013..1cbc30f72 100644 --- a/src/core/io/platform/f4xx/ADCf4xx.cpp +++ b/src/core/io/platform/f4xx/ADCf4xx.cpp @@ -124,7 +124,6 @@ float ADCf4xx::getVref() const { return vref_voltage; } - void ADCf4xx::initADC(uint8_t num_channels) { /** Configure the global features of the ADC (Clock, Resolution, Data * Alignment and number of conversion) From ecf6d1dbc6f41e96825acb3b24fc17cb2b873d1a Mon Sep 17 00:00:00 2001 From: Oleg Lazari Date: Sat, 18 Oct 2025 10:12:14 -0400 Subject: [PATCH 5/6] fixed some changes from commit stuff --- include/core/io/platform/f3xx/ADCf3xx.hpp | 2 +- include/core/io/platform/f4xx/ADCf4xx.hpp | 2 +- samples/adc/multi_adc.cpp | 2 +- samples/adc/single_adc.cpp | 5 +- samples/adc/vref_demo.cpp | 73 +++++++++-------------- 5 files changed, 34 insertions(+), 50 deletions(-) diff --git a/include/core/io/platform/f3xx/ADCf3xx.hpp b/include/core/io/platform/f3xx/ADCf3xx.hpp index 3bcea8e98..9775ad087 100644 --- a/include/core/io/platform/f3xx/ADCf3xx.hpp +++ b/include/core/io/platform/f3xx/ADCf3xx.hpp @@ -34,7 +34,7 @@ class ADCf3xx : public ADC { private: // Max number of channels supported by the ADC static constexpr uint8_t MAX_CHANNELS = 15; - // Default positive reference voltage of the ADC. Can be updated via setVref() + // Default positive reference voltage of the ADC. Current reference voltage can be updated via setVref() static constexpr float DEFAULT_VREF_POS = 3.3; // Max value for a 12 bit ADC reading (2^12 - 1) static constexpr uint32_t MAX_RAW = 4095; diff --git a/include/core/io/platform/f4xx/ADCf4xx.hpp b/include/core/io/platform/f4xx/ADCf4xx.hpp index 355e11336..1f06e5674 100644 --- a/include/core/io/platform/f4xx/ADCf4xx.hpp +++ b/include/core/io/platform/f4xx/ADCf4xx.hpp @@ -39,7 +39,7 @@ class ADCf4xx : public ADC { static constexpr uint8_t MAX_CHANNELS = 16; // Number of supported ADC Peripherals static constexpr uint8_t NUM_ADCS = 3; - // Default positive reference voltage of the ADC. Can be updated via setVref() + // Default positive reference voltage of the ADC. Current reference voltage can be updated via setVref() static constexpr float DEFAULT_VREF_POS = 3.3; // Max value for a 12 bit ADC reading (2^12 - 1) static constexpr uint32_t MAX_RAW = 4095; diff --git a/samples/adc/multi_adc.cpp b/samples/adc/multi_adc.cpp index 361369362..a583eb48c 100644 --- a/samples/adc/multi_adc.cpp +++ b/samples/adc/multi_adc.cpp @@ -30,7 +30,7 @@ int main() { io::ADC& adc1 = io::getADC(); // Optional: Set custom VREF voltage (default is 3.3V) - // adc0.setVref(5.0f); // For 5V reference + // adc0.setVref(3.6f); // For 3.6V reference (max safe voltage) // adc1.setVref(1.8f); // For 1.8V reference while (1) { diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index 405647713..c64c7b46b 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -17,7 +17,6 @@ int main() { io::UART& uart = io::getUART(9600); - // Logger setup removed - using direct UART prints instead uart.printf("Starting ADC test\r\n"); @@ -38,8 +37,8 @@ int main() { uart.printf("--------------------\r\n"); time::wait(500); - adc0.setVref(5.0f); // For 5V reference - uart.printf("5V ADC Reference\r\n"); + adc0.setVref(3.6f); // For 3.6V reference (max safe voltage) + uart.printf("3.6V ADC Reference\r\n"); voltage_mv = static_cast(adc0.read() * 1000); percentage = static_cast(adc0.readPercentage() * 100); uart.printf("ADC0 : %d mV\r\n", voltage_mv); diff --git a/samples/adc/vref_demo.cpp b/samples/adc/vref_demo.cpp index 61e1ec124..974f48d99 100644 --- a/samples/adc/vref_demo.cpp +++ b/samples/adc/vref_demo.cpp @@ -13,15 +13,32 @@ namespace io = core::io; namespace time = core::time; +// Function to perform ADC test at a given reference voltage +void testADCAtVref(io::ADC& adc, float vref, const char* vref_name, io::UART& uart) { + uart.printf("\r\n=== Testing with %s ===\r\n", vref_name); + adc.setVref(vref); + uint32_t vref_mv = static_cast(adc.getVref() * 1000); + uart.printf("VREF: %d mV\r\n", vref_mv); + + for (int i = 0; i < 5; i++) { + float voltage = adc.read(); + float percentage = adc.readPercentage(); + uint32_t raw = adc.readRaw(); + + uint32_t voltage_mv = static_cast(voltage * 1000); + uint32_t percentage_int = static_cast(percentage * 100); + + uart.printf("Reading %d: %d mV (%d%%, raw: %d)\r\n", i + 1, voltage_mv, percentage_int, raw); + time::wait(200); + } +} + int main() { // Initialize system core::platform::init(); io::UART& uart = io::getUART(9600); - // Set up the logger to catch errors in ADC creation - core::log::LOGGER.setUART(&uart); - core::log::LOGGER.setLogLevel(core::log::Logger::LogLevel::INFO); uart.printf("Starting ADC VREF Demo\r\n"); @@ -36,58 +53,26 @@ int main() { time::wait(1000); // Test with default VREF (3.3V) - uart.printf("\r\n=== Testing with default VREF (3.3V) ===\r\n"); - for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); - float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); + testADCAtVref(adc0, 3.3f, "default VREF (3.3V)", uart); - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); - time::wait(200); - } + // Test with maximum safe VREF (3.6V) + testADCAtVref(adc0, 3.6f, "maximum safe VREF (3.6V)", uart); - // Change VREF to 5.0V (common for many sensors) - uart.printf("\r\n=== Changing VREF to 5.0V ===\r\n"); - adc0.setVref(5.0f); - uart.printf("New VREF: %.2f V\r\n", adc0.getVref()); - - // Test with new VREF - uart.printf("\r\n=== Testing with new VREF (5.0V) ===\r\n"); - for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); - float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); - - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); - time::wait(200); - } - - // Change VREF to 1.8V (common for low-voltage systems) - uart.printf("\r\n=== Changing VREF to 1.8V ===\r\n"); - adc0.setVref(1.8f); - uart.printf("New VREF: %.2f V\r\n", adc0.getVref()); - - // Test with new VREF - uart.printf("\r\n=== Testing with new VREF (1.8V) ===\r\n"); - for (int i = 0; i < 5; i++) { - float voltage = adc0.read(); - float percentage = adc0.readPercentage(); - uint32_t raw = adc0.readRaw(); - - uart.printf("Reading %d: %.3f V (%.1f%%, raw: %d)\r\n", i + 1, voltage, percentage * 100, raw); - time::wait(200); - } + // Test with low voltage VREF (1.8V) + testADCAtVref(adc0, 1.8f, "low voltage VREF (1.8V)", uart); // Demonstrate that raw values don't change, only voltage calculations do uart.printf("\r\n=== Demonstrating that raw values are independent of VREF ===\r\n"); uart.printf("Note: Raw ADC values should remain the same regardless of VREF setting\r\n"); - float test_vrefs[] = {1.0f, 2.5f, 3.3f, 5.0f}; + float test_vrefs[] = {1.0f, 2.5f, 3.3f, 3.6f}; for (float vref : test_vrefs) { adc0.setVref(vref); uint32_t raw = adc0.readRaw(); float voltage = adc0.read(); - uart.printf("VREF: %.1fV -> Raw: %d, Voltage: %.3fV\r\n", vref, raw, voltage); + uint32_t vref_mv = static_cast(vref * 1000); + uint32_t voltage_mv = static_cast(voltage * 1000); + uart.printf("VREF: %d mV -> Raw: %d, Voltage: %d mV\r\n", vref_mv, raw, voltage_mv); time::wait(100); } From 131b16edcf8ca9db9b839ab4445be75037e41130 Mon Sep 17 00:00:00 2001 From: GitHub Build Date: Sat, 18 Oct 2025 14:15:39 +0000 Subject: [PATCH 6/6] Applied Formatting Changes During GitHub Build --- samples/adc/single_adc.cpp | 1 - samples/adc/vref_demo.cpp | 15 +++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/samples/adc/single_adc.cpp b/samples/adc/single_adc.cpp index c64c7b46b..ac5f456d1 100644 --- a/samples/adc/single_adc.cpp +++ b/samples/adc/single_adc.cpp @@ -17,7 +17,6 @@ int main() { io::UART& uart = io::getUART(9600); - uart.printf("Starting ADC test\r\n"); time::wait(500); diff --git a/samples/adc/vref_demo.cpp b/samples/adc/vref_demo.cpp index 974f48d99..52ce67f23 100644 --- a/samples/adc/vref_demo.cpp +++ b/samples/adc/vref_demo.cpp @@ -19,15 +19,15 @@ void testADCAtVref(io::ADC& adc, float vref, const char* vref_name, io::UART& ua adc.setVref(vref); uint32_t vref_mv = static_cast(adc.getVref() * 1000); uart.printf("VREF: %d mV\r\n", vref_mv); - + for (int i = 0; i < 5; i++) { float voltage = adc.read(); float percentage = adc.readPercentage(); uint32_t raw = adc.readRaw(); - - uint32_t voltage_mv = static_cast(voltage * 1000); + + uint32_t voltage_mv = static_cast(voltage * 1000); uint32_t percentage_int = static_cast(percentage * 100); - + uart.printf("Reading %d: %d mV (%d%%, raw: %d)\r\n", i + 1, voltage_mv, percentage_int, raw); time::wait(200); } @@ -39,7 +39,6 @@ int main() { io::UART& uart = io::getUART(9600); - uart.printf("Starting ADC VREF Demo\r\n"); time::wait(500); @@ -68,9 +67,9 @@ int main() { float test_vrefs[] = {1.0f, 2.5f, 3.3f, 3.6f}; for (float vref : test_vrefs) { adc0.setVref(vref); - uint32_t raw = adc0.readRaw(); - float voltage = adc0.read(); - uint32_t vref_mv = static_cast(vref * 1000); + uint32_t raw = adc0.readRaw(); + float voltage = adc0.read(); + uint32_t vref_mv = static_cast(vref * 1000); uint32_t voltage_mv = static_cast(voltage * 1000); uart.printf("VREF: %d mV -> Raw: %d, Voltage: %d mV\r\n", vref_mv, raw, voltage_mv); time::wait(100);