/*
 * 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