O Circuito hoje apresentado é um circuito construído com 3 Shift Registers - 74HC595.
Este circuito permite controlar até 24 outputs - no caso LEDs e controlá-los independentemente.
Foi usado um CSEduino para controlar os 24 outputs. Atendendo a que apenas foram usados 4 pinos do ATMega328P este micro-controlador poderia ter sido substituído por outro mais pequeno/simples.
Poderia ser usado um micro-controlador da família ATTiny que é parecido com os ATMega mas que são mais baratos/pequenos e têm menos funcionalidades.
O 74HC595 é um integrado muito comum que permite expandir o número de outputs uma vez que implementa uma interface Série para Paralela. Permite com apenas 3 pinos do micro-controlador controlar até oito pinos de output. Adicionalmente permite ser ligado em cascata e dessa forma permitir o controlo de ainda mais outputs mantendo os 3 pinos do micro-controlador.
O modo de operação do 74HC595 é o seguinte:
- Baixa-se o sinal do LATCH (também designado por ST_CP ou RCLK)
- Envia-se os bits um a um da seguinte forma:
- Baixa-se o pino do CLOCK (também designado por SH_CP ou SRCLK)
- Envia-se um bit para o pino do DATA (também designado por DS ou SER)
- Levanta-se o pino do CLOCK (também designado por SH_CP ou SRCLK)
- Nota: Deverão ser enviados tantos grupos de oito bits (bytes) quantos os 74hc595 estiverem ligados
- Levantar o sinal do LATCH (também designado por ST_CP ou RCLK)
Adicionalmente pode-se usar o pino OE (também designado por G) do 74HC595 para controlar o brilho dos LEDs, ligando o mesmo a um pino com PWM.
A Cascata é feita ligando também os pinos do CLOCK e do LATCH nos outros integrados e ligando o pino Q7’ do primeiro chip para o DATA do segundo e o Q7’ do segundo chip para o DATA do terceiro chip.
Esquemático
Nota: No esquemático apenas são apresentadas as ligações entre os 74HC595 e os LEDs.
O circuito para o CSEduino pode ser consultado na página do CSEduino. Pode igualmente ser usado um Arduino.
Componentes (BOM)
- 3x 74HC595 - 8-bit serial-in, serial or parallel-out shift register with output latches; 3-state (U1, U2 e U3)
- 24x LED 3mm ou de 5mm (D1-D20)
- 24x Resistências de 470 Ohms (R1-R20)
Pin-out dos IC
Para programar o Micro-controlador usou-se o Arduino IDE.
Código
O Sketch usado foi o seguinte:
/*
Created by Joao Alves on 2015-Jun-8.
Copyright 2014 - Under creative commons license 4.0:
Attribution-ShareAlike CC BY-SA
This software is provided "as is", without technical support, and with no
warranty, express or implied, as to its usefulness for any purpose.
Description:
Circuit with defined 24-Led sequences.
The circuit:
* 3 x 74HC595
- 1st 74HC595 - Pin DATA - D10
- 2nd 74HC595 - Pin DATA - 1st 74HC595 Pin Q7'
- 3rd 74HC595 - Pin DATA - 2st 74HC595 Pin Q7'
- All 74HC595 - Pin LATCH - D12
- All 74HC595 - Pin CLOCK - D11
- All 74HC595 - Pin OE - D9
Created on 2015-Jun-8
By Joao Alves <jpralves@gmail.com>
*/
#include <avr/pgmspace.h>
#if defined (__AVR_ATtiny45__)
#define LATCH 1
#define CLOCK 2
#define DATA 3
#define INTENSITY 0
#else
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Code here
#define LATCH 12
#define CLOCK 11
#define DATA 10
#define INTENSITY 9
#endif
#endif
const int patternDelay = 200;
const byte test_pattern[][3] PROGMEM = {
{0,0,0},
{0,0,1},
{0,0,2},
{0,0,4},
{0,0,8},
{0,0,16},
{0,0,32},
{0,0,64},
{0,0,128},
{0,1,0},
{0,2,0},
{0,4,0},
{0,8,0},
{0,16,0},
{0,32,0},
{0,64,0},
{0,128,0},
{1,0,0},
{2,0,0},
{4,0,0},
{8,0,0},
{16,0,0},
{32,0,0},
{64,0,0},
{128,0,0}
};
void testLeds() {
for (int numberToDisplay = 0; numberToDisplay < sizeof(test_pattern)/3; numberToDisplay++) {
digitalWrite(LATCH, LOW);
// shift out the bits:
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(test_pattern[numberToDisplay][0])));
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(test_pattern[numberToDisplay][1])));
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(test_pattern[numberToDisplay][2])));
//take the latch pin high so the LEDs will light up:
digitalWrite(LATCH, HIGH);
delay(100);
}
}
void setup() {
//set pins to output so you can control the shift register
pinMode(LATCH, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(INTENSITY, OUTPUT);
digitalWrite(INTENSITY, LOW); // Funciona ao contrário
testLeds();
}
const byte pattern[][3] PROGMEM = {
{1,0,0},
{1,1,0},
{1,1,1},
{2,1,1},
{2,2,1},
{2,2,2},
{4,2,2},
{4,4,2},
{4,4,4},
{8,4,4},
{8,8,4},
{8,8,8},
{16,8,8},
{16,16,8},
{16,16,16},
{32,16,16},
{32,32,16},
{32,32,32},
{64,32,32},
{64,64,32},
{64,64,64},
{128,64,64},
{128,128,64},
{128,128,128},
{0,0,0},
{1,0,0},
{1,1,0},
{1,1,1},
{3,1,1},
{3,3,1},
{3,3,3},
{7,3,3},
{7,7,3},
{7,7,7},
{15,7,7},
{15,15,7},
{15,15,15},
{31,15,15},
{31,31,15},
{31,31,31},
{63,31,31},
{63,63,31},
{63,63,63},
{127,63,63},
{127,127,63},
{127,127,127},
{255,127,127},
{255,255,127},
{255,255,255},
{0,0,0},
{128,0,1},
{64,0,2},
{32,0,4},
{16,0,8},
{8,0,16},
{4,0,32},
{2,0,64},
{1,0,128},
{0,1+128,0},
{0,2+64,0},
{0,4+32,0},
{0,8+16,0},
{0,4+32,0},
{0,2+64,0},
{0,1+128,0},
{1,0,128},
{2,0,64},
{4,0,32},
{8,0,16},
{16,0,8},
{32,0,4},
{64,0,2},
{128,0,1}
};
void loop()
{
for (int numberToDisplay = 0; numberToDisplay < sizeof(pattern)/3; numberToDisplay++) {
digitalWrite(LATCH, LOW);
// shift out the bits:
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(pattern[numberToDisplay][0])));
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(pattern[numberToDisplay][1])));
shiftOut(DATA, CLOCK, MSBFIRST, pgm_read_byte(&(pattern[numberToDisplay][2])));
//take the latch pin high so the LEDs will light up:
digitalWrite(LATCH, HIGH);
delay(patternDelay);
}
}
// Sketch uses 1,646 bytes (5%) of program storage space. Maximum is 32,256 bytes.
// Global variables use 9 bytes (0%) of dynamic memory, leaving 2,039 bytes for local variables. Maximum is 2,048 bytes.
Este sketch está preparado para funcionar com o Atmega328P assim como com micro-controladores mais simples.
O Sketch acima apresenta uma forma simples de guardar dados na flash. Este método envolve alguns aspectos:
- Deverá ser incluído o ficheiro de header
<avr/pgmspace.h>
- Referenciar na declaração das variáveis a definição PROGMEM
- Aceder às variáveis através de funções especiais designadas por pgm_read_byte ou por pgm_read_word
- As variáveis têm que ser declaradas como const (uma vez que não podem ser alteradas).
Este circuito foi usado para criar uma estrela de Natal animada.