Faros Antiniebla con sensor luces para motocicleta

Buenas tardes.

Soy bastante nuevo en el tema, pero a base de ensayo y error he conseguido realizar la programación de un circuito en Arduino que lo que haría sería encender o apagar los faros antiniebla de una motocicleta con opción de sensor de luz así como la carga wireless para el teléfono móvil.
Hasta ahí todo ha funcionado perfectamente y tengo el hardware totalmente operativo y funcionando.
Mi problema es el siguiente:

Me gustaría añadir un contador de tiempo al pulsador de los antinieblas de unos 2 segundos, para que en vez de saltar a una de las 3 opciones que tiene (off, on, automatico) me cambiase a una opción parpadeo intermitente (blink creo que se llama).
He buscado en mil foros pero no soy capaz de hacerlo funcionar.
¿Alguien me podría echar una mano?

Gracias de antemano.

Aqui pongo el código completo:

// VERSION TOTALMENTE OPERATIVA. 
// 2 PULSADORES, EL 1º CONTROLA RELE 1 QUE SERÁ EL QUE ACTIVE O DESACTIVE LA CARGA WIRELES, EL 2ºCONTROLA ANTINIEBLAS. 3 POSICIONES, OFF, ON Y AUTOMATICO (SENSOR DE LUZ)

// PINES PARA ANTINIEBLAS
// Define los pines a utilizar para antinieblas

int ledRojo = 5;
int ledVerde = 6;
const int ledrele = 3; // En protoboard es un led, pero en realidad irá conectado a un rele

// Guarda los valores a signar a cada color (0-254)
int ValorRojo = 250;
int ValorVerde = 250;
int ValorRojo2 = 250;
int ValorVerde2 = 250;
int Valorrele = 250;

// BOTON SELECTOR LUCES ANTINIEBLA
int BotonSelect = 7;


//sensor de luz
const int FOTOPIN = A0;
int valorSensor = 0;
//const int Ledsensor = 9;
int valorMapeado = 0;


// PINES PARA TELEFONO MOVIL
int ledRojo2 = 9;
int ledVerde2 = 10;
const int ledrele2 = 11; // En protoboard es un led, pero en realidad irá conectado a un rele
int BotonSelect2 = 8;
int ledSeleccionado2 = 0;

// PARA REGULAR EL RETARDO DE LOS LEDS ANTINIEBLA
unsigned long previousMillis = 0;        // will store last time LED was updated

const long interval = 3000;  

// PARA REGULAR EL RETARDO DE LA LUZ ESTROBOSCÓPICA

unsigned long duracion = 0; //almacenará la duración de la pulsación del botón del antiniebla
int pinLed = 0;
int pinLed2 = 0;
float pulsacion;
float tiempo;
void setup()
{
  // Hay que indicar que lo pines utilizados por los botones son de ENTRADA
  pinMode(BotonSelect, INPUT);
   pinMode(BotonSelect2, INPUT);
  analogWrite(ledRojo, 200);
  // datos para sensor de luz
  pinMode (FOTOPIN, INPUT);
  // pinMode (Ledsensor, OUTPUT);
   pinMode (ledrele, OUTPUT);
   Serial.begin(9600);
}

// Valor por defecto: Rojo
// 0= Rojo, 1=Verde, 2=Azul


void loop()
{
  
   
   unsigned long currentMillis = millis();
   if (digitalRead(BotonSelect) == HIGH){
  //   if (pulsacion >= tiempo){
  //   while (pulsacion>2000){
  //    analogWrite (ledrele, 250);
  //   }
  // }
    pinLed++;

    // Para no pasarnos de vueltas
    if (pinLed > 2) {
      pinLed = 0;
    }

    // Apagamos todos los LED ya que luego se mostrarA sOlo el led seleccionado
    analogWrite(ledRojo, 0);
    analogWrite(ledVerde, 0);
  

    // Esperamos a que el boton se suelte
    while (digitalRead(BotonSelect) == HIGH) {  
      analogWrite (ledrele, 0); }
    delay(80); // Esperamos un poquito más...
  }
  if (digitalRead(BotonSelect2) == HIGH)
  {
    pinLed2++;

    // Para no pasarnos de vueltas
    if (pinLed2 > 1) {
      pinLed2 = 0;
    }

    // Apagamos todos los LED ya qu eluego se mostrará sólo el led seleccionado
    analogWrite(ledRojo2, 0);
    analogWrite(ledVerde2, 0);
  

    // Esperamos a que el boton se suelte
    while (digitalRead(BotonSelect2) == HIGH) {  
      analogWrite (ledrele2, 0); }
    delay(80); // Esperamos un poquito más...
  }
   if (pinLed2 == 0) 
  {
    analogWrite(ledRojo2, ValorRojo2);
    analogWrite (ledrele2, 0);
  }
  if (pinLed2 == 1) {
    analogWrite(ledVerde2, ValorVerde2);
    analogWrite (ledrele2, 250);
  }
  // Actualiza el valor del color seleccionado
  if (pinLed == 0) {
    analogWrite(ledRojo, ValorRojo);
    analogWrite (ledrele, 0);
  }
    if (pinLed == 1) {
    analogWrite(ledVerde, ValorVerde);
    analogWrite (ledrele, 250);

  }
     if (pinLed == 2) {
    analogWrite(ledVerde, ValorVerde );
    analogWrite(ledRojo, ValorRojo);
    valorSensor = analogRead (FOTOPIN);
    valorMapeado = map (valorSensor, 1020, 0, 0, 255);
    if ( valorSensor > 970) {
       if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
     if ( valorSensor > 970) {
      analogWrite (ledrele, 0);
       }
    }    
    }

    if (valorSensor < 970) {
   if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    if (valorSensor < 970) {
    analogWrite (ledrele, 250);
    }
    }
  }
    Serial.print ("Sensor: ");
    Serial.println (valorSensor);
  }
   

}

Hola Buen dia!
Bueno después de leer varias veces tu post y ver el código me sugen algunas dudas. Por ejemplo en tu código veo algo como esto:
const int ledrele2 = 11; // En protoboard es un led, pero en realidad irá conectado a un rele y después esto:

 analogWrite (ledrele, 250);

Si es un rele,¿ Porque o para que usas analogWrite()?

Ahora en eso de la carga wireless exactamente que hace el arduino? según lo que entendí por tu código, con un pulsador, activas o desactivas un rele que enciende o apaga el cargador inalambrico... es correcto? ¿ Y porque no poner el interruptor directo al cargador y te evitas algunos problemas?

Me gustaría añadir un contador de tiempo al pulsador de los antinieblas de unos 2 segundos

Segun entiendo tu sistema tiene 3 opciones y quieres agregarle destellos de los faros entonces seria: encendido, apagado, automático e intermitente.¿ Entonces solo quieres agregar ese blink de 2 segundos?

P.D. Gracias por leer las normas de foro y subir correctamente el código a tu post, por lo regular los nuevos nunca lo hacen

Hola! Muchas gracias por contestar.
Te explico:
El codigo lo he ido copiando de unas cosas y otras, por lo que muy probablemente tenga mil y un errores o seguramente haya funciones más faciles y más claras.
En relación a:

const int ledrele2 = 11; // En protoboard es un led, pero en realidad irá conectado a un rele

y después:

analogWrite (ledrele, 250);

era básicamente porque en el momento de la creación lo copiaría en algún sitio de esa forma.
¿Sería mejor poner (HIGH) directamente?

Lo del tema del cargador wireless:
Es un dispositivo que ya tengo montado en la moto, por lo que únicamente sería un pulsador que active y desactive un relé + 2 leds (rojo y verde) para indicar en qué estado se encuentra.

Lo de los antinieblas sería básicamente igual, un relé que los active, pero aqui habría 3 posiciones, la automática con el sensor de luz, más las de encendido y apagado.

Todas estas últimas se activan con una pulsación corta, pero me gustaría añadir la pulsación larga y que las luces parpadeasen en intervalos de 1 o 2 segundos (por temas de averia de la moto en un momentodado, por ejemplo).

Gracias nuevamente por su atención.

Bien, ya me quedo mas claro, déjame hacerle unos cambios a tu código y mas tarde lo subo para que lo pruebes

edito: una pregunta mas: ¿el ledrele y ledrele2? cual corresponde al cargador y cual a los faros?

Ledrele sería el rele correspondiente a los faros
Ledrele2 seria el correspondiente al cargador

Muchísimas gracias de antemano.

Hola de nuevo...

Aquí te dejo el código ya modificado, no lo probé pero compila bien, pruebalo y me comentas si funciona

//LucesNiebla.ino
// VERSION TOTALMENTE OPERATIVA.
// 2 PULSADORES, EL 1º CONTROLA RELE 1 QUE SERÁ EL QUE ACTIVE O DESACTIVE LA CARGA WIRELES, EL 2ºCONTROLA ANTINIEBLAS. 3 POSICIONES, OFF, ON Y AUTOMATICO (SENSOR DE LUZ)

//Casos Posibles de las luces
#define APAGADO 0
#define ENCENDIDO 1
#define AUTOMATICO 2
#define INTERMITENTE 3 
// PINES PARA ANTINIEBLAS
// Define los pines a utilizar para antinieblas
const byte ledRojoLuces = 5;
const byte ledVerdeLuces = 6;
const byte ledreleLuces = 3; // En protoboard es un led, pero en realidad irá conectado a un rele  
// BOTON SELECTOR LUCES ANTINIEBLA
const byte btnLuces = 7;
byte casos;  //Para usarse en el switch-case
String imprimir[]={"Apagadas","Encendidas","automaticas"};   //Solo para imprimir en pantalla el estado de las luces

//sensor de luz
const byte FOTOPIN = A0;
int valorSensor;
int anteriorSensor;

// PINES PARA TELEFONO MOVIL
const byte ledRojoCargador = 9;
const byte ledVerdeCargador = 10;
const byte ledreleCargador = 11; // En protoboard es un led, pero en realidad irá conectado a un rele 
const byte btnCargador = 8;

//Variables de estado
bool estado_btnCargador, estado_btnLuces, anterior_btnCargador, anterior_btnLuces;

//Variable para antirrbote
unsigned long db;

// PARA REGULAR EL RETARDO DE LOS LEDS ANTINIEBLA
unsigned long millisLucesAuto, retardolucesAuto=1500; //puedes cambiar este valor a como te funcione mejor       
unsigned long millisIntermitente, tiempoDeIntermitencia=1000;  //Tiempo entre encendido-apagado de las luces intermitentes

// PARA REGULAR EL RETARDO DE LA LUZ ESTROBOSCÓPICA
unsigned long duracionPulsador = 2000; //tiempo de retardo para encender las luces intermitentes
unsigned long millisPulsador;

void setup()
{
  // Hay que indicar que lo pines utilizados por los botones son de ENTRADA
  pinMode(btnCargador, INPUT);
  pinMode(btnLuces, INPUT);
  pinMode(ledreleLuces, OUTPUT);
  pinMode(ledreleCargador, OUTPUT);
  pinMode(ledRojoCargador, OUTPUT);
  pinMode(ledVerdeCargador, OUTPUT);
  pinMode(ledRojoLuces, OUTPUT);
  pinMode(ledVerdeLuces, OUTPUT);
  digitalWrite(ledRojoLuces, HIGH);
  digitalWrite(ledRojoCargador, HIGH);
   
   Serial.begin(9600);
}


void loop()
{
   //Guarda el estado de los pulsadores
   estado_btnLuces=digitalRead(btnLuces);    
   estado_btnCargador=digitalRead(btnCargador);
     
     //** Desde aqui 
   if(estado_btnCargador && !anterior_btnCargador && millis() - db >= 60UL){  //Se presiono el pulsador del cargador  agruegue un antirrebote
   	    digitalWrite(ledreleCargador, !digitalRead(ledreleCargador));
        digitalWrite(ledVerdeCargador, !digitalRead(ledVerdeCargador));
        digitalWrite(ledRojoCargador, !digitalRead(ledRojoCargador));             
        db=millis();     
    } 
      anterior_btnCargador=estado_btnCargador;    
              //Hasta aqui es para encender o apagar el cargador**                                           

        //**De aqui en adelante es para el control de luces
   if(estado_btnLuces && !anterior_btnLuces && millis()-db >=60UL){ //se presionó el pulsador
          casos++;
          if(casos >2)
               casos=0;
          Serial.println("Las luces estan: " + imprimir[casos]);     
          millisPulsador=millis();   //Se guarda el valor de millis para medir el tiempo del pulsador
          db=millis();
           }
     
    if(millis() - millisPulsador >= duracionPulsador) {    //si pasa el tiempo predeterminado en la variable duracionPulsador
    	   if(estado_btnLuces){          // y si el pulsador esta presionado
    	         casos=INTERMITENTE;     // brincamos al case que hace la intermitencia de luces
                 Serial.println("Las luces estan: intermitentes");
                 millisPulsador=millis();  //Para evitar que se imprima muchas veces la linea anterior (se puede quitar sin problema)
              }      
         }       
     anterior_btnLuces=estado_btnLuces;   //se iguala el estado de las 2 variables para detectar el cambio de estado del pulsador 

  switch (casos) {
      case APAGADO:                               
         digitalWrite(ledreleLuces, LOW);
         digitalWrite(ledRojoLuces, HIGH);
         digitalWrite(ledVerdeLuces, LOW);
        break;

      case ENCENDIDO:
        digitalWrite(ledreleLuces, HIGH);
         digitalWrite(ledRojoLuces, LOW);
         digitalWrite(ledVerdeLuces, HIGH);
        break;

      case AUTOMATICO:
           lucesAuto();  //Llamamos a la funcion que controla las luces automaticas
        break;

      case INTERMITENTE:
           if(millis()-millisIntermitente >=tiempoDeIntermitencia){
           	    digitalWrite(ledreleLuces, !digitalRead(ledreleLuces));
           	    digitalWrite(ledVerdeLuces, !digitalRead(ledVerdeLuces));
        	    digitalWrite(ledRojoLuces, !digitalRead(ledRojoLuces));
        	    Serial.println(digitalRead(ledreleLuces) ?" ON " : "OFF" );
        	    millisIntermitente=millis();
            }
        break;  
     }

}

void lucesAuto(){
         valorSensor = analogRead (FOTOPIN);
         
    if(anteriorSensor != valorSensor){  //Si hay un cambio en el valor del sensor
           Serial.print ("Sensor: ");
           Serial.println (valorSensor);
           millisLucesAuto=millis();     //Guardamos el valor de millis para generar un retardo para apagar o encender las luces

          }  

     if(millis() - millisLucesAuto >= retardolucesAuto){   // este retardo es para evitar que las luces destellen cuando estas cerca del umbral de apagado-encendido
           if(valorSensor < 970){
                digitalWrite(ledreleLuces, HIGH);
                digitalWrite(ledVerdeLuces, HIGH);
                digitalWrite(ledRojoLuces, LOW);
            }
            else {
                digitalWrite(ledreleLuces, LOW);
                digitalWrite(ledRojoLuces, HIGH);
                digitalWrite(ledVerdeLuces, LOW);
                }
         }
     anteriorSensor =valorSensor;
     }

Cambie el nombre de las variables y comenté lo mas posible para hacer el código mas comprensible y evitar posibles errores. Espero te sirva

Saludos

Hola!
Antes de nada, le agradezco de corazón el trabajo que ha realizado, no tengo palabras..., está todo muchisimo más limpio y claro.
Funciona el blink a la perfección, pero el modo automático no llega a funcionar, he probado incluiso con luz directa (del movil y de la calle) y nada, el led (relé) no se apaga.

Como ha cambiado significativamente el código ya me he quedado algo perdido jeje. :sweat_smile: ,

Aparte de ello, no sabría interpretar (imagino que si estará) si tuvo en cuenta la opción del retardo en modo automático (digamos que está en modo on y es de dia y pasamos por una sombra momentánea, con ello evitaría que se activase al momento).

Por cierto, al monitorear las funciones, veo que alternan correctamente pero igual (por el ruido del pulsador) habría que añadir algo más de retardo y también observo como el sensor funciona correctamente sobrepasando el umbral que tenía marcado (970), sin embargo no modifica el estado del relé.

Y ya como nimiedad que trataré de solucionar:

  • Para observar los cambios de estado en las luces, el led que le voy a instalar en un led RG (no pongo uno RGB porque me faltaría 1 hilo en los cables que le puse), por lo que la opción automática quisiera activar tanto el led rojo como el verde y con ello consigo una especie de naranja tal y como estaba en el código original, sin embargo, al editar su código para esa modificación no consigo que funcione tal efecto.

Saludos

Saludos de nuevo.
He conseguido solucionar casi todo excepto lo del modo automático.
El código del sensor automático resultante hasta ahora es el siguiente:

void lucesAuto(){
         valorSensor = analogRead (FOTOPIN);
          digitalWrite(ledVerdeLuces, HIGH);
          digitalWrite(ledRojoLuces, HIGH);
         
    if(anteriorSensor != valorSensor){  //Si hay un cambio en el valor del sensor
           Serial.print ("Sensor: ");
           Serial.println (valorSensor);
           millisLucesAuto=millis();     //Guardamos el valor de millis para generar un retardo para apagar o encender las luces

          } 

     if(millis() - millisLucesAuto >= retardolucesAuto){   // este retardo es para evitar que las luces destellen cuando estas cerca del umbral de apagado-encendido
           if(valorSensor < 970){
                digitalWrite(ledreleLuces, HIGH);
                
            }
            else {
                digitalWrite(ledreleLuces, LOW);
                
                }
         }
     anteriorSensor =valorSensor;
     }

He optado por dejar fuera las opciones "digitalWrite(lXXXX, HIGH)" porque así me aseguro de que enciendan las dos a la vez si o si en 1 sólo led RG (en naranja).

Al monitorear el sensor de luz aparece lo siguiente:

Por debajo del umbral de luz (relé ON):

Sensor: 557
Sensor: 556
Sensor: 553
Sensor: 556
Sensor: 555
Sensor: 557
Sensor: 556
Sensor: 553
Sensor: 556
Sensor: 555
Sensor: 557
Sensor: 556

y

Por encima del umbral de luz (Rele deberia estar OFF)

Sensor: 1007
Sensor: 1005
Sensor: 1007
Sensor: 1006
Sensor: 1007
Sensor: 1006
Sensor: 1007
Sensor: 1006
Sensor: 1007
Sensor: 1006
Sensor: 1007
Sensor: 1006

En principio, todo marca correcto pero al parecer no llega a entrar en la opción If/Else.

¿Podría ser así?

Un saludo

SOLUCIONADO!

Al final conseguí solucionar el modo automático con esto:

void lucesAuto(){
         valorSensor = analogRead (FOTOPIN);
          digitalWrite(ledVerdeLuces, HIGH);
          digitalWrite(ledRojoLuces, HIGH);
         
    if(anteriorSensor != valorSensor){  //Si hay un cambio en el valor del sensor
           Serial.print ("Sensor: ");
           Serial.println (valorSensor);
      [b]    // millisLucesAuto=millis();  [/b]   modifiqué de sitio esta variable //Guardamos el valor de millis para generar un retardo para apagar o encender las luces

          } 
          if(millis()- millisLucesAuto >= retardolucesAuto){   // este retardo es para evitar que las luces destellen cuando estas cerca del umbral de apagado-encendido
          millisLucesAuto=millis();[b] la puse aqui y todo genial [/b] //Guardamos el valor de millis para generar un retardo para apagar o encender las luces

                if(valorSensor < 970){
            
                digitalWrite(ledreleLuces, HIGH);             
            }    
            
            else {
               digitalWrite(ledreleLuces, LOW);
                
            }
            }
       
     anteriorSensor = valorSensor;
     }

Nuevamente y como no podría ser de otra manera, agradecer profundamente su ayuda, se merece como mínimo alguna caña que otra para celebrarlo.

Un abrazo.

Hola de nuevo!!!
Me da gusto que ya esté funcionando como querías.
Responderé algunas cuestiones:

pero el modo automático no llega a funcionar, he probado incluiso con luz directa (del movil y de la calle) y nada, el led (relé) no se apaga.

Bueno imagine que esa parte podría dar problemas porque solo me base a lo que estaba en tu codigo, ademas que no indicaste como tenias conectado el sensor por lo que hice el codigo siguiendo mis instintos :slight_smile:

si tuvo en cuenta la opción del retardo en modo automático (digamos que está en modo on y es de dia y pasamos por una sombra momentánea, con ello evitaría que se activase al momento).

Claro, incluso es la parte que modificaste, incuso lo comenté en esta linea:

unsigned long millisLucesAuto, retardolucesAuto=1500; //puedes cambiar este valor a como te funcione mejor

Por cierto, al monitorear las funciones, veo que alternan correctamente pero igual (por el ruido del pulsador) habría que añadir algo más de retardo

Si tienes problemas de rebotes del pulsador, prueba subiendo el tiempo a la linea

if(estado_btnCargador && !anterior_btnCargador && millis() - db >= 60UL)

cambia el 60UL por un valor mas alto
y finalmente esto:

Al final conseguí solucionar el modo automático con esto:

Ya entendí que es lo que me fallo. Al guardar el valor de millis cada que cambia el sensor No tome en cuenta que el sensor podría estar variando varias veces por segundo por lo que nunca se alcanza el tiempo de la condición del if().
Lo bueno que diste con la solución

Nuevamente y como no podría ser de otra manera, agradecer profundamente su ayuda, se merece como mínimo alguna caña que otra para celebrarlo.

Fue un placer haberte ayudado, si quieres dar por terminado el hilo modifica el titulo de post y agrega la palabra SOLUCIONADO a un lado del titulo, para que el moderador lo cierre

Saludos

Muchísimas gracias por sus aclaraciones.
Disculpe la demora en responderle, llevo un par de días realizando la instalación y el montaje en la caja, cableado, etc y la verdad es que ha quedado bastante profesional.
Tengo únicamente una última pregunta, por si fuese fácil de realizar:

  • Tengo 2 módulos de bluetooth HM-10 para Arduino. ¿Seria muy difícil añadirlos al código que tengo para poder, en un momento dado, editar desde un portátil cerca de la moto a través de bluetooth?

Con ello me evitaría muchas horas de montar y desmontar en la moto ya que hay factores, como la sensibilidad del fotosensor, que las he ido probando en habitación cerrada y con luz artificial.

Como siempre, gracias por su atención.