/*
* Controle de 12 LEDs usando Charlieplexing (Modo Expandido)
*
* 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
const byte LED_PINS[] = { 1, 2, 3, 4, 5 };
const byte NUM_PINS = sizeof(LED_PINS);
// 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.
const int LED_MAP[NUM_PINS][NUM_PINS] = {
{ -1, 0, 1, 2, 3 },
{ 4, -1, 5, 6, 7 },
{ 8, 9, -1, 10, 11 },
{ 12, 13, 14, -1, 15 },
{ 16, 17, 18, 19, -1 }
};
// Array para armazenar o estado de cada LED (true = ligado, false = desligado)
bool ledStates[12] = {false};
// Variáveis de temporização para o loop principal
unsigned long previousPatternMillis = 0;
const int patternInterval = 100; // Intervalo para mudar o padrão (em ms)
int currentLedInPattern = 0;
void setup() {
// Inicializa 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 < 20; i++) {
ledStates[i] = false;
}
ledStates[currentLedInPattern] = true;
// Incrementa o índice para o próximo LED na sequência
currentLedInPattern++;
if (currentLedInPattern >= 20) {
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
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 11).
* @param state O estado para o LED (true para ligado, false para desligado).
*/
void setLED(int ledIndex, bool state) {
if (ledIndex >= 0 && ledIndex < 19) {
ledStates[ledIndex] = state;
}
}