Fig. 1: Imagem mostrando a leitura de tensão no voltímetro miniatura baseado no AVR Attiny85 e no monitor de tensão da bateria
Na maioria das vezes, a medição em circuitos eletrônicos é feita medindo a tensão CC.  Normalmente, colocaremos o multímetro no modo de tensão CC e verificaremos os níveis de tensão em vários pontos da PCB… Normalmente, colocaremos o multímetro no modo de tensão CC e verificaremos os níveis de tensão em vários pontos da PCB.  Principalmente, nossa exigência está entre 5V e 15V DC.  O circuito mostrado é simples, ocupa menos espaço e pode ser conectado diretamente à tensão CC para medição.  Para minimizar o tamanho e o consumo de energia, MCU de 8 pinos e 0,96” OLED é usado no circuito.
O Voltímetro Miniatura possui dois modos de operação.  No primeiro modo (modo bateria de 12V), pode ser conectado diretamente à bateria de 12V, para medir a tensão e monitorar o status da bateria.  No segundo modo (modo voltímetro de 20 VCC), funciona como um voltímetro CC normal, que pode medir de 0,0 a 20,0 VCC.
Dois jumpers J1 e J2 foram fornecidos para escolher entre o modo 1 e o modo 2. Uma vez selecionado o modo, o Attiny85 MCU mede continuamente a tensão através de seu canal ADC, no pino 7 e converte-a em valor digital.  O valor do ADC é convertido no valor de tensão correspondente usando um algoritmo no código.  No modo bateria, dependendo do valor do ADC, diferentes status da bateria (BAIXA, Carregada, Sobrecarregada, etc.), juntamente com o nível de tensão atual da bateria, são exibidos no OLED.  No modo voltímetro, o nível de tensão correspondente é exibido no OLED.
 
Lista de componentes:
ATTINY85 – 1 não.
OLED 0,96” – 1 não.
LM7805 – 1 não.
1N4007 – 3 nºs.
LEDs de 3 mm – 2 nós.
100uF 50V – 1 não.
10uF 16V – 1 não.
Disco 0,1uF – 1 não.
Trimpot 5K – 2 nós.
Resistência de 10K 0,25W – 2 nós.
Resistência de 4,7K 0,25W – 2 nós.
Resistência de 8,6K 0,25W – 1 não.
Resistência de 2,2K 0,25W – 1 não.
Resistência 1K 0,25W – 1 não.
Bateria de 9V – 1 não.
Jumpers de 2,54 mm – 2 nós.
Chave SPDT ou chave deslizante – 1 não.
Diversos.  = conectores, PCB, base IC, tira Berg etc.
IC1 (7805) é um regulador de tensão de 5V usado para fonte de alimentação de IC2 e OLED.  IC2 é um MCU de 8 pinos (ATTINY85) que é o coração do circuito.  Um divisor de tensão é usado para fornecer entrada ao MCU.  O controlador aceita no máximo 5 V como entrada no pino ADC.  O divisor de tensão é usado para trazer a tensão abaixo de 5V.
Módulo OLED (diodo emissor de luz orgânico) de display de 0,96” (com conexões de 4 pinos) é usado aqui para tornar o projeto total compacto.  Apenas dois pinos (SDA e SCL) são usados para transferência de dados para o display OLED e mais dois pinos para fonte de alimentação.  A tela tem resolução de 128×64 pixels.  O texto pequeno é exibido usando tamanho de fonte de 16X8 bits, enquanto a tensão medida é exibida como fonte de tamanho grande usando tamanho de fonte de 32×24 bits.  
Código
Guia de programação –
Neste projeto, o ATtiny85 está programado para exibir o status de carregamento da bateria de 9V ou 12V (conforme o modo selecionado) medindo a tensão terminal da bateria.  O MCU é codificado com C incorporado usando AVR Studio 4.
Constantes usado no código–
#define F_CPU 1000000UL :- Constante usada para definir a frequência do clock do MCU
#define BLINKER 0b00000001 :- Constante usada para piscar o LED como indicação de que o MCU está funcionando corretamente.
#define BATT12V 0B00000010 :- Constante usada para definir o modo de bateria de 12V.
Variáveis usado no código–
A: – Variável usada para armazenar leitura analógica do canal ADC de 10 bits
V: – Variável usada para converter a leitura ADC em tensão e indicar o status da bateria
Prev_mode: – Variável usada para indicar o modo de bateria anterior (modo de bateria de 12V ou 20V)
current_mode: – Variável usada para indicar o modo atual da bateria (modo bateria de 12V ou 20V)
dispstr(6)={'0′,'0′,'.','0′,'/',0} :- Matriz usada para definir o formato do OLED
Arquivos de cabeçalho e bibliotecas usado no código–
#include  : – Cabeçalho AVR padrão para entrada e saída 
#include  : – Cabeçalho AVR padrão para fornecer atrasos de tempo
#include  Cabeçalho AVR padrão incluindo utilitários de espaço de programa 
#include “OLED_LIB.C”: – Biblioteca de uso geral contendo funções para trabalhar com OLED de 0,96”.  Esta biblioteca pode ser usada com qualquer microcontrolador AVR.  Observe que OLED_LIB define o pino 2 como SDA e o pino 3 como SCL de ATtiny85.
#include “FONT_BASIC_16x8.H”: – Este arquivo de cabeçalho contém alfabeto, números e símbolos de tamanho 16 × 8 pixels (pequeno).
#include OLED_NUMS_32x24.H: – Este arquivo de cabeçalho contém apenas números de tamanho de 32 × 24 pixels (grande) para exibir o valor da tensão.
Funções usado no código–
ADC_init : – função usada para inicializar o canal ADC.
readADC : – função usada para ler a tensão analógica do canal ADC 1
OLED_init : – função usada para iniciar a exibição OLED
OLED_floodfill : – função usada para exibir luz brilhante passando o parâmetro 0xFF ou limpar OLED passando o parâmetro 0x00.
Algoritmo –
1) Quando o circuito do voltímetro é ligado, em primeiro lugar, o OLED é inicializado e verificado exibindo uma luz brilhante.  Em seguida, o display OLED é apagado e uma mensagem de boas-vindas – “Bem-vindo ao Voltímetro Miniatura” pisca nele.  O MCU começa a piscar um LED para indicar que está funcionando corretamente.  O MCU verifica o status do modo bateria (modo 12V ou 20V) verificando a entrada digital no pino 6 do Attiny85.  Agora o controlador está pronto para fazer leituras de tensão.
DDRB = BLINKER;
OLED_init ;        //começa a exibir OLED
_atraso_ms(10);
OLED_floodfill(0xFF);   // exibe OLED com luz brilhante como autoteste
_atraso_ms(500);
ADC_init ;                  // inicializa o sistema ADC
OLED_floodfill(0x00);  //exibição em branco do OLED
_atraso_ms(500);
OLED_show_str_16x8 ( ”BEM-VINDO A“,6,0);   // uma mensagem de boas-vindas
OLED_show_str_16x8 ( ”MINIATURA“,11,3);          //é exibido no OLED
OLED_show_str_16x8 ( ” VOLTÍMETRO “,6,6);          // como autoteste de exibição de texto em OLED
_atraso_ms(1000);
OLED_floodfill(0x00);  //exibição em branco do OLED
_atraso_ms(300);
2) O usuário pode fazer a leitura de tensão de uma fonte de tensão padrão (ou conhecida) e ajustar o respectivo potenciômetro (de acordo com o modo atual da bateria) para calibrar o voltímetro.  Neste circuito, o voltímetro é calibrado usando uma fonte de tensão padrão de 12 V onde a leitura ADC é ajustada para 900 (para entrada de 12 V) no modo bateria de 12 V e 750 (para entrada de 12 V) no modo bateria de 20 V.  Após a calibração, espera-se que o voltímetro em miniatura forneça leituras de tensão exatamente precisas.
3) O MCU detecta a tensão da bateria de 12 V ou 20 V no pino 7 (Canal ADC 1) usando a função readADC  e armazena esse valor lido na variável A. O ATtiny85 possui canal ADC de 10 bits, então a leitura do ADC (armazenada em variável A) pode variar de 0 a 1023. Para comparação de tensão para indicar o status da bateria, a leitura ADC de 750 é equivalente a 12 V no caso do modo bateria de 20 V e a leitura ADC de 900 é equivalente a 12 V no caso do modo bateria de 12 V . 
4) O valor armazenado em A é convertido em tensão e armazenado na variável V assumindo que o valor de A sendo 750 (no caso do modo bateria de 20V) ou 900 (no caso do modo bateria de 12V) é equivalente à tensão real de 12V.  Observe que as condições para indicar o status da bateria são definidas no código de acordo.  A suposição acima é derivada da calibração do voltímetro miniatura.  No modo bateria de 20 V, usando tensão conhecida de 12 V, a leitura do ADC é calibrada para 750 usando o potenciômetro.  Da mesma forma, no modo bateria de 12V, ao usar a tensão conhecida de 12V, a leitura do ADC é calibrada para 900 usando o respectivo potenciômetro.  Observe que a conversão da leitura do ADC em tensão depende aqui da calibração.  A fórmula padrão para conversão de terminação única (Vin = ADC*Vref/1024) não é usada no código, considerando o fato de que a tensão de repouso de baterias diferentes pode ser diferente e pode não se ajustar a uma equação de calibração padrão.  
PORTB ^= BLINKER;                         // toggle blinker to indicate MCU is working
A = readAdc ( 1 );                               // read ADC value from channel no 1
curr_mode = (PINB & BATT12V);  // check the mode of operation by usage of jumper J2
// for 12V battery mode or 20VDC voltmeter
if ( prev_mode != curr_mode )
{
OLED_floodfill(0x00);
_delay_ms ( 50 );
}
if ( curr_mode>0 )
V = A/6;
else
V = A/5;
5) O valor de V é comparado em instruções else-if para indicar o status de carregamento da bateria conectada.
if ( curr_mode>0 )        // in case of 12V battery mode, appropriate status is diplayed on OLED
{
OLED_show_str_16x8 ( "12V BAT.METER",0, 0);
if ( V>150 )
OLED_show_str_16x8 ( "NOT 12V BAT  " , 0 ,6);
else if ( V>135 )
OLED_show_str_16x8 ( "OVER CHARG   " , 0 ,6);
else if ( V>120 )
OLED_show_str_16x8 ( "BATT. GOOD   " , 0 ,6);
else if ( V>100 )
OLED_show_str_16x8 ( "BATT. LOW    " , 0 ,6);
else if ( V>90 )
OLED_show_str_16x8 ( "BATT. WEAK   " , 0 ,6);
else if ( V>60 )
OLED_show_str_16x8 ( "BATT. DEAD   " , 0 ,6);
else //if ( V<30 )
OLED_show_str_16x8 ( "BATT.ABSENT  " , 0 ,6);
}
6) O valor de V é formatado em notação decimal e a tensão lida é mostrada no display OLED.  
dispstr(0)=V/100+'0';
V=V%100;
dispstr(1)=V/10+'0';
dispstr(2)='.';
dispstr(3)=V%10+'0';
dispstr(4)='/';
dispstr(5)=0;
7) A leitura ADC armazenada em A é comparada com 1000 para verificar se a tensão excede a faixa designada.
if ( A>1000 )      // in case the ADC read value is out of range then display as OVERFLOW
{
OLED_show_str_16x8 ( " OVERFLOW  " , 0 ,0);
_delay_ms ( 150 );
OLED_show_str_16x8 ( "" , 0 ,0);
_delay_ms ( 100 );
}
Trabalhando: 
Configuração inicial:  
Após montar o circuito em uma placa de circuito impresso, conecte a fonte de alimentação girando SW1 em direção à bateria de 9V.  Em seguida, carregue/grave o arquivo miniVoltMeter.hex no MCU (ATTINY85) usando qualquer programador AVR. 
Inicialmente, o OLED exibe todos os pixels (128×64) no modo ON, tornando a tela brilhante por um tempo.  Em seguida, exibe uma mensagem de boas-vindas como BEM-VINDO AO MEDIDOR DE VOLTS MINIATURA.  Em seguida, exibe a tensão aleatória, que ainda não foi calibrada.
Agora configure a placa para MODO BATERIA 12V, conectando o Jumper J1 e desconectando o Jumper J2.  Em seguida, conecte uma fonte de tensão conhecida de cerca de 12 VCC ou uma bateria de 12 V aos terminais de sinal (ou conecte um multímetro paralelo aos terminais para saber a tensão de entrada exata).  Agora, configure o trim-pot VR1, para mostrar no display a tensão correta no OLED.
Agora, configure a placa para VOLT METER MODE, desconectando o jumper J1 e conectando o jumper J2.  Então, com a mesma fonte de tensão do sinal de entrada, ajuste o trim-pot VR2, para mostrar a tensão correta no OLED.
Agora, a calibração está concluída e o circuito está pronto para uso.  Desconecte a entrada do sinal e configure a placa para um dos modos conforme a necessidade.
Existem dois modos de operação.  12V e 20V.
Para modo bateria de 12V, conecte o jumper J1 e desconecte o jumper J2.  A tensão é lida pelo canal ADC do MCU e exibe a tensão da bateria no OLED em fonte grande.  A linha superior do OLED é exibida como 12V BAT.  METER e resultado final mostram o status da bateria como BATT.ABSENT / BATT.DEAD / BATT.WEAK / BATT.GOOD / OVER CHRG.  etc.
Para modo voltímetro de 20 VCC, desconecte o jumper J1 e conecte o jumper J2.  a tensão do sinal de entrada é lida pelo canal ADC do MCU e exibida em OLED com fonte grande no centro.  Aqui, a linha superior do OLED mostra VOLT METER e a linha inferior mostra 20 DC VOLTS.  
Em ambos os modos, se a tensão de entrada exceder o valor da tensão de entrada ADC (cerca de 5VDC), a linha superior piscará com a mensagem OVERFLOW.  Caso, para ler sinais fracos ou tensões inferiores a 8VDC, o SW1 deve ser voltado para conexão da bateria de 9V.  O circuito voltímetro em miniatura pode ser usado como voltímetro CC rápido para fins de mesa, monitor de tensão e status para carregadores de bateria, bancos de baterias, etc. 
Código-fonte do projeto
/*
Filename : miniVoltMeter.C
author   : Fayaz Hassan
Date     : 15-02-2018
MCU      : ATtiny85 (A)
Display  : OLED (I2C)
*/
#define F_CPU 1000000UL
#include 
#include 
#include 
#include "OLED_LIB.C"
#define BLINKER 0b00000001  
#define BATT12V 0B00000010  
//========================================================================================
void ADC_init ( )
{
    ADCSRA  = ( (1 << ADPS2)   (1 << ADPS1)   (1 << ADPS0)   (1 << ADEN) ); 
}
//========================================================================================
int readAdc ( int channelno )
{
    ADMUX = (channelno%4);
    ADCSRA  = (1 << ADSC);
    while (ADCSRA & (1 << ADSC));
    return ADC;
}
//========================================================================================
int main ( )
{
    int V=0;
    int A=0;
    int prev_mode = -1;
    int curr_mode = 0;
    char dispstr(6)={'0','0','.','0','/',0};
    _delay_ms ( 500 );
    DDRB = BLINKER;
    OLED_init ;
    _delay_ms ( 10 );
    OLED_floodfill(0xFF);
    _delay_ms ( 500 );
    ADC_init ( );
    OLED_floodfill(0x00);
    _delay_ms ( 500 );
    OLED_show_str_16x8 ( " WELCOME TO ",6,0);
    OLED_show_str_16x8 ( " MINIATURE ",11,3); 
    OLED_show_str_16x8 ( " VOLT METER ",6,6); 
    _delay_ms ( 1000 );
    OLED_floodfill(0x00);
    _delay_ms ( 300 );
    readAdc ( 1 );
    readAdc ( 1 );
    while ( 1 )
{
    PORTB ^= BLINKER;
    A = readAdc ( 1 );
    curr_mode = (PINB & BATT12V);
    if ( prev_mode != curr_mode )
{
    OLED_floodfill(0x00);
    _delay_ms ( 50 );
}
    if ( curr_mode>0 )
    V = A/6;
    else
    V = A/5;
    if ( curr_mode>0 )
{
    OLED_show_str_16x8 ( "12V BAT.METER",0, 0);
    if ( V>150 )
    OLED_show_str_16x8 ( "NOT 12V BAT  " , 0 ,6);
    else if ( V>135 )
    OLED_show_str_16x8 ( "OVER CHARG   " , 0 ,6);
    else if ( V>120 )
    OLED_show_str_16x8 ( "BATT. GOOD   " , 0 ,6);
    else if ( V>100 )
    OLED_show_str_16x8 ( "BATT. LOW    " , 0 ,6);
    else if ( V>90 )
    OLED_show_str_16x8 ( "BATT. WEAK   " , 0 ,6);
    else if ( V>60 )
    LED_show_str_16x8 ( "BATT. DEAD   " , 0 ,6);
    else //if ( V<30 )
    OLED_show_str_16x8 ( "BATT.ABSENT  " , 0 ,6);
}
    else
{
    OLED_show_str_16x8 ( " VOLT METER " ,4, 0);
    OLED_show_str_16x8 ( "0-20 DC VOLTS" ,0 ,6);
}
    dispstr(0)=V/100+'0';
    V=V%100;
    dispstr(1)=V/10+'0';
    dispstr(2)='.';
    dispstr(3)=V%10+'0';
    dispstr(4)='/'; 
    dispstr(5)=0;
    if ( dispstr(0)=='0' )
    dispstr(0) = ':';
    OLED_show_str_32x24 ( dispstr , 5, 0,2);
    if ( A>1000 )
{
    OLED_show_str_16x8 ( " OVERFLOW  " , 0 ,0);
    _delay_ms ( 150 );
    OLED_show_str_16x8 ( "           " , 0 ,0);
    _delay_ms ( 100 );
}
prev_mode = curr_mode;
} 
return 0;
}
 
Diagramas de circuito
| Circuito-Diagrama-MiniaturaVOLT-METER-cum-Battery-Tensão-Monitor | 
  | 
 
Vídeo do projeto