/*
* Controle de 132 LEDs usando Charlieplexing (Animação de Texto)
*
* Esta versão adiciona a funcionalidade de alternar entre um padrão animado
* (chase light) e um padrão estático (letra 'A'). O array `ledStates`
* atua como uma matriz virtual na memória, permitindo criar qualquer padrão.
*
* 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 o modo de perseguição (em ms)
const int modeChangeInterval = 5000; // Intervalo para alternar modos (em ms)
int currentLedInPattern = 0;
bool isChaseMode = true;
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();
// Alterna entre o modo de perseguição e o modo de padrão estático
if (currentMillis - previousPatternMillis >= modeChangeInterval) {
previousPatternMillis = currentMillis;
isChaseMode = !isChaseMode;
}
if (isChaseMode) {
runChaseAnimation();
} else {
displayLetterA();
}
}
/*
* Executa a animação de perseguição de luz.
*/
void runChaseAnimation() {
unsigned long currentMillis = millis();
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;
}
}
}
/*
* Desenha a letra 'A' na matriz de LEDs.
*/
void displayLetterA() {
// Desliga todos os LEDs para garantir um novo desenho
for (int i = 0; i < TOTAL_LEDS; i++) {
ledStates[i] = false;
}
// Define os índices dos LEDs que formam a letra 'A'.
// Estes índices são baseados no mapeamento de 12 pinos.
// Padrão de exemplo para uma 'A' maiúscula simples
// Pode ser adaptado para uma matriz virtual 2D
setLED(5, true); // topo
setLED(16, true);
setLED(27, true);
setLED(38, true);
setLED(49, true);
setLED(60, true); // barra horizontal
setLED(61, true);
setLED(62, true);
setLED(71, true);
setLED(82, true);
setLED(93, true);
setLED(104, true);
setLED(115, true);
}
/*
* 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