Embedded C: Convert ADC Value to Voltage Easily
voltage = (adc_value * reference_voltage) / max_adc_value, where reference_voltage is the ADC reference voltage and max_adc_value is the ADC resolution maximum (e.g., 1023 for 10-bit ADC).Examples
How to Think About It
Algorithm
Code
#include <stdio.h> int main() { int adc_value = 512; // example ADC reading float reference_voltage = 5.0; // ADC reference voltage in volts int max_adc_value = 1023; // for 10-bit ADC float voltage = (adc_value * reference_voltage) / (float)max_adc_value; printf("ADC Value: %d\n", adc_value); printf("Voltage: %.3f V\n", voltage); return 0; }
Dry Run
Let's trace adc_value = 512, reference_voltage = 5.0, max_adc_value = 1023 through the code
Read ADC value
adc_value = 512
Calculate voltage
voltage = (512 * 5.0) / 1023 = 2560 / 1023 ≈ 2.502 V
Print voltage
Output: Voltage: 2.502 V
| adc_value | reference_voltage | max_adc_value | voltage |
|---|---|---|---|
| 512 | 5.0 | 1023 | 2.502 |
Why This Works
Step 1: ADC value as fraction
The ADC value represents how much of the reference voltage is measured, so adc_value / max_adc_value gives the fraction of the full scale.
Step 2: Multiply by reference voltage
Multiplying the fraction by reference_voltage converts the fraction back to an actual voltage value.
Step 3: Use float for precision
Using floating-point arithmetic ensures the voltage calculation is accurate and includes decimals.
Alternative Approaches
#include <stdio.h> int main() { int adc_value = 512; int reference_voltage_mv = 5000; // in millivolts int max_adc_value = 1023; int voltage_mv = (adc_value * reference_voltage_mv) / max_adc_value; printf("Voltage: %d mV\n", voltage_mv); return 0; }
#include <stdio.h> float voltage_table[1024]; void init_voltage_table(float ref_voltage) { for (int i = 0; i <= 1023; i++) { voltage_table[i] = (i * ref_voltage) / 1023; } } int main() { int adc_value = 512; init_voltage_table(5.0); printf("Voltage: %.3f V\n", voltage_table[adc_value]); return 0; }
Complexity: O(1) time, O(1) space
Time Complexity
The calculation is a simple arithmetic operation done once per ADC reading, so it runs in constant time O(1).
Space Complexity
Only a few variables are used, so space complexity is O(1), constant memory.
Which Approach is Fastest?
Direct calculation is fastest and simplest; lookup tables trade memory for speed; integer math avoids floating-point but may lose precision.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Direct calculation | O(1) | O(1) | Simple and precise conversions |
| Integer math scaling | O(1) | O(1) | MCUs without floating-point support |
| Lookup table | O(1) | O(n) | Speed-critical applications with enough memory |