Contar tiempo de pulsador

Hola, estoy aprendiendo algo de Arduino y la verdad que lo que se es muy básico y por eso estoy acá en busca de ayuda :D.
Lo que necesito hacer es meter en algún pin un pulso de 5V y que cuando el Arduino detecte este pulso cuente el tiempo en el que ese pulso esta en alto y si es igual a el tiempo en el que esta configurado active una de sus salidas.
Necesitaría algo no muy complicado y si es posible que me expliquen como funciona el código que necesito, me interesa aprender y no solo copiar el código.

¿Para ingresar el pulso de 5V necesito poner alguna resistencia antes de hacerlo entrar al Arduino?

PD: Puse ese titulo porque me pareció una forma corta y relacionada con lo que quiero hacer en definitiva es como si fuese un pulsador, o eso creo :confused: .

Agus123:
Lo que necesito hacer es meter en algún pin un pulso de 5V y que cuando el Arduino detecte este pulso cuente el tiempo en el que ese pulso esta en alto y si es igual a el tiempo en el que esta configurado active una de sus salidas.

pulseIn

Lo que esto retorne, lo comparas con valores predeterminados.

Agus123:
¿Para ingresar el pulso de 5V necesito poner alguna resistencia antes de hacerlo entrar al Arduino?

Si el pulsador introduce voltaje, entonces sería una resistencia de entre 4.7k y 10k; colocada entre pin y tierra (GND). Esto es lo que se conoce como "resistencia pull-down"

Lucario448:
pulseIn

Lo que esto retorne, lo comparas con valores predeterminados.

Si el pulsador introduce voltaje, entonces sería una resistencia de entre 4.7k y 10k; colocada entre pin y tierra (GND). Esto es lo que se conoce como "resistencia pull-down"

Gracias, ya hice algo con eso, agarre el código de ejemplo y le agregue unas lineas para ver el tiempo en monitor serial, pero en que unidad esta el tiempo? Supongo que en mili o micro segundos, pero no se.

milisegundos si usas millis()
microsegundos si usas Micros()

Agus123:
en que unidad esta el tiempo? Supongo que en mili o micro segundos, pero no se.

Microsegundos. Retorna un unsigned long que representa cuantos microsegundos el pin mantuvo el estado establecido en el segundo parámetro. Retorna cero si, por ejemplo, el botón no se presionó durante el tiempo de espera (el cuál también se puede definir).

surbyte:
milisegundos si usas millis()
microsegundos si usas Micros()

Tenes un ejemplo para usar eso en lugar de el pulseIn? si me podes explicar mejor xD

Lucario448:
Microsegundos. Retorna un unsigned long que representa cuantos microsegundos el pin mantuvo el estado establecido en el segundo parámetro. Retorna cero si, por ejemplo, el botón no se presionó durante el tiempo de espera (el cuál también se puede definir).

Si no defino el tiempo de espera, queda todo el tiempo a la espera de un pulso o es un tiempo definido?, porque tengo un problema y es que cuando lo dejo durante por ejemplo, un segundo no devuelve nada, solo ceros... :confused:
Me podes explicar que tipo de variable es la unsigned long y como funciona¿?
Gracias por responder!

Intenta cuantificar que quieres medir?
Pulsos de que frecuencia, de que ancho en mili o microsegundos hablamos?

Agus123:
Si no defino el tiempo de espera, queda todo el tiempo a la espera de un pulso o es un tiempo definido?

Hay un tiempo por defecto (creo que es de 1 segundo); pero como dije antes, se puede establecer por uno más largo o uno más corto.

Agus123:
Me podes explicar que tipo de variable es la unsigned long y como funciona¿?

Respuesta corta: un tipo de variable que puede almacenar valores desde 0 hasta 4294967295.

Respuesta larga: unsigned significa que el valor pierde la propiedad de poder ser negativo (así TODOS los bits se usarán para representar un número entero positivo).
long en términos generales significa “el tipo de variable número-entero más grande” (número “largo”).
El rango de valores que puede almacenar, depende del tipo de microprocesador: para AVR (los Arduinos más populares) este sería de entre 0 y 4294967295 (sin signo) en 4 bytes o 32 bits; para los ARM (Arduino Due, Zero y la línea de Teensy) sería entre 0 y 18446744073709551615 (sin signo) en 8 bytes o 64 bits.

Para el asunto de pulseIn, en AVR podría medir un pulso de hasta 71 minutos y medio. En ARM (si existe tal implementación), sería hasta de… 593 milenos (?). No sé si hice el cálculo correctamente, pero lo que sí se, es que semejante tiempo es completamente ridículo :o

surbyte:
Intenta cuantificar que quieres medir?
Pulsos de que frecuencia, de que ancho en mili o microsegundos hablamos?

Son pulsos de menos de 500 milisegundos, pero estuve haciendo pruebas con el protoboard y no siempre me efectúa la medición a veces queda en cero aunque haya mandado un pulso.
Hay alguna forma sin usar pulsein? necesito que sea lo mas exacta posible la medición ya que es para hacer un comparador y si el tiempo es igual al establecido active o desactive un pin.

Agus123:
Hay alguna forma sin usar pulsein? necesito que sea lo mas exacta posible

No sé si es la más exacta, pero puede funcionar:

volatile unsigned long ancho = 0;
volatile boolean hecho = false;

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP); // Fuente de pulsos al pin 2
  attachInterrupt(0, medir, FALLING);
}

void loop() {
  if (hecho) {
    detachInterrupt(0);
    Serial.println(ancho);
    ancho = 0;
    hecho = false;
    attachInterrupt(0, medir, FALLING);
  }
}

void medir() {
  while (!(PIND & B00000100)) // Una manera más rápida (para el microprocesador) de decir "while (digitalRead(2) == LOW)"
  ancho++;

  hecho = true;
}

La limitante aquí, es que habría que hacer una "calibración"; porque no sé en qué acabaría el conteo con un ancho de pulso de 500 ms.

El pulso debe ser en estado bajo; si es en estado alto, entonces habría que hacer unas cuantas modificaciones.

Es que algo así como "lo más preciso", sería con el timer1. Se puede contar frecuencia, pero periodo... no sé a menos que se saque la inversa de esa frecuencia...

Hola. Supongo, Lucario, que te refieres al código de Nick Gammon. Precisamente, lo que contabiliza es el periodo (elapsedTime).
La frecuencia la entrega calculando la inversa (float freq = 1.0 / ((float (elapsedTime) * 62.5e-9)); // each tick is 62.5 nS).
Ten por seguro que este es el método más exacto posible, si bien no cumple la premisa de ser un método “no muy complicado”, como pedía en el primer post.
Dejando de lado el posible problema de rebotes en la señal, creo que una solución intermedia sería similar a la que acabas de proponer, pero liberando un poco más al loop:

  • Tres variables globales volátiles: InicioPulso, FinPulso y PulsoDetectado.
  • Establecer interrupción 0 en CHANGE, en lugar en FALLING.
  • En la ISR comprobar si la interrupción fue por HIGH o por LOW, dependiendo de ello enviar valor millis a InicioPulso o a FinPulso. Si se ha enviado a FinPulso, activar la variable PulsoDetectado.
  • En el loop comprobamos si se activó PulsoDetectado; si fue así, restamos FinPulso-InicioPulso y tenemos el tiempo. Desactivamos PulsoDetectado.

De esta forma, tendríamos posibilidad de realizar más tareas en el loop, en lugar de estar mirando el estado del pin. Sin embargo, sigue pendiente solventar el problema de posibles rebotes.