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
Olá Fabiano!!!
ResponderExcluirPrimeiramente parabéns pelo post. Cara estou tendo dificuldade para enterpretar seu esquema elétrico. Você poderia me dar uma ajuda, principalmente nas ligações dos transistores, não entendi a ligação para o ci 74hc595. Eu já tenho conhecimento com eletronica, mas ainda não conheço integrado 74hc595. Se puder me mandar por email o esquema eletrico ta ai. e-mail: awnr.bios@gmail.com. Desde já agradeço.
Gostaria de saber qual o limite de tensão. Vou fazer uma fonte 30Vcc ajustável, quero montar um voltimetro para indicar o valor de saída da mesma.
ResponderExcluirEste comentário foi removido pelo autor.
ResponderExcluirFabiano, como você faz para castear os 74HC595 se o pino 14 (Data) do próximo CI vai ligado ao pino 9 do primeiro, sendo que esse pino Data precisa ser ligado ao Arduino ? O segundo módulo então nunca poderá ser o primeiro, certo ?
ResponderExcluirsomente o primeiro 595 que tem o pino 14 ligado ao arduino. os demais 595 têm sempre ligado o pino 14 ao pino 9 do 595 anterior... com isso pode-se ligar tantos cis quanto forem necessários.
ExcluirPois é... mas se vc. quiser ligar um "segundo", como se fosse o "primeiro", não vai poder, ou seja, sempre terá um dos módulos que será considerado o "primeiro". Pensei em no lugar de 4 vias, fazer um barramento com 5 vias e um JUMPER para ligar o pino 14 ou ao pino 9 do próximo ou ao Arduino. Assim, ele poderá ser o primeiro ou segundo, ou terceiro... O que acha ?
Excluiracho que funcionaria sim... mas eu só não consegui enxergar uma aplicação prática pra poder alterar qual dos CIs seria o primeiro.
ExcluirImagina vários displays com dígitos grandes... cada um ligado ao seu próprio 74HC595....
Excluir