Pour réaliser ce test, nous avons utilisé des modules XBee et des cartes Arduino parce que nous les avions sous la main, mais le code peut être utilisé avec toute autre liaison sans-fil (voire même filaire si vous pensez avoir des pertes de connexion).
D’autres solutions existent, notamment par la mesure de la puissance du signal. C’est aussi une donnée intéressante, surtout pour fixer des relais ou valider une solution antiparasites sur un robot mobile.
Matériel
– une carte Arduino Romeo V2 (pour son support intégré) dispo chez Zartronic
– un module à écran LCD keypad shield de DFRobot dispo chez Zartronic
– deux modules XBee série 1 (802.15.4) dispos chez MATLOG
– un support USB/XBee ou simple adaptateur dispo chez MATLOG
– câbles USB ou batteries pour pouvoir bouger
Il s’agit bien sûr de matériel de test réutilisable. Une solution moins onéreuse peut se faire si vous dédiez ces composants à un usage unique.
Assemblage
Plutôt que d’utiliser deux micro-contrôleurs, un de chaque côté, nous avons soudé un câble (on appelle ça un "shunt") entre la patte DO et DI (data out / data in) d’un des deux modules - ou plutôt sur le support - ce qui revient au même que de relier RX et TX (si vous utilisez une liaison série filaire). Ainsi, toute donnée envoyée par le module est aussitôt renvoyée, sans traitement. Comme ce n’est pas un test de débit mais un test de perte de signal, ce n’est pas impactant sur le résultat, et cela limite les erreurs.
Code source
L’archive est disponible en téléchargement :
#include <LiquidCrystal.h>
// déclaration de l'écran LCD connecté à l'Arduino
LiquidCrystal lcd(8,9,4,5,6,7);
// nombre de messages envoyés et reçus
long msg_envoi = 0;
long msg_recu = 0;
// nombre de ms à l'instant du dernier envoi et de la dernière réception (pour mesurer l'écart)
long last_sent = 0;
long last_seen = 0;
// caractère envoyé (s = sent) et reçu (r = receive)
int s = 0;
int r = 0;
// temps écoulé pour la dernière coupure
long last_err = 0;
// temps maximum écoulé pour une coupure
long max_err = 0;
// temps moyen d'une coupure
long moyenne = 0;
// nombre de coupures connues depuis le début
long count = 0;
boolean coupure = false;
void setup()
{
// deux liaisons séries : celle de l'USB et celle du XBee
Serial.begin(9600);
Serial1.begin(9600);
// initialisation de l'écran I2C
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("Test XBee");
delay(1000);
lcd.clear();
}
void loop()
{
Serial1.write(s);
delay(10);
lcd.setCursor(15,0);
lcd.write(s);
s++;
msg_envoi++;
last_sent = millis();
while (Serial1.available() > 0) {
// nouvelle réception
r = Serial1.read();
last_seen = millis();
lcd.setCursor(15,1);
lcd.write(r);
msg_recu++;
}
if (millis() < 3000) {
// on ne prend pas en compte les 3 premières secondes
}
else {
// vérifier si on est en connexion ou en coupure
if (last_sent-last_seen > 1)
{
if (!coupure) {
count++;
coupure = true;
}
last_err = last_sent-last_seen;
max_err = max(last_err,max_err);
}
else {
if (coupure) {
// fin de la coupure
coupure = false;
moyenne = (moyenne*(count-1)+last_err)/count;
}
}
}
// affichage des secondes
lcd.setCursor(0,1);
lcd.print(millis()/1000);
lcd.print("s ");
// affichage du nombre d'erreurs depuis le début
lcd.print(count);
lcd.print(" erreurs");
// affichage des stats
lcd.setCursor(0,0);
lcd.print(100*msg_recu/msg_envoi);
lcd.print("% ");
// alterner les affichages
switch ((millis()/1000)%3) {
case 0:
if (max_err > 5000) {
lcd.print(max_err/1000);
lcd.print("s max ");
}
else {
lcd.print(max_err);
lcd.print("ms max");
}
break;
case 1:
if (moyenne > 5000) {
lcd.print(moyenne/1000);
lcd.print("s moy ");
}
else {
lcd.print(moyenne);
lcd.print("ms moy");
}
break;
case 2:
if (last_err > 5000) {
lcd.print(last_err/1000);
lcd.print("s der ");
}
else {
lcd.print(last_err);
lcd.print("ms der");
}
break;
}
if (coupure) {
lcd.print("!");
}
else {
lcd.print(" ");
}
}
A noter l’usage de la liaison série "Serial1" spécifique aux cartes Leonardo qui ont un port série sur l’USB et un port série disponible (ici connecté au XBee par la carte toute intégrée Romeo V2).
Résultats
Avec un émetteur et un récepteur séparés par 60 centimètres et un peu d’activité (ordinateurs, passage), voilà ce qu’on obtient sur un test de 180 secondes (3 minutes) :
– 95% d’octets bien reçus
– 31 erreurs
– une moyenne de 248 ms de durée d’interruption
– une interruption la plus longue de 6 secondes
Un autre test de même durée avec les modules sans-fil côte à côte n’a montré qu’une seule erreur de 22 ms, et toujours que 4 erreurs de même moyenne au bout de 812 secondes (le temps d’écrire cet article !)