Código-Fonte:
/*************************************************************************************************************
*******************************BIT ARRAY *********************************************************************
**************************************************************************************************************
mais informações aqui: http://fabianoallex.blogspot.com.br/2015/09/arduino-array-de-bits.html
**************************************************************************************************************/
class BitArray{
private:
int _num_bits; //quantidade de bits a serem gerenciados
int _num_bytes; //quantidade de bytes utilizados para armazenar os bits a serem gerenciados
byte * _bytes; //array de bytes onde estaram armazenados os bits
public:
BitArray(int num_bits){
_num_bits = num_bits;
_num_bytes = _num_bits/8 + (_num_bits%8 ? 1 : 0) + 1;
_bytes = (byte *)(malloc( _num_bytes * sizeof(byte) ) );
}
void write(int index, byte value) {
byte b = _bytes[ index/8 + (index%8 ? 1 : 0) ];
unsigned int bit = index%8;
if (value) { b |= (1 << bit); } else { b &= ~(1 << bit); }
_bytes[ index/8 + (index%8 ? 1 : 0) ] = b;
}
void write(byte value) {
for(int j=0; j<_num_bytes;j++) { _bytes[j] = value ? B11111111 : B00000000; }
}
int read(int index) {
byte b = _bytes[ index/8 + (index%8 ? 1 : 0) ];
unsigned int bit = index%8;
return (b & (1 << bit)) != 0;
}
~BitArray(){ free( _bytes ); }
};
/*************************************************************************************************************
*******************************FIM BIT ARRAY *****************************************************************
**************************************************************************************************************/
class Charlieplexing {
private:
byte _numPins; //numero de pinos utilizados
int * _pins; //ponteiro para array com os pinos utilizados
byte _ledsOnPerGroup;//quantidade de leds de um mesmo grupo que pode ser ligada ao mesmo tempo
BitArray * _states; //armazenas o estados do leds
public:
Charlieplexing(int * pins, byte numPins, byte _ledsOnPerGroup=2);
int numLeds() { return _numPins * _numPins - _numPins; }
void update(int delay_=10, int repeat=1);
void turnOn(int i); //liga led i
void turnOff(int i); //desliga led i
void clear();
byte getState(int i); //retorna status led i
};
Charlieplexing::Charlieplexing(int * pins, byte numPins, byte ledsOnPerGroup){
_ledsOnPerGroup = ledsOnPerGroup;
_numPins = numPins;
_pins = pins;
_states = new BitArray(numLeds());
}
void Charlieplexing::turnOn(int i){
if (i < numLeds()){
_states->write(i, HIGH);
}
}
void Charlieplexing::turnOff(int i){
if (i < numLeds()){
_states->write(i, LOW);
}
}
byte Charlieplexing::getState(int i){
if (i < numLeds()){
return _states->read(i);
}
}
void Charlieplexing::clear(){
_states->write(LOW);
}
void Charlieplexing::update(int delay_, int repeat){
if (repeat <=0) { repeat = 1; }
for (int q=0; q<repeat; q++) {
for (int i=0; i<_numPins; i++) {
digitalWrite(_pins[i], LOW);
pinMode(_pins[i], OUTPUT);
byte cont = 0; //conta se há algum led a ser ligado
for (int j=0;j<_numPins;j++){
if (i != j) {
pinMode(_pins[j], INPUT);
digitalWrite(_pins[j], LOW);
}
}
for (int j=0; j<_numPins; j++) {
if (i != j) {
int posLed = 0;
if (i>j){
posLed = i * i - i + 2 * j + 1; //baseado no calculo do numero triangular
} else {
posLed = j * j - j + 2 * i; //baseado no calculo do numero triangular
}
if (_states->read(posLed) == HIGH){
pinMode(_pins[j], OUTPUT);
digitalWrite(_pins[j], LOW);
cont++;
}
}
if (cont == _ledsOnPerGroup && cont > 0 ) {
cont = 0;
digitalWrite(_pins[i], HIGH);
delay(delay_);
digitalWrite(_pins[i], LOW);
for (int jj=0;jj<=j;jj++){
if (i != jj) {
pinMode(_pins[jj], INPUT);
}
}
}
}
if (cont > 0){
cont = 0;
digitalWrite(_pins[i], HIGH);
delay(delay_);
digitalWrite(_pins[i], LOW);
}
}
}
}
int pins[] = {12, 11, 10, 9, 8};
int qtPins = 5;
int qtLedsOn = 2;
Charlieplexing cp(pins, qtPins, qtLedsOn); //pinos, qtpinos, qtledsOn
void setup(){
cp.turnOn(0);
cp.turnOn(2);
cp.turnOn(4);
cp.turnOn(8);
cp.turnOn(14);
cp.turnOn(7);
cp.turnOn(18);
cp.turnOn(13);
cp.turnOn(15);
cp.turnOn(17);
cp.turnOn(19);
}
void loop() {
cp.update(5, 20); //delay, repeat
}