[TUTORIEL] Breakout RFM22. Jouons au PING-PONG!

Le forum de support des breakout de Snootlab

[TUTORIEL] Breakout RFM22. Jouons au PING-PONG!

Message non lude Florian » Ven 12 Déc 2014 17:57

Bonjour,

Aujourd'hui nous allons découvrir le module RFM22.

rfm22-breakout-antenne-patch-433mhz-fr.jpg
rfm22-breakout-antenne-patch-433mhz-fr.jpg (45.9 Kio) Vu 9211 fois


Le RFM22 est un module bidirectionnel, c'est à dire qu'il peut à la fois émettre et recevoir une donnée. Ainsi avec plusieurs de ces modules, on peut les faire interagir et communiquer entre eux.

Datasheet du RFM22 disponible ici.

La librairie utilisée pour faire fonctionner ce produit a été développée par RadioHead, disponible ici.


EXEMPLE D'UTILISATION

Dans ce tutoriel, nous allons réaliser deux programmes. Le premier enverra la data suivante, PING. Le deuxième, à la réception de la précédente data l'affichera sur le moniteur série et enverra à son tour une data qui sera PONG. Cette dernière sera à son tour affiché par le premier programme sur son moniteur série. Ainsi avec le rebouclage des programmes nous aurons un effet PING-PONG!

- MATÉRIEL:


Pourquoi avoir chaque composant en double!?
Simplement car le module RFM22 communique par SPI avec la Uno. Puisque que nous avons besoin de 2 modules pour faire un jeu de PING-PONG, nous avons donc besoin de 2 arduino Uno et donc 2 fois plus de matériel.

- SCHÉMA DU MONTAGE:
Montage complet.png
Montage complet.png (75.22 Kio) Vu 11218 fois


Alimentation du montage:
Le module RFM22 est un module fonctionnant sous une alimentation de 3.3V. Impeccable me direz vous car l'arduino Uno possède une broche capable de délivrer ce niveau de tension. Or nous allons tout de même rencontrer une difficulté ici. Les cartes arduino fonctionnent en logique TTL, en 0-5V. Et nos deux cartes échangent leurs données par communication SPI, les niveaux de tension doivent donc être similaires pour que le protocole fonctionne. Donc le module et la Uno ne pourront pas communiquer puisque l'une est en 3.3 et l'autre en 5.

La seule solution pour faire fonctionner notre montage et d'arriver à mettre l'une des tensions au niveau de l'autre tension. Pour cela, il existe deux méthodes. La première est le "level shifter" (convertisseur de niveaux, ici utilisé en tant que réhausseur de tension), qui consiste à faire passer la tension 3.3V à du 5V. Ceci est réalisable avec l'aide de transistors et de résistances. La deuxième méthode est un pont diviseur de tension, à l'inverse de la technique précédente, il s'agit de partir d'un 5V pour arriver à une tension plus petite, ici du 3.3V. Pour la réaliser, il suffit simplement de disposer de résistances. Nous allons mettre en oeuvre la deuxième procédure.

Il existe également une autre méthode qui permet de ne pas avoir à adapter la tension. Pour cela, il suffit d'utiliser une carte Teensy à la place d'une arduino. En effet la Teensy fonctionne sous une alimentation de 3.3V.

Nous avons besoin de mettre en place des ponts diviseurs de tension pour la broche qui va servir de Clock, celle qui va servir de Chip Select et celle qui va servir de MOSI. Ces dernières sont respectivement les pins 13, 11 et 10 de l'arduino Uno. Il faut donc placer un pont diviseur entre ces dernières et leurs homologues du module RFM22. Ainsi le protocole de communication SPI pourra se dérouler correctement. Le schéma du montage montre comment disposer les résistances pour créer un pont diviseur de tension. Pour passer de 5 à 3.3V, il faut utiliser des résistances de 3.3KOhms et de 1.8KOhms.

Branchements:
    ==> Du module RFM22 au module RFM22:
    - La broche GPIO 0 à la broche TX ANT.
    - La broche GPIO 1 à la broche RX ANT.
ATTENTION: si vous inversez ces branchements la portée de votre antenne sera à peine de quelques centimètres.

    ==> Du module RFM22 à la carte arduino Uno:
    - La broche 3.3V à la broche 3.3V.
    - Le GND au GND.
    - La broche SDO à la broche D12.
    - La broche NIRQ à la broche D2.

    ==> De la carte arduino Uno à la breadboard (pont diviseur):
    - Le GND au GND de chaque pont diviseur (soit à une patte de chaque résistance de valeur 3.3kOhms).
    - La broche D10 à une patte d'une résistance de valeur 1.8kOhms.
    - La broche D11 à une patte d'une résistance de valeur 1.8kOhms.
    - La broche D13 à une patte d'une résistance de valeur 1.8kOhms.

    ==> De la breadboard (pont diviseur) au module RFM22:
    - Du nœud des résistances 1.8 et 3.3kOhms à la broche SDI.
    - Du nœud des résistances 1.8 et 3.3kOhms à la broche SCLK.
    - Du nœud des résistances 1.5 et 3.3kOhms à la broche NIRQ.

Voilà pour les explications de la partie Hardware.

- CODE:
Pour réaliser ce tutoriel, il faut deux sketchs. Le premier qui envoie une donnée en continue et peut afficher une donnée sur le moniteur série dès qu'il en reçoit une. Et le deuxième qui affiche la donnée qu'il reçoit sur le moniteur série puis qui envoie une nouvelle donnée à son tour, seulement et seulement si il en a reçu une avant.

Premier Sketch:
Code: Tout sélectionner
/* Skecth Ping-Pong */

#include <SPI.h>
#include <RH_RF22.h>

RH_RF22 rf22;    // Définition de la commande.

uint8_t data[] = "PING";    // Donnée qui va être émise.

uint8_t buf[RH_RF22_MAX_MESSAGE_LEN];    // Variables qui vont permettre de
uint8_t len = sizeof(buf);               // décrypter les données reçues.

void setup()
{
  Serial.begin(9600);
  Serial.println("Sketch PING.");
 
  if (!rf22.init())    // Vérification que le modem soit correctement initialisé.
  {
    Serial.println("Echec de l'initialisation modem!");
  }
  else
  {
    Serial.println("Succes de l'initialisation modem!");
  }
}

void loop()
{
  rf22.send(data, sizeof(data));    // Envoi de la donnée(PING).
 
  if (rf22.waitAvailableTimeout(500))    // Timeout.
  {   
    if (rf22.recv(buf, &len))    // Réception d'une donnée(PONG).
    {
      Serial.println((char*)buf);    // Affichage de la donnée reçue.
    }
  }
  delay(400);
}

Deuxième Sketch:
Code: Tout sélectionner
/* Skecth Ping-Pong */

#include <SPI.h>
#include <RH_RF22.h>

RH_RF22 rf22;    // Définition de la commande.

uint8_t data[] = "PONG";   // Donnée qui va être émise.

uint8_t buf[RH_RF22_MAX_MESSAGE_LEN];    // Variables qui vont permettre de
uint8_t len = sizeof(buf);               // décrypter les données reçues.

void setup()
{
  Serial.begin(9600);
  Serial.println("Sketch PONG.");

  if (!rf22.init())    // Vérification que le modem soit correctement initialisé.
  {
    Serial.println("Echec de l'initialisation modem!");
  }
  else
  {
    Serial.println("Succes de l'initialisation modem!");
  }
}

void loop()

  if (rf22.recv(buf, &len))    // Réception d'une donnée(PING).
  {
    Serial.println((char*)buf);    // Affichage de la donnée reçue.
   
    rf22.send(data, sizeof(data));    // Envoi de la donnée(PONG).
  } 
}


Une fois les montages correctement réalisés et les deux sketchs dispatchés chacun dans un Arduino Uno, vous devriez obtenir les choses suivantes.

Lorsque vous avez chargé les sketchs. Le premier sketch devrait faire afficher quelque chose de similaire dans le moniteur série :
Sketch Ping.png
Sketch Ping.png (25.78 Kio) Vu 11218 fois

Le deuxième sketch devrait vous fournir quelque chose de semblable à ceci :
Sketch Pong.png
Sketch Pong.png (27.44 Kio) Vu 11218 fois


Et voilà, nous avons transformé nos deux cartes Arduino Uno en vrai pongistes professionnels. Effet PING-PONG. Nous avons réalisé un échange simple de données entre deux modules. Mais il est possible d'ajouter autant de modules que votre projet en nécessite. De plus, vous pouvez transmettre des données issues de capteurs et ainsi faire réagir un mécanisme à l'autre bout de la maison à la réception des données du capteur.

Seule l'imagination peut vous stopper dans vos projets.
Florian
 
Messages: 75
Inscription: Mer 24 Juil 2013 17:36

Re: [TUTORIEL] Breakout RFM22. Envoie d'un donnée

Message non lude xangshu » Mer 13 Mai 2015 14:40

Bonjour,

J'ai vu votre programme et je l'ai testé sur mon module RFM22B et il fonctionne parfaitement, mais maintenant je souhaite récuperer un mesure sur une broche et l'envoyer par transmission mais lorsque je change la donnée, celui-ci ne reçois que du vide. Je suis assez débutant dans ce domaine avec ce module et je souhaiterais savoir comment mon RFM22B récepteur pourrait afficher la valeur que le RFM22B émetteur envoie sachant qu'il récupère sa valeur d'un capteur.

Merci
xangshu
 
Messages: 2
Inscription: Mer 13 Mai 2015 14:34

Re: [TUTORIEL] Breakout RFM22. Envoi d'une donnée

Message non lude Laetitia » Mer 13 Mai 2015 18:15

Bonjour,

Pouvez-vous poster le code complet utilisé ?
"If it's itchy, scratch it !" - "DIY or die"

RTFM (À lire avant de poster) - ANDb (Arduino Noob Database)
Avatar de l’utilisateur
Laetitia
 
Messages: 296
Inscription: Mar 7 Aoû 2012 15:07
Localisation: Toulouse

Re: [TUTORIEL] Breakout RFM22. Envoi d'une donnée

Message non lude xangshu » Jeu 14 Mai 2015 12:23

Bonjour Laetitia,

Voici le code que j'ai utilisé dans mon programme émetteur, il mesure la vitesse de l'anémomètre et je souhaiterais envoyer cette valeur mais en réception je n'obtiens rien (un vide). En réception j'ai gardé la même configuration que celle sur le tutoriel sans renvoi de données :

#include <SPI.h>
#include <RH_RF22.h>

RH_RF22 rf22; // Définition de la commande.
uint8_t buf[RH_RF22_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
int pin = 13;
volatile int state = LOW; // déclartion d'une variable volatile
int capteur = 0;
bool mem = 0; // mémorisation de l'état précédent du capteur
int secondes;
int valeur;
long temps;
float vitesse;


void setup()
{

Serial.begin(19200);
Serial.println("Anemometre");
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, RISING); // attache l'interruption externe n°0 à la fonction blink
secondes = 0; // Comptage à 0
temps = millis(); // Initialisation de l'horloge interne

if (!rf22.init()) // Vérification que le modem soit correctement initialisé.
{
Serial.println("Echec de l'initialisation modem!");
}
else
{
Serial.println("Succes de l'initialisation modem!");
}

}

void loop()
{

uint8_t data[1] = {mesure()}; // Donnée qui va être émise.

rf22.send(data, 1); // Envoi de la donnée.
if (rf22.waitAvailableTimeout(500)) // Timeout.
{
if (rf22.recv(buf, &len)) // Réception d'une donnée.
{
Serial.println((char*)buf); // Affichage de la donnée reçue.
}
}
delay(500);
}


//******************************ANEMEMOMETRE****************************//

float mesure()
{
digitalWrite(pin, state); // la LED reflète l'état de la variable

if (state) // C1 est la broche où arrive le signal capteur
{
if (mem == 0) // si C1 est à 1 et étais précédemment à 0
{
mem = 1; // mémorisation du fait que C1 est passée à 1
capteur += 1; // incrémentation du compteur

}
}
else
{
mem = 0; // RAZ de la mémorisation si C1 est repassé à 0
}

if (horloge() == 0) // Si l'horloge affiche 0
{
vitesse = (2*3.141592654*0.0355*capteur)*3,6;
Serial.print(vitesse); // Il affiche la valeur compté du capteur
Serial.println(" km/h");
}
else if (horloge () == 1) // Si l'horloge passe à 1
{
capteur = 0; // Il remet la valeur du capteur à 0
}
return(vitesse);
}

void blink() // la fonction appelée par l'interruption externe n°0
{
state = !state; // inverse l'état de la variable
}

int horloge() // Compteur de secondes
{
if ((millis() - temps) > 1000) // Si l'intervalle de temps entre l'horloge interne et le temps correspond à 1s
{
secondes += 1; // incrémentation du compteur
temps = millis(); // On enregistre la valeur du temps
if (secondes == 5) // Lorsqu'il compte 5s
{
secondes = 0; // Il recommence le comptage
}
}
return(secondes); // la valeur qu'il renvoie
}
xangshu
 
Messages: 2
Inscription: Mer 13 Mai 2015 14:34

Re: [TUTORIEL] Breakout RFM22. Jouons au PING-PONG!

Message non lude Florian » Mer 22 Juil 2015 13:52

Bonjour,

Si j'ai bien compris vous souhaitez transmettre la vitesse du vent à l'autre module!?

uint8_t data[1] = {mesure()};

En regardant votre code, il me semble que vous ne rentriez pas la bonne variable dans la fonction d'envoi.
Je m'explique, vous associez la fonction "mesure()" à uint8_t data[1]. La data en question qui est transmise par le module RFM22 dans la fonction rf22.send(data,1).
Or comme dit juste avant "mesure()" est une fonction alors que la data envoyée doit être une variable. Votre fonction "mesure()" se charge de calculer la vitesse du vent et stocke ce résultat dans la variable "vitesse". Il s'agit de la variable qui doit être associée à uint8_t data[1].
Soit comme ceci:

Code: Tout sélectionner
uint8_t data[1] = {vitesse};

rf22.send(data, 1);

Côté réception, il faut légèrement modifier le code.
Dans le tuto, la data envoyée était un mot donc composé de caractères. Or lors de l'envoi, les données sont stockées dans un tableau d'octets et à la réception sont décodées et données sous forme ASCII. Puisqu'il s'agissait d'envois de mots il n'y avait aucun problème de traduction avec la table ASCII qui donne le caractère de chaque octet et ainsi on retrouvait les mots Ping et Pong.

Dans votre contexte vous envoyez une valeur décimale. Il faut donc convertir le caractère ASCII décodé lors de la réception en son nombre décimal correspondant dans la table ASCII.
Pour cela vous pouvez utilisez le fonction "sscanf(VariableReçue (par le RF22), "%s", &Variable (stockant le résultat de la conversion en décimal))"
Soit quelque chose comme ceci:

Code: Tout sélectionner
if(rf22.recv(buf, &len))
{
    ValeurASCII = ((char*)buf);
    sscan(ValeurASCII, "%s", &Vitesse);
    Serial.print(Vitesse);
    Serial.println(" Km/h");
}

Pour vous aider à réaliser ceci, vous pouvez regarder comment faire dans le
[TUTORIEL] Breakout RFM22. Envoi Température
Florian
 
Messages: 75
Inscription: Mer 24 Juil 2013 17:36

Re: [TUTORIEL] Breakout RFM22. Jouons au PING-PONG!

Message non lude Maneke » Mer 16 Sep 2015 09:11

Bonjour Florian,

Merci pour ce tuto instructif.

J'aimerais faire des essais avec ce module qui est une sorte d'arduino avec le RFM22 directement soudé dessus. http://api.ning.com/files/T4z81ZAAcwlJl ... /eagle.png

Apparemment le module n'est pas connecté sur les broches spi de l'arduino.
NIRQ -> D2
SEL -> D4
SDK -> A2
SDI -> A1
SDO -> A0

Y a t-il un moyen d'utiliser la bibliothèque RadioHead avec ces connections ?
Maneke
 
Messages: 1
Inscription: Mer 16 Sep 2015 09:03

Re: [TUTORIEL] Breakout RFM22. Jouons au PING-PONG!

Message non lude Laetitia » Mer 21 Oct 2015 09:19

Bonjour,

La librairie RadioHead est préconfigurée pour une utilisation avec le bus SPI hardware (pins 10 à 13 sur un Arduino Uno), mais il est possible d'émuler une liaison SPI software pour utiliser d'autres pins. Pour la configuration, se reporter à la documentation spécifique, paragraphe "SPI Interface".

Petit rappel au passage : la plupart des modules RFM22 étant alimentés en 3.3V, il vous faudra soit utiliser un Arduino type Pro Mini (lui aussi alimenté en 3.3V), soit utiliser un convertisseurs de niveaux pour assurer la bonne communication entre les éléments.

Et juste par curiosité : pourquoi avoir choisi cette carte en particulier ?
"If it's itchy, scratch it !" - "DIY or die"

RTFM (À lire avant de poster) - ANDb (Arduino Noob Database)
Avatar de l’utilisateur
Laetitia
 
Messages: 296
Inscription: Mar 7 Aoû 2012 15:07
Localisation: Toulouse


Retourner vers Breakout de Snootlab

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité

cron