51. Compute ADC Voltage Scale

#include <iostream>
#include <cstdint>

using namespace std;

// Compile-time ADC scale computation using integer truncation
constexpr int32_t computeScale(int32_t maxAdc, int32_t maxVoltage_mV) {
    // Convert millivolts to microvolts, then divide by ADC resolution
    // (3300 * 1000) / 4095 = 805.86... -> truncated to 805
    return (maxVoltage_mV * 1000) / maxAdc;
}

// Compile-time microvolts-per-count scale factor
constexpr int32_t SCALE_UV = computeScale(4095, 3300);

int main() {
    int32_t x;
    if (!(cin >> x)) return 0;

    // Runtime ADC-to-voltage conversion
    // Max result: 4095 * 805 = 3,296,475 (fits in int32_t)
    int32_t voltage_uv = x * SCALE_UV;

    cout << voltage_uv;
    return 0;
}

Explanation & Logic Summary

  • Compile-time optimization:
    The constexpr function ensures the scale factor is computed at compile time, eliminating division at runtime.
  • Fixed-point scaling:
    Microvolts are used instead of volts to preserve precision while using integer arithmetic, which is preferred on MCUs without FPUs.
  • Deterministic truncation:
    Integer division truncates toward zero, matching the behavior expected in embedded fixed-point math.
  • Portability:
    Using int32_t guarantees consistent behavior across 8-bit, 16-bit, and 32-bit embedded targets.

Firmware Relevance & Real Embedded Meaning

In real embedded systems (e.g., STM32, AVR, MSP430), ADC peripherals produce raw digital counts. Converting these counts into meaningful physical units is a fundamental firmware task.

Using constexpr for scale factors is a best practice in modern Embedded C++:

  • Eliminates runtime overhead
  • Improves determinism
  • Enables zero-cost abstractions
  • Keeps code readable and maintainable without sacrificing performance

This pattern is commonly used in HAL drivers, sensor pipelines, battery monitors, and analog measurement subsystems.

 

 

 

 

 

Loading...

Input

0

Expected Output

0