Summary of The simplest digital voltmeter with AVR
This project describes a minimal digital voltmeter built around an Atmel AVR ATmega8 microcontroller, driving a three-digit seven-segment LED display via multiplexing. It measures 0–9.99 V on the input divider (2.5 V ADC span) with 10-bit ADC, shows 0–999 counts (values above 999 display ---), offers decimal point jumper options, uses a 1 MHz internal oscillator, ~4 Hz refresh, and is powered from about 5 V. Calibration is via trimmer P1; input impedance ≈1 MΩ (optionally ≈10 MΩ for 100 V range with resistor changes).
Parts used in the Simplest Digital Voltmeter with AVR:
- Atmel AVR ATmega8 (ATmega8L) microcontroller (IO1)
- Three-digit seven-segment LED display (e.g., T-5631BUY-11)
- Resistors R1 to R8 (current limiting for display)
- Input divider resistors R9 and R10
- Trimmer potentiometer P1 (calibration)
- Decimal point jumpers DP1 and DP2
- Power supply (approximately 5 V)
- Wiring/connectors for multiplexed display (port D cathodes, lower 3 bits of port B anodes)
What this is
A voltmeter built from an ATmega8, a 16×2 character LCD and a handful of resistors. The microcontroller’s analog-to-digital converter measures the input, the firmware converts the reading to millivolts, and the LCD shows it. There is no dedicated meter chip and no external ADC: the whole instrument is the AVR’s 10-bit converter plus arithmetic.
The interesting part is not the wiring, it is knowing what the number on the display is actually worth. A 10-bit converter with a 5 V reference resolves about 4.9 mV per step before any error is counted, and the resistor divider that extends the range adds its own error on top. This article covers the circuit, the register settings, the conversion arithmetic and the limits, in that order.
Circuit
- Reference: AVcc (5 V) with a 100 nF capacitor from AREF to ground, or the internal 2.56 V reference when the input range is small. Never leave AREF floating.
- Input divider: two resistors from the measured voltage to the ADC pin, for example 10 kΩ and 4.7 kΩ, giving a division ratio of about 3.13. That turns a 0–15 V input into 0–4.8 V at the pin. The divider’s bottom resistor must be low enough that the ADC’s input leakage does not matter, and the top resistor must be high enough not to load the circuit being measured.
- Protection: a series resistor at the pin and a signal diode to AVcc and to ground. The divider already limits the current, but a divider connected to a 30 V source with the wrong resistor values is a destroyed pin.
- LCD: HD44780-compatible display in 4-bit mode. Six wires: RS, E, D4–D7, plus 5 V and ground. Contrast on the Vo pin from a 10 kΩ potentiometer.
Firmware: the converter
#include <avr/io.h>
void adc_init(void)
{
ADMUX = (1 << REFS0); /* AVcc as reference, channel ADC0 */
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
/* enable, prescaler 128 -> 125 kHz at 16 MHz */
}
uint16_t adc_read(void)
{
ADCSRA |= (1 << ADSC); /* start conversion */
while (ADCSRA & (1 << ADSC)) { } /* wait for the flag to clear */
return ADC; /* 10-bit result, 0..1023 */
}
Two details decide whether the reading is stable. The ADC clock must sit between 50 and 200 kHz for full 10-bit resolution, which is why the prescaler is 128 on a 16 MHz part. And the first conversion after switching channels is not valid; discard one reading before using the next.
From counts to volts
uint16_t raw = adc_read(); uint32_t mv = (uint32_t) raw * 5000UL / 1023UL; /* pin voltage in millivolts */ mv = mv * (R_TOP + R_BOTTOM) / R_BOTTOM; /* undo the divider */
Dividing by 1023 rather than 1024 is the conventional mapping, because the top step represents the reference voltage itself. With a 5 V reference each count is therefore 4.887 mV, not 4.883 mV — a difference that only matters when you are chasing the last digit, but it costs nothing to get right.
Average a burst of readings if the display flickers. Sixteen samples is enough to settle a noisy supply without making the update visibly slow.
Where the accuracy actually goes
- Reference tolerance. The AVR’s AVcc is your 5 V rail. A 7805 is typically ±2 % over temperature and load, which is ±40 counts at full scale. If the reading has to be trusted, measure the actual reference with a known-good meter and use that number in the arithmetic instead of 5000.
- Divider tolerance. Ordinary 5 % resistors give a ratio error of a few percent; 1 % parts or a trim on the divider bring it inside 1 %. Calibrate by measuring a known voltage and storing a single scale factor in EEPROM.
- Input impedance. The ADC wants a source impedance below about 10 kΩ for full accuracy at the recommended sample rate. A 10 kΩ/4.7 kΩ divider has a Thevenin resistance of roughly 3.2 kΩ, which is comfortable.
- Noise. Keep the analog ground return separate from the LCD’s backlight current, and put the 100 nF at AREF close to the pin.
What this instrument is not
It is a panel meter for trends and thresholds, not a calibrated bench instrument. A real DMM resolves microvolts with a stable reference and a integrating converter; this design resolves 4.9 mV, and the absolute accuracy is dominated by the reference and the divider, not by the ADC. If you need better, use an external reference (for example a 2.500 V shunt reference) and a 16-bit converter, and calibrate against a known source.
References
- Microchip/Atmel, ATmega8/ATmega8L datasheet — ADC chapter: reference selection, prescaler table, conversion timing, input impedance guidance.
- Hitachi, HD44780U dot-matrix liquid crystal display controller datasheet — 4-bit interface timing and initialisation sequence.
The register settings and arithmetic above follow those documents. No measurement on a physical build is claimed; if you build it, check the reference with a known meter before trusting the display.
- What microcontroller is used in this voltmeter?
The Atmel AVR ATmega8 (ATmega8L) is used as IO1. - What display is used and how is it driven?
A three-digit seven-segment LED display (example T-5631BUY-11) is used and driven by multiplexing with cathodes on port D and anodes on the lowest 3 bits of port B. - What is the measurement range and resolution?
The voltmeter range corresponds to an ADC input span of 2.5 V with a 1/4 divider giving a 0–9.99 V input range and resolution of 0.01 V. - How are values above 999 displayed?
Values higher than 999 are shown as the symbol ---. - How is calibration performed?
Calibration is performed by adjusting the trimmer potentiometer P1 to match a known reference voltage. - Can I get a 100 V range with this design?
Yes; modify R10 to 9M1 and P1 to 2M2 to get a 100 V range with 0.1 V resolution and about 10 MΩ input impedance. - What is the input impedance of the voltmeter?
The input impedance is approximately 1 MΩ in the described configuration (about 10 MΩ if modified for 100 V range). - What powers the circuit and what oscillator setting is used?
The circuit is powered from about 5 V and IO1 uses the internal RC oscillator set to 1 MHz. - How can decimal points be enabled?
Use jumpers DP1 and DP2 to light decimal points: DP1 for 0.00 and DP2 for 00.0. - What is the refresh rate of the display?
The voltmeter refresh rate is about 4 Hz.
