Arduino borracho con 7 Ifs? (SOLUCIONADO)

Hola a todos!

He hecho un programilla para un shield Joystick de 2 potenciómetros y 7 buttons. Lo he agregado mas abajo, y consta de:

Una función checkbutton() para coger y guardar el estado de los 2 potenciómetros y los 7 buttons. La función incluye debounce en los 7 buttons y un hold para el joystick, si nos quedamos en una posición va marcando cada 500 millis la posición.

Una función actionbutton() que, si hay cambios en los datos, manda a Serial el button o joystick que se ha pulsado o soltado.

Mientras construía el programa, he utilizado un for() para saber el estado de cada button, y oye, funciona de maravilla. Es el código que hay comentado en el inicio de la función actionbutton().

La sorpresa me viene cuando sustituyo el for() por 7 ifs, para poder tener opciones diferentes para cada button, es decir, if(estado[x_button]) { hago loque quiero aquí con cada button}.

Pero cuando lo pruebo, todo son errores. Con un debug de las variables justo antes de la función actionbutton() no hay cambio de variables, pero marca algun boton como pressed o released.

He probado de mover la función antes de void loop(), después de Void loop(), sin función con el código dentro de void loop(), con bucles else if y sin...Los resultados son diferentes. Lee falsos push de algun button en bucle infernal, o cambia todos los botones de entrada y haciendo bucle de escritura en algun button.

Estoy seguro que el error es mío, pero, alguien sabe algun porqué?

Porqué funciona de maravilla con for(), y intentar hacer lo mismo manualmente con if() no funciona?

Agradecería si alguien tiene algo que decir...

JSTK_7Btn_Dbce_holdV2.ino (5.92 KB)

Ui, perdón, mi primer post, claro :o

Dejo el código para no tener que descargar.

#define A_BUTTON 2
#define B_BUTTON 3
#define C_BUTTON 4
#define D_BUTTON 5
#define E_BUTTON 6
#define F_BUTTON 7
#define KEY_BUTTON 8
#define AXIS_X A0
#define AXIS_Y A1

#define MINJOY 80
#define MAXJOY 170
#define NUMBUTTONS sizeof(buttons)

byte buttons[] = {A_BUTTON, B_BUTTON, C_BUTTON, D_BUTTON,
                  E_BUTTON, F_BUTTON, KEY_BUTTON};
byte axisX, axisY;  
byte Xstate, Ystate, lastXstate, lastYstate;                
int debouncetime = 10;
int holdtime = 500;
    
unsigned long lasttime;
unsigned long timeXjoy, timeYjoy;

char *btntext[] = {" A", " B", " C", " D", " E", " F", " K" };
char *text[] = {" pressed", " Released"};

int laststate[NUMBUTTONS], currentstate[NUMBUTTONS];
int firstpressed[NUMBUTTONS], pressed[NUMBUTTONS], released[NUMBUTTONS];
int hold[NUMBUTTONS]; 

//=================== SETUP ===============================
void setup() {
    Serial.begin(9600); 
    Serial.print(F("Prova amb "));
    Serial.print(NUMBUTTONS, DEC);
    Serial.println(F(" buttons i Joystick"));
    for (byte i=0; i< NUMBUTTONS; i++) {
        pinMode(buttons[i], INPUT_PULLUP);
        currentstate[i] = true;
        laststate[i] = true;
        firstpressed[i] = false;
        pressed[i] = false;
        released[i] = false;}
    Xstate = 0;
    Ystate = 0;    
    
}
 /*    for (byte i=0; i< NUMBUTTONS; i++) {
      if(firstpressed[i] && !currentstate[i])
          {Serial.print(btntext[i]); Serial.print(text[0]);}
    }
    for (byte i=0; i< NUMBUTTONS; i++) {
      if(released[i] && currentstate[i])
          {Serial.print(btntext[i]); Serial.println(text[1]);}
    }  */
void actionbuttons(){
     if(firstpressed[A_BUTTON])
        {Serial.print(btntext[0]); Serial.print(text[0]);}
    else if(firstpressed[B_BUTTON])
        {Serial.print(btntext[1]); Serial.print(text[0]);}
    else if(firstpressed[C_BUTTON])
        {Serial.print(btntext[2]); Serial.print(text[0]);}
    else if(firstpressed[D_BUTTON])
        {Serial.print(btntext[3]); Serial.print(text[0]);}
    else if(firstpressed[E_BUTTON])
        {Serial.print(btntext[4]); Serial.print(text[0]);}
    else if(firstpressed[F_BUTTON])
        {Serial.print(btntext[5]); Serial.print(text[0]);}
    else if(firstpressed[KEY_BUTTON])
        {Serial.print(btntext[6]); Serial.print(text[0]);}   
} 
      

 /*  if(released[A_BUTTON]){Serial.print(btntext[0]); Serial.println(text[1]);}
    if(released[B_BUTTON]){Serial.print(btntext[1]); Serial.println(text[1]);}
    if(released[C_BUTTON]){Serial.print(btntext[2]); Serial.println(text[1]);}
    if(released[D_BUTTON]){Serial.print(btntext[3]); Serial.println(text[1]);}
    if(released[E_BUTTON]){Serial.print(btntext[4]); Serial.println(text[1]);}
    if(released[F_BUTTON]){Serial.print(btntext[5]); Serial.println(text[1]);}
    if(released[KEY_BUTTON]){Serial.print(btntext[6]); Serial.println(text[1]);}; */

    
void checkbuttons(){ 
  if (millis() < lasttime) { lasttime = millis(); } 
  if (millis() < timeXjoy) { timeXjoy = millis(); }
  if (millis() < timeYjoy) { timeYjoy = millis(); } 
  
//  ================ BUTTONS ============================
  
  for (byte i=0; i< NUMBUTTONS; i++) {
    currentstate[i] = digitalRead(buttons[i]);
    if( !currentstate[i] && laststate[i]){ lasttime = millis(); }
    
    if(released[i]) {released[i]=false;}
    
    if( currentstate[i] && !laststate[i]){
        if(pressed[i]){
            pressed[i] = false;
            released[i] = true; }
    }
    if(firstpressed[i]){
        pressed[i] = true;
        firstpressed[i] = false;
    }   
    if(millis()-lasttime > debouncetime){
        if( !pressed[i] && !currentstate[i] ) {firstpressed[i] = true;}
    } 
    laststate[i] = currentstate[i];
  } 
 // ================== JOYSTICK ============================
  
  axisX = analogRead(AXIS_X)/4; 
  axisY = analogRead(AXIS_Y)/4;  
  if(axisX < MINJOY) Xstate = 2;  
  else if(axisX > MAXJOY)  Xstate = 1; 
  else (Xstate = 0 );

  if(Xstate != lastXstate){
      if(Xstate == 2) {
          Serial.print(F("RIGHT"));
          timeXjoy = millis();         
      }
      else if(Xstate == 1){
          Serial.print(F("LEFT"));
          timeXjoy = millis();
      }
      else(Serial.println(F(" X Out")));
  }else{
      if(Xstate == 2 && (millis() - timeXjoy > holdtime)){
          Serial.print(F(" R+"));
          timeXjoy = millis();
      }else if(Xstate == 1 && millis() - timeXjoy > holdtime){
          Serial.print(F(" L+"));
          timeXjoy = millis();
      }
  };
  
  if(axisY < MINJOY) Ystate = 2; 
  else if(axisY > MAXJOY)Ystate = 1;
  else(Ystate = 0 ); 

  if(Ystate != lastYstate){
      if(Ystate == 2) {
          Serial.print(F("UP"));
          timeYjoy = millis();
      }
      else if(Ystate == 1){
          Serial.print(F("DOWN"));
          timeYjoy = millis();
      }
      else(Serial.println(F(" Y Out")));
  }else{
      if(Ystate == 2 && (millis() - timeYjoy > holdtime)){
          Serial.print(F(" Up+"));
          timeYjoy = millis();
      }else if(Ystate == 1 && millis() - timeYjoy > holdtime){
          Serial.print(F(" Dw+"));
          timeYjoy = millis();
      }
  };
  lastXstate = Xstate;
  lastYstate = Ystate; 
} 
//======================= VOID LOOP =====================
void loop() {
  checkbuttons();
  /*for(int i=0; i<NUMBUTTONS; i++){
      Serial.print("Button ");Serial.print(btntext[i]);
      Serial.print(" cuSt=");Serial.print(currentstate[i]);
      Serial.print(" laSt=");Serial.print(laststate[i]);
      Serial.print(" fiPr=");Serial.print(firstpressed[i]);
      Serial.print(" prss=");Serial.print(pressed[i]);
      Serial.print(" rel=");Serial.println(released[i]);     
  }
   Serial.println(""); */
   actionbuttons(); 
  //delay(1000);
}

Claro, mira lo que pasa:

#define NUMBUTTONS sizeof(buttons)
byte buttons[] = {A_BUTTON, B_BUTTON, C_BUTTON, D_BUTTON,
                  E_BUTTON, F_BUTTON, KEY_BUTTON};

Reservas memoria antes de tener valores en buttons, según tú, pero resulta que no es eso lo que haces, lo que haces es decirle al preprocesador que cada vez que encuentre NUMBUTTONS lo sustituya por sizeof(buttons) entonces la línea 28 se reescribe de esto:

int laststate[NUMBUTTONS], currentstate[NUMBUTTONS];

a esto

int laststate[sizeof(buttons)], currentstate[sizeof(buttons)];

Lo que me estaña es que compile
Creo que lo correcto es poner

#define NUMBUTTONS 7

Hola Tony,

gracias por la rápida respuesta.

Lo he probado tal y como dices, y los comportamientos son los mismos, con el for() va bien y con los ifs va mal.

De hecho, esto de sizeof(), lo utilizo y nunca me ha dado estos problemas, ya que el resultado es el mismo, no?

No sabía que está mal hacerlo.

Pero vaya, arduino se va de copas con solo 7 ifs, aun le doy vueltas, que demonios ocurre? No marca nada en los debugs de cada paso que pruebo...

Perdona tony,

cierto es que reservo la memoria sin asignar, pero viendo que tenía problemas, en el setup() he asignado cada variable en el for() de los pinmode(). En todas las pruebas de debug todas las variables estan bien, justo antes de entrar en la función. Donde cambia las variables para poder hacer el serial.print()??

Misterios de la naturaleza...

sizeoff reserva memoria, pero define cambia el comportamiento del pre procesador, no tengo tu hard para probarlo y no me hago una idea exacta de cómo deseas resolver el problema la verdad, ausencia absoluta de comentarios
Te seré sincero, he quitado al código todo lo que le sobra por los comentarios y si no lo arreglo barbaridades, no veo qué sucede y qué hace, está muy desordenado y sin comentario o forma que al menos yo pueda seguir la lógica que se pretende resolver

Una pregunta ¿si mantienes el botón pulsado mucho tiempo si reacciona?

TonyDiana: Algo me he debido de perder, pero sizeof solo devuelve la cantidad de memoria asignada por la variable. Por ese motivo a puttysforever no le altera el resultado. Lo correcto sería poner 7.

Saludos

PD: me he liado con los else if. No llego a comprender como funcionan. ¿has probado a quitar los else's y dejar solo los if's?

No puedo probar tu código, no tengo el hard, sólo puedo teorizar mentalmente el funcionamiento si comprendo la lógica que hay detrás la cual no estoy entendiendofunction googleTrButton8498343627013327() { var el = new google.translate.TranslateElement({ includedLanguages: "es", layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL, autoDisplay: false, multilanguagePage: true, floatPosition: 0 }); el.onTurnOffLanguageClick = function() { var event = document.createEvent("Event"); event.initEvent("te_disable_lang", true, true); document.body.dispatchEvent(event); }; el.showBanner(true); }

Texto original

Sugiere una traducción mejor


A mi me funciona en una simulación.
Abajo dejo la captura de pantalla de una simulación con Sofia.
Lo único que modifiqué (porque el simulador es lento) son los tiempos de debounce y holdtime.
Lo que veo es que pulsando en orden del pin 2 al 8 da la secuencia FKABCDE en lugar de ABCDEFK. Otra cosa, F y K (o sea pin 2 y 3) repiten a lo tonto, supongo que algo no funciona bien con holdtime.

¿Qué es Sofía?

Vale, ya veo qué es, ok, yo tengo manzano

Y, nadie es perfecto... Jajaja

Hola a todos,

muchas gracias por vuestra atención.

Ya he encontrado el problema!!! claro, error garrafal de principiante, como no.

Cuando la hacía con la función for() cogía el argumento de la variable i del indice, con valores del 0 al 6.

cuando ponía los ifs, lo hacía con la confusión de poner el nombre del #define del pin como argumento, por eso se alteraba el orden en los buttons.

Con poner el número correspondiente del 0 al 6 como argumento, y todo solucionado.

Os agradezco vustros comentarios, de hecho ha sido los comentarios de tony que me han hecho dar vueltas hasta encontrar el error.

PUCHA PUES NO ME DI CUENTA tienes razón era eso, jajajajajaj

Acostúmbrate a algo, comentarios, muchos comentarios, los cuales expliquen la lógica que pretendes, de echo, para que te hagas una idea, tengo un objeto que tiene 75 líneas de código y 230 de comentarios, en serio. Está en Python, si no te lo pasaba, un servidor de imail (e mails entre módulos de la aplicación) que me he construido para simplificar pasar parámetros de múltiples lugares a un objeto.

Sin comentarios, das por supuesto todo y es muy difícil pedir ayuda

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.