#include <Encoder.h> // Incluir la librería Encoder
#include <Bounce2.h> // Incluir la librería Bounce2 para debounce
// Pines del contador binario
const int bit0 = 2; // LSB
const int bit1 = 3;
const int bit2 = 4;
const int bit3 = 5; // MSB
// Pin para la fuente de pulso externo
const int clockPin = A3;
// Pines del encoder rotativo
const int pinA = 6; // Canal A del encoder
const int pinB = 7; // Canal B del encoder
const int buttonPin = 8; // Pin para el pulsador del encoder
// Pines del LED RGB
const int ledR = 9;
const int ledG = 10;
const int ledB = 11;
// Pines adicionales para los nuevos pulsadores
const int playPausePin = A0; // Pulsador para Play/Pause
const int incrementPin = A1; // Pulsador para incrementar manualmente
const int decrementPin = A2; // Pulsador para decrementar manualmente
const int resetPin = A4; // Pulsador para resetear el contador
// Nuevo pin para el pulso externo de play/pause
const int externalPlayPausePin = A5; // Pin para el pulso externo
// Variables del contador
int counter = 0;
int lastClockState = LOW;
int maxCount = 7; // Valor máximo ajustable, comienza en 15
int mode = 0; // Modo actual de conteo (0 = ascendente)
bool isPaused = false; // Estado de pausa
// Variables para el modo ascendente/descendente
bool ascending = true; // Variable para alternar el sentido del conteo
// Objetos Encoder y Bounce2
Encoder myEnc(pinA, pinB);
// Objetos para debounce de los pulsadores
Bounce playPauseDebouncer = Bounce();
Bounce incrementDebouncer = Bounce();
Bounce decrementDebouncer = Bounce();
Bounce resetDebouncer = Bounce();
// Variables para gestionar el pulso externo de play/pause
int lastExternalPlayPauseState = LOW;
// Variable para guardar la posición del encoder
long encoderPosition = -999;
void setup() {
// Configurar los pines de salida para los bits
pinMode(bit0, OUTPUT);
pinMode(bit1, OUTPUT);
pinMode(bit2, OUTPUT);
pinMode(bit3, OUTPUT);
// Configurar el pin de entrada para el reloj
pinMode(clockPin, INPUT);
// Configurar los pines del encoder y el botón
pinMode(buttonPin, INPUT_PULLUP);
// Configurar los pines del LED RGB como salida
pinMode(ledR, OUTPUT);
pinMode(ledG, OUTPUT);
pinMode(ledB, OUTPUT);
// Configurar los pines de los nuevos pulsadores
pinMode(playPausePin, INPUT_PULLUP);
pinMode(incrementPin, INPUT_PULLUP);
pinMode(decrementPin, INPUT_PULLUP);
pinMode(resetPin, INPUT_PULLUP);
// Configurar el pin del pulso externo play/pause
pinMode(externalPlayPausePin, INPUT);
// Configurar debounce para los pulsadores
playPauseDebouncer.attach(playPausePin);
playPauseDebouncer.interval(50); // Intervalo de 50 ms para evitar rebotes
incrementDebouncer.attach(incrementPin);
incrementDebouncer.interval(50);
decrementDebouncer.attach(decrementPin);
decrementDebouncer.interval(50);
resetDebouncer.attach(resetPin);
resetDebouncer.interval(50);
// Inicializar la comunicación serial para depuración (opcional)
Serial.begin(9600);
// Establecer el modo inicial (ascendente)
updateLEDColor();
}
void loop() {
// Actualizar el estado de los pulsadores con debounce
playPauseDebouncer.update();
incrementDebouncer.update();
decrementDebouncer.update();
resetDebouncer.update();
// Verificar si el pulsador Play/Pause ha sido presionado
if (playPauseDebouncer.fell()) {
togglePlayPause(); // Cambiar entre pausa y reproducción
}
// Verificar el estado del pulso externo de Play/Pause
int externalPlayPauseState = digitalRead(externalPlayPausePin);
if (externalPlayPauseState == HIGH && lastExternalPlayPauseState == LOW) {
togglePlayPause(); // Cambiar entre pausa y reproducción si el pulso externo se activa
}
lastExternalPlayPauseState = externalPlayPauseState;
// Si está en modo de reproducción, procesar el reloj externo
if (!isPaused) {
int clockState = digitalRead(clockPin);
if (clockState == HIGH && lastClockState == LOW) {
performCounting();
updateLEDs(counter);
}
lastClockState = clockState;
} else {
// Si está en modo pausa, permitir el incremento y decremento manual
if (incrementDebouncer.fell()) {
manualIncrement();
}
if (decrementDebouncer.fell()) {
manualDecrement();
}
}
// Verificar si el botón de reset ha sido presionado
if (resetDebouncer.fell()) {
resetCounter();
}
// Actualizar el valor máximo según el encoder
updateMaxCount();
// Verificar si se ha presionado el botón del encoder
checkButtonPress();
}
// Función para alternar el estado de Play/Pause
void togglePlayPause() {
isPaused = !isPaused;
Serial.println(isPaused ? "Paused" : "Running");
}
// Función para realizar el conteo en función del modo seleccionado
void performCounting() {
switch (mode) {
case 0: // Modo ascendente
counter++;
if (counter > maxCount) {
counter = 0;
}
break;
case 1: // Modo descendente
counter--;
if (counter < 0) {
counter = maxCount;
}
break;
case 2: // Modo ascendente/descendente
if (ascending) {
counter++;
if (counter > maxCount) {
ascending = false; // Cambiar a descendente
counter = maxCount - 1;
}
} else {
counter--;
if (counter < 0) {
ascending = true; // Cambiar a ascendente
counter = 1;
}
}
break;
case 3: // Modo aleatorio
counter = random(0, maxCount + 1);
break;
}
}
// Función para actualizar los LEDs según el valor del contador
void updateLEDs(int count) {
digitalWrite(bit0, count & 0x01); // Bit 0 (LSB)
digitalWrite(bit1, count & 0x02); // Bit 1
digitalWrite(bit2, count & 0x04); // Bit 2
digitalWrite(bit3, count & 0x08); // Bit 3 (MSB)
}
// Función para ajustar el valor máximo según el encoder
void updateMaxCount() {
long newEncoderPosition = myEnc.read() / 4; // Ajustar la sensibilidad del encoder
if (newEncoderPosition != encoderPosition) {
if (newEncoderPosition > encoderPosition) {
maxCount++;
if (maxCount > 15) {
maxCount = 15;
}
} else {
maxCount--;
if (maxCount < 1) {
maxCount = 1;
}
}
Serial.print("Nuevo valor máximo: ");
Serial.println(maxCount);
encoderPosition = newEncoderPosition;
}
}
// Función para verificar si el botón del encoder fue presionado
void checkButtonPress() {
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
mode = (mode + 1) % 4; // Cambiar al siguiente modo
updateLEDColor(); // Cambiar el color del LED RGB
}
}
// Función para incrementar el contador manualmente
void manualIncrement() {
counter++;
if (counter > maxCount) {
counter = 0;
}
updateLEDs(counter);
Serial.print("Manual Increment: ");
Serial.println(counter);
}
// Función para decrementar el contador manualmente
void manualDecrement() {
counter--;
if (counter < 0) {
counter = maxCount;
}
updateLEDs(counter);
Serial.print("Manual Decrement: ");
Serial.println(counter);
}
// Función para resetear el contador
void resetCounter() {
counter = 0;
updateLEDs(counter);
Serial.println("Counter Reset");
}
// Función para actualizar el color del LED RGB dependiendo del modo
void updateLEDColor() {
switch (mode) {
case 0: // Ascendente
digitalWrite(ledR, HIGH);
digitalWrite(ledG, LOW);
digitalWrite(ledB, LOW);
break;
case 1: // Descendente
digitalWrite(ledR, LOW);
digitalWrite(ledG, HIGH);
digitalWrite(ledB, LOW);
break;
case 2: // Ascendente/descendente
digitalWrite(ledR, LOW);
digitalWrite(ledG, LOW);
digitalWrite(ledB, HIGH);
break;
case 3: // Aleatorio
digitalWrite(ledR, HIGH);
digitalWrite(ledG, HIGH);
digitalWrite(ledB, LOW);
break;
}
}