Problemas con encoders... (codigo lento?)

Hola gente, por este código eh hecho varias consultas a lo largo del desarrollo, tengo 6 encoders en el, y cada cosa nueva que agregaba me traía problemas con la lectura de los mismos, fui resolviendo y el código funcionaba completo.

Lo ultimo que agrege al codigo y ahora no encuentro solucion a la falla de lectura de los enconders es una matriz de botones de 6 x 7 de la cual aca dejo el link:
https://forum.arduino.cc/t/matriz-de-botones/663252/19

Repito el problema: los encoders no muestran datos, como si el código fuese muy lento para leer el cambio de posición

aca les comparto el codigo completo a lo mejor a los ojos de algún experto la solución es simple:

#include <Arduino.h>
// Pertenece a la botonera de linea 3 a 7
#define BUTTON_COUNT 42
#define KEYPAD_OUTPUT_BEGIN 18
#define KEYPAD_OUTPUT_END 23
#define KEYPAD_INPUT_BEGIN 24
#define KEYPAD_INPUT_END 30


// Variables Globales Encodres
unsigned long time;
char buffer_temporal[10];

// encoder "PGM1" - Palanca de Gases Motor 1
int PGM1_PCLK = 48;//"PCLK" Pin CLK.
int PGM1_PDT = 49;//_"PDT" Pin DT.
int PGM1_RE_P = 1;//_"P" Posicion.
unsigned long PGM1_RE_T;
bool PGM1_RE_A = true;
bool PGM1_RE_B = true;

// encoder "PGM2" - Palanca de Gases Motor 2
int PGM2_PCLK = 52;// "PCLK" Pin CLK.
int PGM2_PDT = 53;// _"PDT" Pin DT.
int PGM2_RE_P = 1;// _"P" Posicion.
unsigned long PGM2_RE_T;
bool PGM2_RE_A = true;
bool PGM2_RE_B = true;

// encoder "PHM1" - Paso de Helice Motor 1
int PHM1_PCLK = 50;//"PCLK" Pin CLK.
int PHM1_PDT = 51;//_"PDT" Pin DT.
int PHM1_RE_P = 1;//_"P" Posicion.
unsigned long PHM1_RE_T;
bool PHM1_RE_A = true;
bool PHM1_RE_B = true;

// encoder "PHM2" - Paso de Helice Motor 2
int PHM2_PCLK = 45;// "PCLK" Pin CLK.
int PHM2_PDT = 44;// _"PDT" Pin DT.
int PHM2_RE_P = 1;// _"P" Posicion.
unsigned long PHM2_RE_T;
bool PHM2_RE_A = true;
bool PHM2_RE_B = true;

// encoder "PMM1" - Palanca de Mezcla Motor 1
int PMM1_PCLK = 42;//"PCLK" Pin CLK.
int PMM1_PDT = 43;//_"PDT" Pin DT.
int PMM1_RE_P = 9;//_"P" Posicion.
unsigned long PMM1_RE_T;
bool PMM1_RE_A = true;
bool PMM1_RE_B = true;

// encoder "PMM2" - Palanca de Mezcla Motor 2
int PMM2_PCLK = 47;// "PCLK" Pin CLK.
int PMM2_PDT = 46;// _"PDT" Pin DT.
int PMM2_RE_P = 9;// _"P" Posicion.
unsigned long PMM2_RE_T;
bool PMM2_RE_A = true;
bool PMM2_RE_B = true;

//Variables Tren de Aterrizaje
int TALN = 41; // _ _ _ _ _ _ _ _ "L" Led, "N" Nariz.
int TALI = 40; // _ _ _ _ _ _ _ _ "L" Led, "I" Izquierda.
int TALD = 38; // _ _ _ _ _ _ _ _ "L" Led, "D" Derecha.
int TALP = 39; // _ _ _ _ _ _ _ _ "L" Led, "P" Peligro.
int TAI = 36; //_ _ _ _ _ _ _ _ _ "I" Interruptor.
int TAPT = 37; // _ _ _ _ _ _ _ _ "P" Pulsador, "T" Test ok.
int TACR; //_ _ _ _ _ _ _ _ _ _ _ "C" Codigo, "R" Recibido: Almacena codigo de Link2FS para TA.
int TAVEI = digitalRead(TAI);// _ "V" Variable, "E" Estado, "I" Interruptor.
int TAVEAI = 0;// _ _ _ _ _ _ _ _ "V" Variable, "E" Estado, "A" Anterior , "I" Interruptor.

//Variables Flaps
int FAL = 33; //_ _ _ _ _ "L" Led.
const int FPD = 34; //_ _ "P" Pulsador, "D" Down.
const int FPU = 35; //_ _ "P" Pulsador, "U" Up.
int FPUV = 0; //_ _ _ _ _ "V" Variable.
int FPUVA = 0; // _ _ _ _ "V" Variable, "A" Anterior.
int FPDV = 0; //_ _ _ _ _ "V" Variable.
int FPDVA = 0; // _ _ _ _ "V" Variable, "A" Anterior.
int FP = 0; // _ _ _ _ _ _"P" Posicion.

//Variables Freno de Estacionamiento
int FELP = 32; // _ _ _ _ _ _ _ _ "L" Led, "P" Peligro.
int FEI = 31; //_ _ _ _ _ _ _ _ _ "I" Interruptor.
int FEVEI = digitalRead(FEI);// _ "V" Variable, "E" Estado, "I" Interruptor.
int FEVEAI = 0;// _ _ _ _ _ _ _ _ "V" Variable, "E" Estado, "A" Anterior , "I" Interruptor.

//Subcodigo Botonera

uint8_t keypad_button_pressed[BUTTON_COUNT];
volatile uint32_t ticks;
uint32_t lastTrigger;


ISR(TIMER0_COMPA_vect, ISR_BLOCK) {
  ticks++;
}

void init_systicks() {

  TCCR0B = _BV(CS02) | _BV(CS00);
  TCCR0A = _BV(WGM01);
  TIMSK0 = _BV(OCIE0A);

  // 8000000/1024/78 == 100HZ -> 10 ms
  OCR0A = 38; // !!! must be set last or it will not work!
}

uint32_t math_calc_diff(uint32_t value1, uint32_t value2) {
  if (value1 == value2) {
    return 0;
  }
  if (value1 > value2) {
    return (value1 - value2);
  }
  else {
    // check for overflow
    return (0xffffffff - value2 + value1);
  }
}

void keypad_reset_output() {
  // configure pull ups
  digitalWrite(18, HIGH);
  digitalWrite(19, HIGH);
  digitalWrite(20, HIGH);
  digitalWrite(21, HIGH);
  digitalWrite(22, HIGH);
  digitalWrite(23, HIGH);
}

void clear_buttons() {
  for(int i=0; i < BUTTON_COUNT; i++) {
    keypad_button_pressed[i] = 0;
  }
}

void keypad_setup() {
  // initialize the digital pin as an output:
  pinMode(18, OUTPUT);
  pinMode(19, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(21, OUTPUT);
  pinMode(22, OUTPUT);
  pinMode(23, OUTPUT);

  keypad_reset_output();

  pinMode(24, INPUT);
  pinMode(25, INPUT);
  pinMode(26, INPUT);
  pinMode(27, INPUT);
  pinMode(28, INPUT);
  pinMode(29, INPUT);
  pinMode(30, INPUT);

  // configure pull ups
  digitalWrite(24, HIGH);
  digitalWrite(25, HIGH);
  digitalWrite(26, HIGH);
  digitalWrite(27, HIGH);
  digitalWrite(28, HIGH);
  digitalWrite(29, HIGH);
  digitalWrite(30, HIGH);
}


void keypad_read_buttons() {
  clear_buttons();
  uint8_t y=0;
  for(int i=KEYPAD_OUTPUT_BEGIN; i <= KEYPAD_OUTPUT_END; i++) {
    keypad_reset_output();
    digitalWrite(i, LOW);
    uint8_t x=0;
    for(int j=KEYPAD_INPUT_BEGIN; j <= KEYPAD_INPUT_END; j++) {
      if (digitalRead(j) == LOW) {
        uint8_t index = x+7*y;  //OJO el numero de la ecuacion es la cantidad de columnas
        keypad_button_pressed[index] = 1;
      }
      x++;
    }
    y++;
  }
}

uint8_t keypad_button_is_pressed() {
  for (int i=0; i < BUTTON_COUNT; i++) {
    if (keypad_button_pressed[i]) {
      return 1;
    }
  }
  return 0; // no button pressed
}

String datos[42] = {"H01", "H02","H03","H04","H05","H06","H07","H08","H09","H10","H11","H12","H13","H14", "H15","H16","H17","H18","H19","H20",
                "H21", "H22","H23","H24","H25","H26","H27","H28","H29","H30","H31","H32","H33","H34", "H35","H36","H37","H38","H39","H40",
                "H41", "H42"};

//Fin Subcodigo botonera


void setup() {
Serial.begin (115200);

// SETUP de Encoders
  pinMode (PGM1_PCLK,INPUT);
  pinMode (PGM1_PDT,INPUT);
   
  pinMode (PGM2_PCLK,INPUT);
  pinMode (PGM2_PDT,INPUT);

  pinMode (PHM1_PCLK,INPUT);
  pinMode (PHM1_PDT,INPUT);
   
  pinMode (PHM2_PCLK,INPUT);
  pinMode (PHM2_PDT,INPUT);

  pinMode (PMM1_PCLK,INPUT);
  pinMode (PMM1_PDT,INPUT);
   
  pinMode (PMM2_PCLK,INPUT);
  pinMode (PMM2_PDT,INPUT);

//Setup Tren de aterrizaje
  pinMode(TALN, OUTPUT);
  pinMode(TALI, OUTPUT);
  pinMode(TALD, OUTPUT);
  pinMode(TALP, OUTPUT);
  pinMode(TAI, INPUT_PULLUP);
  pinMode(TAPT, INPUT_PULLUP);

//Setup Flaps
  pinMode(FPU, INPUT_PULLUP);
  pinMode(FPD, INPUT_PULLUP);
  pinMode(FAL, OUTPUT);

//Setup Freno de Estacionamiento
  pinMode(FEI, INPUT_PULLUP);
  pinMode(FELP, OUTPUT);

//Setup Botonera
  init_systicks();
  keypad_setup();
}

void loop() {
//_________ LOOP Encoders______________
time = millis();
//------Palanca de Gases Motor 1
  if (digitalRead(PGM1_PCLK) == LOW){
    PGM1_RE_T = time;
    if (PGM1_RE_A == true){
      PGM1_RE_P ++;
      PGM1_RE_A = false;
      PGM1_RE_B = false;
      PGM1_RE_P = min(10, max(0, PGM1_RE_P));
      sprintf(buffer_temporal, "C56%03u\r\n", PGM1_RE_P*99/10);
      Serial.print(buffer_temporal);
      }
  }
  if (digitalRead(PGM1_PDT)== LOW){
    PGM1_RE_T = time;
    if(PGM1_RE_B == true){
      PGM1_RE_P --;
      PGM1_RE_A = false;
      PGM1_RE_B = false;
    PGM1_RE_P = min(10, max(0, PGM1_RE_P));
      sprintf(buffer_temporal, "C56%03u\r\n", PGM1_RE_P*99/10);
      Serial.print(buffer_temporal);     }
  }
  if (time - PGM1_RE_T>10){
    PGM1_RE_A = true;
    PGM1_RE_B = true;
  }
  
 //------Palanca de Gases Motor 2
   if (digitalRead(PGM2_PCLK) == LOW){
    PGM2_RE_T = time;
    if (PGM2_RE_A == true){
      PGM2_RE_P ++;
      PGM2_RE_A = false;
      PGM2_RE_B = false;
      PGM2_RE_P = min(10, max(0, PGM2_RE_P));
      sprintf(buffer_temporal, "C57%03u\r\n", PGM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (digitalRead(PGM2_PDT)== LOW){
    PGM2_RE_T = time;
    if(PGM2_RE_B == true){
      PGM2_RE_P --;
      PGM2_RE_B = false;
      PGM2_RE_A = false;
      PGM2_RE_P = min(10, max(0, PGM2_RE_P));
      sprintf(buffer_temporal, "C57%03u\r\n", PGM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (time - PGM2_RE_T>10){
    PGM2_RE_A = true;
    PGM2_RE_B = true;
  }
  
  //------Paso Helice Motor 1
  if (digitalRead(PHM1_PCLK) == LOW){
    PHM1_RE_T = time;
    if (PHM1_RE_A == true){
      PHM1_RE_P ++;
      PHM1_RE_A = false;
      PHM1_RE_B = false;
      PHM1_RE_P = min(10, max(0, PHM1_RE_P));
      sprintf(buffer_temporal, "C60%03u\r\n", PHM1_RE_P*99/10);
      Serial.print(buffer_temporal);
      }
  }
  if (digitalRead(PHM1_PDT)== LOW){
    PHM1_RE_T = time;
    if(PHM1_RE_B == true){
      PHM1_RE_P --;
      PHM1_RE_A = false;
     PHM1_RE_B = false;
    PHM1_RE_P = min(10, max(0, PHM1_RE_P));
      sprintf(buffer_temporal, "C60%03u\r\n", PHM1_RE_P*99/10);
      Serial.print(buffer_temporal);
     }
  }
  if (time - PHM1_RE_T>10){
    PHM1_RE_A = true;
    PHM1_RE_B = true;
  }

 //------Paso Helice Motor 2
   if (digitalRead(PHM2_PCLK) == LOW){
    PHM2_RE_T = time;
    if (PHM2_RE_A == true){
      PHM2_RE_P ++;
      PHM2_RE_A = false;
      PHM2_RE_B = false;
      PHM2_RE_P = min(10, max(0, PHM2_RE_P));
      sprintf(buffer_temporal, "C61%03u\r\n", PHM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (digitalRead(PHM2_PDT)== LOW){
    PHM2_RE_T = time;
    if(PHM2_RE_B == true){
      PHM2_RE_P --;
      PHM2_RE_B = false;
      PHM2_RE_A = false;
      PHM2_RE_P = min(10, max(0, PHM2_RE_P));
      sprintf(buffer_temporal, "C61%03u\r\n", PHM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (time - PHM2_RE_T>10){
    PHM2_RE_A = true;
    PHM2_RE_B = true;
  }

//------Palanca de Mezcla Motor 1
  if (digitalRead(PMM1_PCLK) == LOW){
    PMM1_RE_T = time;
    if (PMM1_RE_A == true){
      PMM1_RE_P ++;
      PMM1_RE_A = false;
      PMM1_RE_B = false;
      PMM1_RE_P = min(10, max(0, PMM1_RE_P));
     sprintf(buffer_temporal, "C58%03u\r\n", PMM1_RE_P*99/10);
      Serial.print(buffer_temporal);
      }
  }
  if (digitalRead(PMM1_PDT)== LOW){
    PMM1_RE_T = time;
    if(PMM1_RE_B == true){
      PMM1_RE_P --;
      PMM1_RE_A = false;
      PMM1_RE_B = false;
      PMM1_RE_P = min(10, max(0, PMM1_RE_P));
     sprintf(buffer_temporal, "C58%03u\r\n", PMM1_RE_P*99/10);
      Serial.print(buffer_temporal);
     }
  }
  if (time - PMM1_RE_T>10){
    PMM1_RE_A = true;
    PMM1_RE_B = true;
  }
//------Palanca de Mezcla Motor 2
   if (digitalRead(PMM2_PCLK) == LOW){
    PMM2_RE_T = time;
    if (PMM2_RE_A == true){
      PMM2_RE_P ++;
      PMM2_RE_A = false;
      PMM2_RE_B = false;
      PMM2_RE_P = min(10, max(0, PMM2_RE_P));
       sprintf(buffer_temporal, "C59%03u\r\n", PMM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (digitalRead(PMM2_PDT)== LOW){
    PMM2_RE_T = time;
    if(PMM2_RE_B == true){
      PMM2_RE_P --;
      PMM2_RE_B = false;
      PMM2_RE_A = false;
      PMM2_RE_P = min(10, max(0, PMM2_RE_P));
     sprintf(buffer_temporal, "C59%03u\r\n", PMM2_RE_P*99/10);
      Serial.print(buffer_temporal);
    }
  }
  if (time - PMM2_RE_T>10){
    PMM2_RE_A = true;
    PMM2_RE_B = true;
  }
// Control TA - Tren de Aterrizaje
  if(Serial.available()){
   TACR = getChar(); // _ _ Lectura codigo Link2FS para pocision del TA (ASCII) ? -> 63 Y -> 89
    if(TACR == 63){
     TACR = getChar();
      if(TACR == 89){
       int TAVN = getChar()-48; // _ _ "V" Variable, "N" Nariz. (Se resta 48 pq el 2 en ASCII se representa con el codigo 50)
       int TAVI = getChar()-48; // _ _ "V" Variable, "I" Izquierda. (Se resta 48 pq el 2 en ASCII se representa con el codigo 50)
       int TAVD = getChar()-48; // _ _ "V" Variable, "N" Derecha. (Se resta 48 pq el 2 en ASCII se representa con el codigo 50)          
       if(TAVN == 2){digitalWrite(TALN, HIGH);}else {digitalWrite(TALN, LOW);}
       if(TAVI == 2){digitalWrite(TALI, HIGH);} else {digitalWrite(TALI, LOW);}
       if(TAVD == 2){digitalWrite(TALD, HIGH);} else {digitalWrite(TALD, LOW);}
       if(TAVN+TAVI+TAVD<6 && TAVN+TAVI+TAVD>0){digitalWrite(TALP, HIGH);} else {digitalWrite(TALP, LOW);}
    }
   }
 }
// Envio de codigo a Link2FS acorde a la posicion del interruptor de TA 
  TAVEI = digitalRead(TAI);
  if(TAVEI == 0 && digitalRead(TALN)== LOW && TAVEI != TAVEAI){Serial.println("C02");}
  if(TAVEI != 0 && digitalRead(TALN) == HIGH && TAVEI != TAVEAI){Serial.println("C01");}
  TAVEAI = TAVEI;
 int TAVPT = digitalRead(TAPT);//"V" Variable, "P" Pulsador, "T" Test.
  if(TAVPT == 0){
   digitalWrite(TALN, HIGH); digitalWrite(TALI, HIGH); digitalWrite(TALD, HIGH);digitalWrite(TALP, HIGH);delay(500);
   digitalWrite(TALN, LOW); digitalWrite(TALI, LOW); digitalWrite(TALD, LOW);digitalWrite(TALP, LOW);}

// Control F - Flaps
  FPUV = digitalRead(FPU);
  if (FPUV == HIGH && FPUVA != HIGH) {
    Serial.println("C15");
    FP --;
    FP = min(4, max(0, FP));
    }
    delay(10);
    FPUVA = FPUV;
    
  FPDV = digitalRead(FPD);
  if (FPDV == HIGH && FPDVA != HIGH) {
    Serial.println("C14");
    FP ++;
    FP = min(4, max(0, FP));
    }
  FPDVA = FPDV;
    
  if(FP == 0){digitalWrite(FAL, LOW);} else {digitalWrite(FAL, HIGH);}

// Control FE - Freno de Estacionamiento
 FEVEI = digitalRead(FEI);
  if(FEVEI == 0 && digitalRead(TALN)== HIGH && FEVEI != FEVEAI){Serial.println("C040"); digitalWrite(FELP, LOW);}
  if(FEVEI != 0 && digitalRead(TALN) == HIGH && FEVEI != FEVEAI){Serial.println("C041");digitalWrite(FELP, HIGH);}
  FEVEAI = FEVEI;

// Matriz de Botonera
 keypad_read_buttons();

  // allow button processing only every 300ms (30 systicks)
  if (keypad_button_is_pressed() && (math_calc_diff(ticks, lastTrigger) > 50)) {
    lastTrigger = ticks;

    for(int i=0; i < BUTTON_COUNT; i++) {
      if (keypad_button_pressed[i]) {
        Serial.println(datos[i]);
      }
    }
   }
} // FINAL void loop OJO!!!!

//FUNCION getChar() Pertenece al Tren de Aterrizaje
char getChar(){
  while(Serial.available()==0);
  return((char)Serial.read());
}

aca les dejo el codigo de la botonera que esta repartido dentro del de arriba:

#include <Arduino.h>

#define BUTTON_COUNT 42
#define KEYPAD_OUTPUT_BEGIN 2
#define KEYPAD_OUTPUT_END 7
#define KEYPAD_INPUT_BEGIN 8
#define KEYPAD_INPUT_END 14


uint8_t keypad_button_pressed[BUTTON_COUNT];
volatile uint32_t ticks;
uint32_t lastTrigger;


ISR(TIMER0_COMPA_vect, ISR_BLOCK) {
  ticks++;
}

void init_systicks() {

  TCCR0B = _BV(CS02) | _BV(CS00);
  TCCR0A = _BV(WGM01);
  TIMSK0 = _BV(OCIE0A);

  // 8000000/1024/78 == 100HZ -> 10 ms
  OCR0A = 77; // !!! must me set last or it will not work!
}

uint32_t math_calc_diff(uint32_t value1, uint32_t value2) {
  if (value1 == value2) {
    return 0;
  }
  if (value1 > value2) {
    return (value1 - value2);
  }
  else {
    // check for overflow
    return (0xffffffff - value2 + value1);
  }
}

void keypad_reset_output() {
  // configure pull ups
  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
}

void clear_buttons() {
  for(int i=0; i < BUTTON_COUNT; i++) {
    keypad_button_pressed[i] = 0;
  }
}

void keypad_setup() {
  // initialize the digital pin as an output:
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);

  keypad_reset_output();

  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  pinMode(14, INPUT);

  // configure pull ups
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
  digitalWrite(14, HIGH);
}



// the loop() method runs over and over again,
// as long as the Arduino has power

void keypad_read_buttons() {
  clear_buttons();
  uint8_t y=0;
  for(int i=KEYPAD_OUTPUT_BEGIN; i <= KEYPAD_OUTPUT_END; i++) {
    keypad_reset_output();
    digitalWrite(i, LOW);
    uint8_t x=0;
    for(int j=KEYPAD_INPUT_BEGIN; j <= KEYPAD_INPUT_END; j++) {
      if (digitalRead(j) == LOW) {
        uint8_t index = x+7*y;  //OJO el numero de la ecuacion es la cantidad de columnas
        keypad_button_pressed[index] = 1;
      }
      x++;
    }
    y++;
  }
}

uint8_t keypad_button_is_pressed() {
  for (int i=0; i < BUTTON_COUNT; i++) {
    if (keypad_button_pressed[i]) {
      return 1;
    }
  }
  return 0; // no button pressed
}


String datos[42] = {"H01", "H02","H03","H04","H05","H06","H07","H08","H09","H10","H11","H12","H13","H14", "H15","H16","H17","H18","H19","H20",
                "H21", "H22","H23","H24","H25","H26","H27","H28","H29","H30","H31","H32","H33","H34", "H35","H36","H37","H38","H39","H40",
                "H41", "H42"};

// The setup() method runs once, when the sketch starts
void setup() {
  init_systicks();
  keypad_setup();

  Serial.begin(9600);
}

void loop() {

  keypad_read_buttons();

  // allow button processing only every 300ms (30 systicks)
  if (keypad_button_is_pressed() && (math_calc_diff(ticks, lastTrigger) > 50)) {
    lastTrigger = ticks;

    for(int i=0; i < BUTTON_COUNT; i++) {
      if (keypad_button_pressed[i]) {
        Serial.println(datos[i]);
      }
    }
   }
  delay(1);
}

desde ya gracias ya con esto casi tengo terminada mi cabina de simulador :smiley:

¿Qué arduino estás usando?
¿Qué tal mostrar un esquema o dibujo con los dispositivos conectados a este arduino?

RV mineirin

perdon falto eso ahora lo describo

Arduino utilizado es un MEGA
hay 6 encoders rotativos de 20 pasos por vuelta
4 leds
3 botones push
2 llaves on off
y la matriz de botones push de 6 x 7

tengo los cables conectados relativamente en orden ocupando desde el pin 18 al 53 del arduino mega, y mientras tenga lugar y pueda me gustaría ir agregando funciones

el código lee el estado de los diferentes comandos (encoders, botones) y manda por puerto serie codigos compuestos por una letra y un numero de dos cifras, ej: H01, C30, etc..

en solo un caso el arduino escucha el puerto serie para requerir información del simulador.
en la parte de control de aterrizaje donde lee el estado del mismo para encender o no los leds

esos codigos son interpretados por un programa y los reenvia a el flight simulator X ( pero esta parte ya no afecta al arduino

El problema es que pierdes los pulsos por el tamaño del programa. No tienes alternativa, debes utilizar interrupciones para leer los encoders. Como estas utilizando un mega tienes seis de ellas, si no son suficientes tienes que hallar una solución por hardware.

En serio me decís que un programa largo de solo botones ralentiza tanto la lectura de un encoder?

Nada se usa en simultáneo, nada transmite información constante...

Veo cosas impresionantes y complejas hechas con Arduino en internet y la respuesta es que mi código es largo.

No veo lógica la respuesta.

Lo de las interrupciones lei pero tendré que investigar cómo hacerlas y las probaré

Cuando mas largo el codigo, mayor tiempo de ejecución. Cuando ese tiempo de ejecución supera a la frecuencia del pulso, pierdes pulsos.

Vuelve a la carga este hilo Matriz de botones, que se cerró hace dias solamente. Ahora los hilos tienen cierre automático asi que si te interesa lo uno con el anterior.
Lo que dice @PeterKantTropus es exactamente la razón de tu problema.
Código demasiado largo y muchos encoders que atender que solo puede hacerse usando interrupciones.
Si no crees lo que te dice el compañero, simplemente mira el tiempo que demora tu código en ejectutarse y comparado con lo que demora un pulso de cualquier enconder.
Para que funcione lo que has escrito, un ciclo debe ejecturarse mas rápidamente de lo que tarda un cambio de pulos de cualquiera de tus enconders.
Busca en el Gestor de Librerías Enconder y recomienza por ahi.

Hola. Aclarar que no se trata de que el código sea más o menos "grande", sino cuánto tiempo transcurre entre se comprueba el estado de un encoder y se vuelve a comprobar de nuevo el estado de ese encoder. Porque si se tarda demasiado entre cada comprobación, es muy probable que se "pierdan" los cambios que nos indican los pasos del encoder. ¿Cuánto es "tardar demasiado"? Pues depende de la velocidad de los cambios de las señales del encoder.

Como he dicho, no depende del tamaño del programa, sino lo que tarde en "hacer el resto de cosas" entre cada verificación del estado del encoder. No sólo líneas y líneas de ejecución de programa "alargan" ese tiempo, sino que también los los delay() (que los hay en en programa aunque rara vez se ejecuten), y los bucles for. Hay unos cuantos bucles que hacen que un par de líneas de código se ejecuten como si fueran unas decenas de líneas.

Para solucionar el problema de los delay() y los for habría que orientar el código a millis() y máquinas de estados. Pero si quieres "hacer un apaño" y ver si "escapas", dispuestos ha hacer una chapuza, yo pondría el control de los encoders en una función y llamaría a esa función justo antes de cada trozo de programa que contenga un for. Pero, eso sería un apaño bastante chapucero. Lo mejor es orientar todo el código a máquinas de estados y millis(). Y aún así, tal vez, si los encoders van a "demasiada velocidad",
no garantizo que funcionen adecuadamente y sería necesario hacerlo con interrupciones. Si lo hicieras con interrupciones, tal vez no fueran tan críticos los bucles que tienes en el código.

¿Cómo nos podemos librar de los for? La idea es que en lugar de procesar todos los botones "de golpe" y en una sola pasada con bucles, procesamos un botón por cada ciclo del loop(). En cada ciclo de ejecución del loop() yo verificaría todos los encoders y luego uno de los botones. Incluso el resto de cosas no las verificaría todas en cada ciclo, sino una de ellas cada vez.

Como ejemplo de cómo "deshacerse" de un for, para que éste no "entretenga" el loop(), puedes ver este foro el hilo usar millis() junto con for() donde propongo un par de ideas.

En cuanto a las máquinas de estado, hay unos cuantos tutoriales en este mismo foro en la sección de documentación: Indice de temas Tutoriales.

Y si quieres un ejemplo de uso de máquinas de estados "paso a paso", en el hilo alarma temporizada en un mismo led al presionar un botón trato de explicar paso a paso el desarrollo de un programa usando máquinas de estados y millis().

1 Like

Hola IgnoranteAbsoluto, ya que te explicaste tanto, te cuento los encoders son los rotativos de 20 pasos y estan conectados cada uno a una palanca (son los comandos de aceleracion, paso de helices, y mezcla de combustible) la velocidad de uso es baja pq las palancas se mueven unos pocos grados y lento y aparte no se usan constantemente.

una base para lo que describo abajo => no se programar, todo lo que esta ahí lo aprendí interpretando códigos de otras cosas y haciendo pruebas para adaptar a mi necesidad cuando funcionaba lo metia al código principal, si funcionaba seguí con otra cosa, si no volvía a empezar jeje.

ahora a la otra parte, como comentan los chicos arriba, eh tratado de usar las librerias, soy sincero me costo un monton tratar de configurar los 6 encoders con las librerías y el serial print y no pude hacerlo funcionar.
En mi cabeza redundaba siempre la posibilidad de hacer lo que vos mencionas. Sin saber si se podia hacer o no, pense armo una función en la que los pines de encoder sean variables que al mover un encoder entre en la función cumpla el cometido y siga hasta que otro encoder se mueva. Esa era la idea en mi cabeza XD jajaj pero tampoco pude hacerlo
La otra idea mas loca para mi nivel de conocimiento era crear una librería para mi necesidad , estudiando como era la librería de encoder y adaptarla para mi, pero otra vez me sobrepaso.

Ya estaba mirando de aprender las interrupciones, o dedicar un arduino nano solo para los encoders, que me la complicaron siempre, o caer a volver a los potenciómetros y renegar con el filtrado de señales.

Algo adicional, no creo agregar mas nada, con este codigo ya tengo bastante cubiertas las funciones principales del control del vuelo para el simulador. (en relacion a esto :

Pero si quieres "hacer un apaño" y ver si "escapas", dispuestos ha hacer una chapuza, yo pondría el control de los encoders en una función y llamaría a esa función justo antes de cada trozo de programa que contenga un for . Pero, eso sería un apaño bastante chapucero.

Gracias por la respuesta sigo escarbando por mi lado y si se les prende un foco bienvenido sea :smiley: .

Hola. He estado probando "suelto" el código que controla cada encoder y creo que, tal vez, si en cada una de las comparaciones que tienes del tipo:

  if (time - PGM1_RE_T>10){
    PGM1_RE_A = true;
    PGM1_RE_B = true;
  }

... cambias el 10 en cada una de ellas por un valor más bajo, puede que te funcione bastante mejor a como te funciona ahora sin ningún otro cambio. Prueba a cambiarlo por un 2 en todas y nos cuentas que tal.

Hola de nuevo, ignorante eso le fui bajando al valor como me dijiste, incluso a 1, no hubo cambios, siguen sin funcionar:

  }
  if (time - PMM2_RE_T>2){
    PMM2_RE_A = true;
    PMM2_RE_B = true;
  }

pregunta, modificar esto puede ayudar en algo? (forma parte del codigo de la matriz de botones)

  // 8000000/1024/78 == 100HZ -> 10 ms
  OCR0A = 120; // !!! must me set last or it will not work!
  // allow button processing only every 300ms (30 systicks)
  if (keypad_button_is_pressed() && (math_calc_diff(ticks, lastTrigger) > 100)) {
    lastTrigger = ticks;

Ya que estamos les comparto unas imagenes de lo que estoy haciendo.
en la primera se ven 2 de las 3 placas que tengo que armar de la matriz de botones y iran puestas al rededor de la pantalla de la izquierda del simulador (foto 2)
Espero les guste

Creo que he dado con el origen del problema. He montado 4 encoders en un MEGA y le he metido tu programa. Al probarlos vi que, salvo una primera vez, el movimientos de los encoders no daba resultado alguno. Como si el programa se hubiera quedado bloqueado. Me dio por mostrar por la salida serie el valor de time justo después de que se le asigna el valor de millis(), más que nada para ver que el loop() no se detenía y hacerme una idea de si se ejecutaba muy lento, cuando para sorpresa mía vi que el valor siempre era cero.

Me quedé pensando en algo muy raro que tienes en el código. En ciertas partes del código parece utilizar un temporizador para "medir el tiempo", con la ayuda de la variable ticks. Me dio por comentar la llamada a la función init_systicks() que se hace al final de setup() y entonces se mostraban valores "normales" para time. A la vez que los encoders funcionaban perfectamente.

Tengo la impresión de que está utilizando el mismo temporizador que usa millis() y está deshabilitando la funcionalidad de millis(). La función que configura el temporizador es esta, por si algún conocedor de los temporizadores del MEGA nos lo puede confirmar:

void init_systicks() {

  TCCR0B = _BV(CS02) | _BV(CS00);
  TCCR0A = _BV(WGM01);
  TIMSK0 = _BV(OCIE0A);

  // 8000000/1024/78 == 100HZ -> 10 ms
  OCR0A = 38; // !!! must be set last or it will not work!
}

Supongo que con sustituir el uso de ticks por el uso de time tendrías solucionado el problema. Prueba con comentar la línea que llama a init_systicks() tal que así:

//Setup Botonera
  //init_systicks();
  keypad_setup();

Y sustituir la variable ticks por la variable time en las dos líneas:

  if (keypad_button_is_pressed() && (math_calc_diff(ticks, lastTrigger) > 50)) {
    lastTrigger = ticks;

Quedando tal que así:

  if (keypad_button_is_pressed() && (math_calc_diff(time, lastTrigger) > 50)) {
    lastTrigger = time;

Los tiempos de "repetición" de la tecla pulsada serán ahora algo menor. Puedes ajustarlo cambiando el 50 de la primera línea por un valor mayor.

Si te funciona y convence, elimina las funciónes init_systicks() y ISR(TIMER0_COMPA_vect, ISR_BLOCK). También puedes eliminar la definición de la variable ticks. Todo eso ya no sería necesario.

1 Like

SOS UN GRANDE jaja

Funciona perfecto a cualquier velocidad de movimiento de los encoders con el cambio de ticks por time, eso si, me quedo rápida la velocidad de lectura de la matriz así que ese valor lo puse en 200, si no, me tiraba dos valores o tres con una sola pulsada.

  if (keypad_button_is_pressed() && (math_calc_diff(time, lastTrigger) > 200)) {
    lastTrigger = time;

¡Qué grande @IgnoranteAbsoluto ! :clap:t2: :clap:t2: :clap:t2:

¿Sabes que revisé como 10 veces el código y se me escapó que estaba usando el timer 0?

No comenté nada porque como no daba con el error no tenía nada para aportar pero mirá que es evidente, eh!

Al mejor cazador se le escapa una liebre, dicen. :rofl:

Saludos