Tuto communication sans fil arduino par ondes radio !

Salut tout le monde aujourd’hui nous allons voir comment mettre en place une communication sans fil entre deux cartes arduinos.

Les codes sources, ainsi que la description des fonctions de la bibliothèque VirtualWire proviennent du blog Skyduino (https://skyduino.wordpress.com/2011/12/29/tutoriel-arduino-et-emetteurrecepteur-433mhz-virtualwire/). À la demande de l'auteur d'origine, il est précisé aux lecteurs de cet article que les codes sources ont été modifiés et certains commentaires et remarques importantes de l'article d'origine ont été retirés. N'hésitez pas non plus à visiter son nouveau site Le carnet du maker.

Avec cette technique vous pourrez entre autre faire avancer votre robot à partir du terminal serial d’arduino donc de votre ordinateur, contrôler l’allumage des led ou même de n’importe quel composant électrique.
Éléments nécessaires :
-ide d’Arduino avec la librairie virtual wire disponible ici : http://www.open.com.au/mikem/arduino/

-un émetteur et un récepteur radio 433-4 mhz. Ceux du tuto sont achetable ici :
https://www.sparkfun.com/products/10532
https://www.sparkfun.com/products/10534

-deux cartes arduino ou compatibles arduino je suppose que si vous lisez ce tutoriel c’est que vous en avez déjà au moins une néanmoins je vous mets le lien pour la carte la plus basique pour ce tuto :
http://store.arduino.cc/index.php?main_page=product_info&cPath=11&products_id=195
(n’oubliez pas de vous procurez le câble nécessaire permettant de connecter votre arduino à votre ordinateur)

-des fils de connections de ce type :
https://www.sparkfun.com/products/9140
Ou bien sur une plaque d’essai et des câbles M/M mais si vous le saviez-vous n’avez pas besoin de lien :p.

Maintenant procédont au montage:
La partie émetteur:

Le câble rouge correspond à l'alimentation, le noir à la masse et le orange au data. Le rouge relis la broche VCC de l'émetteur à la broche 5V de l'arduino, le noir les deux broches GND et le orange relie la broche Data de l'émetteur à la broche 12.

Le câble rouge correspond à l'alimentation, le noir à la masse et le orange au data. Le rouge relis la broche VCC du récepteur à la broche 5V de l'arduino, le noir les deux broches GND et le orange relie la broche Data du récepteur à la broche 11.


Maintenant que nos branchements sont effectués commençons à programmer !
Pour cela ouvrez votre IDE Arduino et vérifier que la librairie VirtualWire est bien importer ! Si c'est le cas elle devrait apparaitre dans Croquis -> importer bibliothèque..., Sinon au même endroit faîtes Add Library.
< Maintenant voyons un peu les fonctions que cette librairies contient avant de commencer à coder:

Fonctions de Configuration:


vw_set_tx_pin(transmit_pin)
Configure la broche de transmission, par défaut c'est la 12.

vw_set_rx_pin(receive_pin)
Configure la broche reception, par défaut c'est la 11.

vw_set_ptt_pin(transmit_en_pin)
Configure la broche permettant l'envoi d'information par exemple si on ne veut pas envoyer l'information à l'infini mais que lorsque un boutton est appuyé nous ne nous y interesserons pas dans ce tuto car notre émetteur n'a pas cette option. La broche par défault est la 10.

vw_set_ptt_inverted(true)
Configure la position de la broche d'envoi false-> HIGH, true-> LOW.

vw_setup(2000)
Initialise la librairie et assigne la vitesse de transmission. Note: plus la vitesse de transmission est lente plus la porté est accentué, au contraire une vitesse de transmission élevée diminuera la porté du signal.

Fonctions de Transmission :


vw_send(message, length)
Cette fonction transmet le message contenu dans le tableau message, ainsi que sa taille ainsi le récepteur peut controler que le message reçu est de la même taille que celui envoyé.

vw_tx_active()
Retourne true si le message est en cours de transmission et false sinon.

vw_wait_tx()
Attends que le message soit completement transmis.

Fonctions de Réception :


vw_rx_start()
Active le proccessus de réception.

vw_have_message()
Retourne vrai si un message à été reçu.

vw_wait_rx()
Attends qu'un message soit reçu avant de redonner la main à la suite du programme.

vw_wait_rx_max(timeout_ms)
Attends qu'un message soit reçu avant de redonner la main à la suite du programme mais donne un temps max a ne pas dépasser.

vw_get_message(buf, &buflen))
Fonction qui permet de tester le dernier message reçu avec la taille envoyer pour voir si le message n'as pas été corrompu pendant l'envoi.

vw_rx_stop()
Arrete le processus de réception.

Maintenant que vous commprenez cette bibliothèque commençons par un programme qui ne fait qu'envoyer un message prédéfini et l'afficher sur l'ordinateur connecté au recepteur:

Partie émetteur :


#include <VirtualWire.h> // On inclus la librairie VirtualWire
#include <VirtualWire_Config.h>
 
const char *msg = "Bonjour"; // Tableau qui contient notre message
                                             
void setup()
{
    Serial.begin(9600); // Initialisation du port série pour avoir un retour sur le serial monitor
    Serial.println("Début communication"); // Petit message pour tester que l'interface sérial se lance bien
                                             
    vw_setup(2000);     // initialisation de la librairie VirtualWire à 2000 bauds
}
                                             
void loop()
{
    Serial.print("Envoie..."); // On signale le début de l'envoi
    vw_send((uint8_t *)msg, strlen(msg)); // On envoie le message 
    vw_wait_tx(); // On attend la fin de l'envoi
    Serial.println("Done !"); // On signal la fin de l'envoi
    delay(1000); // Et on attend 1s pour éviter que deux messages se superpose
}
                                        

Partie récepteur :


#include <VirtualWire.h> // On inclus la librairie VirtualWire
#include <VirtualWire_Config.h>
 
void setup()
{
    Serial.begin(9600); // Initialisation du port série pour avoir un retour sur le serial monitor
    Serial.println("Début communication");
 
    vw_setup(2000); // initialisation de la librairie VirtualWire à 2000 bauds
    vw_rx_start();  // Activation de la partie réception de la librairie VirtualWire
}
 
void loop()
{
    uint8_t msgRecu[VW_MAX_MESSAGE_LEN]; // Tableau qui va contenir le message reçu (de taille maximum VW_MAX_MESSAGE_LEN)
    uint8_t longueurMsg = VW_MAX_MESSAGE_LEN; // Taille maximum de notre tableau
 
    if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent
    {
        if (vw_get_message(msgRecu, &longueurMsg)) // On copie le message, qu'il soit corrompu ou non
        {
            Serial.print("On recoit : ");
            for (byte i = 0; i < longueurMsg; i++) // Si il n'est pas corrompu on l'affiche via Serial
                Serial.print(msgRecu[i]);
            Serial.println("");
        }
    }
}
                                        

Et voila votre premier programme que vous pouvez tester pour vérifier que vos composant marche bien.
Maintenant que cette première étape est passée nous allons voir comment envoyer des messages changeant et adapter l'action effectuer par la carte arduino en fonction du message envoyé.
Pour cela nous allons demander à l'utilisateur de rentrer une lettre et en fonction de la lettre reçu faire clignoter la led plus ou moins vite. La led n'étant bien sur qu'un exemple vous pourrez inclure n'importe quel code et ensuite faire n'importe quel action à distance.
Note: Je ne vais utiliser dans le code qui suis qu'un caractère si jamais vous voulez faire un programme qui envoie un mot entier et non juste un caractère il faudra transformer la variable msg en tableau et faire une boucle pour stocker les différent caractère lu par Serial.Read().

Partie émetteur


#include <VirtualWire.h>
#include <VirtualWire_Config.h>

char *msg;   // for incoming serial data
int msgRentrer;

void setup() {
  Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
  Serial.println("Début communication");
  
  vw_setup(2000);     // initialisation de la librairie VirtualWire à 2000 bauds
 
}

void loop() {
  msgRentrer = 0;
  Serial.println("Rentrer la lettre à envoyer");
  // on attend que l'utilisateur nous envoie un caractère
  while (msgRentrer == 0) 
  {
    if (Serial.available() > 0)//On vérifie qu'un caractère à été envoyé
    {
      // lis le caractère
      *msg = Serial.read();
      msgRentrer = 1;
    }
  }
  Serial.print("Envoie..."); // On signale le début de l'envoi
  vw_send((uint8_t *)msg, strlen(msg)); // On envoie le message 
  vw_wait_tx(); // On attend la fin de l'envoi
  Serial.println("Done !"); // On signal la fin de l'envoi
  delay(1000); // Et on attend 1s pour éviter que deux messages se superpose
}
                                            

Partie récepteur :


#include <VirtualWire.h> // On inclus la librairie VirtualWire
#include <VirtualWire_Config.h>

int led = 13;
 
void setup()
{
    Serial.begin(9600); // Initialisation du port série pour avoir un retour sur le serial monitor
    Serial.println("Début communication");
    
    pinMode(led, OUTPUT);
 
    vw_setup(2000); // initialisation de la librairie VirtualWire à 2000 bauds
    vw_rx_start();  // Activation de la partie réception de la librairie VirtualWire
}
 
void loop()
{
    digitalWrite(led, LOW);
    uint8_t msgRecu[VW_MAX_MESSAGE_LEN]; // Tableau qui va contenir le message reçu (de taille maximum VW_MAX_MESSAGE_LEN)
    uint8_t longueurMsg = VW_MAX_MESSAGE_LEN; // Taille maximum de notre tableau
 
    if (vw_wait_rx_max(200)) // Si un message est reçu dans les 200ms qui viennent
    {
        if (vw_get_message(msgRecu, &longueurMsg)) // On copie le message, qu'il soit corrompu ou non
        {
            Serial.print("On recoit : ");
            for (byte i = 0; i < longueurMsg; i++) // Si il n'est pas corrompu on l'affiche via Serial
                Serial.print(msgRecu[i]);
            Serial.println("");
            if(strcmp("a", (char*)msgRecu) == 0) // Si la lettre envoyer est a alors...
            {
              digitalWrite(led, HIGH);   // allume la led 1s
              delay(1000); 
            }
            else  if(strcmp("b", (char*)msgRecu) == 0) // Sinon si la lettre envoyer est b...
            {
              digitalWrite(led, HIGH);   // allume la led 3s
              delay(3000); 
            }
            else // Sinon...
            {
              digitalWrite(led, HIGH);   // allume la led 0,3s
              delay(300); 
            }
        }
    }
}