Rafagas moto con Arduino nano

Buenas noches
Estoy con un nuevo proyecto y quería integrarme en la moto un arduino nano para que controlara un mando del parking, he visto que este proyecto alguien lo hizo en el 2013, pero el hilo esta cerrado y el código que esta allí no funciona...

El mando tiene 3 botones, pero yo solo voy a gastar dos, que soldaré unos cables en los contactos de los pulsadores y los conectare a 2 relés que quiero controlar con el arduino

La idea es la misma que propusieron en el 2013, cuando se le da a las ráfagas una vez actúa el relé 1 y si después de la primera ráfaga, en menos de 1.5 seg., se le da otra ráfaga, pues actúa el relé 2...

He estado peleando estos días y obviamente en algo o bastantes cosas estoy fallando, os pongo el código a ver si algún compañero me puede ayudar.

Muchas gracias por adelantado a todos

/***   Global variables   ***/
int boton;
long tiempo;
int contador;

/***   Function declaration   ***/
void activarele1 ();
void activarele2 ();
void variables_a_0 ();

void setup()

{
  pinMode(2,INPUT);

  boton=digitalRead(2);

  tiempo=0;

  contador=0;

  pinMode(3,OUTPUT);

  pinMode(4,OUTPUT);
  
  digitalWrite(3,LOW);

  digitalWrite(4,LOW);

}


void loop()

{
    if (boton == HIGH) 

    {
        delay(100);

        tiempo=millis();
     
        contador=1;

        while (tiempo + 1500 > millis()) 

        {
             if (boton == HIGH)
       
             {
                  delay(100);

                  contador=2;
              }
        }

        if (contador == 1)
       {
        activarele1();
        }

        if (contador == 2) 
       {
        activarele2();
        }
       
      variables_a_0();
      

     }

}


/***   Function definition   ***/

void activarele1 () {
  digitalWrite(3,HIGH);
  delay(2000);
  digitalWrite(3,LOW);
 }

void activarele2 () {
  digitalWrite(4,HIGH);
  delay(2000);
  digitalWrite(4,LOW);
 }

void variables_a_0 () {
  contador=0;
  tiempo=0;
 }

Y el problema es? Por que no lo dices.

Algo que ya veo mal en el código, delay y millis() no van juntos.
Decide que usarás pero los dos no.
Delay frena el programa y millis() no. Si esperas que responda a tus ráfagas no uses delay

Hi,
Perdona mi ignorancia pero que quiere decir rafagas. A que te refieres cuando dices rafagas.

surbyte:
Y el problema es? Por que no lo dices.

Algo que ya veo mal en el código, delay y millis() no van juntos.
Decide que usarás pero los dos no.
Delay frena el programa y millis() no. Si esperas que responda a tus ráfagas no uses delay

Buenos dias, pues el delay esta puesto para evitar los rebotes, tenia entendido que con un delay (100 o 200) era la forma mas facil de eliminarlos, por eso va justo despues de la lectura de la entrada 2.

El problema es que no me va nada, jajjaja

tauro0221:
Hi,
Perdona mi ignorancia pero que quiere decir rafagas. A que te refieres cuando dices rafagas.

Es el pulsador que llevan los vehiculos para echar las largas, pero no el interruptor, es un pulsador, que cuando le das va y cuando sueltas ya no va.

EL compañero Danzz en el 2013, hizo este, pero lo he compilado y acciona las 3 salidas ciclicamente esté o no esté la entrada.

//BEAMS BIKE GDO
//Programa para controlar tres reles que cerrarn los botones de un mando para abrir las puertas del garage.
// Declaracion de constantes
const int boton = 2;
const int rele1 = 3;
const int rele2 = 4;
const int rele3 = 5;
long lapso = 0;                                             // Es la variable que controlara el tiempo en el que se pulsa el boton, que sera de un maximo de 1,5 segundos
long lapsorestante = 0;

// Declaracion de variables
long actualmillis = 0;                                      //controla el tiempo desde el cual fue pulsado el boton la primera vez
long laprestante = 0;                                       // controla el lapso de tiempo que queda para ver cuantas veces se pulsa el boton
int pulsacion = 0;                                          //controla si el boton es pulsado
int contador = 0;                                           //Para contar las veces que se pulsa el boton

void setup() {
// Declaracion de entradas y salidas
pinMode (boton, INPUT);                                     // declara boton como entrada para el pulsador
pinMode (rele1, OUTPUT);                                    // declara rele1 como salida para el rele 1
pinMode (rele2, OUTPUT);                                    // declara rele2 como salida para el rele 2
pinMode (rele3, OUTPUT);                                    // declara rele3 como salida para el rele 3
}
void loop() {
  pulsacion= digitalRead(boton);                            // lee el boton
    if (pulsacion== HIGH);{                                 // comprueba que si el boton es pulsado
      delay (200);                                          // para evitar rebotes en la pulsacion
      actualmillis= millis();                               // Da el valor actual del tiempo transcurrido para la futura comprobacion del lapso 
      contador= 1;                                          // El contador del boton se pone a 1 ya que ha sido pulsado el boton 1 vez
      lapso= 1500000;                                       // Da el valor de 1,5 segundos al lapso de tiempo para pulsar el boton, este sera el maximo 
         while ((actualmillis- millis())<lapso);{           // funcion que controla si en el lapso de tiempo de 1,5 segs se vuelve a pulsar el boton
          laprestante= (actualmillis- millis());            // Actualiza el valor del tiempo del lapso por el restante por si se vuelve a pulsar el boton 
          pulsacion= digitalRead(boton);                    // lee el boton
            if (pulsacion== HIGH); {                        // comprueba que si el boton es pulsado
              delay(200);                                   // para evitar rebotes en la pulsacion 
              actualmillis= millis();                       // Da el valor actual del tiempo transcurrido para la futura comprobacion del lapso
              contador= 2;                                  // El contador del boton se pone a 2 ya que ha sido pulsado el boton 2 veces 
              lapso= lapsorestante;                         // Da el valor del tiempo restante a lapso 
                while ((actualmillis- millis())<lapso); {   // funcion que controla si en el lapso de tiempo restatante se vuelve a pulsar el boton
                   pulsacion= digitalRead(boton);           // lee el boton
                   if (pulsacion== HIGH); {                 // comprueba que si el boton es pulsado
                     delay(200);                            // para evitar rebotes en la pulsacion
                     contador= 3; }                         // El contador del boton se pone a 3 ya que ha sido pulsado el boton 3 veces   
            }                                                            
          }                                                              
        }
      }
      if (contador== 1); {                                  // Comprueba si el boton se ha pulsado una vez
        digitalWrite (rele1, HIGH);                         // Si se ha pulsado el boton solo una vez, pone en HIGH el pin del rele 1   
        delay(250);                                         // Tiempo durante el cual se activa el rele para cerrar el boton 1 del mando  
        digitalWrite (rele1, LOW);}                         // Pone en LOW el rele 1 para que  deje de cerrar el boton 1 del mando  
      if (contador== 2);{                                   // Comprueba si el boton se ha pulsado dos veces
        digitalWrite (rele2, HIGH);                         // Si se ha pulsado el boton dos veces, pone en HIGH el pin del rele 2
        delay(250);                                         // Tiempo durante el cual se activa el rele para cerrar el boton 2 del mando
        digitalWrite (rele2, LOW);}                         // Pone en LOW el rele 2 para que  deje de cerrar el boton 2 del mando
      if (contador== 3); {                                  // Comprueba si el boton se ha pulsado tres veces
        digitalWrite (rele3, HIGH);                         // Si se ha pulsado el boton tres veces, pone en HIGH el pin del rele 3
        delay(250);                                         // Tiempo durante el cual se activa el rele para cerrar el boton 3 del mando 
        digitalWrite (rele3, LOW); }                        // Pone en LOW el rele 3 para que  deje de cerrar el boton 3 del mando
        contador= 0;
}

Moderador: Código editado con etiquetas[/code]

Ve a Documentación => indice de temas tutoriales => millis() y de paso lee tmb máquina de estados que será de ayuda en este programa.

Repito. No uses delay si usas millis(). Simple como eso.
No puedes poner un delay de 100 200 o mas mseg y luego esperar que el sistema responda a tu presion del pulsador.
Esa es la simple razón.

Partes de un programa que supones esta bien pero te estoy diciendo porque esta mal hecho, o traducido, reaccionará tarde a tus pulsaciones.

Buenas noches surbyte!
Ya tengo el código bien… me funcionaba con los delays, pero te hago caso y los quito, el problema es que al quitarlos, la pulsación 1 nunca la detecta, he estado leyendo y me he bajado e instalado la librería Swicth que dejaste en algunos post, pero no tengo ni idea de como implementarla en mi código, tengo que crear mas variables? tengo que llamar a alguna función y en que parte del código??

Asi se ha quedado el código:

/***   Global variables   ***/
#include <Switch.h>
int boton;
unsigned long tiempo;
unsigned long tiempo_rafaga = 1000;
int contador;

/***   Function declaration   ***/
void activarele1 ();
void activarele2 ();
void variables_a_0 ();

void setup()
{
  pinMode(2,INPUT);

  tiempo=0;

  contador=0;

  pinMode(3,OUTPUT);

  pinMode(4,OUTPUT);

}


void loop()
{
    if (digitalRead(2) == HIGH)
    {
      contador=1;
      tiempo=millis(); 
      while (millis () - tiempo <= tiempo_rafaga)
      {
        digitalRead(2);
        if (digitalRead(2) == HIGH) {
          contador=2;
         }
       }
             
       }
      if (contador == 1) {
        activarele1();
       }
      if (contador == 2) {
        activarele2();
       }
      variables_a_0();

}

/***   Function definition   ***/
void activarele1 () {
  digitalWrite(3,HIGH);
  delay(2000);
  digitalWrite(3,LOW);
 }
void activarele2 () {
  digitalWrite(4,HIGH);
  delay(2000);
  digitalWrite(4,LOW);
 }
void variables_a_0 () {
  contador=0;
  tiempo=0;
 }

Muchas gracias de nuevo.

No es quitarlos GRATUITAMENTE, hay que hacerlo criteriosamente.
Si quitas un delay tienes que poner algo con millis() que responda del mismo modo.

Desde ayer que tenía pendiente tu respuesta y por trabajo no pude completarla.
Esta es una versión que quiero pruebes pero te advierto de algo.
SI FUNCIONA cosa que supongo hará, las pulsaciones del botón 2 ahora no estarán limitadas a cuando la orden se establezca.
Con esto quiero decir, que si presionas de modo que se inicia la rafaga1, y mantienes comenzará la ráfaga2, hablo de los procedimientos.
Tu dime si funciona correctamente o no.
Tiene dos máquinas de estado para cada blink de Rele1 y Rele2.

#define RAFAGA              1000
#define TIEMPO              2000

const byte boton            = 2;
const byte pinRele1         = 3;
const byte pinRele2         = 4;

unsigned long tiempo        = 0;
byte contador               = 0;
byte estado1                = 0;
byte estado2                = 0;

unsigned long start;

void setup() {
  pinMode(boton,INPUT);
  pinMode(pinRele1,OUTPUT);
  pin ode(4,OUTPUT);
}

void loop() {
    
    if (digitalRead(boton)) {
        contador  = 1;
        estado1 = 0;
        tiempo    = millis(); 
        while (millis () - tiempo <= RAFAGA) {
          digitalRead(boton);
          if (digitalRead(boton)) {
              contador = 2;
              estado2 = 0;
          }
        }
             
    }
    switch(contador) {
      case 1: activarele1();
              break;
      case 2: activarele2();
              break;
    }
    contador = 0;
    tiempo   = 0;
}

/***   Function definition   ***/
void activarele1 () {
  switch(estado1) {
    case 0: digitalWrite(pinRele1,HIGH);
            start = millis();
            estado1 = 1;
            break;
    case 1: if (millis()-start > TIEMPO) {
                digitalWrite(pinRele1,LOW);              
                start = millis();
                estado1 = 2;
            }
            break;
    default: 
            break;
  }
}

void activarele2 () {
  switch(estado2) {
    case 0: digitalWrite(pinRele2,HIGH);
            start = millis();
            estado1 = 1;
            break;
    case 1: if (millis()-start > TIEMPO) {
                digitalWrite(pinRele2,LOW);              
                start = millis();
                estado1 = 2;
            }
            break;
    default: 
            break;
  }
}

Buenas tardes surbyte, muchísimas gracias, menuda currada te has pegado… pues ya lo he probado… y no funciona… tengo que meter la librería switch? el caso es que no funciona sin la librería ni con la librería, cuando le doy al pulsador se enciende directamente la salida 4 (rele2) y no se apaga…

Yo con lo que pretendía con los delays que quite, era hacer como un antirrebote… pero ya se que con delays es una forma muy “básica y poco fiable” de conseguirlo, por eso quería llamar a la función de la librería Switch para el antirrebote… pero no tengo ni idea la verdad… que puede haber fallado?

Esperaba que le pusieras 1 minuto de tu tiempo.
Copie el 2do procedimiento del primero y no cambié las variables estado1 a estado2 y se repetía todo el tiempo

Tendrias que haberlo descubierto tu.
BUeno, acá hice tu tarea.

#include <Bounce2.h> //https://github.com/thomasfredericks/Bounce2


#define RAFAGA              1000
#define TIEMPO              2000

const byte boton            = 2;
const byte pinRele1         = 3;
const byte pinRele2         = 4;

unsigned long tiempo        = 0;
byte contador               = 0;
byte estado1                = 0;
byte estado2                = 0;

unsigned long start;
// Instantiate a Bounce object
Bounce debouncer = Bounce(); 
boolean value, valueAnt = false;

void setup() {
  Serial.begin(9600);
  pinMode(boton,INPUT);
  pinMode(pinRele1,OUTPUT);
  pinMode(4,OUTPUT);

    // After setting up the button, setup the Bounce instance :
  debouncer.attach(boton);
  debouncer.interval(RAFAGA); // interval in ms
}

void loop() {
    
  // Update the Bounce instance :
  debouncer.update();

  // Get the updated value :
  value = debouncer.read();
  if (value && !valueAnt) {
      contador++;
      Serial.println("Contador "+String(contador));
  }
  valueAnt = value;

  switch(contador) {
    case 1: activarele1();
            break;
    case 2: activarele2();
            break;
    case 3: contador = 0;
            break;
  }
}

/***   Function definition   ***/
void activarele1 () {
  switch(estado1) {
    case 0: digitalWrite(pinRele1,HIGH);
            start = millis();
            estado1 = 1;
            break;
    case 1: if (millis()-start > TIEMPO) {
                digitalWrite(pinRele1,LOW);              
                start = millis();
                estado1 = 2;
            }
            break;
    default: 
            break;
  }
}

void activarele2 () {
  switch(estado2) {
    case 0: digitalWrite(pinRele2,HIGH);
            start = millis();
            estado2 = 1;
            break;
    case 1: if (millis()-start > TIEMPO) {
                digitalWrite(pinRele2,LOW);              
                start = millis();
                estado2 = 2;
            }
            break;
    default: 
            break;
  }
}

La librería Bounce2 es la que se usa en lugar de Switch.
Juega con RAFAGA porque 1seg de debouce es mucho… pero lo dejo a tu criterio
En el código esta la ruta o path a la librería

Buenas noches surbyte
Pues me he pasado toda la tarde del sábado jugando con esto… y creo que lo tengo

Lo que hace el programita es:

Si se pulsa un pulsador una vez en un tiempo de 2 seg - Salida a Rele 1
Si se pulsa un pulsador dos o mas veces en un tiempo de 2 seg - Salida a Rele 2

El unico problemita que tampoco lo es mucho es que si se queda pulsado se activa una vez el rele 1, de esta forma si lo conecto en la moto en la luz de las largas, cuando ponga las largas se activara el relé 1 una vez… pero bueno, tampoco es mucho problema

Por lo demas creo que va perfecto

Aqui esta:

/***   Global variables   ***/
const int tiempoAntirebote = 10;
const int pulsador = 2;
unsigned long tiempo;
unsigned long tiempo_rafaga = 2000;
int cuenta;
int estadoboton=0;
int estadobotonanterior=0;

/***   Function declaration   ***/
void activarele1 ();
void activarele2 ();
void variables_a_0 ();
boolean antirebote(int pin);

void setup()
{
  pinMode(pulsador,INPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  tiempo=0;
  cuenta=0;
}


void loop()
{
    estadoboton=digitalRead(2);                               // Leemos el boton
        if(estadoboton!=estadobotonanterior)                  // Si hemos presionado el boton
          {
            if(antirebote(pulsador))                          // Llamada a Funcion antirebote
            {
               estadoboton=digitalRead(2);                    // Actualizamos el estado del boton
               cuenta=1;                                      // La cuenta esta en 1
               estadobotonanterior = estadoboton;             // Actualizamos el estado anterior del boton
               tiempo=millis(); 
               while (millis () - tiempo <= tiempo_rafaga)    // Tiempo de espera por si segunda pulsacion
               {
                 estadoboton=digitalRead(2);                  // Leemos el boton
                 if(estadoboton!=estadobotonanterior)         // Si hay una segunda pulsacion
                 {
                   if(antirebote(pulsador))                   // Llamada a Funcion antirebote
                   {
                     estadoboton=digitalRead(2);              // Actualizamos el estado del boton
                     cuenta=2;                                // La cuenta pasa a 2 en caso de segunda pulsacion
                     estadobotonanterior = estadoboton;       // Actualizamos el estado anterior del boton
                   }
                  }
                }
             
                if (cuenta == 1)                              // Si se ha pulsado una vez
                {                           
                  activarele1();                              // Llamada a Funcion para activar el Rele 1
                }
                if (cuenta == 2)                              // Si se ha pulsado 2 veces
                {
                  activarele2();                              // Llamada a Funcion para activar el Rele 2
                }
                variables_a_0();                              // Llamada a Funcion para poner las variables a 0
         
             }
          }
}

/***   Function definition   ***/

boolean antirebote(int pin)        // Funcion Antirebote
{
  int contador=0;                  // Contador interno
  boolean estado;                  // guarda el estado del boton
  boolean estadoAnterior;          // guarda el ultimo estado del boton

  do 
      {
        estado = digitalRead(pin);
        if(estado != estadoAnterior)
        {
          contador = 0;
          estadoAnterior = estado;
        }
        else
        {
          contador = contador + 1;
        }
        delay(1);
      } while (contador < tiempoAntirebote);
      
      return estado;
}

void activarele1 ()          // Funcion para activar el Rele 1
{
  digitalWrite(3,HIGH);
  delay(2000);
  digitalWrite(3,LOW);
}
void activarele2 ()          // Funcion para activar el Rele 2
{
  digitalWrite(4,HIGH);
  delay(2000);
  digitalWrite(4,LOW);
}
void variables_a_0 ()        // Funcion para poner las variables a 0
{
  cuenta=0;
  tiempo=0;
}

Lo que te pasé funciona porque lo probé con mi simulador.
Ahora ajusta los tiempos de RAFAGAS que no se si estan o no bien.

Muchas gracias de verdad! si que funciona, mil gracias!