Translate

viernes, 28 de septiembre de 2012

Módulo de intermitencia para moto con Arduino

Hasta ahora mis experimentos con Arduino eran meros entretenimientos, pero llega un día en que necesitas cierto artilugio y recuerdas tener guardado en un cajón el Arduino que puede darle vida.


Hace unos días noté un comportamiento extraño en mi moto, los intermitentes izquierdos parpadeaban de forma irregular, a veces muy ténue, otras tardaba en empezar... hasta que deduje que la unidad que controla la intermitencia estaba dañada. Seguramente alguna resistencia de carga.

El comportamiento original de la moto era que el intermitente se ponía en marcha mediante un pulsador a cada lado del manillar, y se apagaba al girar o al cabo de un recorrido, dependiendo de la velocidad, información que procede de un encoder dentro del cuenta-km.

Ya desde el principio a mí no me acavaba de gustar el hecho de que se apagara solo al cabo de un recorrido, muchas veces me gusta avisar con tiempo de que voy a salir, y lógicamente tengo que frenar y molesto al resto de vehículos. Y el hecho de que se apagara a los pocos parpadeos, me obligaba a estar pendiente de cuando ocurría y volver a encenderlo.

Buscando por Google vi que en USA se venden unidades "universales" de intermitencia que se pueden adaptar a cualquier moto, y su funcionamiento me gustó: si pulsas 1 segundo, parpadea 7 veces, si pulsas 2 segundos, parpadea 20 veces, y si pulsas 4 segundos parpadea 70 veces. Así que partiendo de esta idea, cogí mi Arduino Uno, le puse dos leds y dos pulsadores y me puse a modelar un programa.





Pero decidí modificar algo el comportamiento. Si pulsas un botón menos de 1 segundo, parpadea 7 veces, si lo pulsas entre 1 y 3 segundos parpadea 20, y si lo pulsas más de 3 segundos parpadea indefinidamente hasta que vuelves a pulsar el mismo botón.

Además mientras está en modo 7 parpadeos o 20 parpadeos, si pulsas el mismo botón se para, y si pulsas el otro, cambia de intermitente y dura el mismo periodo que teníamos seleccionado.

Y para los cuatro intermitentes, pulsando los dos botones a la vez se encienden, y parpadean hasta que pulsas cualquier botón.

La idea la tenía, programarlo ocupó su ratillo pero al final salió un programa que es bastante funcional. Como puerto de entrada para el botón del intermitente derecho utilizo el 3, y el 4 para el izquierdo. La salida para encender y apagar los intermitentes son el puerto 9 y 10 para los derechos e izquierdos, respectivamente.

Os adjunto el código:

/*

Este modesto código pertenece a RosHardware. Se autoriza el uso 
parcial o total del mismo siempre y cuando se indique su procedencia. 

http://www.entremaqueros.com/bitacoras/roshardware

Este programa está diseñado para el funcionamiento de los intermitentes en una moto o coche.
Mediante dos pulsadores, uno para cada lado, activamos o desactivamos los intermitentes. Las salidas
digitales utilizadas sirven para pilotar relés o MOSFETs, que serán los encargados de encender 
y apagar las bombillas.

*/


int pushright=3; //pulsador derecho
int pushleft=4;  //pulsador izquierdo
int turnright=9;  //intermitente derecho
int turnleft=10;  //intermitente izquierdo
unsigned long timebase=0;
unsigned long tright=0; //para guardar el tiempo de pulsación
unsigned long tleft=0;  //para guardar el tiempo de pulsación
int lederror=13; //para casos else
int i=0; //variable bucles

void derecha(int a) //función encender intermitente derecho tiempo 'a'
{
  for(i=1; i<=a; i++)
       {
         digitalWrite(turnright,HIGH);
         delay(300);
         digitalWrite(turnright,LOW);
         if(digitalRead(pushright)==HIGH) //si se pulsa el mismo botón, para
         {
           delay(500);
           break;
         }
         if(digitalRead(pushleft)==HIGH)  //si se pulsa el otro botón cambia de función
         {
           izquierda(a);
           break;           
         }
         delay(400);
         if(digitalRead(pushright)==HIGH) //si se pulsa el mismo botón, para
         {
           delay(500);
           break;
         }
         if(digitalRead(pushleft)==HIGH)  //si se pulsa el otro botón cambia de función
         {
           izquierda(a);
           break;           
         }
       }
}

void izquierda(int a)  //función encender intermitente izquierdo tiempo 'a'
{
   for(i=1; i<=a; i++)
       {
         digitalWrite(turnleft,HIGH);
         delay(300);
         digitalWrite(turnleft,LOW);
          if(digitalRead(pushleft)==HIGH)  //si se pulsa el mismo botón, para
         {
           delay(500);
           break;
         }
         if(digitalRead(pushright)==HIGH)  //si se pulsa el otro botón cambia de función
         {
           derecha(a);
           break;           
         }
         delay(400);
         if(digitalRead(pushleft)==HIGH)  //si se pulsa el mismo botón, para
         {
           delay(500);
           break;
         }
         if(digitalRead(pushright)==HIGH)  //si se pulsa el otro botón cambia de función
         {
           derecha(a);
           break;           
         }
       }
}

void error() //por si no se diera ninguna condición
{
  digitalWrite(lederror, HIGH);
  delay(200);
  digitalWrite(lederror, LOW);
}

void setup()
{
  pinMode(pushright, INPUT);
  pinMode(pushleft, INPUT);
  pinMode(turnright, OUTPUT);
  pinMode(turnleft, OUTPUT);
  pinMode(lederror, OUTPUT);
  //Serial.begin(9600);      // abre el puerto serie a 9600 bps: 
}

void loop()
{
   timebase=millis(); //tiempo de referencia al empezar el bucle
  
  if(digitalRead(pushright)==HIGH && digitalRead(pushleft)==HIGH) // cuatro intermitentes,
                                                                       // para si se pulsa algún botón
  {
    do
    {
      digitalWrite(turnright, HIGH);
      digitalWrite(turnleft, HIGH);
      delay(300);
      if(digitalRead(pushright)==HIGH || digitalRead(pushleft)==HIGH)
      {
        digitalWrite(turnright,LOW);
        digitalWrite(turnleft,LOW);
        delay(500);
        break;
      }
      digitalWrite(turnright, LOW);
      digitalWrite(turnleft, LOW);
      delay(400);
     }while(digitalRead(pushright)==LOW && digitalRead(pushleft)==LOW);
    
    delay(250);
    
  }
   
   else if(digitalRead(pushright)==HIGH && digitalRead(pushleft)==LOW) //si se pulsa el derecho
  {
    delay(20);
    do
    {
      tright=millis(); //tiempo al terminar de pulsar el botón.
    }while(digitalRead(pushright)==HIGH);
    
    tright=tright-timebase; //tiempo pulsando
    //Serial.print(tright);
    //Serial.print( "\n");
    if(tright<=1200)  //si se pulsa aprox 1 segundo
     {
       derecha(7);
     }
     
     else if(tright<=3000)  //si se pulsa aprox 2 segundos
     {
       derecha(20);
     }
     
     else if(tright>3000)  //si se pulsa más de 3 segundos funcionará siempre 
                           //hasta que pulse el mismo botón
     {
        do
        {
        digitalWrite(turnright, HIGH);
        delay(300);
        if(digitalRead(pushright)==HIGH)
        {
          digitalWrite(turnright,LOW);
          delay(300);
          break;
        }
        digitalWrite(turnright, LOW);
        delay(400);
       }while(digitalRead(pushright)==LOW);
    
      delay(500);
     }
     
     else
     {
       error;
     }
  }
  
  else if(digitalRead(pushright)==LOW && digitalRead(pushleft)==HIGH)  //si se pulsa el izquierdo
  {
    delay(20);
    do
    {
      tleft=millis(); //tiempo al terminar de pulsar el botón.
    }while(digitalRead(pushleft)==HIGH);
    
    tleft=tleft-timebase;  //tiempo pulsando
    //Serial.print(tleft);
    //Serial.print( "\n");
    if(tleft<=1200)  //si se pulsa aprox 1 segundo
     {
       izquierda(7);
     }
     
     else if(tleft<=3000)  //si se pulsa aprox 2 segundos
     {
       izquierda(20);
     }
     
     else if(tleft>3000)  //si se pulsa más de 3 segundos funcionará siempre 
                          //hasta que pulse el mismo botón
     {
        do
        {
        digitalWrite(turnleft, HIGH);
        delay(300);
        if(digitalRead(pushleft)==HIGH)
        {
          digitalWrite(turnleft,LOW);
          delay(300);
          break;
        }
        digitalWrite(turnleft, LOW);
        delay(400);
       }while(digitalRead(pushleft)==LOW);
    
      delay(500);
     }
     
     else
     {
       error;
     }
  }
  
    
  else
  {
    digitalWrite(turnright,LOW); //por si a caso
    digitalWrite(turnleft,LOW);  //por si a caso
  }
  
}


Y el fichero listo para cargarlo en la placa Arduino:

intermitentesV8

Una vez escrito el programa faltan dos cosas todavía, reducirlo a la mínima expresión para que ocupe bien poco, y pasar de controlar dos leds con un consumo ridículo a poder manejar unos 50w por canal, puesto que cada bombilla de intermitente consume 21w. Tened en cuenta que el hecho de que pueda manejar consumos de 50W no impide, sinó todo lo contrario, permite controlar intermitentes a leds o cualquier sistema con menor consumo.

Para ello utilizaremos dos MOSFETs P-channel, concretamente los IRF9540, que admiten hasta 100V y 13A, y en nuestro caso trabajaremos a 13.8V y sobre los 5A. Estos MOSFETs necesitan mínimo 10V para operarlos, y al ser P-channel se controlan al revés, al recibir los 10V cortan la salida, y al quitarlos y dejarlo a 0V abren la salida, de modo que añadiendo un transistor BC547 "en serie" entre Arduino y MOSFET conseguiremos dos cosas a la vez, invertir la señal para que cuando Arduino esté en HIGH, encienda los intermitentes, y además elevar la tensión de 5V que saca Arduino a los 13.8V que saca la moto.

Tanto en el puerto 9 como en el 10 añadiremos el siguiente montaje:





Y para los pulsadores recordad que Arduino admite de entrada máximo 5V, de manera que tenemos que mandarle a los botones 5V que podemos sacar del propio Arduino, en vez de los 13.8 que saca la Moto. MUCHO CUIDADO NO OLVIDAR ESTO.

Y para que el montaje final quede compacto, en lugar de un Arduino UNO que es algo grande, he utilizado un Arduino Nano, que podéis encontrar por ebay a partir de 8€





Para alimentar un Arduino Nano se requieren 5V, de modo que añadiendo un 7805 (o un R785.0 en mi caso) conseguimos bajar de 13.8V a 5V fácilmente:





Os adjunto una foto donde he intentado resumir todas las conexiones, espero no haberme dejado nada y que esté suficientemente claro:





He comprado una pequeña caja de aluminio en la tienda de electrónica, le añado un fusible al conjunto de 15A por si las moscas, y el montaje final queda así:


fotos


Antes de que se me olvide, doy las gracias por su ayuda y sus ideas a FXSTC95 de ForoHarley, y a mis compañeros de trabajo Adolf, Martí y Jordi.

Y en estos vídeos podéis ver su funcionamiento, a falta de ser instalado en la moto. Tened en cuenta que es difícil pulsar los pulsadores con una sola mano, estando montados "al aire", además de que son reutilizados y no van muy finos. Solo son para ilustrar el ejemplo:








English translate version.

6 comentarios:

  1. Me gusta! En mi moto tengo que mantener apretado el botón del intermitente para que funcione, con esto solo pulsando funciona, no tendría que mantener, que a veces es complicado.

    Gracias!!

    ResponderEliminar
  2. [...] he querido publicar “oficialmente” sobre ella, aunque sí discretamente, cuando hice el tutorial para fabricar un módulo de intermitencia, pero hoy vamos con otra operación sobre dos [...]

    ResponderEliminar
  3. Hola Eduard.
    He encontrado en aliexpress unos arduinos nano a 1.57€ y no he podido evitar hacerme con un par para ir probando cosas. Mientras llegan me he repasado tu programa, desde la óptica del lenguaje asm que me tuve que aprender un poco para programar el pic y veo que repites bucles:
    - cuando asignas la función de encender derecho, repites dos veces el bucle 'si se pulsa otro botón' y el bucle 'si se pulsa el mismo botón'.
    - lo mismo cuando asignas la función del izquierdo.

    Esto es así? es que estoy intentando entender el lenguaje del arduino y me ha extrañado ésto.

    Y otra cosa del hardware: veo que en el esquema de fondo verde has puesto en las salidas a los BC547 resistencias de 10K a masa- Hacen falta?

    Si lo termino realizando, los pulsadores los mantendré funcionando tal como están en la moto haciendo un divisor con un para de resistencias y un zener que limite a +5v. No pienso pasar cables.

    Y el caso es que mi módulo de intermitencias va perfecto...

    ResponderEliminar
  4. Hola.

    Todo código es mejorable. El lenguaje Arduino es una variante del C. Seguramente esos trozos de código que repito se podrían convertir en función, yo lo dejé así y funciona. Mis conocimientos de C son básicos, seguramente alguien con más nivel lo condensa mucho más.

    Referente a la resistencia de 10k en los BC547, no recuerdo muy bien para qué eran, pero sí ten claro que en un arduino las señales de entrada y salida admiten como máximo 5V, tiene pinta de ser un divisor de tensiones.

    Y respecto a los pulsadores, yo al final hice lo mismo, no pasé cables, coloqué un par de divisores de tensión para que, cuando le lleguen 13,5v, al arduino le lleguen 4V. Me reservé ese voltio hasta los 5v por si a caso alguna vez falla el regulador de tensión. No lo añadí aquí porque ya había hecho todos los esquemas.

    Te divertirás, e incluso si buscas hay arduinos mucho más pequeños actualmente.

    Suerte!

    ResponderEliminar
    Respuestas
    1. Ah, vale. Probaré cuando me lleguen a ver si soy capaz de meterle los cambios que me gustan. Como son para luces led de 1w, quiero que vayan como las mías: 0.03 seg encendidas y 0.97 seg apagadas.
      En el PIC también son señales de E/S a 5v y manejaba el transistor de potencia con un optoacoplador en vez del BC547.
      Vamos a ver cuando llegue que acople le hago para meter eso y que se quede compacto. Elegí el nano porque tiene el conector USB, los otros mas pequeños igual no lo traen y hay que soldarle un cable USB. Se estudiará en todo caso, como los precios son tan asequibles...
      Un abrazo.

      Eliminar
  5. hola buenas!!,me he comprado todo lo necesario (creo)..... para realizar esta maravila,pero el programa me pide un codigo para funcionar,y no tengo ni idea si es privado o uno por defecto es la primera vez que toco un arduino ,y la verdad estoy temblando jejeje si aun mirais este hilo ayudarme un poco gracias y un saludooooooooo!!!!!!!!

    ResponderEliminar