[SOLUCIONADO] Reduccionismo: De 10 pulsadores a un encoder KY-040

Buenas a todos, espero que estén bien.

Hace un tiempo, gracias a la ayuda de algunos miembros de la comunidad, despejé un montón de dudas y me permitió concretar un poco mas mi proyecto, el cual nuevamente se ve demorado por mi inexperiencia en este campo, obligándome a recurrir nuevamente a sus conocimientos.

El proyecto:
El proyecto se trata de un dispositivo para contar distintos tipos de valores (Vida, Veneno y daño de comandantes (3) ) en un juego de cartas, en este caso, MTG. Y cuyos valores incrementan o decrecen gracias a dos pulsadores por contador, lo cual hace un total de 10 pulsadores.

El problema:
Por cuestiones de tamaño, el diseño final del dispositivo me impide contar con 10 pulsadores físicos para la tarea, por lo cual me veo obligado a optar por un encoder, específicamente el KY-040 (adjunto imagen de referencia)
Sensor-Encoder-Rotatorio-KY-040-1
y solo dos pulsadores para incrementar o decrecer los valores seleccionados.

Mi solicitud:
No cuento con los conocimientos necesarios en este campo, solo soy un aficionado que quiere diseñar un objeto para enriquecer su juego de mesa, por eso humildemente les solicito ayuda con este problema.
Quisiera que me ayudaran a modificar mi código para:

  1. Que el dispositivo solo cuente con un Encoder KY-040 y dos pulsadores normalmente abiertos como métodos de entrada.
  2. Que el Encoder KY-040 funcione como selector (omitiendo su switch) y que los pulsadores puedan variar el valor sobre donde esta posicionado el encoder.

Dicho en palabras simples, quiero utilizar el encoder como una rueda de selección entre los 5 contadores y que con los pulsadores dichos contadores cambien de valor.

El código:

//Proyecto: "Contador para MTG - Commmander"
//Descripcion: Dispositivo que permite tener cinco contadores: 1 para la Vida, 1 para Veneno y 3 contadores para puntos de daños por parte de los comandantes enemigos, cuyos valores incrementan o decrecen segun el pulsador asociado. 
             //Los valores limite para ellos son: Vida = 20, Veneno = 10, COM (1/2/3) = 21. Los valores son impresos en un dispaly OLED SSD1306 de 0.91 pulgadas.
//Creador: KingAbaaddon

//**Librerias
//Pantalla
#include <Adafruit_SSD1306.h>   // libreria para controlador SSD1306
//Pantalla
#define ANCHO 128     // reemplaza ocurrencia de ANCHO por 128
#define ALTO 64       // reemplaza ocurrencia de ALTO por 64
//Reset
#define OLED_RESET -1      // necesario por la libreria pero no usado. -1 porque tiene boton
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);  // crea objeto

//**Declaraciones
//Vida
int valor_actual = -1; // valor inicial -1 para inicializar antes de contar
int pulsador = 4; // pin en donde se conecta el pulsador
int despulsador = 3; // pin en donde se conecta el pulsador
bool estPulActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estPulAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador

//Veneno
int valor_actual_veneno = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_veneno = 6; // pin en donde se conecta el pulsador
int pulsador_veneno_negativo = 5; // pin en donde se conecta el pulsador
bool estVenActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estVenAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador

//Comandantes
//COM1
int valor_actual_COM1 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM1 = 8; // pin en donde se conecta el pulsador
int pulsador_COM1n = 7; // pin en donde se conecta el pulsador
bool estCOM1Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM1Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador
//COM2
int valor_actual_COM2 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM2 = 10; // pin en donde se conecta el pulsador
int pulsador_COM2n = 9; // pin en donde se conecta el pulsador
bool estCOM2Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM2Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador
//COM3
int valor_actual_COM3 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM3 = 12; // pin en donde se conecta el pulsador
int pulsador_COM3n = 11; // pin en donde se conecta el pulsador
bool estCOM3Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM3Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador


//**Logo

// 'LOGO', 128x48px
const unsigned char Mi_Logologo [] PROGMEM = {
  
  0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x03, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x07, 0xc2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x0f, 0xe2, 0x02, 0x00, 0x04, 0x30, 0x7c, 0x01, 0xf9, 0xe2, 0x13, 0xc0, 0x60, 0x30, 0x20, 
  0x02, 0x0f, 0xe3, 0x06, 0x00, 0x1f, 0x7c, 0x7c, 0x19, 0xfd, 0xf7, 0x37, 0xc0, 0xf8, 0x60, 0x60, 
  0x02, 0x1f, 0xf1, 0xfc, 0x00, 0x19, 0x64, 0x70, 0x18, 0x30, 0xe7, 0x37, 0x00, 0x4c, 0x4e, 0x60, 
  0x02, 0x1f, 0xf0, 0xd8, 0x00, 0x30, 0x6c, 0x70, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60, 
  0x02, 0x0f, 0xe0, 0x88, 0x00, 0x30, 0x6c, 0x60, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60, 
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x20, 0x76, 0x60, 0x2c, 0x30, 0xe3, 0x67, 0x00, 0x6c, 0x42, 0x60, 
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x60, 0x04, 0x60, 0x24, 0x30, 0x61, 0x66, 0x00, 0x4c, 0x42, 0x60, 
  0x02, 0x03, 0x81, 0x8c, 0x00, 0x60, 0x3c, 0x78, 0x24, 0x30, 0x61, 0x63, 0x80, 0x78, 0x40, 0x60, 
  0x1f, 0xf9, 0x03, 0x06, 0x00, 0x60, 0x38, 0x3c, 0x24, 0x30, 0x61, 0x63, 0xc0, 0x70, 0x40, 0x60, 
  0x3f, 0xf8, 0x02, 0x02, 0x00, 0x60, 0x38, 0x38, 0x24, 0x30, 0x61, 0xe3, 0xc0, 0x60, 0x42, 0x60, 
  0x20, 0x08, 0x06, 0x01, 0x00, 0x60, 0x38, 0x30, 0x24, 0x30, 0x61, 0xe3, 0x00, 0x70, 0x5a, 0x60, 
  0x26, 0x4f, 0xff, 0x01, 0x00, 0x60, 0x38, 0x30, 0x7e, 0x30, 0x61, 0xe3, 0x00, 0x70, 0xd2, 0x60, 
  0x24, 0x4c, 0x03, 0x01, 0x80, 0x60, 0x3c, 0x30, 0x4e, 0x30, 0x60, 0xc3, 0x00, 0x78, 0xd2, 0x60, 
  0x20, 0x0c, 0x03, 0x01, 0x80, 0x30, 0x34, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x58, 0xd2, 0x60, 
  0x20, 0x08, 0x01, 0x81, 0xc0, 0x30, 0x36, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x5c, 0x42, 0x60, 
  0x26, 0x48, 0x81, 0xff, 0xc0, 0x1b, 0x36, 0x70, 0xc2, 0x30, 0x60, 0xc3, 0x00, 0x4c, 0x64, 0x70, 
  0x24, 0x48, 0x01, 0x80, 0xc0, 0x0f, 0x37, 0x7d, 0xc2, 0x30, 0xf0, 0x83, 0xe0, 0x66, 0x3c, 0x7e, 
  0x20, 0x08, 0x01, 0x82, 0xc0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x01, 0xc0, 0x00, 0x10, 0x3c, 
  0x30, 0x18, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x3f, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  
};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 784)
const int Mi_LogoallArray_LEN = 1;
const unsigned char* Mi_LogoallArray[1] = {
  Mi_Logologo
};


//**Setup

void setup() {
  pinMode(pulsador, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(despulsador, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_veneno, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_veneno_negativo, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM1, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM1n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM2, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM2n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM3, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM3n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  delay(100);  // se da una espera de 100ms para que el display inicie correctamente
  Wire.begin();         // inicializa bus I2C
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inicializa pantalla con direccion 0x3C
  oled.clearDisplay();      // limpia pantalla
  oled.drawBitmap(0, 17, Mi_Logologo, 128, 32, WHITE);
  oled.display();
  delay(2000);  // se da una espera de 100ms para que el display inicie correctamente
  oled.setRotation(0);  // se escoje la orientacion del display puede ser 0, 1, 2 o 3
  oled.setTextColor(WHITE);  // se le dice a la pantalla que el texto que se va a desplegar es en color blanco
  oled.dim(false); //dejamos el brillo en maximo
  oled.setTextSize(2);      // establece tamano de texto en 2
  oled.clearDisplay();      // limpia pantalla
}

void loop() {

  //..Vida
  
  //SUMA vida
  estPulActual = digitalRead(pulsador); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estPulAnterior == 1 && estPulActual == 0) || valor_actual == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual++; // suma 1 al valor de la variable contador
    if (valor_actual > 99) { // si el contador supera 99
      valor_actual = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estPulAnterior = estPulActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA vida
  estPulActual = digitalRead(despulsador); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estPulAnterior == 1 && estPulActual == 0) || valor_actual == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual--; // resta 1 al valor de la variable contador
    if (valor_actual < 0) { // si el contador supera 99
      valor_actual = 99; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estPulAnterior = estPulActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  

  //..Veneno
  
  //SUMA veneno
  estVenActual = digitalRead(pulsador_veneno); //se lee el valor logico del pin de entraday se guarda en la variable estVenActual
  if ((estVenAnterior == 1 && estVenActual == 0) || valor_actual_veneno == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_veneno++; // suma 1 al valor de la variable contador
    if (valor_actual_veneno > 10) { // si el contador supera 10
      valor_actual_veneno = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estVenAnterior = estVenActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estVenAnterior


  //RESTA veneno
  estVenActual = digitalRead(pulsador_veneno_negativo); //se lee el valor logico del pin de entraday se guarda en la variable estVenActual
  if ((estVenAnterior == 1 && estVenActual == 0) || valor_actual_veneno == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_veneno--; // resta 1 al valor de la variable contador
    if (valor_actual_veneno < 0) { // si el contador menor a 0
      valor_actual_veneno = 10; // devuelve el contador a 10
    }
  }
  delay(20); //pausa de 20 milisegundos
  estVenAnterior = estVenActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //..Comandantes
  
  //COM1

  //SUMA puntos
  estCOM1Actual = digitalRead(pulsador_COM1); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM1Anterior == 1 && estCOM1Actual == 0) || valor_actual_COM1 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM1++; // suma 1 al valor de la variable contador
    if (valor_actual_COM1 > 21) { // si el contador supera 99
      valor_actual_COM1 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM1Anterior = estCOM1Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM1Actual = digitalRead(pulsador_COM1n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM1Anterior == 1 && estCOM1Actual == 0) || valor_actual_COM1 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM1--; // resta 1 al valor de la variable contador
    if (valor_actual_COM1 < 0) { // si el contador supera 99
      valor_actual_COM1 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM1Anterior = estCOM1Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //COM2

  //SUMA puntos
  estCOM2Actual = digitalRead(pulsador_COM2); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM2Anterior == 1 && estCOM2Actual == 0) || valor_actual_COM2 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM2++; // suma 1 al valor de la variable contador
    if (valor_actual_COM2 > 21) { // si el contador supera 99
      valor_actual_COM2 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM2Anterior = estCOM2Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM2Actual = digitalRead(pulsador_COM2n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM2Anterior == 1 && estCOM2Actual == 0) || valor_actual_COM2 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM2--; // resta 1 al valor de la variable contador
    if (valor_actual_COM2 < 0) { // si el contador supera 99
      valor_actual_COM2 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM2Anterior = estCOM2Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //COM3

  //SUMA puntos
  estCOM3Actual = digitalRead(pulsador_COM3); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM3Anterior == 1 && estCOM3Actual == 0) || valor_actual_COM3 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM3++; // suma 1 al valor de la variable contador
    if (valor_actual_COM3 > 21) { // si el contador supera 99
      valor_actual_COM3 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM3Anterior = estCOM3Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM3Actual = digitalRead(pulsador_COM3n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM3Anterior == 1 && estCOM3Actual == 0) || valor_actual_COM3 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    valor_actual_COM3--; // resta 1 al valor de la variable contador
    if (valor_actual_COM3 < 0) { // si el contador supera 99
      valor_actual_COM3 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM3Anterior = estCOM3Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior
  

  //**Impresion de pantalla

  //Campos
  oled.drawRect(0, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawRect(31, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawTriangle(62, 17, 92, 17, 77, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(79, 47, 94, 17, 110, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(96, 17, 127, 17, 112, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  
  //Titulos
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(2, 0);
  oled.println("LIFE");
  oled.setCursor(31, 0);
  oled.println("VENOM");
  oled.setCursor(69, 0);
  oled.println("COMMANDER");
  oled.setCursor(74, 9);
  oled.println("1");
  oled.setCursor(92, 9);
  oled.println("2");
  oled.setCursor(109, 9);
  oled.println("3");
  
  //Impresion de valores Vida y Veneno
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(3, 25);   // ubica cursor en coordenadas 15,32
  oled.print(valor_actual);     // escribe texto
  oled.setCursor(34, 25);   // ubica cursor en coordenadas 34,25
  oled.print(valor_actual_veneno);     // escribe texto

  //Impresion de valores COM1/2/3
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(74, 22);   // ubica cursor en coordenadas 34,25
  oled.print(valor_actual_COM1);     // escribe texto
  
  oled.setCursor(92, 35);   // ubica cursor en coordenadas 34,25
  oled.print(valor_actual_COM2);     // escribe texto
 
  oled.setCursor(109, 22);   // ubica cursor en coordenadas 34,25
  oled.print(valor_actual_COM3);     // escribe texto
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
}


Desde ya, muchas gracias a la comunidad por el espacio.
Saludos!

Hay librerías que conforman menúes de fácil armado, los has visto y considerado?
Busca librerias encoder Oled como para tener algo mas segmentado.

1 Like

Hola surbyte, un gusto verte de nuevo por un hilo mio.
Si, observe un par de librerias, pero realmente no se como extrapolar lo que necesito, por ejemplo en este codigo

/*********************************************************************
 * 
 * This example is for a 128x64 size display using I2C to communicate
 * 3 pins are required to interface (2 I2C and one reset)
 * 
 *********************************************************************/

#include <MenuSystem.h>
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


// Encoder Pins

const int                                 PinCLK   = 2;     // Used for generating interrupts using CLK signal
const int                                 PinDT    = 4;     // Used for reading DT signal
const int                                 PinSW    = 8;     // Used for the push button switch


volatile int                              virtualPosition = 0;

// -----------------------------------------------------------------------------
// Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK

void isr ()  {

  static unsigned long  lastInterruptTime = 0;

  unsigned long   interruptTime = millis();

  // If interrupts come faster than 5ms, assume it's a bounce and ignore
  if (interruptTime - lastInterruptTime > 5) {
    if (!digitalRead(PinDT))
      virtualPosition = virtualPosition + 1;
    else
      virtualPosition = virtualPosition - 1;
  }
  lastInterruptTime = interruptTime;
} // ISR



#define SELECTED_DISPLAY_DELAY 1500

// Menu variables
MenuSystem ms;
Menu mm("Main Menu");
MenuItem mm_mi1("Read A0 PIN");
MenuItem mm_mi2("Blink led");

Menu mu1("Date & Time");
MenuItem mu1_mi1("Show current");
//MenuItem mu1_mi2("Set");
MenuItem mu1_mi3("Go back");


boolean menuSelected = false; // no menu item has been selected
boolean commandReceived = false;// no command has been received (Seria, button, etc)
enum setMenuSelected_Type { 
  DATETIME, OTHER }; // this enum is in case we want to expand this example
setMenuSelected_Type setMenu;

byte cursorPosition;


int led = 13; // connect a led+resistor on pin 41 or change this number to 13 to use default arduino led on board
int ledState = LOW;
String dateTime = "14.08.2015 16:00";

// Menu callback functions
void on_item1_selected(MenuItem* p_menu_item) {
  display.clearDisplay();

  display.setCursor(0,1);
    display.setTextSize(1);
  display.print("Analog A0: ");

    display.setCursor(0,3);
    display.setTextSize(2);

  display.print(analogRead(A0));
  display.display();
    delay(SELECTED_DISPLAY_DELAY);

}

void on_item2_selected(MenuItem* p_menu_item) {
  ledState = !ledState;
  digitalWrite(led,ledState);
  display.setCursor(0,1);
  display.setTextSize(2);

  if(ledState)
  {
    display.clearDisplay();
    display.print("Led: ON ");
  }
  else
  {
    display.clearDisplay();
    display.print("Led: OFF ");

  }
  display.display();
  delay(SELECTED_DISPLAY_DELAY);

}

// on_back_selected is usefull if you don't have a button to make the back function
void on_back_selected(MenuItem* p_menu_item) {
  ms.back();
}

void on_time_show_selected(MenuItem* p_menu_item) {
  display.clearDisplay();
  display.setCursor(0,1);
    display.setTextSize(2);

  display.print(dateTime);
  delay(SELECTED_DISPLAY_DELAY);
  display.display();

}

void setup()   {  

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  Serial.begin(9600);

  pinMode(PinCLK,INPUT);
  pinMode(PinDT, INPUT);
  pinMode(PinSW, INPUT);

  attachInterrupt(0, isr, FALLING);   // interrupt 0 is always connected to pin 2 on Arduino UNO

  mm.add_item(&mm_mi1, &on_item1_selected);
  mm.add_item(&mm_mi2, &on_item2_selected);
  mm.add_menu(&mu1);
  mu1.add_item(&mu1_mi1, &on_time_show_selected);
  // mu1.add_item(&mu1_mi2, &on_time_set_selected);
  mu1.add_item(&mu1_mi3, &on_back_selected);
  ms.set_root_menu(&mm);
  displayMenu();

}


void loop() {


  display.setTextSize(1);
  display.setTextColor(WHITE);  

  int lastCount = 0;

  displayMenu();

  while (true) {

    if (!(digitalRead(PinSW))) {        // check if pushbutton is pressed
      virtualPosition = 0;            // if YES, then reset counter to ZERO
      while (!digitalRead(PinSW)) {
      }  // wait til switch is released
      if(!menuSelected)
        ms.select();
      else if(cursorPosition<15)
        display.setCursor(++cursorPosition,1);
      display.display();


    }   



    if (virtualPosition != lastCount) {
      if(lastCount < virtualPosition)
      {
        ms.next();
        displayMenu();

        display.display();

      }
      if(lastCount > virtualPosition)
      {
        ms.prev();
        displayMenu();

        display.display();

      }
      lastCount = virtualPosition;


    } 
  }
}







void displayMenu() {
  display.clearDisplay();
  display.setCursor(0,0);
    display.setTextSize(1);

  // Display the menu
  Menu const* cp_menu = ms.get_current_menu();

  display.println(cp_menu->get_selected()->get_name());

  display.display();
}

recuperado de un sitio en github y por mas que lo vea y trate de entenderlo, no lo logro.

Donde esta esto?

#include <MenuSystem.h>

No lo encuentro en github pero acá si lo encontré

2da opcion:
Acá encontré otro que pueda servirte

1 Like

Observe ambas librerías y la verdad, no logro visualizar lo que necesito.
Anduve buscando un poco mas por la web y me tope con este video y se acerca bastante a lo que quiero. El código que se trabaja en el video es este:

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#define OLED_ADDR   0x3C
Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

#define encoder0PinA  2
#define encoder0PinB  3
volatile unsigned int encoder0Pos = 0;

int valA;
int valB;
int valC;

byte clk;
byte menuCount = 1;
byte dir = 0;
bool runState = false;

void setup() {
  pinMode(6, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.display();
  display.clearDisplay();
  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
}

void loop() {
  clk = digitalRead(4);
  ledControl();
  menuCheck();
  staticMenu();
  display.clearDisplay();
  delay(50);
}

void staticMenu() {
  display.setTextSize(2);
  display.setTextColor(WHITE);

  display.setCursor(10, 0);
  display.println("yyRobotic");
  //---------------------------------
  display.setTextSize(1);
  display.setCursor(10, 20);
  display.println("Value A:");
  display.setCursor(60, 20);
  display.println(valA);

  display.setCursor(10, 30);
  display.println("Value B:");
  display.setCursor(60, 30);
  display.println(valB);

  display.setCursor(10, 40);
  display.println("Value C:");
  display.setCursor(60, 40);
  display.println(valC);

  display.setCursor(10, 50);
  display.println("Start:");
  display.setCursor(45, 50);
  if (encoder0Pos > 5 && menuCount == 4) {
    display.println("Run!");
    runState = true;
  } else {
    display.println("Idle");
    runState = false;
  }
  display.setCursor(2, (menuCount * 10) + 10);
  display.println(">");

  display.display();
}

void ledControl() {
  if (runState == true) {
    analogWrite(6, valA);
    analogWrite(9, valB);
    analogWrite(10, valC);
  }
}
void menuCheck() {
  if (clk == LOW && menuCount < 5) {
    menuCount++;
    encoder0Pos = 0;
  }
  if (clk == LOW && menuCount >= 5) {
    menuCount = 1;
  }

  if (menuCount == 1) {
    valA = encoder0Pos;
  }
  if (menuCount == 2) {
    valB = encoder0Pos;
  }
  if (menuCount == 3) {
    valC = encoder0Pos;
  }
}

void doEncoder() {
  if (digitalRead(encoder0PinA) == HIGH) {
    if (digitalRead(encoder0PinB) == LOW && encoder0Pos > 0) {
      encoder0Pos = encoder0Pos - 1;
      dir = 0;
    }
    else {
      encoder0Pos = encoder0Pos + 1;
      dir = 1;
    }
  }
  else
  {
    if (digitalRead(encoder0PinB) == LOW ) {
      encoder0Pos = encoder0Pos + 1;
      dir = 1;
    }
    else {
      if (encoder0Pos > 0) {
        encoder0Pos = encoder0Pos - 1;
        dir = 0;
      }
    }
  }
}

con la diferencia de que yo no quiero usar el pulsador incorporado, sino que quiero navegar por el menú con el decoder y cambiar los valores con dos pulsadores externos.

Creo entender que este fragmento:

void doEncoder() {
 if (digitalRead(encoder0PinA) == HIGH) {
   if (digitalRead(encoder0PinB) == LOW && encoder0Pos > 0) {
     encoder0Pos = encoder0Pos - 1;
     dir = 0;
   }
   else {
     encoder0Pos = encoder0Pos + 1;
     dir = 1;
   }
 }
 else
 {
   if (digitalRead(encoder0PinB) == LOW ) {
     encoder0Pos = encoder0Pos + 1;
     dir = 1;
   }
   else {
     if (encoder0Pos > 0) {
       encoder0Pos = encoder0Pos - 1;
       dir = 0;
     }
   }
 }

es lo que define en que sentido gira el decoder, pero como lo puedo utilizar para mi cometido?

Disculpa Surbyte, pero no logro dar con la lógica de lo que quiero.

Buenas de nuevo.
Después de darle vueltas al tema, el diseño final del dispositivo seria algo así:

Requerimientos finales:

1 El pulsador "Mode" me permite seleccionar que contador se va a modificar (Life, Venom, Commander 1, Commmander 2 o Commander 3).

2 Una vez posicionado sobre el contador a modificar y según el sentido de la rueda (decoder KY-040) los valores incrementaran o disminuirán.

No logro entender como modificar mi código para eliminar los pulsadores que tengo actualmente en el mismo.
Si alguien esta dispuesto (de tiempo, paciencia y energía) a enseñarme como procedo seria mas que agradecido.

Saludos

Crea un array donde almacenar el valor de 5 contadores.
Cada uno corresponderá a Life, Venom, Commander 1, Commmander 2 y Commander 3.
Crea una variable que almacene un contador para mode.
Con cada pulsación del botón incrementas este contador (mode) entre 0 y 4 (o sea 5 valores), entonces cuando llega a 5 lo pones otra vez en 0.
Ese contador lo usas como indice del array que guarda los valores de cada item.
El encoder incrementa o decrementa el valor del array indizado por el valor de mode.

1 Like

Hola gatul!
Genial! Gracias por la explicación, intentaré hacer lo que me indicas.
Mas tarde traigo un avance. :smiley:

Lo siento @kingabaaddon pero no entiendo cómo funciona todo, nunca juge a esas cartas MTG y creo que existen contradicciones:

Es lo que siempre entendí tres comandantes con sus propias tres variables en total 9 variables. Después dices:

Ya me faltan 4 variables ????
En el #6 utilizas un pulsador para moverte entre esas 5 variables y el decoder para incrementar o disminuir su valor, no dibujas el decoder y ¿ para qué sirve entonces el pulsador +/- ?.
Explícamelo un poco mejor antes de seguir.

1 Like

Sean 5 o 9 variables no hace la diferencia, solo hay que ampliar un array y el límite de un contador.

Da igual que sea un juego, el ecualizador del radio del auto, una lavadora o un tablero en un módulo de la ISS.
Da igual que sean un pulsador + y otro - , la idea es la misma.

Con un pulsador selecciona un item del array, con el encoder aumenta o disminuye el valor del item seleccionado (tal como dice en #6).

También podría hacerse al revés, seleccionar con el encoder, aumentar/disminuir con los pulsadores.
La idea base seguiría siendo la misma, no cambia.

1 Like

Hola gon, gracias por estar por aqui.

No es necesario conocer el juego, así que por eso no te abrumes.
En pocas palabras, son 5 contadores, independientes uno del otro, los cuales selecciono con el pulsador "MODE" (navego por ellos) y sus valores son incrementados o reducidos según hacia donde gire la rueda (encoder).

gatul me dio instrucciones muy claras para el cometido, intentare escribir el código en lo que termino con este comentario.

Nuevamente, gracias por responder gon.

Hola gatul, esto es lo que he podido hacer:

1. no tenia ni idea de lo que era una array (puede que no este bien escrito):

int contadores [5] = {Vida,Veneno,Com1,Com2,Com3};

2. Cree la variable para el contador Mode:

int mode = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_mode = 13; // pin en donde se conecta el pulsador
bool estmodeActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estmodeAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador

y el código para que cambie su valor respecto al estado de un pulsador:


  estmodeActual = digitalRead(pulsador_mode); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estmodeAnterior == 1 && estmodeActual == 0) || mode == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    mode++; // suma 1 al valor de la variable contador
    if (mode > 4) { // si el contador supera 4
      mode = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estmodeAnterior = estmodeActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estmodeAnterior

Cosas que no entendí:

Ese contador lo usas como indice del array que guarda los valores de cada item.
El encoder incrementa o decrementa el valor del array indizado por el valor de mode.

Código completo:

//Proyecto: "Contador para MTG - Commmander"
//Descripcion: Dispositivo que permite tener cinco contadores: 1 para la Vida, 1 para Veneno y 3 contadores para puntos de daños por parte de los comandantes enemigos, cuyos valores incrementan o decrecen segun el pulsador asociado. 
             //Los valores limite para ellos son: Vida = 20, Veneno = 10, COM (1/2/3) = 21. Los valores son impresos en un dispaly OLED SSD1306 de 0.91 pulgadas.
//Creador: KingAbaaddon

//**Librerias
//Pantalla
#include <Adafruit_SSD1306.h>   // libreria para controlador SSD1306
//Pantalla
#define ANCHO 128     // reemplaza ocurrencia de ANCHO por 128
#define ALTO 64       // reemplaza ocurrencia de ALTO por 64
//Reset
#define OLED_RESET -1      // necesario por la libreria pero no usado. -1 porque tiene boton
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);  // crea objeto

//**Declaraciones
//Vida
int Vida = -1; // valor inicial -1 para inicializar antes de contar
int pulsador = 4; // pin en donde se conecta el pulsador
int despulsador = 3; // pin en donde se conecta el pulsador
bool estPulActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estPulAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador

//Veneno
int Veneno = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_veneno = 6; // pin en donde se conecta el pulsador
int pulsador_veneno_negativo = 5; // pin en donde se conecta el pulsador
bool estVenActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estVenAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador

//Comandantes
//COM1
int Com1 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM1 = 8; // pin en donde se conecta el pulsador
int pulsador_COM1n = 7; // pin en donde se conecta el pulsador
bool estCOM1Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM1Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador
//COM2
int Com2 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM2 = 10; // pin en donde se conecta el pulsador
int pulsador_COM2n = 9; // pin en donde se conecta el pulsador
bool estCOM2Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM2Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador
//COM3
int Com3 = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_COM3 = 12; // pin en donde se conecta el pulsador
int pulsador_COM3n = 11; // pin en donde se conecta el pulsador
bool estCOM3Actual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estCOM3Anterior = 1; // variable donde se guarda el estado logico anterior del pulsador

/// PRUEBAS BETA

int contadores [5] = {Vida,Veneno,Com1,Com2,Com3};


//MENU MODE
int mode = -1; // valor inicial -1 para inicializar antes de contar
int pulsador_mode = 13; // pin en donde se conecta el pulsador
bool estmodeActual = 1; // variable donde se guarda el estado logico actual del pulsador
bool estmodeAnterior = 1; // variable donde se guarda el estado logico anterior del pulsador
///


//**Logo

// 'LOGO', 128x48px
const unsigned char Mi_Logologo [] PROGMEM = {
  
  0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x00, 0x03, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x07, 0xc2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x02, 0x0f, 0xe2, 0x02, 0x00, 0x04, 0x30, 0x7c, 0x01, 0xf9, 0xe2, 0x13, 0xc0, 0x60, 0x30, 0x20, 
  0x02, 0x0f, 0xe3, 0x06, 0x00, 0x1f, 0x7c, 0x7c, 0x19, 0xfd, 0xf7, 0x37, 0xc0, 0xf8, 0x60, 0x60, 
  0x02, 0x1f, 0xf1, 0xfc, 0x00, 0x19, 0x64, 0x70, 0x18, 0x30, 0xe7, 0x37, 0x00, 0x4c, 0x4e, 0x60, 
  0x02, 0x1f, 0xf0, 0xd8, 0x00, 0x30, 0x6c, 0x70, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60, 
  0x02, 0x0f, 0xe0, 0x88, 0x00, 0x30, 0x6c, 0x60, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60, 
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x20, 0x76, 0x60, 0x2c, 0x30, 0xe3, 0x67, 0x00, 0x6c, 0x42, 0x60, 
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x60, 0x04, 0x60, 0x24, 0x30, 0x61, 0x66, 0x00, 0x4c, 0x42, 0x60, 
  0x02, 0x03, 0x81, 0x8c, 0x00, 0x60, 0x3c, 0x78, 0x24, 0x30, 0x61, 0x63, 0x80, 0x78, 0x40, 0x60, 
  0x1f, 0xf9, 0x03, 0x06, 0x00, 0x60, 0x38, 0x3c, 0x24, 0x30, 0x61, 0x63, 0xc0, 0x70, 0x40, 0x60, 
  0x3f, 0xf8, 0x02, 0x02, 0x00, 0x60, 0x38, 0x38, 0x24, 0x30, 0x61, 0xe3, 0xc0, 0x60, 0x42, 0x60, 
  0x20, 0x08, 0x06, 0x01, 0x00, 0x60, 0x38, 0x30, 0x24, 0x30, 0x61, 0xe3, 0x00, 0x70, 0x5a, 0x60, 
  0x26, 0x4f, 0xff, 0x01, 0x00, 0x60, 0x38, 0x30, 0x7e, 0x30, 0x61, 0xe3, 0x00, 0x70, 0xd2, 0x60, 
  0x24, 0x4c, 0x03, 0x01, 0x80, 0x60, 0x3c, 0x30, 0x4e, 0x30, 0x60, 0xc3, 0x00, 0x78, 0xd2, 0x60, 
  0x20, 0x0c, 0x03, 0x01, 0x80, 0x30, 0x34, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x58, 0xd2, 0x60, 
  0x20, 0x08, 0x01, 0x81, 0xc0, 0x30, 0x36, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x5c, 0x42, 0x60, 
  0x26, 0x48, 0x81, 0xff, 0xc0, 0x1b, 0x36, 0x70, 0xc2, 0x30, 0x60, 0xc3, 0x00, 0x4c, 0x64, 0x70, 
  0x24, 0x48, 0x01, 0x80, 0xc0, 0x0f, 0x37, 0x7d, 0xc2, 0x30, 0xf0, 0x83, 0xe0, 0x66, 0x3c, 0x7e, 
  0x20, 0x08, 0x01, 0x82, 0xc0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x01, 0xc0, 0x00, 0x10, 0x3c, 
  0x30, 0x18, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x3f, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  
};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 784)
const int Mi_LogoallArray_LEN = 1;
const unsigned char* Mi_LogoallArray[1] = {
  Mi_Logologo
};


//**Setup

void setup() {
  pinMode(pulsador, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(despulsador, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_veneno, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_veneno_negativo, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM1, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM1n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM2, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM2n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM3, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  pinMode(pulsador_COM3n, INPUT_PULLUP); //el pin pulsador es asignado como entrada
  delay(100);  // se da una espera de 100ms para que el display inicie correctamente
  Wire.begin();         // inicializa bus I2C
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inicializa pantalla con direccion 0x3C
  oled.clearDisplay();      // limpia pantalla
  oled.drawBitmap(0, 17, Mi_Logologo, 128, 32, WHITE);
  oled.display();
  delay(2000);  // se da una espera de 100ms para que el display inicie correctamente
  oled.setRotation(0);  // se escoje la orientacion del display puede ser 0, 1, 2 o 3
  oled.setTextColor(WHITE);  // se le dice a la pantalla que el texto que se va a desplegar es en color blanco
  oled.dim(false); //dejamos el brillo en maximo
  oled.setTextSize(2);      // establece tamano de texto en 2
  oled.clearDisplay();      // limpia pantalla
}

void loop() {

  //..Vida
  
  //SUMA vida
  estPulActual = digitalRead(pulsador); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estPulAnterior == 1 && estPulActual == 0) || Vida == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Vida++; // suma 1 al valor de la variable contador
    if (Vida > 99) { // si el contador supera 99
      Vida = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estPulAnterior = estPulActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA vida
  estPulActual = digitalRead(despulsador); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estPulAnterior == 1 && estPulActual == 0) || Vida == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Vida--; // resta 1 al valor de la variable contador
    if (Vida < 0) { // si el contador supera 99
      Vida = 99; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estPulAnterior = estPulActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  

  //..Veneno
  
  //SUMA veneno
  estVenActual = digitalRead(pulsador_veneno); //se lee el valor logico del pin de entraday se guarda en la variable estVenActual
  if ((estVenAnterior == 1 && estVenActual == 0) || Veneno == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Veneno++; // suma 1 al valor de la variable contador
    if (Veneno > 10) { // si el contador supera 10
      Veneno = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estVenAnterior = estVenActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estVenAnterior


  //RESTA veneno
  estVenActual = digitalRead(pulsador_veneno_negativo); //se lee el valor logico del pin de entraday se guarda en la variable estVenActual
  if ((estVenAnterior == 1 && estVenActual == 0) || Veneno == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Veneno--; // resta 1 al valor de la variable contador
    if (Veneno < 0) { // si el contador menor a 0
      Veneno = 10; // devuelve el contador a 10
    }
  }
  delay(20); //pausa de 20 milisegundos
  estVenAnterior = estVenActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //..Comandantes
  
  //COM1

  //SUMA puntos
  estCOM1Actual = digitalRead(pulsador_COM1); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM1Anterior == 1 && estCOM1Actual == 0) || Com1 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com1++; // suma 1 al valor de la variable contador
    if (Com1 > 21) { // si el contador supera 99
      Com1 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM1Anterior = estCOM1Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM1Actual = digitalRead(pulsador_COM1n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM1Anterior == 1 && estCOM1Actual == 0) || Com1 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com1--; // resta 1 al valor de la variable contador
    if (Com1 < 0) { // si el contador supera 99
      Com1 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM1Anterior = estCOM1Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //COM2

  //SUMA puntos
  estCOM2Actual = digitalRead(pulsador_COM2); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM2Anterior == 1 && estCOM2Actual == 0) || Com2 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com2++; // suma 1 al valor de la variable contador
    if (Com2 > 21) { // si el contador supera 99
      Com2 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM2Anterior = estCOM2Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM2Actual = digitalRead(pulsador_COM2n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM2Anterior == 1 && estCOM2Actual == 0) || Com2 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com2--; // resta 1 al valor de la variable contador
    if (Com2 < 0) { // si el contador supera 99
      Com2 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM2Anterior = estCOM2Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //COM3

  //SUMA puntos
  estCOM3Actual = digitalRead(pulsador_COM3); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM3Anterior == 1 && estCOM3Actual == 0) || Com3 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com3++; // suma 1 al valor de la variable contador
    if (Com3 > 21) { // si el contador supera 99
      Com3 = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM3Anterior = estCOM3Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior


  //RESTA puntos
  estCOM3Actual = digitalRead(pulsador_COM3n); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estCOM3Anterior == 1 && estCOM3Actual == 0) || Com3 == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    Com3--; // resta 1 al valor de la variable contador
    if (Com3 < 0) { // si el contador supera 99
      Com3 = 21; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estCOM3Anterior = estCOM3Actual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estPulAnterior

  //MENU BETA

  estmodeActual = digitalRead(pulsador_mode); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estmodeAnterior == 1 && estmodeActual == 0) || mode == -1) { //valida si el pulsador ha cambiado de 1 a 0 ó si el contador esta en -1
    mode++; // suma 1 al valor de la variable contador
    if (mode > 4) { // si el contador supera 4
      mode = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estmodeAnterior = estmodeActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estmodeAnterior

  //**Impresion de pantalla
  
  oled.clearDisplay();      // limpia pantalla

  //Campos
  oled.drawRect(0, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawRect(31, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawTriangle(62, 17, 92, 17, 77, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(79, 47, 94, 17, 110, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(96, 17, 127, 17, 112, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  
  //Titulos
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(2, 0);
  oled.println("LIFE");
  oled.setCursor(31, 0);
  oled.println("VENOM");
  oled.setCursor(69, 0);
  oled.println("COMMANDER");
  oled.setCursor(74, 9);
  oled.println("1");
  oled.setCursor(92, 9);
  oled.println("2");
  oled.setCursor(109, 9);
  oled.println("3");
  
  //Impresion de valores Vida y Veneno
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(3, 25);   // ubica cursor en coordenadas 15,32
  oled.print(Vida);     // escribe texto
  oled.setCursor(34, 25);   // ubica cursor en coordenadas 34,25
  oled.print(Veneno);     // escribe texto

  //Impresion de valores COM1/2/3
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(74, 22);   // ubica cursor en coordenadas 34,25
  oled.print(Com1);     // escribe texto
  
  oled.setCursor(92, 35);   // ubica cursor en coordenadas 34,25
  oled.print(Com2);     // escribe texto
 
  oled.setCursor(109, 22);   // ubica cursor en coordenadas 34,25
  oled.print(Com3);     // escribe texto
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
}

Agradezco las correcciones.
Saludos.

la idea es en realidad algo así

// contadores contiene {Vida,Veneno,Com1,Com2,Com3} (solo como ayuda memoria)
int contadores [5] = {0,0,0,0,0};

entonces la variable que llamabas Vida ahora será contadores[0], de igual forma Veneno será contadores[1] y lo mismo para los otros 3 items.
¿Se entiende ahora la idea?
Fijate, por ejemplo,

nivel = contadores[mode];  

cuando mode es 0 apunta a contadores[0] que sería valor de la variable Vida (que ya no existe), cuando mode es 1 apunta a contadores[1] que sería valor de la variable Veneno (que tambien dejó de existir), etc..
O sea, reemplazas esas 5 variables "sueltas" por items agrupados en el array y que se seleccionan de acuerdo al valor de "mode".

Ahora estoy en el trabajo por un rato más, más tarde cuando llegue a casa le pego una mirada a tu código.

1 Like

Hola gatul! gracias por comentar rápido mi mensaje anterior, pero por favor tomate la libertad de usar el tiempo como mejor te parezca, no tengo ningún apuro.

Respecto a lo que me respondiste, gracias ahora entiendo lo del array:

Seguì tu consejo y renombre cada variable (Vida, Veneno, etc...) por sus nuevos nombres dados por el array, pero me salio un error al intentar verificar

Mensaje de error:

Arduino:1.8.19 (Windows 10), Tarjeta:"Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"





















Etapa_11_Arrays_:18:21: error: array must be initialized with a brace-enclosed initializer

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

                     ^

Etapa_11_Arrays_:25:17: error: conflicting declaration 'int contadores [1]'

 int contadores[1] = -1; // valor inicial -1 para inicializar antes de contar

                 ^

C:\Users\Gian\Desktop\Proyecto Contador\Etapa_11_Arrays_\Etapa_11_Arrays_\Etapa_11_Arrays_.ino:18:5: note: previous declaration as 'int contadores [0]'

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

     ^~~~~~~~~~

Etapa_11_Arrays_:33:17: error: conflicting declaration 'int contadores [2]'

 int contadores[2] = -1; // valor inicial -1 para inicializar antes de contar

                 ^

C:\Users\Gian\Desktop\Proyecto Contador\Etapa_11_Arrays_\Etapa_11_Arrays_\Etapa_11_Arrays_.ino:18:5: note: previous declaration as 'int contadores [0]'

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

     ^~~~~~~~~~

Etapa_11_Arrays_:39:17: error: conflicting declaration 'int contadores [3]'

 int contadores[3] = -1; // valor inicial -1 para inicializar antes de contar

                 ^

C:\Users\Gian\Desktop\Proyecto Contador\Etapa_11_Arrays_\Etapa_11_Arrays_\Etapa_11_Arrays_.ino:18:5: note: previous declaration as 'int contadores [0]'

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

     ^~~~~~~~~~

Etapa_11_Arrays_:45:17: error: conflicting declaration 'int contadores [4]'

 int contadores[4] = -1; // valor inicial -1 para inicializar antes de contar

                 ^

C:\Users\Gian\Desktop\Proyecto Contador\Etapa_11_Arrays_\Etapa_11_Arrays_\Etapa_11_Arrays_.ino:18:5: note: previous declaration as 'int contadores [0]'

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

     ^~~~~~~~~~

Etapa_11_Arrays_:53:18: error: conflicting declaration 'int contadores [5]'

 int contadores [5] = {0,0,0,0,0};

                  ^

C:\Users\Gian\Desktop\Proyecto Contador\Etapa_11_Arrays_\Etapa_11_Arrays_\Etapa_11_Arrays_.ino:18:5: note: previous declaration as 'int contadores [0]'

 int contadores[0] = 0; // valor inicial -1 para inicializar antes de contar

     ^~~~~~~~~~

exit status 1

array must be initialized with a brace-enclosed initializer



Este informe podría contener más información con
"Mostrar salida detallada durante la compilación"
opción habilitada en Archivo -> Preferencias.

Saludos!

Tenes que definir las 5 juntas

int contadores [5] = {0,0,0,0,0};

Fijate en los ejemplos de la IDE que si no me equivoco hay un ejercicio con arrays asi te das cuenta como hacerlo.

Miré el ejemplo de control en el IDE y no entendí la verdad jajaja.

Eso te ocurre porque intentas asignar un valor a una casilla de la matriz en la zona de declaraciones, como te indica el compilador y @anon90500195, en esa zona tienes que definir las 5 casillas de la matriz juntas. Una celda individualmente solo la puedes modificar en el setup o en el loop y una vez declarada antes del setup.

¿ Porque el "-1" y arrastrar en los " if " la coletilla " || variable == -1" ?. lo veo innecesario, piénsalo, en la primera pasada por los if la coletilla anterior activa el ++ y cambia la variable a cero. Después en los limites cuando supera la variable el límite superior la haces cero y cuando baja de cero la haces igual al límite superior, nunca vuelve a valer -1 ninguna de las variables. Te sobra todo eso.

En estos momentos no tengo un encoder para probar, pero si un nano tres botones y una de esas pantallas asi que vamos a desarrollar un código según el dibujo del #6 ,( botón +, botón - y botón mode), ya sustituiremos el botón +/- por el encoder o se los dejamos si no logramos un ajuste "fino" con el encoder.

Lo primero tienes que limpiar tu código de botones inútiles, dejando en la zona de declaraciones y en el setup solo lo necesario para tres botones, cada uno de ellos con su pin y variables anterior y actual, uno para incrementar otro para disminuir y otro para el mode, ( este ultimo es el que apuntara a la casilla de la matriz que contiene la variable a modificar para navegar entre variables).

En la zona de declaraciones creamos la matriz:

int contadores [5] = {0,0,0,0,0};
// ó
int contadores [5];

Que es lo mismo creamos una matriz de 5 variables inicianizandolas todas a cero, posteriormete en el setup o en el loop podemos hacer lo que antes te daba error, por ejemplo:

contadores [0] = 20; // asignamos a la 1ª casilla de la matriz el valor 20

Aunque viendo cómo va el contador la asignación correcta, si no me equivoco seria:

int contadores [5] = {99,0,21,21,21};

Vamos con el loop:
El botón Mode, Indice de la matriz. Ese si le quitas la comparacion del -1 lo tienes perfecto:

//MENU BETA
  estmodeActual = digitalRead(pulsador_mode); //se lee el valor logico del pin de entraday se guarda en la variable estPulActual
  if ((estmodeAnterior == 1 && estmodeActual == 0)) { //valida si el pulsador ha cambiado de 1 a 0
    mode ++; // suma 1 al valor de la variable contador
    if (mode > 4) { // si el contador supera 4
      mode = 0; // devuelve el contador a 0
    }
  }
  delay(20); //pausa de 20 milisegundos
  estmodeAnterior = estmodeActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estmodeAnterior

Perfecto el índice de la matriz va de 0 a 4 y te permite hacer cosas como:

contadores [mode] ++; // Aumenta vida ,(primera casilla), en una unidad, si mode vale cero
// ó
contadores [mode] --; // Disminuye comander3 ,(ultima  casilla), en una unidad, si mode vale cuatro.

¿ Con esto y lo que te explico @anon90500195 vas pillando las matrices?.

A continuación codificamos el botón de aumentar, es exactamente lo mismo que lo tenías antes, con su pin y sus variables propias:

//SUMA puntos
  estMasActual = digitalRead(mas); //se lee el valor logico del pin de entraday se guarda en la variable estMasActual
  if ((estMasAnterior == 1 && estMasActual == 0)) { //valida si el pulsador ha cambiado de 1 a 0
    contadores [mode] ++; // suma 1 al valor de la variable indicada por mode
  }
  delay(20); //pausa de 20 milisegundos
  estMasAnterior = estMasActual; //el valor booleano actual del contador ya fue procesado asi que se guarda en la variable estMasAnterior
// OJO HE PODIDO CAMBIAR ALGUN NOMBRE DE VARIABLE, COMPRUEBALO.

Lo unico que cambia es que antes con cada boton cambiabas la variable directamente y ahora cambias la variable a la que apunta mode´.

A continuación codificamos el botón de disminuir, es exactamente lo mismo que el de aumentar, su pin y sus variables propias, solo cambias la línea que modifica la variable a:

 contadores [mode] --; // resta 1 al valor de la variable indicada por mode

Limites: Anteriormente cada uno de los 10 botones limitaban los valores max. y min. de cada variable, con este código como hemos quitado esos limites se los añadimos a continuacion de los tres botone:

// LIMITES
  //Vida
  if (contadores [0] < 0 ) {contadores [0] = 99;}
  if (contadores [0] > 99 ) {contadores [0] = 0;}
  //veneno
  if (contadores [1] < 0) {contadores [1] = 10;}
  if (contadores [1] > 10) {contadores [1] = 0;}
  //comandante 1
  if (contadores [2] < 0) {contadores [2] = 21;}
  if (contadores [2] > 21) {contadores [2] = 0;}
  //comandante 2
  if (contadores [3] < 0) {contadores [3] = 21;}
  if (contadores [3] > 21) {contadores [3] = 0;}
  //comandante 3
  if (contadores [4] < 0) {contadores [4] = 21;}
  if (contadores [4] > 21) {contadores [4] = 0;}

Impresión de pantalla, lo más facil:

// Donde antes tenías: oled.print(vida); ahora:
oled.print(contadores [0]);
// Donde antes tenías: oled.print(veneno); ahora:
oled.print(contadores [1]);
// Donde antes tenías: oled.print(com1); ahora:
oled.print(contadores [2]);
// Donde antes tenías: oled.print(com2); ahora:
oled.print(contadores [3]);
// Donde antes tenías: oled.print(com3); ahora:
oled.print(contadores [4]);

El resto no cambia.
Mientras pruebas esto me pienso lo del encoder que mientras lo escribía me ha venido una iluminación y creo que no va a ser complicado.

1 Like

No está muy prolijo pero cumple

#include "EncoderStepCounter.h"   // del Administrador de Librerías

#define ENCODER_PIN1 2
#define ENCODER_INT1 digitalPinToInterrupt(ENCODER_PIN1)
#define ENCODER_PIN2 3
#define ENCODER_INT2 digitalPinToInterrupt(ENCODER_PIN2)

//Pantalla
#include <Adafruit_SSD1306.h>   // libreria para controlador SSD1306
//Pantalla
#define ANCHO 128     // reemplaza ocurrencia de ANCHO por 128
#define ALTO 64       // reemplaza ocurrencia de ALTO por 64
//Reset
#define OLED_RESET -1      // necesario por la libreria pero no usado. -1 porque tiene boton
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);  // crea objeto

// Create instance for one full step encoder
EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2);
// Use the following for half step encoders
//EncoderStepCounter encoder(ENCODER_PIN1, ENCODER_PIN2, HALF_STEP);
// 'LOGO', 128x48px
const unsigned char Mi_Logologo [] PROGMEM = {

  0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x03, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x03, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x07, 0xc2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x02, 0x0f, 0xe2, 0x02, 0x00, 0x04, 0x30, 0x7c, 0x01, 0xf9, 0xe2, 0x13, 0xc0, 0x60, 0x30, 0x20,
  0x02, 0x0f, 0xe3, 0x06, 0x00, 0x1f, 0x7c, 0x7c, 0x19, 0xfd, 0xf7, 0x37, 0xc0, 0xf8, 0x60, 0x60,
  0x02, 0x1f, 0xf1, 0xfc, 0x00, 0x19, 0x64, 0x70, 0x18, 0x30, 0xe7, 0x37, 0x00, 0x4c, 0x4e, 0x60,
  0x02, 0x1f, 0xf0, 0xd8, 0x00, 0x30, 0x6c, 0x70, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60,
  0x02, 0x0f, 0xe0, 0x88, 0x00, 0x30, 0x6c, 0x60, 0x1c, 0x30, 0xe3, 0x37, 0x00, 0x4c, 0xde, 0x60,
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x20, 0x76, 0x60, 0x2c, 0x30, 0xe3, 0x67, 0x00, 0x6c, 0x42, 0x60,
  0x02, 0x07, 0xc1, 0x8c, 0x00, 0x60, 0x04, 0x60, 0x24, 0x30, 0x61, 0x66, 0x00, 0x4c, 0x42, 0x60,
  0x02, 0x03, 0x81, 0x8c, 0x00, 0x60, 0x3c, 0x78, 0x24, 0x30, 0x61, 0x63, 0x80, 0x78, 0x40, 0x60,
  0x1f, 0xf9, 0x03, 0x06, 0x00, 0x60, 0x38, 0x3c, 0x24, 0x30, 0x61, 0x63, 0xc0, 0x70, 0x40, 0x60,
  0x3f, 0xf8, 0x02, 0x02, 0x00, 0x60, 0x38, 0x38, 0x24, 0x30, 0x61, 0xe3, 0xc0, 0x60, 0x42, 0x60,
  0x20, 0x08, 0x06, 0x01, 0x00, 0x60, 0x38, 0x30, 0x24, 0x30, 0x61, 0xe3, 0x00, 0x70, 0x5a, 0x60,
  0x26, 0x4f, 0xff, 0x01, 0x00, 0x60, 0x38, 0x30, 0x7e, 0x30, 0x61, 0xe3, 0x00, 0x70, 0xd2, 0x60,
  0x24, 0x4c, 0x03, 0x01, 0x80, 0x60, 0x3c, 0x30, 0x4e, 0x30, 0x60, 0xc3, 0x00, 0x78, 0xd2, 0x60,
  0x20, 0x0c, 0x03, 0x01, 0x80, 0x30, 0x34, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x58, 0xd2, 0x60,
  0x20, 0x08, 0x01, 0x81, 0xc0, 0x30, 0x36, 0x30, 0xc6, 0x30, 0x60, 0xc3, 0x00, 0x5c, 0x42, 0x60,
  0x26, 0x48, 0x81, 0xff, 0xc0, 0x1b, 0x36, 0x70, 0xc2, 0x30, 0x60, 0xc3, 0x00, 0x4c, 0x64, 0x70,
  0x24, 0x48, 0x01, 0x80, 0xc0, 0x0f, 0x37, 0x7d, 0xc2, 0x30, 0xf0, 0x83, 0xe0, 0x66, 0x3c, 0x7e,
  0x20, 0x08, 0x01, 0x82, 0xc0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x01, 0xc0, 0x00, 0x10, 0x3c,
  0x30, 0x18, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x3f, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 784)
const int Mi_LogoallArray_LEN = 1;
const unsigned char* Mi_LogoallArray[1] = {
  Mi_Logologo
};

const byte PIN_BOTON = 4;

int contadores[5] = {0, 0, 0, 0, 0};  // {vida, veneno, com1, com2, com3}

byte botonAnt = 1; //  guarda ultimo estado del boton
byte mode = 0;
char lastpos = 0;  // guarda ultima posicion del encoder

void setup() {
  pinMode(PIN_BOTON, INPUT_PULLUP);
  Serial.begin(9600);
  Wire.begin();         // inicializa bus I2C
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inicializa pantalla con direccion 0x3C
  oled.clearDisplay();      // limpia pantalla
  oled.drawBitmap(0, 17, Mi_Logologo, 128, 32, WHITE);
  oled.display();
  delay(2000);  // se da una espera de 100ms para que el display inicie correctamente
  oled.setRotation(0);  // se escoje la orientacion del display puede ser 0, 1, 2 o 3
  oled.setTextColor(WHITE);  // se le dice a la pantalla que el texto que se va a desplegar es en color blanco
  oled.dim(false); //dejamos el brillo en maximo
  oled.setTextSize(2);      // establece tamano de texto en 2
  oled.clearDisplay();      // limpia pantalla
  oled.display();
  // Initialize encoder
  encoder.begin();
  attachInterrupt(ENCODER_INT1, interrupt, CHANGE);
  attachInterrupt(ENCODER_INT2, interrupt, CHANGE);
}

void interrupt() {   // NO TOCAR rutina de interrupcion del encoder
  encoder.tick();
}

void loop() {
  byte boton = digitalRead(PIN_BOTON);
  if (boton != botonAnt) {
    botonAnt = boton;
    if (boton == LOW) {
      mode = (mode + 1) % 5;  // devuelve resto de dividir por 5 entonces mode contiene entre 0 y 4
    }
  }

  char pos = encoder.getPosition();
  if (pos != lastpos) {
    char delta = pos - lastpos;
    lastpos = pos;
    contadores[mode] = contadores[mode] + delta;
    switch (mode) {
      case 0:   // ** vida **
        if (contadores[0] < 0) contadores[0] = 99;
        else if (contadores[0] > 99) contadores[0] = 0;
        break;
      case 1:   // ** veneno **
        if (contadores[1] < 0) contadores[1] = 10;
        else if (contadores[1] > 10) contadores[1] = 0;
        break;
      default:  // ** comandante **  (cualquiera de los 3)
        if (contadores[mode] < 0) contadores[mode] = 21;
        else if (contadores[mode] > 21) contadores[mode] = 0;
        break;
    }
  }

  //**Impresion de pantalla

  //Campos
  oled.drawRect(0, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawRect(31, 17, 30, 30, WHITE); // dibuja rectangulo X, Y, Pixel de alto , Pixel de ancho
  oled.drawTriangle(62, 17, 92, 17, 77, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(79, 47, 94, 17, 110, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);
  oled.drawTriangle(96, 17, 127, 17, 112, 47, WHITE); //(FirstX , FirstY, SecondX, SecondY, ThirdX, ThirdY, WHITE);

  //Titulos
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(2, 0);
  oled.println("LIFE");
  oled.setCursor(31, 0);
  oled.println("VENOM");
  oled.setCursor(69, 0);
  oled.println("COMMANDER");
  oled.setCursor(74, 9);
  oled.println("1");
  oled.setCursor(92, 9);
  oled.println("2");
  oled.setCursor(109, 9);
  oled.println("3");


  for (byte i = 0; i < 5; i++) {
    oled.setCursor(2 + 30 * i, 50);
    oled.setTextColor(WHITE, BLACK);
    if (i == mode) {
      oled.print("-");
    } else {
      oled.print(" ");
    }
  }

  //Impresion de valores Vida y Veneno
  oled.setTextSize(2);
  oled.setTextColor(WHITE, BLACK);
  oled.setCursor(3, 25);   // ubica cursor en coordenadas 15,32
  oled.print(contadores[0]);     // ** vida **
  if (contadores[0] < 10) oled.print(" ");

  oled.setCursor(34, 25);   // ubica cursor en coordenadas 34,25
  oled.print(contadores[1]);     // ** veneno **
  if (contadores[1] < 10) oled.print(" ");

  //Impresion de valores COM1/2/3
  oled.setTextSize(1);
  oled.setTextColor(WHITE, BLACK);
  oled.setCursor(74, 22);   // ubica cursor en coordenadas 34,25
  oled.print(contadores[2]);     // ** com1 **
  if (contadores[2] < 10) oled.print(" ");

  oled.setCursor(92, 35);   // ubica cursor en coordenadas 34,25
  oled.print(contadores[3]);     // ** com2 **
  if (contadores[3] < 10) oled.print(" ");

  oled.setCursor(109, 22);   // ubica cursor en coordenadas 34,25
  oled.print(contadores[4]);     // ** com3 **
  if (contadores[4] < 10) oled.print(" ");

  oled.display();     // muestra en pantalla todo lo establecido anteriormente
}

Acá la simulación en Wokwi
https://wokwi.com/projects/343903291113996883

Agrego:
El encoder usa necesariamente los pines 2 y 3 porque trabaja con interrupciones.
Si la cuenta te sale invertida (disminuye cuando debe aumentar y viceversa) simplemente intercambia la conexión de los pines 2 y 3 o si quieres cambia en el código

#define ENCODER_PIN1 2
y
#define ENCODER_PIN2 3

por

#define ENCODER_PIN1 3
y
#define ENCODER_PIN2 2

Tu eliges lo que te sea más práctico.

El pulsador está en el pin 4 como en tu código original pero lo puedes cambiar si hace falta.

Te agregué un guión "-" para que muestre cual ítem se cambia pero no se si es muy visible.
Tal vez podrías agregar 5 LEDs, tenelo en cuenta.

PD: En la simulación agregué los LEDs para que te hagas idea de como podría quedar. :wink:

1 Like

Gon, gracias!!

Entendí a la perfección cada paso que comentas, realmente si no sos profesor, deberías tomarlo en cuenta para un futuro. Tu forma de explicar es muy practica.

Saludos.

@anon90500195 , que decir? Muchas gracias por intentar explicarme aunque soy duro como un tronco.
Tu código funciona a la perfección y realmente me alegra poder entender como funciona el (maldito) encoder jajaja.

@Surbyte gracias por estar ahi en el proceso, sin duda fuiste de gran ayuda.
@gonpezzi gracias por recortar un poco tus vacaciones para aportar tu conocimiento en el tema.

Gracias a los 3.
Doy por terminado este tema.

Saludos.