Articles - Arduino

Commande multifonctions

  |   2429  |  Poster commentaire  |  Arduino
Histoire de ne plus me poser de questions sur les fréquences, j'ai acheté un module (FrSky) afin de passer ma bonne vieille FC18 en 2.4Ghz.
Malheureusement cette modification entraîne le dysfonctionnement des modules "multiswitch" "multiprop" ou "éclairage camion" . Il est pourtant possible d'acheter des kits de la marque d'origine de votre radio, ou un kit JETI mais aussi SERVONAUT (et quelques autres aussi), qui eux fonctionnent parfaitement mais qui sont d'un coût assez élevé !!!

1 Version simple


L'éclairage étant indispensable sur un camion, je viens donc de réaliser un kit permettant de commander 8 fonctions a partir d'une simple voie proportionnelle. Il est compatible avec toutes les radios et facile a adapter aux besoins de chacun, et d'un coût très raisonnable (environ 30€ pour équiper la radio et le véhicule).

L'idée de base n'est pas de moi et je me suis largement inspiré de différentes sources trouvées sur internet. La solution que je vous propose ci dessous est celle que j'ai adaptée pour mon utilisation.

- Côté émetteur


Dans un premier temps j'ai créé un tableau de commande comportant 8 boutons poussoirs et quelques résistances que j'ai raccordé sur une voie proportionnelle de ma radio.


Le montage est vraiment très simple puisqu'il est possible de souder les fils et résistances directement sur les poussoirs, il n'est donc pas nécessaire de réaliser un circuit imprimé. Avec une radio de type PUPITRE il suffit d'utiliser les emplacements prévus pour les modules MULTI, alors que pour les autres radios il faudra fabriquer un support. Pour raccorder ce pupitre sur la radio il suffit d'utiliser un câble récupéré sur un vieux servo qui ne fonctionne plus.
Le principe de ce tableau de commande est tout simplement de simuler une position différente bien précise d'un manche (ici c'est comme si nous avions un manche avec 8 positions).
D'après mes mesures, il doit être possible de passer à 10 commandes sans trop de problème mais il faudrait tester pour voir si le système reste fiable.


- Côté récepteur


Côté récepteur il est nécessaire de créer un module de commutation genre CTI PS4 mais plus évolué. J'ai choisi pour cela le module ARDUINO qui peut être programmé afin d'obtenir le résultat désiré.

Dans un premier temps, si l'on raccorde un servo sur la voie utilisée par le multi, on peut observer que celui ci se déplace selon 8 positions distinctes en fonction du poussoir qui est activé.

Dans un deuxième temps, on va téléverser le sketch suivant sur l'ARDUINO afin que celui si soit en mesure de capter les informations transmises par le récepteur.
Code CPP :
 
/*================= Eclairage  ========================
   Commande 7 fonctions pour un éclairage de camion + 2 fonctions pour le son du camion
 
======================================================*/
  int signal = 0;    // Raccorder sur l'INPUT DIGITAL 0 le fil SIGNAL provenant du récepteur
  int val1;
  int s1 = 1; int s2 = 2; int s3 = 3; int s4 = 4; int s5 = 5; int s6 = 6; int s7 = 7; int s8 = 8; int s9 = 9; int s10 = 10;
  int e1 = 0; int e2 = 0; int e3 = 0; int e4 = 0; int e5 = 0; int e6 = 0; int e7 = 0; int e8 = 0; int e9 = 0;
  int mini = 1000;
  int maxi = 2000;
 
 
void setup()
{
  pinMode(s1,OUTPUT); pinMode(s2,OUTPUT); pinMode(s3,OUTPUT); pinMode(s4,OUTPUT);          
  pinMode(s5,OUTPUT); pinMode(s6,OUTPUT); pinMode(s7,OUTPUT); pinMode(s8,OUTPUT); 
  pinMode(s9,OUTPUT); pinMode(s10,OUTPUT); 
}
 
//==============================================================================================
  void loop()
{   
  val1 = 0; 
  val1 = pulseIn(signal, HIGH),30000; 
  val1 = map(val1,mini,maxi,950,2000);
  // val1=constrain(val1, 900, 2000); 
 
   delay (50);
   if (val1 > 2000 || val1 < 980 )  { val1 = 1500; }
 
      //veilleuses ; codes
      if (val1 > 1790 && val1 < 1860 && e1 == 0)   { e1 = 1; val1 = 0; delay(300);}
      if (val1 > 1790 && val1 < 1860 && e1 == 1)   { e1 = 2; val1 = 0; delay(300);}
      if (val1 > 1790 && val1 < 1860 && e1 == 2)   { e1 = 0; e3 = 0; e4 = 0; e5 = 0; val1 = 0; delay(300);}
 
      // demar moteur / arret moteur
      if (val1 > 1900 && val1 < 1980 && e2 == 0)   { e2 = 1; val1 = 0; delay(300);}
      if (val1 > 1900 && val1 < 1980 && e2 == 1)   { e2 = 0; val1 = 0; delay(300);}
 
      //phares
      if (val1 > 1660 && val1 < 1740 && e3 == 0)   { e3 = 1; e5 = 0; val1 = 0; delay(300);}
      if (val1 > 1660 && val1 < 1740 && e3 == 1)   { e3 = 0; e4 = 0; val1 = 0; delay(300);}
 
      //longues portees
      if (val1 > 1560 && val1 < 1640 && e4 == 0 && e3 == 1)   { e4 = 1; val1 = 0; delay(300);}
      if (val1 > 1560 && val1 < 1640 && e4 == 1)   { e4 = 0; val1 = 0; delay(300);}
 
      //antibrouillard
      if (val1 > 1360 && val1 < 1440 && e5 == 0 && e3 == 0 && e1 == 2)   { e5 = 1; val1 = 0; delay(300);}
      if (val1 > 1360 && val1 < 1440 && e5 == 1)   { e5 = 0; val1 = 0; delay(300);}
 
      //cligno gauche
      if (val1 > 1140 && val1 < 1220 && e6 == 0)   { e6 = 1; val1 = 0; delay(300);}
      if (val1 > 1140 && val1 < 1220 && e6 == 1)   { e6 = 0; val1 = 0; delay(300);}
 
      //cligno droit
      if (val1 > 1250 && val1 < 1340 && e7 == 0)   { e7 = 1; val1 = 0; delay(300);}
      if (val1 > 1250 && val1 < 1340 && e7 == 1)   { e7 = 0; val1 = 0; delay(300);}
 
      //KLAXON
      if (val1 > 1010 && val1 < 1100)   { digitalWrite(s8,HIGH); val1 = 0; delay(300); digitalWrite(s8,LOW);}
 
 
      if (e1 == 1) { digitalWrite(s1,HIGH); } //veilleuse
      if (e1 == 2) { digitalWrite(s1,HIGH); digitalWrite(s9,HIGH); }// code
      if (e1 == 0) { digitalWrite(s1,LOW); digitalWrite(s9,LOW); } // arret veilleuse code 
      if (e2 == 1) { digitalWrite(s2,HIGH); } else { digitalWrite(s2,LOW); } // demarrage arret moteur
      if (e3 == 1) { digitalWrite(s3,HIGH); } else { digitalWrite(s3,LOW); } //phares
      if (e4 == 1) { digitalWrite(s4,HIGH); } else { digitalWrite(s4,LOW); } // longues portees
      if (e5 == 1) { digitalWrite(s5,HIGH); } else { digitalWrite(s5,LOW); } // anti-brouillard
      if (e6 == 1) { digitalWrite(s6,HIGH); } else { digitalWrite(s6,LOW); } // cligno Gauche
      if (e7 == 1) { digitalWrite(s7,HIGH); } else { digitalWrite(s7,LOW); } // cligno droit
 
   }
 //============================ FIN DU PROGRAMME =================================================
 
 

On obtient ainsi le comportement suivant :
  • - Une impulsion sur le bouton 1 => Veilleuses
  • - Deuxième impulsion sur le bouton 1 => les veilleuses restent allumées et les feux de croisements s'allument
  • - Troisième impulsion sur le bouton 1 => arrêt des veilleuses et des feux de croisement
  • - Une impulsion sur le bouton 2 => Son de démarrage moteur
  • - Deuxième impulsion sur le bouton 2 => Son d'arrêt du moteur
  • - Une impulsion sur le bouton 3 => Les phares s'allument
  • - Deuxième impulsion sur le bouton 3 => les phares s'éteignent
  • - Une impulsion sur le bouton 4 => Les longues portées s'allument seulement si les phares sont actifs
  • - Deuxième impulsion sur le bouton 4 => Les longues portées s'éteignent
  • - Une impulsion sur le bouton 5 => Les anti-brouillard s'allument seulement si les feux de croisement sont actifs et si les phares sont éteint
  • - Deuxième impulsion sur le bouton 5 => Les anti-brouillard s'éteignent
  • - Une impulsion sur le bouton 6 => Les clignotant gauche s'allument
  • - Deuxième impulsion sur le bouton 6 => Les clignotant gauche s'éteignent
  • - Une impulsion sur le bouton 7 => Les clignotant droite s'allument
  • - Deuxième impulsion sur le bouton 7 => Les clignotant droite s'éteignent
  • - Une impulsion sur le bouton 8 => coup de klaxon


En modifiant ce code il est possible de faire des tonnes de choses, et ainsi de l'adapter pour les besoins de chacun.


2 Version spécifique USM


Dans mes véhicules, j'utilise maintenant le module USM-RC2 (de la marque BEIER) pour gérer l'éclairage et le son.
J'ai donc créé un module multifonctions qui est spécifiquement adapté à la commande EKMFA de l'USM, et me permet de transmettre 9 commandes sur une seule voie. Je pourrais en transmettre plus (le mode EKMFA peut recevoir jusque 30 commandes) mais je n'en ai pas besoin.

- Principe du mode EKMFA


Ce mode est assez simple et impose certaines limitations, néanmoins il permet de commander presque toutes les fonctions sur une seule voie.
Il compte le nombre d'impulsions envoyées afin d'activer la fonction correspondant.
Mais s'il est facile d'utiliser ce mode avec un simple manche sur la radio, cela devient vite galère quand il faut compter plus de 3 impulsions, sachant qu'il faut aussi retenir a quelle fonction correspond chaque nombre d'impulsions.

- Côté émetteur


Dans un premier temps, il y a un gros travail de câblage a réaliser sur cette version mais ce n'est pas d'une très grande complexité.




Dans un deuxième temps, on va téléverser le sketch suivant sur l'ARDUINO afin que celui si soit en mesure de transmettre les bonnes informations.
Code CPP :
/*================= TDB USM  ========================
   Commande 10 fonctions pour piloter un USM-RC2
======================================================*/
int pinplus = 10;  // position D
int pinmoins = 11;    //position A
#define E1_PIN          2  // gyro
#define E2_PIN          3  // phares
#define E3_PIN          4  //cligno d
#define E4_PIN          5  // cligno g
#define E5_PIN          6  // veilleuses
#define E6_PIN          7  // detresse
#define E7_PIN          8  // klaxon
#define E8_PIN          9  //demarreur
#define E9_PIN          12  //anti brouillard
#define E10_PIN          13  //option
#define NBR_ENTREES    10
uint8_t IdxToPin[NBR_ENTREES] ={ E1_PIN, E2_PIN, E3_PIN, E4_PIN, E5_PIN, E6_PIN, E7_PIN, E8_PIN, E9_PIN, E10_PIN };
int cmd;
 
void setup()
{
  uint8_t Idx;
  for(Idx = 0;Idx < NBR_ENTREES;Idx++)
  {
    pinMode(IdxToPin[Idx], INPUT);
    digitalWrite(IdxToPin[Idx], HIGH); /* Activation des pull-ups internes */
  }
  pinMode(pinplus, OUTPUT); 
  pinMode(pinmoins, OUTPUT);
}
 
void loop()
{
  uint8_t  Idx;
  for(Idx = 0;Idx < NBR_ENTREES;Idx++)
    {
      if(digitalRead(IdxToPin[Idx]))
      {
        cmd = 0;
      } else {
        cmd = Idx+1;
 
switch (cmd) { // on faite un test de la valeur de cet octet
      case 1 : 
     impuls(pinmoins,4);
      break;
      case 2 : 
     impuls(pinplus,2);
      break;
      case 3 : 
     impuls(pinplus,1);
      break;
      case 4 : 
     impuls(pinmoins,1);
      break;
      case 5 : 
     impuls(pinmoins,2);
      break;
      case 6 : 
     impuls(pinmoins,5);
      break;
      case 7 : 
     impuls(pinplus,3);
      break;
    case 8 : // si c'est un b
     impuls(pinmoins,3);
      break;
    case 9 : 
     impuls(pinplus,4);
      break;
     case 10 : 
     impuls(pinplus,5);
      break;
     default:
     cmd=0;
    }
      }   
  }
  delay(20);
}
 
void impuls(int x,int y)
{
  uint8_t  Idx;
  for(Idx = 0;Idx < y;Idx++)
    {
      digitalWrite(x, HIGH);
      delay(50);
      digitalWrite(x, LOW);
      delay(50);
    }
    delay(250);
}

- Côté récepteur


Là, c'est très simple puisque c'est l'USM qui décode lui même les commandes. Il suffit donc de raccorder le récepteur et l'USM, et le tour est joué.
Attention de ne pas avoir oublié de configurer correctement l'USM.
Voici la configuration qui correspond au sketch précedent :