Communication entre deux nœuds DW1001 avec le code Ranger
I. Introduction
Ce TP se focalise sur la communication entre deux nœuds DW1001 grâce à la bibliothèque Ranger.
Objectifs du TP
Le but de ce TP est de vous familiariser avec l’utilisation de la bibliothèque Ranger pour rĂ©aliser des communications Ă courte portĂ©e en utilisant la technologie UWB (Ultra-Wideband). Vous serez amenĂ© Ă utiliser les modules DecaDuino pour Ă©tablir des communications entre diffĂ©rents nĹ“uds et mesurer les distances entre eux.
Matériel Utilisé
- Un ordinateur avec une connexion internet
- Des nœuds DWM1001 disponibles sur la plateforme LOCURA4IoT
II. Présentation du Matériel et des Bibliothèques
Les Cartes DW1001
Les cartes DW1001 sont des cartes sans fil basées sur la technologie UWB (Ultra Wideband), qui permet de mesurer avec précision les distances entre les différents nœuds.

La Technologie UWB (Ultra-Wideband)
a. Concepts de base de l’UWB
Dans cette section, nous explorerons les concepts fondamentaux de la technologie UWB, qui joue un rôle clé dans les communications sans fil et la localisation précise.
- Principes de fonctionnement : L’UWB utilise des impulsions brèves et Ă©nergĂ©tiques pour transmettre des donnĂ©es sur une large gamme de frĂ©quences.
- Avantages en communication : L’UWB offre une haute rĂ©solution en distance, une faible consommation d’Ă©nergie et une immunitĂ© aux interfĂ©rences.
b. Protocoles UWB
Dans cette partie, nous aborderons les protocoles UWB qui déterminent comment les nœuds communiquent et mesurent les distances. Notre focus sera sur le protocole Two-Way Ranging (TWR).
- Présentation du Two-Way Ranging (TWR) : Le TWR permet des mesures précises de distance en utilisant des échanges bidirectionnels et des mesures de temps de vol.
- Utilisation du TWR avec les nœuds DW1001 : Les nœuds DWM1001 exploitent la puissance du TWR pour la localisation précise et la communication fiable à courte portée.
Bibliothèque Ranger
La bibliothèque Ranger est une bibliothèque logicielle spécialement conçue pour simplifier la communication UWB en utilisant les modules DecaDuino. Elle est conçue pour configurer les modules, établir des communications et effectuer des mesures de distances.
III. Configuration de l’Environnement de DĂ©veloppement
PrĂ©paration de l’Environnement Arduino IDE
Pour commencer, nous devons configurer l’environnement de dĂ©veloppement Arduino IDE pour travailler avec les nĹ“uds DW1001. Suivez ces Ă©tapes :
- TĂ©lĂ©charger et installer l’IDE Arduino sur votre ordinateur, si ce n’est pas dĂ©jĂ fait. L’IDE Arduino est disponible gratuitement sur le site officiel d’Arduino.
Installez la chaîne de compilation en suivant les instructions sur cette page.
Installation des Bibliothèques Requises
Pour pouvoir flacher le code Ranger sur les nœuds DW1001, nous devons installer les bibliothèques nécessaires. Suivez ces étapes :
- Téléchargez le fichier ranger_dependencies.zip.
- Extrayez son contenu dans le dossiez “libraries” de votre installation Arduino
- Astuce : vous trouverez le chemin oĂą se situe de ce dossier dans l’IDE Arduino : PrĂ©fĂ©rences > Emplacement du carnet de croquis
- Note : il faut que les dossiers suivants se retrouvent directement dans le dossier “libraries”
- base64
- DecaDuino
- Ranger
- DWM100x_id/
- printfserial
Ces bibliothèques fournissent les fonctionnalités nécessaires pour la communication UWB avec les nœuds DW1001.
Configuration de la Carte DW1001
Maintenant que les bibliothèques sont installées, nous devons configurer Arduino IDE pour reconnaître la carte DW1001. Suivez ces étapes :
- Allez dans le menu “Outils” (Tools).
- SĂ©lectionnez “Type de carte” (Board) et choisissez “DecaWave DWM1001 Module Development Board”.
IV. Téléversement du Code sur les Nœuds DW1001
Maintenant que l’environnement de dĂ©veloppement est configurĂ©, vous pouvez tĂ©lĂ©verser le code Ranger sur les nĹ“uds DW1001. Voici comment procĂ©der :
- Ouvrez le fichier > Exemples > ranger > minimalRangerExample dans Arduino IDE.
Cliquez pour afficher le code complet
// minimalRangerExample
// This sketch shows the bare minimum required to use the Ranger library to perform distance measurements using
// the TWR ranging protocol over the UWB radio on a DWM1001-DEV board.
// by Cassandre Vey <cassandre.vey@irit.fr>
// This sketch is a part of the Ranger Project - please refer to the Ranger LICENCE file for licensing details
// Use the following parameters to set ranging cycle (period), client address and server address.
#define CLIENT_RANGING_PERIOD 1000 //ms. Client performs a ranging cycle every x ms
#define CLIENT_ADDRESS 0x8C30 // client/mobile/initiator address
#define SERVER_ADDRESS 0xA55E // server/anchor/target address
#include <DecaDuino.h>
#include <Ranger.h>
#include <DWM100x_id.h>
#include <printfToSerial.h>
DecaDuino decaduino(SS1, DW_IRQ);
uint8_t txData[1024];
uint8_t rxData[1024];
uint8_t sqn = 0;
uint16_t rxLen;
uint16_t nodeAddress = 0;
uint32_t prevSoftwareInterrupt = 0;
uint32_t rangingPeriod;
Ranger ranger;
Ranger::RangingRequestStatus_e rangingStatus;
Ranger::ranging_t ranging;
Ranger::message_t txMsg, rxMsg;
// Performs the actual message sending
void prepareAndSendMessage(Ranger::message_t *txmsg) {
int i, l = 0;
// create a simple L2 header :
// sender address,
// destination address,
// sequence number,
// protocol
decaduino.plmeRxDisableRequest();
decaduino.encodeUint16(nodeAddress, &txData[l]);
l += 2;
decaduino.encodeUint16(txMsg.destination, &txData[l]);
l += 2;
txData[l++] = ++sqn;
txData[l++] = txMsg.protocol;
// adds the ranging payload
for ( i = 0 ; i < txMsg.payloadLen ; i++ ) {
txData[l + i] = txMsg.payload[i];
}
// actual sending
decaduino.pdDataRequest(txData, l + i);
// wait until the transmission is successful
while ( !decaduino.hasTxSucceeded() ) {
decaduino.engine();
};
// record transmission timestamp
txMsg.tsTx = decaduino.getLastTxTimestamp();
}
// This function is the glue-code between Decaduino and Ranger.
// It translates the requests from ranger in actions by Decaduino and notifies the
// ranger state machine when appropriate
void processHal()
{
// Is there a message to send?
if ( ranger.getTxBufferStatus() ) {
// A new message has to be sent.
// Warning : RX is not re-enabled after message is sent.
prepareAndSendMessage( &txMsg);
// notify ranger that the transmission is done
ranger.setTxBufferStatus(Ranger::TX_STATUS_DONE);
}
// Enable RX?
if ( ranger.getRxRequestStatus() ) {
rxMsg.trxTemperatureBegin = decaduino.getTemperature();
decaduino.plmeRxEnableRequest();
// clears the RX enable request
ranger.rxEnableRequest(false);
}
// Has a message been received?
if ( decaduino.rxFrameAvailable() ) {
// A new message has been received: analyse-it
// simple L2 header decoding
uint16_t sourceAddress = decaduino.decodeUint16( &rxData[0]);
uint16_t destinationAddress = decaduino.decodeUint16( &rxData[2]);
uint8_t sqn = rxData[4];
uint8_t msgType = rxData[5];
// destination address filtering
if ( (destinationAddress == nodeAddress) || (destinationAddress == 0xffff) ) {
// record the metadata of the packet
rxMsg.source = sourceAddress;
rxMsg.destination = destinationAddress;
rxMsg.tsRx = decaduino.getLastRxTimestamp();
rxMsg.skew = decaduino.getLastRxSkew();
rxMsg.protocol = (Ranger::protocols_e)msgType;
// record the ranging payload
for ( int i = 0 ; i < rxLen ; i++ ) {
rxMsg.payload[i] = rxData[6 + i];
}
// if protocol is TWR, notify ranger
if ( rxMsg.protocol == Ranger::PROTOCOL_TWR ) {
ranger.newRxMessage();
}
// otherwise re-enable reception
else {
decaduino.plmeRxEnableRequest();
}
}
else {
// This message is not for this node. Re-enable RX
decaduino.plmeRxEnableRequest();
}
}
}
void setup() {
Serial.begin(115200);
delay(500);
nodeAddress = getIotlabID();
printf("My nodeAddress is %x\n", nodeAddress);
// check configuration
while ( (nodeAddress != CLIENT_ADDRESS && nodeAddress != SERVER_ADDRESS) || !CLIENT_ADDRESS || !SERVER_ADDRESS ) {
printf("My nodeAddress is %x and is neither client nor server, or these are not properly defined (must be non-zero)\n", nodeAddress);
delay(1000);
}
while ( !decaduino.init() ) {
Serial.println("DecaDuino init failed... retry...");
delay(100);
}
while ( !ranger.init() ) {
Serial.println("Ranger init failed... retry...");
delay(100);
}
// Configure DecaDuino
decaduino.setRxBuffer(rxData, &rxLen);
// Configure Ranger
ranger.setTxBuffer( &txMsg);
ranger.setRxBuffer( &rxMsg);
ranger.setNodeAddress(nodeAddress);
ranger.enableTwrServer(true);
// Various
if ( (nodeAddress == CLIENT_ADDRESS) ) {
rangingPeriod = CLIENT_RANGING_PERIOD;
}
prevSoftwareInterrupt = millis();
}
void loop() {
// Process incoming/outgoing messages
processHal();
// Call the Decaduino Engine (must be called regularly)
decaduino.engine();
// Call the Ranger Engine (must be called regularly)
ranger.engine();
// Periodic action
if ( rangingPeriod && (millis() - prevSoftwareInterrupt) > rangingPeriod ) {
prevSoftwareInterrupt = millis();
ranger.rangingRequest(SERVER_ADDRESS, Ranger::PROTOCOL_TWR, RANGING_UNIT, &ranging);
}
// Handle result at the end of the ranging
if ( ranger.rangingIndication( &rangingStatus) ) {
switch ( rangingStatus ) {
case Ranger::RANGING_STATUS_ERROR :
printf("Error while ranging with %d\n", ranging.other);
break;
case Ranger::RANGING_STATUS_DONE :
printf("Result for this ranging with %04x:\n", ranging.other);
ranger.printRangingMinimumAsJson( &ranging);
printf("\r\n");
Serial.flush();
break;
default :
break;
}
}
}
Ce code est conçu pour utiliser la bibliothèque Ranger et permettre la communication entre nœuds DW1001 en utilisant le protocole Two-Way Ranging (TWR) sur la radio UWB.
Voici un résumé des points clés de ce code :
-
Le code est conçu pour être exécuté sur un nœud DW1001 configuré en tant que serveur TWR (
ranger.enableTwrServer(true);
). -
Il est destinĂ© Ă ĂŞtre utilisĂ© avec un client dont l’adresse est dĂ©finie par
CLIENT_ADDRESS
. -
L’ancre (serveur) est dĂ©finie par
SERVER_ADDRESS
.
Assurez-vous que toutes les configurations spĂ©cifiques Ă votre environnement telle que l’adresse du client, les adresses des nĹ“uds, les dĂ©lais, etc.
#define CLIENT_ADDRESS 0x0D81 // adresse du noeud dwm1001-1.toulouse.iot-lab.info (mobile/client)
#define SERVER_ADDRESS // adresse du noeud dwm1001-2.toulouse.iot-lab.info (ancre/serveur)
Flasher le code sur la carte DWM1001
- Connectez vous sur IoT-Lab Fit.
- Créer une nouvelle expérience sur IoT-Lab Fit et sélectionner les nœuds sur lesquels vous souhaitez flasher le code.
Remarque : Vous pouvez choisir les nœuds en fonction de leur emplacement, de leur disponibilité et des besoins de votre projet.
-
SĂ©lectionnez l’icĂ´ne de tĂ©lĂ©versement et spĂ©cifiez le chemin d’accès vers le fichier elf gĂ©nĂ©rĂ© lors de la compilation du code Blink avec l’IDE Arduino, Ă partir de l’emplacement suivant : \Users\username\AppData\Local\Temp\arduino_build\ . Vous devrez modifier le nom du fichier en supprimant “.ino” pour qu’il soit acceptĂ©.
-
Les nœuds DW1001 devraient maintenant exécuter le code.
-
Une fois que vous avez rĂ©ussi Ă tĂ©lĂ©verser et Ă exĂ©cuter le code sur la plateforme Fit Lab et Ă observer la communication entre les nĹ“uds DW1001, On peut visualiser ces messages il suffit de vous connecter sur le serveur toulouse.iot-lab.info avec votre nom d’utilisateur et votre mot de passe, en entrant la commande suivante
iotlab-auth -u username
. Ensuite, vous pouvez taper la commandeserial_aggregator
pour afficher les messages.

Le résultat affiché dans le Serial Aggregator représente les données de communication entre les nœuds DW1001 lors de l'exécution du code Ranger. Voici une explication des informations fournies dans ces données :
-
Les lignes, comme dwm1001-5;My nodeAddress is 52332, indiquent le nĹ“ud Ă©metteur et son adresse. Par exemple, “dwm1001-5” est le nĹ“ud Ă©metteur avec l’adresse “52332”, et “dwm1001-6” est le nĹ“ud destinataire avec l’adresse “3457”.
-
Les données suivantes sont au format JSON et contiennent des informations sur la communication entre les nœuds. Ces informations sont divisées en plusieurs catégories :
“initiator” et “target” indiquent respectivement le nĹ“ud Ă©metteur et le nĹ“ud destinataire. -
“protocol” spĂ©cifie le protocole utilisĂ©, ici “TWR” pour Two-Way Ranging.
-
Les valeurs comme “t1”, “t2”, “t3” et “t4” reprĂ©sentent les temps de vol mesurĂ©s entre les nĹ“uds.
-
“skew”, “skewRequest”, “skewAck” et “skewData” sont des valeurs de synchronisation entre les nĹ“uds.
-
“nlosIndicator” donne un indicateur sur la visibilitĂ© directe entre les nĹ“uds.
-
“tof” reprĂ©sente le temps de vol total.
-
“range” est la distance mesurĂ©e entre les nĹ“uds.
-
“rssiRequest”, “rssiData” et “rssiAck” sont les niveaux de puissance du signal dans diffĂ©rentes phases de la communication.
-
Les autres valeurs telles que “fp_powerRequest”, “fp_powerAck”, “fp_powerData”, “pa_powerRequest”, “pa_powerAck”, “pa_powerData”, “voltage”, “temperature”, et “distantTemperature” sont des donnĂ©es supplĂ©mentaires liĂ©es Ă la communication.
Ces informations permettent de suivre la communication entre les nĹ“uds DW1001, de mesurer les distances et d’Ă©valuer la qualitĂ© de la communication en termes de synchronisation, de force de signal, etc.