/*
* Controle de 132 LEDs usando Charlieplexing (Animação de Perseguição)
*
* Esta versão refatora o código para usar um sistema de temporização
* não-bloqueante baseado em 'millis()', permitindo animações
* mais complexas e reduzindo a cintilação (flicker).
*
* Autoria: Gemini
*/
// Pinos do Arduino usados para o Charlieplexing
// Nota: O código original usava 12 pinos, que podem controlar 132 LEDs.
// A lógica a seguir foi adaptada para esta configuração.
const byte LED_PINS[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
const byte NUM_PINS = sizeof(LED_PINS);
const int TOTAL_LEDS = NUM_PINS * (NUM_PINS - 1);
// Tabela de mapeamento para ligar um LED específico
// A primeira dimensão representa o pino ANODO (+), a segunda o pino CATODO (-)
// A matriz mapeia o índice do LED para os pinos correspondentes.
int LED_MAP[NUM_PINS][NUM_PINS];
// Array para armazenar o estado de cada LED (true = ligado, false = desligado)
bool ledStates[TOTAL_LEDS] = {false};
// Variáveis de temporização para o loop principal
unsigned long previousPatternMillis = 0;
const int patternInterval = 50; // Intervalo para mudar o padrão (em ms)
int currentLedInPattern = 0;
void setup() {
// Inicializa a tabela de mapeamento
int ledIndex = 0;
for (byte i = 0; i < NUM_PINS; i++) {
for (byte j = 0; j < NUM_PINS; j++) {
if (i == j) {
LED_MAP[i][j] = -1; // Combinação inválida
} else {
LED_MAP[i][j] = ledIndex++;
}
}
}
// Configura todos os pinos como INPUT para evitar curto-circuito
for (byte i = 0; i < NUM_PINS; i++) {
pinMode(LED_PINS[i], INPUT);
}
}
void loop() {
unsigned long currentMillis = millis();
// Executa a função de varredura constantemente para evitar cintilação
scanLEDs();
// Controla a lógica da animação (chase light)
if (currentMillis - previousPatternMillis >= patternInterval) {
previousPatternMillis = currentMillis;
// Desliga todos os LEDs e liga apenas o próximo na sequência
for (int i = 0; i < TOTAL_LEDS; i++) {
ledStates[i] = false;
}
ledStates[currentLedInPattern] = true;
// Incrementa o índice para o próximo LED na sequência
currentLedInPattern++;
if (currentLedInPattern >= TOTAL_LEDS) {
currentLedInPattern = 0;
}
}
}
/*
* Função de varredura (scanning) para atualizar o estado de todos os LEDs.
* Esta função é chamada repetidamente e não usa 'delay()'.
*/
void scanLEDs() {
static int i = 0; // Pinos Anodo
static int j = 0; // Pinos Catodo
// Encontra a próxima combinação válida de pinos para varrer
do {
j++;
if (j >= NUM_PINS) {
j = 0;
i++;
if (i >= NUM_PINS) {
i = 0;
}
}
} while (i == j);
// Desliga os pinos da varredura anterior para evitar correntes parasitas
pinMode(LED_PINS[i], INPUT);
pinMode(LED_PINS[j], INPUT);
int ledIndex = LED_MAP[i][j];
if (ledIndex != -1 && ledStates[ledIndex]) {
// Liga o LED atual se ele estiver no estado 'true'
pinMode(LED_PINS[i], OUTPUT);
pinMode(LED_PINS[j], OUTPUT);
digitalWrite(LED_PINS[i], HIGH); // Anodo
digitalWrite(LED_PINS[j], LOW); // Catodo
}
}
/*
* Função auxiliar para ligar ou desligar um LED específico.
* @param ledIndex O índice do LED (de 0 a 131).
* @param state O estado para o LED (true para ligado, false para desligado).
*/
void setLED(int ledIndex, bool state) {
if (ledIndex >= 0 && ledIndex < TOTAL_LEDS) {
ledStates[ledIndex] = state;
}
}
2
3
4
5
6
7
8
9
10
11
12
13