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