Visando reduzir a quantidade de pinos utilizados, alterei o circuito para trabalhar com o 74HC595, que é um expansor de portas bem útil (veja aqui outros exemplos desse CI).
O primeiro 74HC595 foi utilizado para acionar cada um dos 8 segmentos do display, enquanto que o segundo foi utilizado pra controlar qual dos displays será exibido a cada vez. Como no exemplo foi utilizado apenas 4 displays, sobraram 4 pinos do segundo 595, sendo possível expandir esse exemplo para até oito displays.
Para saber como fazer as ligações entre os dois expansores e o Arduino, veja o esquema abaixo.

Ligações entre Arduino / 74HC595
Arduino - pino 08 ---> 74HC595 - DS - DATA PIN (Ligar apenas no primeiro 595)
Arduino - pino 09 ---> 74HC595 - STCP- LATCH PIN (Ligar em todos os 595)
Arduino - pino 10 ---> 74HC595 - SHCP- CLOCK PIN (Ligar em todos os 595)
Ligações entre os 74HC595 e os Displays
PRIMEIRO 74HC595 - Q0 --> DP (segmento de ponto decimal)
PRIMEIRO 74HC595 - Q1 --> g
PRIMEIRO 74HC595 - Q2 --> f
PRIMEIRO 74HC595 - Q3 --> e
PRIMEIRO 74HC595 - Q4 --> d
PRIMEIRO 74HC595 - Q5 --> c
PRIMEIRO 74HC595 - Q6 --> b
PRIMEIRO 74HC595 - Q7 --> a
SEGUNDO 74HC595 - Q0 --> primeiro display
SEGUNDO 74HC595 - Q1 --> segundo display
SEGUNDO 74HC595 - Q2 --> terceiro display
SEGUNDO 74HC595 - Q3 --> quarto display
SEGUNDO 74HC595 - Q4..Q7 --> não utilizados (mas poderiam ser utilizados para gerenciar mais displays)
Verifique como ligar os demais pinos no esquema abaixo, ou verifique nesse site aqui.
Código-fonte:
/************************************************************************************************************
**********************************expansor 74hc595***********************************************************
************************************************************************************************************/
class Expansor74HC595 {
private:
int _pin_clock;
int _pin_latch;
int _pin_data;
int _num_cis;
byte* _pins;
int _auto_send;
public:
Expansor74HC595(int pin_clock, int pin_latch, int pin_data, int num_cis){
_pin_clock = pin_clock;
_pin_latch = pin_latch;
_pin_data = pin_data;
_num_cis = num_cis;
_auto_send = true;
_pins = new byte[_num_cis];
pinMode(_pin_clock,OUTPUT);
pinMode(_pin_latch,OUTPUT);
pinMode(_pin_data, OUTPUT);
clear();
};
void startWrite() { _auto_send = false; };
void clear() {
for (int i=0; i<_num_cis; i++) { _pins[i] = 0b00000000; }
send();
};
int read(int pin) {
if (pin >= _num_cis * 8) {return LOW;}
int pos = pin / 8;
pin = pin % 8;
return (_pins[pos] & (1 << pin)) != 0;
};
byte readByte(int num_ci) { return _pins[num_ci]; };
void send(){
digitalWrite(_pin_latch, LOW);
for(int i=_num_cis-1; i>=0; i--) { shiftOut(_pin_data, _pin_clock, MSBFIRST, readByte(i) ); }
digitalWrite(_pin_latch, HIGH);
_auto_send = true;
};
void writeByte(int num_ci, byte b, int first = MSBFIRST) {
if (first == MSBFIRST){
byte reversed;
for(int i=0;i<8;i++){
reversed |= ((b>>i) & 0b1)<<(7-i);
}
b = reversed;
}
_pins[num_ci] = b;
if (_auto_send) { send(); }
};
void write(int pin, int value) {
if (pin >= _num_cis * 8) { return; }
int pos = pin / 8;
pin = pin % 8;
if (value){
_pins[pos] |= (1 << pin); //set a bit HIGH
} else {
_pins[pos] &= ~(1 << pin); //set a bit LOW
}
if (_auto_send) { send(); }
};
};
const int PIN_CLOCK = 10; //SHCP
const int PIN_LATCH = 9; //STCP
const int PIN_DATA = 8; //DS
Expansor74HC595 *exp1;
/************************************************************************************************************
**********************************fim expansor 74hc595*******************************************************
************************************************************************************************************/
/************************************************************************************************************
**********************************display de 7 segmentos*****************************************************
************************************************************************************************************/
const int d7seg_595_index = 0; //em qual dos 595´s será usado pra armazenar os segmentos a, b, c, d, e, f, g e dp
const int d7seg_595_pin_enable[] = {8,9,10,11}; //pinos do 595 para habilitar os displays
const byte d7seg_digits[] = {B11111100, B01100000, B11011010, B11110010, B01100110,
B10110110, B10111110, B11100000, B11111110, B11110110}; //Babcdefg. 0--9
void d7seg_write(int digit, int pos, boolean point=false) {
exp1->startWrite();
exp1->write(d7seg_595_pin_enable[pos], HIGH);
exp1->writeByte(d7seg_595_index, point ? d7seg_digits[digit] | (1 << 0) : d7seg_digits[digit], LSBFIRST); // | (1 << 0) --> alterar o bit que representa o dp (ponto) do display. envia para o 595
exp1->send();
delay(1);
exp1->write(d7seg_595_pin_enable[pos], LOW);
}
void d7seg_write_number(float f, int decimals=0) {
f = (f+0.000001) * pow(10, decimals);
for(int i=0; i<sizeof(d7seg_595_pin_enable)/sizeof(int); i++) {
d7seg_write( (unsigned int)(f/pow(10, i)) % 10, i, (i!=0)&&(decimals==i) );
}
}
/************************************************************************************************************
**********************************fim display de 7 segmentos*************************************************
************************************************************************************************************/
/************************************************************************************************************
**********************************voltimetro*****************************************************************
************************************************************************************************************/
const unsigned long r1 = 1000000; //resistor de 1M
const unsigned long r2 = 100000; //resistor de 100K
const unsigned int aRef = 5; //referencia de 5v
float tensao = 0; //tensao lida
unsigned long millis_ref = 0;
const unsigned long time_refresh = 500; //faz nova leitura a cada 500 ms
float get_tensao(int pin){
return (analogRead(pin) * aRef) / 1023.0 * ( (r1+r2)/r2 );
}
/************************************************************************************************************
**********************************fim voltimetro*************************************************************
************************************************************************************************************/
/************************************************************************************************************
**********************************setup/loop*****************************************************************
************************************************************************************************************/
void setup(){
exp1 = new Expansor74HC595(PIN_CLOCK, PIN_LATCH, PIN_DATA, 2);
}
void loop() {
if ( (millis()-millis_ref) > time_refresh ) { //intervalo de tempo pra atualizar a leitura.
tensao = get_tensao(A0); //calculo da tensão lida
millis_ref = millis();
}
float f = tensao;
d7seg_write_number(f, f>=1000 ? 0 : (f>=100 ? 1 : (f>=10 ? 2 : 3) ) ); //de acordo com o numero, mostra 0, 1, 2 ou 3 casas decimais
}
/************************************************************************************************************
**********************************fim setup/loop*************************************************************
************************************************************************************************************/
Veja também: montagem dos 74hc595


