[SOLUCIONADO] while{} en void loop()

Hola Tengo conectado a un arduino uno en un pin un sensor de proximidad que cuenta marcas en una rueda. Similar a un encoder pero muy lento y con pocos dientes. La cantidad de pulsos es mas o menos 100 por minuto. En el void loop() se debe ejecutar un codigo solo cuando el pin esta HIGH. Al ser muy poca la cantidad de señales, durante un un pulso se ejecuta muchas veces el el codigo: if( digitalRead( 2 ) ). Lo que quiero es hacer una pausa mientras esta en LOW para que se ejecute una vez sola. Solo cuando esta en HIGH. Lo intente con un while{} y no me da resultado. Alguien me puede dar una idea de como hacerlo ?

void loop()
{
   while( ! digitalRead( 2 ) )  { }


   if( digitalRead( 2 ) )
   {...

Gracias Daniel

dp10: ``` Hola

Al ser muy poca la cantidad de señales, durante un un pulso se ejecuta muchas veces el el codigo: if( digitalRead( 2 ) ). Lo que quiero es hacer una pausa mientras esta en LOW para que se ejecute una vez sola. Solo cuando esta en HIGH.

[/quote]

Hola,

Lo demás se medio entiende; esto no ...

Saludos

Hola vffgaston

vffgaston: Hola,

Lo demás se medio entiende; esto no ...

Saludos

A grandes rasgos necesito contar la cantidad de pulsos recibidos dentro del codigo if( digitalRead( 2 ) )

Pero al pasar la rueda lento por el sensor,(el pin esta en HIGH bastante tiempo) y el codigo dentro de if( digitalRead( 2 ) ) se ejecuta muchas veces y contador suma mas pulsos de los reales. Supongo que es la cantidad de veces que se ejecuta del void loop() mientras esta en HIGH el pin. Lo intente con variables y con el while{}. Creo que si el sensor mandara mas señales por segundo que las veces que se ejecuta el void loop() no habria problemas.

Supuse que el while{} se ejecutaria mientras la condicion permanece LOW, pero no. seguramente estoy haciendo algo mal pero no me doy cuenta que.

Gracias por la atencion

A ver, creo entender que tienes que contar los dientes mientras que otro pin esté en "alto".

Bueno, sea así o que solamente tienes que contar los dientes:

Tienes que usar una variable que se ponga a "1" cuando ya has contado el diente (y no contar hasta que esté otra vez en "0") y que se ponga a "0" cuando no haya diente; de esta forma se cuenta el diente una sola vez.

Esta variable la tienes que actualizar (1 - 0 -1 - 0, ...) tanto cuentas como si no. Si no quieres contar si hay otra condición un "if" y a correr.

No puedes estar al albur de lo que dure el loop (que, ciertamente, dura poquísimo para tus necesidades -estás hablando de poco más de un diente al segundo y el (tu) loop durará microsegundos).

Saludos.

Moderador: No repitas lo que se lee arriba

A ver si entendi, es algo asi lo que dices? porque asi tengo el mismo problema, mientras que este en HIGH se ejecuta el codigo tantas veces como el void loop() lo haga

     if( digitalRead( 2 ) )
     {
        lSenialEncoder = 1;
     }
     else
     {
        lSenialEncoder = 0;
     }

     if( lSenialEncoder )
     {
        encoder ++ ;

otra prueba que hize

   if( lSenialEncoder == 0 )
     {
       if( digitalRead( 2 ) )
       {
          lSenialEncoder = 1;
       }
       else
       {
          lSenialEncoder = 0;
       }
     }

     if( lSenialEncoder )
     {
        lSenialEncoder = 0;
        ...

ambas con el mismo resultado

Podrias usar una interrupcion hardware: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

jose ; la interrupciones lei que es una posibilidad pero no lo manejo bien, tengo que estudiarlo mejor.

haciendo otra prueba con la variable hize esto:

     while( digitalRead( DIGITAL_INPUT_PIN_ENCODER ) )
     {
        lSenialEncoder = 1;
     }

     if( lSenialEncoder )
     {
        lSenialEncoder = 0;
        encoder ++ ;

y aparentemente funciona, tengo que probarlo mas a fondo, pero la salida por el monitor me muestra que lee cada diente una vez y no repite.

Gracias vffgaston y jose por su tiempo.

si no funciona volvere a molestar.

Daniel

Puedes ver transiciones 0 a 1 o 1 a 0 Veamos cuando pasa de 0 a 1

Aunque le faltan cosas esto es una buena aproximación

#define PIN 2
bool estado, estadoAnterior = false;
int contador = 0;
unsigned long tiempo;

void setup() {}

void loop() {
   
   estado = digitalRead(PIN);

   if (!estado && estadoAnterior) {
       contador++;
   }
   estadoAnterior = estado;
   if (millis()-tiempo > 1000UL) { // uso UL para que sepa que son unsigned long
      Serial.println(contador);   // falta calcular las RPM 
      contador = 0;
   }
}

hize algo con millis() pero al ser una velocidad variable la del dispositivo se complica. de todos modos creo que ahora funciona como se espera con el while y la variable

gracias surbyte

Daniel

La velocidad puede ser variable pero tu ventana de medicion nunca lo será. En realidad estamos midiendo mal. Jamas se mide en bajas frecuencias justamente la frecuencia, sino que se debe leer el periódo. Eso tiene menos error de lectura.

En tu caso seria el tiempo entre transiciones 0-1. puedes medir muchas, promediarlas y obtener mejor resolucion.

En cambio una frencuena lenta requiere de una ventana grande. Para mejorar la precisión deberías aumentar ese tiempo que yo puse de 1 segundo a algo mayor, total es matématica. De todos modos 1 seg siempre es un lapso mas que utilizado.

Veamos con números, dices que medirás 100 rpm = 100 1/60 rpseg = 10/6 revoluciones por segundo o Hz ya ves que tu sistema por bueno que sea podra contar 10/6 = 1.66 rpseg Quiere decir que la ventan permite medir 1 o 2 cuentas... MAL Si tienes una rueda dentada de 60 dientes entonces eso mejora las cosas. Ya no seran 1 o 2 pulsos sino 100 pulsos y como pobre estarás oscilando entre 99 a 101 cuentas.

Has mejorado notablemente Veamos ahora como período Seguimos con un sensor por vuelta, pero ahora contamos tiempos entre disparos 0-1 o sea flanco de subida

pasa el primero y luego pasa el segundo a 6/10 seg = 0.6 seg = 600 mseg Si usara solo millis() ya podrias leer 599/600/601 mseg sin problemas. Esta dentro de las posibilidades. Si usaras micros() podrias leer 599999/600000/600001 useg suponiendo que lo demas no existiera ya vez como cambia, es notable pasar de algo casi medido a otra cosa BIEN medida.