Autor Tema: Problema con digitalRead  (Leído 2630 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 20
Problema con digitalRead
« en: 18 de Marzo de 2018, 14:25:21 »
Buenas tardes amigos, soy nuevo en esto, estoy con problemas con un codigo el cual si lo escribo de una forma funciona y si lo escribo de otra no funciona y se supone que es lo mismo pero escrito de distinta forma  :(

De la siguiente forma el codigo no funciona:
Código: [Seleccionar]
int buttonPin = 2;                           
int contador  = 0;
int resultado = 0;

void setup() {
 
Serial.begin(9600);
pinMode(buttonPin,INPUT);                   
}

void loop() {
            resultado = digitalRead(buttonPin);
            if(resultado == LOW){
               if(resultado == HIGH){
               contador++;
               Serial.println(contador);
               delay(100);
               }
            }
           
         
}

De esta otra forma corre bien aunque en algunas ocasiones al hacer el push no da nada pero debe de ser por el delay que le puse tal vez variandolo debe de ser por el efecto rebote imagino...

Código: [Seleccionar]


int buttonPin = 2;                           
int contador  = 0;

void setup() {
 
Serial.begin(9600);
pinMode(buttonPin,INPUT);                   
}

void loop() {
               if(digitalRead(2) == LOW){
               if(digitalRead(2) == HIGH){
               contador++;
               Serial.println(contador);
               delay(100);
               }
            }
           
         
}


La placa que utilizo es Arduino UNO y la configuracion para el pushbutton es con una resistencia pull-up.

Les agradezco mucho por su ayuda y tengo un bonito dia!

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Problema con digitalRead
« Respuesta #1 en: 18 de Marzo de 2018, 15:00:57 »
 
Tu primer programa no es igual al segundo, en el primer IF no puedes comprobar el estado de la variable para ver si está HIGH, y dentro de ese IF volver a comprobarla para ver si está LOW, eso es un contrasentido.

Prueba con este código. Consejo, documenta e indenta el fuente para que sea más legible y en el futuro fácil de retomar.

Código: C++
  1. //************************************
  2. //***** Variables Globales ***********
  3. //************************************
  4. int buttonPin = 2;
  5. int contador = 0;
  6. int status = 0; // Anti rebote
  7.  
  8. //************************************
  9. //***** Configuración ****************
  10. //************************************
  11. void setup()
  12. {
  13.     Serial.begin(9600);
  14.     pinMode(buttonPin, INPUT);
  15. }
  16.  
  17. //*************************************
  18. //******** Programa principal *********
  19. //*************************************
  20. void loop()
  21. {
  22.     if (digitalRead(buttonPin))
  23.     {
  24.        if(status==0)    
  25.        {
  26.             contador++;
  27.             Serial.println(contador);
  28.             status=1;
  29.         }    
  30.     } else status =0;
  31. }
  32. //*************************************
  33. //*************************************
  34. //*************************************

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con digitalRead
« Respuesta #2 en: 18 de Marzo de 2018, 15:08:03 »
Como dijo planeta, tu problema son los if, en realidad deberias acostumbrarte a poner llaves, aunque no comparto que su codigo sea lo mas simple para entenderle ( adaptando la version que das a la tuya), aunque la de planeta tiene una ventaja que es la de no depender del delay, asi que voy a dejar mi codigo como ayuda extra al problema, siguiendo con el esquema que vos  propusiste:

Código: C
  1. const int buttonPin = 2;                // const para que simplemente el compilador lo reemplace y no cree una variable en la RAM sin sentido, C++ lo hace con el const solo.
  2.  
  3. int contador  = 0;
  4. int resultado = 0;
  5.  
  6. void setup(void)
  7. {
  8.         Serial.begin(9600);
  9.         pinMode(buttonPin,INPUT);                  
  10. }
  11.  
  12. void loop(void)
  13. {
  14.             resultado = digitalRead(buttonPin);
  15.             if(resultado == HIGH)
  16.             {
  17.                // Aca entra cuando esta en HIGH
  18.                contador++;
  19.                Serial.println(contador);
  20.                delay(100);
  21.             }
  22.             else
  23.             {
  24.                 //Aca cuando esta en LOW, de no necesitarlo quito el else.
  25.             }
  26.          
  27. }

Solo tener en cuenta que como el delay es de 100ms si lo tenes presionado mucho tiempo va a aumentar varias veces. Si queres esperar hasta que se suelte o usas el codigo de planeta9999 o reemplazas en mi codigo el delay por:

Código: C
  1. const int buttonPin = 2;                // const para que simplemente el compilador lo reemplace y no cree una variable en la RAM sin sentido, C++ lo hace con el const solo.
  2.  
  3. int contador  = 0;
  4. int resultado = 0;
  5.  
  6. void setup(void)
  7. {
  8.         Serial.begin(9600);
  9.         pinMode(buttonPin,INPUT);                  
  10. }
  11.  
  12. void loop(void)
  13. {
  14.             if(digitalRead(buttonPin) == HIGH)
  15.             {
  16.                // Aca entra cuando esta en HIGH
  17.                contador++;
  18.                Serial.println(contador);
  19.                while(digitalRead(buttonPin) == HIGH);           // Observa el punto y coma es como hacer un while con nada dentro while(xxx) {}
  20.             }
  21.             else
  22.             {
  23.                 //Aca cuando esta en LOW, de no necesitarlo quito el else.
  24.             }
  25.          
  26. }

Este codigo sigue teniendo una desventaja frente a la de planeta, y es que queda encerrado en el while, mientras que la de planeta puede hacer otras cosas. Asi que tenelo en cuenta.
« Última modificación: 18 de Marzo de 2018, 15:13:25 por KILLERJC »

Desconectado tsk

  • PIC18
  • ****
  • Mensajes: 258
Re:Problema con digitalRead
« Respuesta #3 en: 18 de Marzo de 2018, 15:17:04 »
Lo que está intentando detectar es el flanco de subida, por lo que su código guarda mucho parecido con el que se encuentra en el enlace siguiente

https://www.arduino.cc/en/Tutorial/StateChangeDetection

Aunque se podría usar una interrupción.

Código: C
  1. attachInterrupt(digitalPinToInterrupt(buttonPin),funcion,RISING);

Código: C
  1. void funcion(){
  2.     ...
  3. }

También no usaría la función delay, en cierto modo es mejor usar la función millis para obtener retardos sin bloquear la función loop()

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 20
Re:Problema con digitalRead
« Respuesta #4 en: 18 de Marzo de 2018, 15:30:17 »
Muchas gracias a los dos!!! edite el codigo y ya me jaló de la siguiente forma:

código: C

int buttonPin = 2;
int ledPin    = 4;                           
int contador  = 0;
int resultado = 0;

void setup() {
 //Aqui se da la configuración de los pines para hacerlos de entrada
 //para el caso del pin2 y salida para el caso del pin1.

Serial.begin(9600);
pinMode(buttonPin,INPUT);                   // Con esto el pin 2 de la placa Arduino que ahora es buttonPin lo hago de entrada actuará solo cuando lo presione.
pinMode(ledPin,OUTPUT);                     // Con esto hago el pin 1 de salida para que cuando precione el pulsador conectado al pin 2 el LED encienda.

}
 
//Cuerpo del programa.

void loop() {
            resultado = digitalRead(buttonPin);
            if(resultado == LOW)
            {
               delay(500);
               contador++;
               Serial.println(contador);
            }
            else
            {
              (resultado==HIGH);             
               
               }
                   
}


Pero aún no entiendo planeta9999 por qué me dices que el if del primer programa es distinto al del segundo, disculpa pero soy nuevo en esto y ahi está el dolor de cabeza que me tengo desde ayer ya llevo 1 dia en esto  :( explicame por favor.

KILLERJC Muchas gracias también a vos por tu explicación!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con digitalRead
« Respuesta #5 en: 18 de Marzo de 2018, 16:14:30 »
El if tiene una sola condicion... el else se ejecuta si la condicion NO se cumple. En tu caso en el else si no vas a poner nada, entonces no pongas nada.

Código: C
  1. if (aca dentro la condicion)
  2. {
  3.      //Aca lo que va a pasar si se cumple
  4. }
  5. else
  6. {
  7.      //Aca lo que va a pasar si NO se cumple la condicion
  8. }

El else es opcional, si por ejemplo no tengo nada que hacer cuando NO se cumple entonces puedo hacer:

Código: C
  1. if (aca dentro la condicion)
  2. {
  3.      //Aca lo que va a pasar si se cumple
  4. }

Por lo que el codigo que pusiste seria asi:
Código: C
  1. void loop() {
  2.             resultado = digitalRead(buttonPin);
  3.             if(resultado == LOW)
  4.             {
  5.                delay(500);
  6.                contador++;
  7.                Serial.println(contador);
  8.             }
  9. }

O si queres dejar el else (pero como ves es menos legible ), seria asi:

Código: C
  1. void loop() {
  2.             resultado = digitalRead(buttonPin);
  3.             if(resultado == LOW)
  4.             {
  5.                delay(500);
  6.                contador++;
  7.                Serial.println(contador);
  8.             }
  9.             else
  10.             {
  11.             }
  12.                    
  13. }

-----------------------------------------------------------------------------------

Ahora pasemos a tus codigos
Tu primer codigo era asi:

Código: [Seleccionar]
Obtengo Estado del boton en este momento y lo guardo en "Resultado"
if(Resultado en alto?)
{
     if(Resultado en bajo?)
     {
       //Aca hace el codigo de enviar
     }
}

El problema y la diferencia con el segundo codigo, es que lees el pin una sola ves, si por ejemplo el pin estaba en alto eso se guardo en "resultado". Pero luego preguntas por "resultado" primero por si esta en alto y leugo en bajo, obviamente "resultado" queda con el valor que se le asigno al momento de leer el pin ( no se actualiza solo ). Por lo tanto no puede cambiar entre medio de los ifs, y tampoco puede estar en alto ( HIGH) y bajo (LOW) a la ves como para entrar en ambos if.

Tu segundo codigo:
Código: [Seleccionar]
if(Leo boton y pregunto si esta en alto?)
{
     if(Leo boton y pregunto si esta en bajo?)
     {
       //Aca hace el codigo de enviar
     }
}

Ahora preguntamos en cada if el estado del pin, entonces vamos a leer 2 veces el estado del boton.

El problema del segundo codigo es que el micro es muy rapido le tomara microsegundos pasar de un if al otro, al primer if entra cuando el boton esta en alto, pero luego preguntas por si esta bajo, ese if seguramente que no entre (ya que es muy corto el tiempo que pasa), a no ser que poseas suerte no creo nunca logres ponerlo en bajo en microsegundos LUEGO de entrar al primer if.

Y eso es lo que ocurria, y por eso no funcionaba siempre tu codigo. todo dependia de cuando soltabas el boton... me doy a entender con un ejemplo

Citar
if(boton en alto)
{
          <---------   En este punto soltaste el boton
     if(boton en bajo)
     {
       //Aca hace el codigo de enviar
     }
}

Si lo hiciste justo en ese punto va a entrar al otro if. Si lo hiciste en cualquier otro punto del programa NO va a entrar. Es como una ruleta, pasa miles de veces por ahi, y vos estas intentando soltar el boton justo en un punto especifico del programa. Y eso no deberia ocurrir, vos necesitas tener si o si un comprtamiento determinado.
« Última modificación: 18 de Marzo de 2018, 16:20:57 por KILLERJC »

Desconectado NicaUnlock

  • PIC10
  • *
  • Mensajes: 20
Re:Problema con digitalRead
« Respuesta #6 en: 18 de Marzo de 2018, 17:17:35 »
Muchas gracias KILLERJC excelente tu explicación!!!  ((:-))


 

anything