O circuito de hoje tem por objectivo podermos controlar bastantes LEDs com poucos pinos e sem recorrer a outros integrados. A técnica usada chama-se charlieplexing e foi proposto em 1994 por Charlie Allen da Maxim, tendo no entanto sido alvo de uma patente nos final dos anos 70 por parte da AEG-Telefunken.
A técnica usada por este método reduz o numero de pinos necessários para acender os LEDs pois os pinos assumem os três estados possíveis: alto, baixo e input (alta impedância ou desconectado).
Para se controlarem n(n-1) LEDs são necessários n pinos ou de outra forma para se controlarem L LEDs são necessários (1+sqrt(1+4L))/2.
Pins | LEDs |
---|---|
1 | 0 |
2 | 2 |
3 | 6 |
4 | 12 |
5 | 20 |
6 | 30 |
7 | 42 |
8 | 56 |
9 | 72 |
10 | 90 |
n | n²-n |
É preciso ter em atenção que este método recorre à propriedade da persistência de visão para que tenhamos a aparência de que estão vários LEDs acesos quando na pratica apenas está um. Para que essa aparência seja mantida é necessário que o refrescamento ocorra a mais de 50 Hz.
Por outro lado no circuito apresentado parte-se do principio que todos os LEDs são idênticos. Com LEDs diferentes torna-se necessário garantir que a “forward-voltage” dos LEDs é mais ou menos a mesma.
Esquemático
Nota:
O circuito para o CSEduino pode ser consultado nesta página. Pode igualmente ser usado um Arduino.
Componentes (BOM)
- 12x LED 5mm ou de 3mm (D1-D12)
- 4x Resistências de 1K Ohms (R1-R4)
Código
O Sketch usado foi o seguinte:
#include "Chaplex.h"
byte ctrlpins[] = {10,11,12,13}; //Arduino pins controlling charlieplexed leds
#define PINS 4 //number of these pins
#define DELAY 500 //speed of switching leds in bar on and off
Chaplex myCharlie(ctrlpins, PINS); //control instance
charlieLed myLeds[] = {
{ 0 , 1 },
{ 0 , 2 },
{ 0 , 3 },
{ 1 , 0 },
{ 1 , 2 },
{ 1 , 3 },
{ 2 , 0 },
{ 2 , 1 },
{ 2 , 3 },
{ 3 , 0 },
{ 3 , 1 },
{ 3 , 2 }
};
byte timer2TCNT2 = 178; //preload timer 256-16MHz/1024/78 = near 5 ms
void setup() {
// initialize timer2
noInterrupts(); //disable all interrupts
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = timer2TCNT2;
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); //prescaler 1024 = 64 micro secs
TIMSK2 |= (1 << TOIE2); //enable timer overflow interrupt
interrupts(); //enable all interrupts
}
ISR(TIMER2_OVF_vect) { //timer2 interrupt routine
myCharlie.outRow(); //output for one led row
TCNT2 = timer2TCNT2; //preload timer for next interrupt
}
void loop() {
for (int i=0; i< PINS*PINS-PINS; i++) {
myCharlie.ledWrite(myLeds[i], ON);
delay(DELAY);
}
for (int i=0; i<PINS*PINS-PINS; i++) {
myCharlie.ledWrite(myLeds[i], OFF);
delay(DELAY);
}
}
O Sketch faz uso de uma biblioteca que pode ser descarregada neste link ou então localmente daqui