SOLUCIONADO -- Gestionar pulso continuado?

Hola de nuevo.

Tengo una duda acerca de como gestionar o hacer el código cuando queremos que se ejecute algo en función de cuando una entrada digital sea HIGH, pero después de un tiempo siendo HIGH.

Que básicamente se ejecute el código después de 5 segundos pulsando el interruptor.

No se como eticamente haceis para este tipo de situaciones, ya que hacerlo casí no me parece muy bonito que se diga.

if (digitalRead(Pulsador)==(HIGH)
{
delay(5000);
    if (digitalRead(Pulsador)==(HIGH)
     {
      digitalWrite(Led)=HIGH
      }
}

He leido sobre el "Debounce" pero esa manera de hacerlo es más bien para evitar rebotes de pulsadores, en este caso querría que se ejecutara la orden si ese pulsador es HIGH en firme, y a que a veces puede ser HIGH, durante menos de 1 segundo, y no me interesa ejecutar la orden.

Gracias por vuestra paciencia.

Mas alla de que eso funciona, estas 5 seg con Arduino sin hacer nada. Eso te sirve?

Como servir, me serviría, si funcionara.

Pero la gracia es que tengo 5 entradas digitales que quiero que espere esos 5 segundo antes de actuar y rellenando condicional sobre condicional, no me parece una solución factible.

Por otro lado usar la funcion milis(), me parece complicar demasiado el código, y ya sabemos que si lo complicamos a la hora de revisarlo en un tiempo, se complica la cosa.

El tema de los rebotes o el "Debounce", lo soluciono por HardWare. Poniendo condensadores entre positivo y la salida del pulsador.

Al final me sale más a cuenta mandarte una placa entera armada, de paso que pruebas los componentes repasamos el código.

:grin: :grin: :grin:

Estas son excelentes librerías que te pueden ayudar con minimo esfuerzo.

Bounce Library

Esta es Bounce2 supuestamente mejor que la anterior

:o :o
No sabía que existían librerías para tratar el Bounce.

Gracias mil

Estudiaré el tema. :grin:
:grin:

Cuando saque alguna conclusión, la expongo y cierro el post

Hola de nuevo:

He estado probando el código con Debounce.

Tengo una dudilla.
El Debounce en el momento que una entrada digital es HIGH, llama a la función millis, esta espera el tiempo que le dices y una vez pasado, vuelve e leer el pin para saber si continua HIGH. Una vez leida y cumplida la condición entraría en el "if".

Si es así y creo que así funciona, no es lo que busco.

Pretendo que el arduino haga la función que le programo (En este caso que encienda el LED), si la entrada digital es HIGH durante 5 segundos.

No me interesa que lea la entrada digital, contabilice con millies, y al cabo de esos 5 segundos y vuelva a leerla.
Busco que la lea constantemente y que actue solo, si durante esos 5 segundos esa entrada es HIGH.

Seguiré buscando.
Algo tiene que habe para esta función.

Pretendo que el arduino haga la función que le programo (En este caso que encienda el LED), si la entrada digital es HIGH durante 5 segundos

Aca dice que si la entrada es high por 5 segundos haga la función que quieres.
Bueno.. es como un debounce de 5 segundos. No importa si usas millis() o delay.

if (digitalRead(Pulsador)==(HIGH) {
    delay(5000);
    if (digitalRead(Pulsador)==(HIGH) {
      digitalWrite(Led, HIGH);
   }
}

Eso que pusiste al comienzo hace lo que deseas. si es high y se mantiene en high por 5 seg entonces pone la función o ejecuta en tu caso encender un led.

Que no te gusta?

Hola Surbyte, buen día:

Te explico un poco la cuestión:

Para que nos hagamos una idea, solo tengo que controlar que 5 entradas digitales no sean HIGH, en el caso de ser LOW, el procesador no hace nada.

Por decir una similitud. Lo único que hace es de policía, esperando a que algo sea HIGH.

Para programar el código. Lo hice con IF.
No se si hay otra manera de hacerlo, pero fué la más directa que se me ocurrió.
Lo que me encuentro a la hora de que procese, es que cuantos más IF, mas lento es el código.

Parece como si el procesador tubiera que ir procesando condicional, tras condicional, y eso le cuesta su tiempo.

Como bien dices:

Aca dice que si la entrada es high por 5 segundos haga la función que quieres.
Bueno.. es como un debounce de 5 segundos. No importa si usas millis() o delay.

Con la función delay o millis, puedes leer la entrada de un PIN en dos espacios de tiempo cercanos, pero distintos.

"Mido. Si su estado es HIGH. Espero 5 segundos y vuelvo a medir"

Lo que ando buscando es una función, que una vez ese PIN sea HIGH, lo mida constantemente durante 5 segundos.
Sólo si durante ese tiempo la entrada es continuadamente HIGH, realice la condición que hay dentro del IF.

Que no te gusta?

Cuando veo un código llego de IF.... ELSE, me dan la impresión de que les falta estilo.
Seguro que hay maneras de hacerlo que funcionen mucho mejor.

Katynga:

surbyte:
Que no te gusta?

Cuando veo un código llego de IF.... ELSE, me dan la impresión de que les falta estilo.
Seguro que hay maneras de hacerlo que funcionen mucho mejor.

¿Estilo? ¿Falta estilo en un if else? No sabía que había que adornar el código :grin::grin::grin:
Yo pensaba que la eficiencia lo era todo...

Yendo al tema, ¿por qué no te haces un timer y ya? Como hoy fue un día "light" en el trabajo acabo de hacer algo así a modo de ejemplo tonto. Y no, no es tiempo perdido, va bien como material para mi web de Arduino.

Si tienes controlado el debounce de los botones sólo es adaptarlo.
(Entiendo que la idea es repetir una función todo el rato durante el tiempo designado)

Por favor no me digas ahora también que a los punteros de C le faltan estilo... Vaale, sí, en los lenguajes de ahora esto de los punteros es raro, pero C peina canas ya y es lo que hay :cold_sweat: :stuck_out_tongue_closed_eyes:
Si te fijas sólo he modificado la forma de hacer un debounce y cambiar el sentido del timer.

/*
Ejecutar una funcion durante un tiempo determinado

variables goblales -> array con 3 elementos

índice 1: tiempo durante el cual se repite la función
índice 2: determina que sólo entre en la función repetir una vez
índice 3: en 0 está en ejecución, en 1 parado.
*/

int
isa[] = {2000,0,0},
adri[] = {4000,0,0};

void setup() {
Serial.begin(9600);
Serial.println("Simon dice:");
Serial.println("Isabel, di hola durante 2 segundos");
}

void loop() {
//Mientras isa no acabe
if(!isa[2]){
//Irá a la función hola y escribirá "hola Simon" durante el timpo designado
*isa = repetir(isa,hola);
}
//Al finalizar
else{
//Mientras adri no acabe
if(!adri[2]){
Serial.println("Simon dice:");
Serial.println("Adrian, di hello durante 4 segundos");
//Irá a la función hello y escribirá "hello Simon" durante el timpo designado
*adri = repetir(adri,hello);
}
}
}

int repetir(int *arr, void (*f)(void) ) { //punteros
if(!arr[1] && !arr[2]){
arr[1] = true;
if( tiempo( arr[0], (*f) ) ){
arr[1] = false;
arr[2] = true;
}
}
return *arr;
}

boolean tiempo(unsigned long cont_extra, void (*f)(void) ) { //y más punteros :smiley:
unsigned long tiempo_hasta = millis() + cont_extra;
while(millis() < tiempo_hasta ){
(*f)();
}
return true;
}

void hola(){
Serial.println("Hola Simon");
}

void hello(){
Serial.println("Hello Simon");
}

Como resultado "isa" escribe hola durante 2 segundos y al finalizar lo hace "adri" durante 4 segundos. Cuando acaban ambos no se muestra en consola nada más.

Saludos.

:astonished: :astonished:
Como decía mi abuela: "¡Eso te pasa por preguntar!"

Función "Timer", explicada con semejante código....

Una que no entiendo ni papa. Otra que copio y pego y no funciona en el Stech.
Hay varias funciones que no están definidas, así que se me hace más complicado entenderlo.

*adri = repetir(adri,hello);

"Repetir" No declarado.

if( tiempo( arr[0], (*f) ) ){

"Tiempo" No declarado.

Si podeis os agradezco que me pongais un ejemplo más basico:

Si aprieto un botón durante 5 segundo que encienda un led.

:sob: :sob:
Buscaré más sobre la función Timer

Bueno.
Intentando aprender un poco....

De la función Timer no encuentro gran cosa, a parte de un montón de librerías para usarla.
En este caso no me apetece usar librerías.
Prefiero saber como se hace, tecleando código.

Hice esto.
No se si está bien así:

unsigned long Tiempo;
unsigned long Tiempo_Disparo;
const int Boton =8;
const int LED=13;

void setup()
{
  Tiempo=millis();
  Tiempo_Disparo=5000;    //Tiempo que tiene que estar el pulsador HIGH antes de que encienda el LED
  
  pinMode(LED,OUTPUT);  //Conectamos LED a pin 13 como salida
  pinMode(Boton,INPUT);    // PIN 8 el Botón como entrada
}

void loop()
{
  if (digitalRead(Boton)==LOW)   
       {
         digitalWrite(LED,LOW);  
         Tiempo=millis(); 
       }
  
  if(millis()-Tiempo>=Tiempo_Disparo) 
       {     
         digitalWrite(LED,HIGH);  
       }
}

Katynga:
:astonished: :astonished:
Como decía mi abuela: "¡Eso te pasa por preguntar!"

Función "Timer", explicada con semejante código....

Una que no entiendo ni papa. Otra que copio y pego y no funciona en el Stech.
Hay varias funciones que no están definidas, así que se me hace más complicado entenderlo.

*adri = repetir(adri,hello);
"Repetir" No declarado.

if( tiempo( arr[0], (*f) ) ){
"Tiempo" No declarado.

Si podeis os agradezco que me pongais un ejemplo más basico:

Si aprieto un botón durante 5 segundo que encienda un led.

:sob: :sob:
Buscaré más sobre la función Timer

¿Cómo que repetir() y tiempo() no están declarados? :o

int repetir(int *arr, void (*f)(void) ) { //punteros 
  if(!arr[1] && !arr[2]){
    arr[1] = true;
    if( tiempo( arr[0], (*f) ) ){
      arr[1] = false;
      arr[2] = true;
    }
  }
  return *arr;
}
boolean tiempo(unsigned long cont_extra, void (*f)(void) ) { //y más punteros 
  unsigned long tiempo_hasta = millis() + cont_extra;
  while(millis() < tiempo_hasta ){
    (*f)();
  }
  return true; 
}

Me encanta cuando después de ponerles un ejercicio hecho no hacen el copy and paste bien y dicen que se lo ponemos mal :grin: :grin: :grin: :grin: :grin: (ni revisan el copiado)

No es mi culpa que no entiendas los punteros. También te parecía mal el if else de otro compañero.

Edito: Acabo de copiarr tal cual aquí el código que te puse y no hay ni problemas en la compilación ni nada, funciona correctamente. que no te guste por falta de conocimientos es otra historia.

Podías adaptarlo y poner que al presionar un botón, llamar a X función, sea encender leer o lo que quisieras, pero vale quizás fue demasiado y sólo quieres encender leds y no más.

que no te guste por falta de conocimientos es otra historia.

Hombre!! no te pongas así, que un erro en el punteo lo tiene cualquiera.
Y si primeramente no entiendo tu código, menos lo voy a entender cuando me da error de compilación.

No te enfades que no merece la pena.

No es que me guste por falta de conocimientos.
Falta de conocimiento ya se que tengo, ya que la sabiduría plena creo que nunca se consigue.

A lo que me refiero, es, que como primer ejemplo para exponer una función "Timer".
Es demasiado completo y se me hace ilegible.

Muchas veces reduciendo las cosas a lo absurdo se entienden mejor de base.

¿Me entiendes ahora?

no hacen el copy and paste bien y dicen que se lo ponemos mal :grin: :grin: :grin: :grin: :grin: (ni revisan el copiado)

Copy-Paste vuelto a hacer tres veces, con el mismo resultado.

Katynga:
Hombre!! no te pongas así, que un erro en el punteo lo tiene cualquiera.
Y si primeramente no entiendo tu código, menos lo voy a entender cuando me da error de compilación.

No te enfades que no merece la pena.

No es que me guste por falta de conocimientos.
Falta de conocimiento ya se que tengo, ya que la sabiduría plena creo que nunca se consigue.

A lo que me refiero, es, que como primer ejemplo para exponer una función "Timer".
Es demasiado completo y se me hace ilegible.

Muchas veces reduciendo las cosas a lo absurdo se entienden mejor de base.

¿Me entiendes ahora?

No estoy enfado. voy a revisar porque te sale sin definir la función. Espera que te estoy poniendo otro ejemplo más simple. Sé que por texto no se percibe el estado de ánimo pero te aseguro que no me has ofendido ni me he enfado, me hizo gracia que dijeras que no estaba definido. Pongo el otro y reviso eso. Sé que a mí me compila perfectamente y funciona.

Es posibleque tampoco te guste de esta forma, pero puede que a otros sí, así que ahí lo dejo:

/********************************************************/
unsigned long tiempo;
unsigned long tiempo_Disparo = 5000;
const int boton = 8;

boolean contando = false;
boolean estuvo_presionado_X_Tiempo = false;

//Estas dos variables String son para no volvernos locos con los textos del Serial.println()
// Pueden omitirse, son para visualizar mejor el ejemplo.

String msg_prev = "";
String msg_next = "";

void setup(){
Serial.begin(9600);
pinMode(boton, INPUT);
tiempo = millis(); // iniciamos el tiempo
}

void loop(){
if (digitalRead(boton) == HIGH) { // al presionar el pulsador
if(contando == false){ //para ejecutar una sola vez al pulsarlo y no entre al mantenerlo presionado
tiempo = millis(); // tiempo actual
contando = true; //cambiamos el valor, sólo entra aquí una vez.
}
}else{
contando = false; //Si soltamos el pulsador permitimos que se vuelva a contar
estuvo_presionado_X_Tiempo = contando = false; // Reiniciamos todas las variables para que no entre en el if del timer
tiempo = tiempo_Disparo;
}

if(millis()-tiempo < tiempo_Disparo && contando == true){ //Si el tiempo es inferior al dado y se ha iniciado la cuenta del tiempo
if(digitalRead(boton) == HIGH ){ //Mientras el pulsador siga presionado
estuvo_presionado_X_Tiempo = true; //La variable estará en true
msg_next = "Lo mantienes pulsado";
//Serial.println("Lo mantienes pulsado");
}
else{ // Pero si se suelta
estuvo_presionado_X_Tiempo = contando = false; // Reiniciamos todas las variables para que no entre en el if del timer
tiempo = tiempo_Disparo;
msg_next = "Has soltado";
//Serial.println("Has soltado"); //Avisa que se apretó el pulsador pero se soltó antes de tiempo
}
}else{
// Mostrará "No lo mantuviste" siempre que no se presione el pulsador
// Mostrará "Lo mantuviste el tiempo acordado" si se completa el timer con el pulsador presionado.
//Serial.println( (estuvo_presionado_X_Tiempo == true) ? "Lo mantuviste el tiempo acordado" : "No lo mantuviste" );
msg_next = (estuvo_presionado_X_Tiempo == true) ? "Lo mantuviste el tiempo acordado" : "No lo mantuviste";
}

if(msg_next != msg_prev){
msg_prev = msg_next;
Serial.println(msg_next);
}
}

No te asustes. Si le quitas los comentarios verás que no es tanto código. He intentado dejar los true los false en vez de usar los if sólo con la variable y evitando usar el operador -> !

Edito: Lo dejo dentro del Tag code para que no haya problema al copiar.

/********************************************************/
unsigned long tiempo;
unsigned long tiempo_Disparo = 5000;
const int boton = 8;

boolean contando = false;
boolean estuvo_presionado_X_Tiempo = false;

//Estas dos variables String son para no volvernos locos con los textos del Serial.println()
// Pueden omitirse, son para visualizar mejor el ejemplo.

String msg_prev = "";
String msg_next = "";

void setup(){
  Serial.begin(9600);
  pinMode(boton, INPUT);
  tiempo = millis();  // iniciamos el tiempo
}

void loop(){
  if (digitalRead(boton) == HIGH)  { // al presionar el pulsador
    if(contando == false){           //para ejecutar una sola vez al pulsarlo y no entre al mantenerlo presionado
      tiempo = millis();             // tiempo actual
      contando = true;               //cambiamos el valor, sólo entra aquí una vez.
    }
  }else{
    contando = false;                                                       //Si soltamos el pulsador permitimos que se vuelva a contar
    estuvo_presionado_X_Tiempo = contando = false;        // Reiniciamos todas las variables para que no entre en el if del timer
    tiempo = tiempo_Disparo;
  }
 
  if(millis()-tiempo < tiempo_Disparo && contando == true){  //Si el tiempo es inferior al dado y se ha iniciado la cuenta del tiempo
    if(digitalRead(boton) == HIGH ){                              //Mientras el pulsador siga presionado
      estuvo_presionado_X_Tiempo = true;                    //La variable estará en true
      msg_next = "Lo mantienes pulsado";   
      //Serial.println("Lo mantienes pulsado");
    }
    else{                                                                        // Pero si se suelta              
       estuvo_presionado_X_Tiempo = contando = false;   // Reiniciamos todas las variables para que no entre en el if del timer
       tiempo = tiempo_Disparo;
       msg_next = "Has soltado";
       //Serial.println("Has soltado");                        //Avisa que se apretó el pulsador pero se soltó antes de tiempo
    }
  }else{
    // Mostrará "No lo mantuviste" siempre que no se presione el pulsador
    // Mostrará "Lo mantuviste el tiempo acordado" si se completa el timer con el pulsador presionado.
    //Serial.println( (estuvo_presionado_X_Tiempo == true) ? "Lo mantuviste el tiempo acordado" : "No lo mantuviste" );
    msg_next = (estuvo_presionado_X_Tiempo == true) ? "Lo mantuviste el tiempo acordado" : "No lo mantuviste";
  }

  if(msg_next != msg_prev){
    msg_prev = msg_next;
    Serial.println(msg_next);
  }
}

Respecto al anterior a mí sigue sin darme problemas. Cuidado porque el código para colorearlo lo puse dentro del Quote, no vaya ser que te hayas "comido" algún caracter al seleccionar.

pero no pasa nada lo pongo dentro del tag code a ver si seleccionándolo de ahí se va el problema... porque no creo que vaya a ser por la versión del IDE... :o

/*
Ejecutar una funcion durante un tiempo determinado

variables goblales -> array con 3 elementos

índice 1: tiempo durante el cual se repite la función
índice 2: determina que sólo entre en la función repetir una vez
índice 3: en 0 está en ejecución, en 1 parado.
*/

int
isa[]  = {2000,0,0},
adri[] = {4000,0,0};

void setup() {
  Serial.begin(9600);
  Serial.println("Simon dice:");
  Serial.println("Isabel, di hola durante 2 segundos");
}

void loop() {
  //Mientras isa no acabe
  if(!isa[2]){
    //Irá a la función hola y escribirá "hola Simon" durante el timpo designado
    *isa = repetir(isa,hola);
  }
  //Al finalizar
  else{
    //Mientras adri no acabe
    if(!adri[2]){
      Serial.println("Simon dice:");
      Serial.println("Adrian, di hello durante 4 segundos");
      //Irá a la función hello y escribirá "hello Simon" durante el timpo designado
      *adri = repetir(adri,hello);
    }
  }
}

int repetir(int *arr, void (*f)(void) ) { //punteros
  if(!arr[1] && !arr[2]){
    arr[1] = true;
    if( tiempo( arr[0], (*f) ) ){
      arr[1] = false;
      arr[2] = true;
    }
  }
  return *arr;
}

boolean tiempo(unsigned long cont_extra, void (*f)(void) ) { //y más punteros :D
  unsigned long tiempo_hasta = millis() + cont_extra;
  while(millis() < tiempo_hasta ){
    (*f)();
  }
  return true;
}

void hola(){
  Serial.println("Hola Simon");
}

void hello(){
  Serial.println("Hello Simon");
}

Un saludo, mira ver si el código anterior te parece más simple.

Buenooo......

Muchisimo más sencillo que el primero que mandaste.

No estoy acostumbrada a trabajar con variables Booleanas.
Uso Byte.
Ocupa lo mismo y puedo tener más variables para ella que no True o False.

El codigo con True/False, tengo que pensarlo con calma, pero por lo menos la idea la entiendo perfectamente.

Graciñas por todo

Katynga:
Buenooo......

Muchisimo más sencillo que el primero que mandaste.

No estoy acostumbrada a trabajar con variables Booleanas.
Uso Byte.
Ocupa lo mismo y puedo tener más variables para ella que no True o False.

El codigo con True/False, tengo que pensarlo con calma, pero por lo menos la idea la entiendo perfectamente.

Graciñas por todo

Poco a poco, ya respondí tu privado a ver si consigo ayudarte a reducir esos IF.
En cuanto a lo de byte o boolean, es lo mismo, true / false que 0 / 1 que HIGH / LOW para gustos colores, no te austes con los booleans, es más yo veo indistintamente en un condicional el 0 que el 1 al false and true.

Incluso no me gusta poner los == true o == false al ser redundante.

Pseudocódigo:

boolean a = false;
byte b = 0;

if( !a ) falso
if( !b ) falso

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

boolean a = true;
byte b = 1;

if( a ) verdadero
if( b ) verdadero


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

Y en Arduino:

digitalWrite(my_pin, HIGH) //encendido
digitalWrite(my_pin, true)  //encendido

Puede verse quizás mejor así:

void setup() {
pinMode(4, OUTPUT);

}

void loop() {
  digitalWrite(4,HIGH);
  delay(1000);
  digitalWrite(4,LOW);
  delay(1000);
  digitalWrite(4,1);
  delay(3000);
  digitalWrite(4,0);
  delay(3000);
  digitalWrite(4,true);
  delay(5000);
  digitalWrite(4,false);
  delay(5000); 
}

En cuanto a lo de byte o boolean,

Me refiero a usar byte en que puedo ponerle más variables que solo HIGH / LOW o TRUE /FALSE.

byte contador=0;
int boton=0;
int boton_Reset=0;

If(digitalRead(boton==HIGH)&&contador=0
{Te tocas el pié;
contador=1;
}

If(digitalRead(boton==HIGH)&&contador=1
{Te rascas la oreja;
contador=2;
}

If(digitalRead(boton==HIGH)&&contador=2
{Te saldrán piojos;
contador=3;
}

If(digitalRead(boton_Reset==HIGH)
{ contador=0;
}

Me refería a eso.
:wink: :wink: