P15 Réseau de capteurs temps réel : Différence entre versions

De Wiki de Projets IMA
(Test sur la communication réseau)
(Livrables)
 
(158 révisions intermédiaires par le même utilisateur non affichées)
Ligne 4 : Ligne 4 :
 
==Cahier des charges==
 
==Cahier des charges==
  
====Présentation générale du projet====
+
====Contexte====
Le projet réseau de capteurs temps réel consiste à développer et évaluer la possibilité de contrôler en temps réel un moteur par liaison sans fil.  
+
L'industrie 4.0 propose d'organiser les moyens de production de façon agile et autonome.
 +
Pour cela, on peut envisager de créer des ilots de travail interconnectés. Chaque ilot
 +
pourrait être déplacé pour optimiser soit l'utilisation des ressources soit la production.
 +
Dans le cas d'ilots identiques, pour faciliter la mise à jour des systèmes et le contrôle des
 +
machines, il peut être intéressant de faire la régulation sur un système "serveur". Les
 +
ilots deviennent alors les clients et envoient leurs données au serveur qui renvoie par la
 +
suite la commande.
  
====Contexte====
+
====Description du projet====
L'industrie 4.0 propose d'organiser les moyens de production de façon agile et autonome. Pour cela, on peut envisager de créer des ilots de travail interconnectés. Chaque ilot pourrait être déplacé pour optimiser soit l'utilisation des ressources soit la production.
+
Ce projet consiste à évaluer la possibilité de contrôler en temps réel un robot par liaison
Dans le cas d'ilots identiques, pour faciliter la mise à jour des systèmes et le contrôle des machines, il peut être intéressant de faire la régulation sur un système "serveur". Les ilots deviennent alors les clients et envoient leurs données au serveur qui renvoie par la suite la commande.  
+
sans fil. Cela sera possible avec la mise en place d'un réseau sans fil de capteurs temps
 +
réel, afin d'échanger des informations entre les nœuds. Ce réseau va devoir être capable
 +
d'effectuer le chemin le plus court vers la cible dans le but de diminuer le temps de
 +
propagation de l'information, comme montre la figure ci-après:   
 +
[[Fichier:iot1.png|800px|thumb|center|Architecture matérielle]]
  
 
====Objectif du projet====
 
====Objectif du projet====
L'objectif du projet consiste à mettre en place un réseau radio multi-saut classique (temps réel). Pour cela il va falloir:
+
L'objectif est donc la mise en place d'un réseau avec des cartes stm32 équipées d'un
 
+
module radio at86rf231, plus précisément:
- Développer un réseau non temps réel basé sur des cartes STM32 et des radios à 868 MHz, embarquant un système d'exploitation Riot OS,
 
 
 
- Évaluer les temps de propagation de l'information en fonction de l'environnement (perturbations, distance, ...),
 
 
 
- Modifier la partie MAC de Riot OS pour garantir les temps de latence.
 
 
 
====Description du projet====
 
Ce projet consiste à la mise en place d'un réseau sans fil de capteurs temps réel, afin de pouvoir envoyer/recevoir des commandes/informations d'un serveur vers la cible (un robot dans ce cas). Le réseau qu'on va mettre en place va devoir être capable d’effectuer le chemin le plus court vers le nœud cible dans le but de diminuer le temps de propagation de l'information. Comme montre la figure ci-après:   
 
[[Fichier:iot.png|800px|thumb|center|Architecture matérielle]]
 
  
====Liste des tâches à effectuer====
 
 
#Faire des recherches bibliographiques: temps réel, MAC, RIOT OS...
 
#Faire des recherches bibliographiques: temps réel, MAC, RIOT OS...
 
#Prise en main de RIOT OS et de la carte STM32F4
 
#Prise en main de RIOT OS et de la carte STM32F4
Ligne 51 : Ligne 51 :
 
Il faudra aussi installer les outils nécessaires à la compilation et au débogage de la famille de microcontrôleurs ARM:
 
Il faudra aussi installer les outils nécessaires à la compilation et au débogage de la famille de microcontrôleurs ARM:
 
   
 
   
  apt-get install build-essential g++-multilib gtkterm openocd
+
  sudo apt-get install build-essential g++-multilib gtkterm openocd
  
 
Le paquetage g++-multilib est uniquement nécessaire si le système hôte est 64bits.
 
Le paquetage g++-multilib est uniquement nécessaire si le système hôte est 64bits.
Ligne 57 : Ligne 57 :
 
Installation des compilateurs et ses outils associés:
 
Installation des compilateurs et ses outils associés:
  
  apt install gcc-arm-none-eabi gdb-arm-none-eabi binutils-arm-linux-gnueabi
+
  sudo apt-get install gcc-arm-none-eabi gdb-arm-none-eabi binutils-arm-linux-gnueabi
  
 
====Prise en main de RIOT OS et STM32F4discovery====
 
====Prise en main de RIOT OS et STM32F4discovery====
Ligne 65 : Ligne 65 :
 
Pour prendre à main RIOT et la carte STM32, On a commencé par réaliser une application basé sur l'exemple "hello_world" de RIOT: cette simple application "gpio_to_serial" est capable d'allumer/éteindre une led dès qu'une interruptions est générée lors qu'on appuie sur le bouton "user" et affiche l'état de la led au terminal:
 
Pour prendre à main RIOT et la carte STM32, On a commencé par réaliser une application basé sur l'exemple "hello_world" de RIOT: cette simple application "gpio_to_serial" est capable d'allumer/éteindre une led dès qu'une interruptions est générée lors qu'on appuie sur le bouton "user" et affiche l'état de la led au terminal:
 
   
 
   
2017-10-22 19:02:26,692 - INFO # GPIO Callback
+
  # GPIO Callback
2017-10-22 19:02:26,693 - INFO # Message received, LED is ON
+
  # Message received, LED is ON
2017-10-22 19:02:34,944 - INFO # GPIO Callback
+
  # GPIO Callback
2017-10-22 19:02:34,945 - INFO # Message received, LED is OFF
+
  # Message received, LED is OFF
2017-10-22 19:02:35,040 - INFO # GPIO Callback
+
  # GPIO Callback  
2017-10-22 19:02:35,041 - INFO # Message received, LED is ON
+
  # Message received, LED is ON
2017-10-22 19:02:38,184 - INFO # GPIO Callback
+
  # GPIO Callback
2017-10-22 19:02:38,186 - INFO # Message received, LED is OFF
+
  # Message received, LED is OFF
2017-10-22 19:02:38,280 - INFO # GPIO Callback
+
  # GPIO Callback
2017-10-22 19:02:38,281 - INFO # Message received, LED is ON
+
  # Message received, LED is ON
2017-10-22 19:02:40,578 - INFO # GPIO Callback
+
  # GPIO Callback
2017-10-22 19:02:40,580 - INFO # Message received, LED is OFF
+
  # Message received, LED is OFF
  
 
Cette application m'a permit de comprendre comment fonctionne le système riot et de passer à la mise en place d'un premier réseau.
 
Cette application m'a permit de comprendre comment fonctionne le système riot et de passer à la mise en place d'un premier réseau.
  
====Mise en place d'un réseau statique====
+
====Mise en place d'un réseau statique entre 3 nœuds====
  
Maintenant On vais réaliser la mise en place d'un réseau multi-point avec 3 nœuds (2 sauts); Pour que cela soit possible chaque carte ayant un module radio doit avoir son adresse ipv6 global qui va permettre d'échanger des paquets entre elles. On a défini une adresse global du type '''baad:a555::Hwaddr'''.
+
Maintenant on vais réaliser la mise en place d'un réseau multi-point avec 3 nœuds (2 sauts); Pour que cela soit possible chaque carte ayant un module radio doit avoir son adresse ipv6 global qui va permettre d'échanger des paquets entre elles. On a défini une adresse global du type '''baad:a555::Hwaddr'''.
  
 
Le réseau statique à 3 nœuds se comporte comme un réseau linéaire avec un nœud central se chargeant uniquement de router les paquets vers la destination:
 
Le réseau statique à 3 nœuds se comporte comme un réseau linéaire avec un nœud central se chargeant uniquement de router les paquets vers la destination:
Ligne 99 : Ligne 99 :
 
Le node1/client, enverra des paquets avec des ordres de commande vers le node3/serveur (qui correspond au robot avec des moteurs). Ces informations vont tout d'abord passer par le node2 qui est responsable au routage de ces paquets vers le node2. Le node2 va aussi pouvoir retourner des informations vers le node1, par exemple la vitesse de rotation des roues.
 
Le node1/client, enverra des paquets avec des ordres de commande vers le node3/serveur (qui correspond au robot avec des moteurs). Ces informations vont tout d'abord passer par le node2 qui est responsable au routage de ces paquets vers le node2. Le node2 va aussi pouvoir retourner des informations vers le node1, par exemple la vitesse de rotation des roues.
  
====Test sur la communication réseau====
+
====Test, communication réseau====
  
 
Une fois le réseau mis en place, on a fait des tests afin de voir si les cartes arrivaient à communiquer entre-elles. Les résultats ont étés satisfaisants comme le montre les figures ci-dessous:
 
Une fois le réseau mis en place, on a fait des tests afin de voir si les cartes arrivaient à communiquer entre-elles. Les résultats ont étés satisfaisants comme le montre les figures ci-dessous:
  
[[Fichier:Ping term1 1.png| ping node1 vers node3]]
+
[[Fichier:Ping term1 1.png|thumb|center|700px|ping node1 vers node3]]
 +
 
 +
 
 +
[[Fichier:Ping term2 1.png|thumb|center|700px|ping node3 vers node1]]
 +
 
 +
Après on a éteint node2 et on a essayé de faire un ping à nouveau afin de tester si les paquets ne passaient pas directement du node1 vers node3, sans passer par le deuxième. D'après l'image on voit bien qu'il maintenant impossible de faire un ping:
 +
 
 +
 
 +
[[Fichier:Ping_fail.png|thumb|center|700px|ping node1 vers node3]]
 +
 
 +
=====Server/Client UDP=====
 +
 
 +
Tout d'abord on a démarré un serveur upd au node3:
 +
 
 +
> udp server start 12345
 +
  #  udp server start 12345
 +
  # Success: started UDP server on port 12345
 +
 
 +
Ensuite on a envoyé un message ("test") UDP du node1 vers le node3:
 +
 
 +
  udp send baad:a555::1736 12345 test
 +
  #  udp send baad:a555::1736 12345 test
 +
  # Success: sent 4 byte(s) to [baad:a555::1736]:12345
 +
 
 +
Le message a été bien reçu par le node3, cela montre que le réseau  a été bien mis en place:
 +
 
 +
#  PKTDUMP: data received:
 +
# ~~ SNIP  0 - size:  4 byte, type: NETTYPE_UNDEF (0)
 +
# 00000000  74  65  73  74
 +
# ~~ SNIP  1 - size:  8 byte, type: NETTYPE_UDP (4)
 +
#    src-port: 12345  dst-port: 12345
 +
#    length: 12  cksum: 0xc94b
 +
# ~~ SNIP  2 - size:  40 byte, type: NETTYPE_IPV6 (2)
 +
# traffic class: 0x00 (ECN: 0x0, DSCP: 0x00)
 +
# flow label: 0x00000
 +
# length: 12  next header: 17  hop limit: 63
 +
# source address: baad:a555::1702
 +
# destination address: baad:a555::1736
 +
# ~~ SNIP  3 - size:  24 byte, type: NETTYPE_NETIF (-1)
 +
# if_pid: 7  rssi: 21  lqi: 255
 +
# flags: 0x0
 +
# src_l2addr: 10:10:64:32:14:0f:17:32
 +
# dst_l2addr: 10:10:64:2d:14:39:17:36
 +
# ~~ PKT    -  4 snips, total size:  76 byte
 +
 
 +
====Routage dynamique avec le protocole RPL====
 +
 
 +
Les progrès technologiques permettent maintenant d’envisager la connexion des objets du quotidien à l’Internet. Des solutions ouvertes et interopérables doivent cependant être utilisées pour garantir une communication optimum entre ces objets. Le protocole de routage est un élément clé de cet objectif, car il permet pour chaque objet de décider comment joindre un autre objet. Les contraintes s’appliquant aux objets (faible puissance, communications instables) doivent être prises en compte pour le développement de protocole de routages adaptés.
 +
 
 +
=====Brève introduction du protocole RPL =====
 +
 
 +
Les périphériques réseau exécutant le protocole RPL sont connectés de manière acyclique. Ainsi, un graphe acyclique DODAG (Destination-Oriented Directed
 +
Acyclic Graph) est crée comme montre la figure ci-après:
 +
[[Fichier:Rpl dodag.png | center |500px | thumb | DODAG RPL]]
 +
 
 +
Chaque nœud choisit le meilleur chemin pour arriver jusqu'au nœud racine, chaque nœud utilise un objectif function (OF) afin de trouver le mieux chemin pour arriver au nœud racine, cette fonction définie le metric de routage qui va être appliqué.
 +
 
 +
Le processus de routage commence avec la création d'un DAG, le nœud racine envoie son DODAG à tout les noeuds accessible. A chaque niveau de l'arbre de routage les nœuds font le routage en se basant sur l'OF. Une fois qu'un noeud joint le DODAG, il choisit une racine comme son parent et calcule son rank, ce rank correspond au metric qui indique les coordonnées du nœud dans la hiérarchie du réseau. Les autres nœuds vont répéter ce processus de sélection des parents et de notification des informations DODAG pour de nouveaux appareils possibles. Lorsque ce processus se stabilise, le routage des données peut alors commencer. Le processus crée des routes ascendantes (des nœuds à une racine). Pour construire les routes descendantes, le protocole RPL envoie des messages ICMPv6 telles que:
 +
 
 +
#'''DAG Information Object (DIO)''' - transmet des informations qui permettent à un nœud de découvrir une instance RPL, d'apprendre ses paramètres de configuration et de choisir des parents dans le DODAG
 +
#'''DAG Information Solicitation (DIS)''' - sollicite un DIO à partir d'un nœud RPL
 +
#'''Destination Advertisement Object (DAO)''' - utilisé pour propager les informations de destination vers le haut le long du DODAG.
 +
 
 +
=====Application dans RIOT OS=====
 +
 
 +
Le protocole RPL est présent dans RIOT OS. On s'est basé sur le travail de nos collègues de l'année dernier (PFE 7) pour mettre en place ce réseau dynamique. En effet  ils ont changé les fichiers de base de l’implémentation du protocole RPL dans RIOT OS afin d'améliorer le choix du parent avec lequel un nœud communique. Le fichier sont les suivant:
 +
 
 +
  Dans '''RIOT/sys/net/gnrc/routing/rpl''':
 +
    gnrc_rpl.c
 +
    gnrc_rpl_control_messages.c
 +
    of0.c
 +
  Dans '''RIOT/sys/include/net/gnrc/rpl''':
 +
    struct.h
 +
======Calcul et utilisation de LQI et RSSI======
 +
 
 +
LQI (Link Quality Indicator) est une métrique de la qualité actuelle du signal reçu. Le LQI donne une estimation de la facilité avec laquelle un signal reçu peut être démodulé en accumulant l'amplitude de l'erreur entre les constellations idéales et le signal reçu sur les 64 symboles immédiatement après le mot de synchronisation. LQI est mieux utilisé en tant que mesure relative de la qualité de la liaison (une valeur faible indique une meilleure liaison qu'une valeur élevée), puisque la valeur dépend du format de modulation.
 +
 
 +
RSSI (Received Signal Strength Indication) est une indication de force du signal. Il ne se soucie pas de la «qualité» ou de la «correction» du signal. LQI ne se soucie pas de la puissance réelle du signal, mais la qualité du signal est souvent liée à la puissance du signal. En effet, un signal fort est susceptible d'être moins affecté par le bruit et sera donc perçu comme "plus propre" ou plus "correct" par le récepteur.
 +
 
 +
Il y a quatre à cinq «cas extrêmes» qui peuvent être utilisés pour illustrer comment RSSI et LQI fonctionnent:
 +
 
 +
#Un signal faible en présence de bruit peut donner un RSSI faible et un LQI élevé.
 +
#Un signal faible en absence totale de bruit peut donner un RSSI faible et un LQI faible.
 +
#Un fort bruit (provenant généralement d'un interféreur) peut donner un RSSI élevé et un IQI élevé.
 +
#Un signal fort sans trop de bruit peut donner un RSSI élevé et un faible LQI.
 +
#Un signal très fort qui provoque la saturation du récepteur peut donner un RSSI élevé et un LQI élevé.
 +
 
 +
Notez que RSSI et LQI sont mieux utilisés en tant que mesures relatives puisque les valeurs dépendent du format de modulation.
 +
 
 +
La fonction qui calcul le rang d'un nœud, en fonction des indicateurs et le RSSI:
 +
 
 +
//Avec base_rank=256, rssi <= 28 et lqi <=255
 +
add = 256 - (parent->mc.rssi + parent->mc.lqi)/10;
 +
my_rank = base_rank + add;
 +
 
 +
De cette manière, on se rendre mieux compte de la distance d'un nœud par rapport au DODAG racine diminuant son rang en fonction de ces deux facteurs.
 +
 
 +
Pour lancer le routage RPL dans sur le cartes il suffit de choisir un nœud comme racine (avec la fonction '''gnrc_rpl_root_init''' ) et ajouter les lignes suivant dans le fichier Makefile du projet:
 +
 
 +
USEMODULE += gnrc_rpl
 +
USEMODULE += auto_init_gnrc_rpl
 +
 
 +
Une telle solution permet de choisir le parent avec le rang le plus faible et autorise un choix plus objectif du parent:
 +
 
 +
  #  rpl
 +
  # instance table: [X]
 +
  # parent table: [X] [ ] [ ]
 +
  #
 +
  # instance [1 | Iface: 7 | mop: 2 | ocp: 0 | mhri: 229 | mri 0]
 +
  # dodag [baad:a555::1702 | R: 485 | OP: Router | PIO: on | CL: 0s | TR(I=[8,20], k=10, c=11, TC=4088s)]
 +
  # parent [addr: fe80::1210:642c:1432:1702 | rank: 256 | lifetime: 256s]
 +
 
 +
====Implémentation d'un driver sur RIOT OS====
 +
 
 +
Les cartes STM32 n'ont pas la puissance nécessaire pour piloter les deux moteurs DC utilisés sur le robot. Pour cela on utilise un module driver de moteur afin d'accomplir cette tâche.
 +
 
 +
Le driver TB6612FNG est un driver de moteur à courant continue, qui possède deux entrées IN1 et IN2 permettant de choisir l'un de quatre mode suivant: mode CW ( tourner dans le sens des aiguilles de la montre), mode CCW (tourner dans le sens anti horaire), frein court et mode d'arrêt.
 +
 
 +
Dans RIOT OS, on trouve plusieurs driver déjà implémenté mais le TB6612FNG n'en fait pas partie. Alors on a mise en place un module qui l'on a appelé '''robot''' incluant le '''driver de moteur + un codeur infrarouge'''. Le codeur infrarouge va nos permettre, avec la roue codeuse, de donner la distance que le robot va devoir parcourir.
 +
 
 +
Dans RIOT OS, les drivers de trouver dans les répertoires: '''RIOT/drivers/''' pour la définit des fonction (.c) et '''RIOT/drivers/include''' pour le prototypage de fonctions (.h). On a inclut un fichier '''robotcar.c''' et '''robotcar.h''', pour l'utiliser, il suffit d'ajouter dans le fichier Makefile la ligne suivante: '''USEMODULE += robotcar'''.
 +
 
 +
=====Les fonctions implémentées=====
 +
 
 +
Sur la première fonction on doit mettre en paramètre les pins sur lesquels le driver/moteur est connecté. 
 +
 
 +
  '''initialisation'''
 +
  robot_init(robot_t *dev, pwm_t pwm, int pwm_channel, gpio_t in1, gpio_t in2, gpio_t stby, gpio_t encoder,int id)
 +
 +
  '''permet de guider le robot en choisissant la direction souhaité'''
 +
  robot_drive( robot_t *dev, uint16_t speed, int direction)
 +
 
 +
  '''aller tout droit'''
 +
  robot_move_forward(robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)
 +
 
 +
  '''aller en arrière'''
 +
  robot_move_reverse( robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)
 +
 +
  '''tourner à droite'''
 +
  robot_spin_right( robot_t *dev1, robot_t *dev2, uint16_t speed,int steps)
 +
 
 +
  '''tourner à gauche'''
 +
  robot_spin_left( robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)
 +
 
 +
  '''arreter le robot'''
 +
  robot_stop(robot_t *dev1, robot_t *dev2)
 +
 
 +
  '''convertir des centimètres en pas'''
 +
  cm_to_steps(uint8_t cm)
 +
 
 +
Le robot peut être pilote manuel au automatiquement. A ce qui concerne le pilotage manuel, on a utilisé le shell de RIOT OS et on a créé des lignes de commandes. Par exemple pour aller tout droit il suffit de taper la commande sur le shell côté client: '''motor move forward 500 50'''. Ici on a demandé au robot d'aller tout droit avec une vitesse de 500 jusqu'à 50 cm.
 +
 
 +
====Conception d'un nouveau module RF====
 +
 
 +
Les modules radios que l'on utilise maintenant, ne sont pas directement fixés sur les cartes stm32 et on doit à chaque fois faire les câblage lors de tests. Les cartes stm32 n'ont pas aussi un trou permettant de la fixer sur le robot. Alors pour rendre les tâches moins difficiles, on a décidé d'en concevoir des nouveaux.
 +
 
 +
=====Commande des composants=====
 +
{| class="wikitable alternance centre"
 +
|-
 +
! Matériel !!Fournisseur !! Quantité !!Prix à l'unité (€) !! Prix Total (€) !! URL
 +
|-
 +
! SMD balun/filter
 +
| Mouser Electronics
 +
| 5
 +
| 1,39 €
 +
| 6.95 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=2450FB15L0001Evirtualkey58450000virtualkey609-2450FB15L0001E
 +
|-
 +
! Condensateur 1uF
 +
| Mouser Electronics
 +
| 20
 +
| 0,085 €
 +
| 1.7 €
 +
| https://www.mouser.fr/productdetail/murata-electronics/grm188r61c105ka12j?qs=sGAEpiMZZMs0AnBnWHyRQNchIam%2FLmo3hf6crLvws8Q%3D
 +
|-
 +
! Condensateur 12 pF
 +
| Mouser Electronics
 +
| 10
 +
| 0,085 €
 +
| 0,85 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=06035A120JAT2Avirtualkey58110000virtualkey581-06035A120J
 +
|-
 +
! Condensateur 22 pF
 +
| Mouser Electronics
 +
| 10
 +
| 0,085 €
 +
| 0,85 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=06035A220JAT2Avirtualkey58110000virtualkey581-06035A220J
 +
|-
 +
! Résistance 680 ohms
 +
| Mouser Electronics
 +
| 5
 +
| 0,085 €
 +
| 0,425 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=CRCW0603680RFKEAvirtualkey61300000virtualkey71-CRCW0603-680-E3
 +
|-
 +
! AT86RF231-ZF
 +
| Mouser Electronics
 +
| 5
 +
| 2,87 €
 +
| 14,35 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=AT86RF231-ZFvirtualkey55660000virtualkey556-AT86RF231-ZF
 +
|-
 +
! Condensateur 2.2pF
 +
| Mouser Electronics
 +
| 5
 +
| 0,247 €
 +
| 1,235 €
 +
| http://www.mouser.fr/Search/ProductDetail.aspx?R=C0603C229D5GACTUvirtualkey64600000virtualkey80-C0603C229D5G
 +
|-
 +
! Antenne 2.4GHz
 +
| Mouser Electronics
 +
| 5
 +
| 0,536 €
 +
| 2.68 €
 +
| https://www.mouser.fr/ProductDetail/Johanson/2450AT18A100E/?qs=%2fha2pyFaduheg09XJzH1azVZtpYax9RgXRvA4o0ekxpMdtXIwMW11g%3d%3d
 +
|-
 +
! Oscillateur 16 MHz
 +
| Conrad
 +
| 5
 +
| 0,94 €
 +
| 4,7 €
 +
| http://www.conrad.fr/ce/fr/product/1009305/Cristal-de-quartz-EuroQuartz-16000MHz-MT3030-408512pF-CMS-4-16000-MHz-12-pF-32-mm-25-mm-07-mm-1-pcs
 +
|-
 +
! CONN HEADR FMALE 50POS .1" DL AU
 +
| digikey
 +
| 10
 +
| 2,03 €
 +
| 20,3 €
 +
| https://www.digikey.fr/products/fr?keywords=SFH11-PBPC-D25-ST-BK%20
 +
|-
 +
|}
 +
 
 +
=====Réalisation du schematic sous KiCad=====
 +
 
 +
On s'est basé, sur la datasheet du composant AT86RF231, pour réaliser le schéma électrique de la carte. On peut y trouver plusieurs notes d'application ainsi qu'un BOM pour la réalisation du module radio. On a choisit de réaliser la carte avec KiCad car, est un logiciel facile à utiliser et gratuit.
 +
 
 +
[[Fichier:Schematic radio.png]][[Fichier:Connector stm32.png]]
 +
 
 +
=====Routage de la carte=====
 +
Le tramsmetteur radio AT86RF231 envoie les données modulées via les pins RFP et RFN. La bande utilisée pour les liaisons Zigbee est à 2,45 GHz ce qui correspond aux hyperfréquences.L'antenne utilisée a une impédance d'entrée de 50 Ohms et il de même pour l’impédance de sortie du balun. Pour adapter ces deux éléments, il faut une ligne d’impédance caractéristique de 50 Ohms.Pour une ligne microstrip, l'impédance caractéristiques dépend fortement de ses dimensions et du matériau isolant. Pour calculer la taille de piste nécessaire, on a utilisé un outil en ligne:
 +
 
 +
[[Fichier:Impendance line.png|center|400px]]
 +
 
 +
Il nous faut donc l’épaisseur t de la piste, l’épaisseur h du diélectrique ainsi que sa permittivité. A Polytech, il est possible de réaliser des cartes avec des pistes d'épaisseur 35 um avec un diélectrique verre-epoxy FR4 d'épaisseur 0,8 mm. Avec ces informations, on trouve une largeur de piste égale à 1,42 mm. Selon la datasheet de l'antenne, il était conseillé d’ajouter un guide d’onde coplanaire constitué de trous afin d'améliorer le transport de l'énergie jusqu'à l'antenne. De plus, l'ajout de vias permet d'atténuer l'effet capacitif des plans de masses situés de part et d'autres du diélectrique. Le rôle du balun est de transformer une impédance symétrique en impédance asymétrique et vice versa. Le balun réalise également une fonction d'adaptation d'impédance entre les ports RFP et RFN et l'antenne.  Enfin les condensateurs à l’entrée des ports RFP/RFN sont utilisés pour supprimer la composante continue de l'entrée RF provenant de l'antenne.
 +
 
 +
[[Fichier:Radio pcb.png|center|500px]]
 +
 
 +
=====Soudure et test du module radio=====
 +
[[Fichier:At86 pfe15 1.jpg|400px]][[Fichier:At86rf pfe15.jpg|400px|right]]
 +
======Problèmes rencontrés======
 +
Une fois la soudure du module radio terminé, on est passé au test de ce même; Tout paraissait marcher correctement mais le module ne démarrait pas lorsque le pin CS (chip select) était connecté.
 +
 
 +
<code>
 +
# AT86RF2xx device driver test
 +
# Initializing AT86RF2xx radio at SPI_1
 +
</code>
 +
 
 +
Le résultat avec le CS déconnecté est le suivant:
 +
 
 +
<code>
 +
 
 +
# AT86RF2xx device driver test
 +
# Initializing AT86RF2xx radio at SPI_1
 +
# Initialization successful - starting the shell now
 +
 
 +
</code>
 +
 
 +
Ensuite on avait essayé de trouver d'où venait le problème, en mesurant le niveau de tension à chaque pin tout en regardant la note d'application du composant at86rf231. On avait trouvé que sur les deux pins du quartz on devait avoir le même niveau de tension (0.9 Volts), pourtant on avait 0.7 Volts sur un seul pin et 0 volts sur l'autre; cela nous as emmené à une conclusion: le quartz n'oscille pas; Pour vérifier nous avons branché un oscilloscope et c’était vraiment le cas. Alors soit le problème viens du composant at86rf231, soit du quartz.
 +
 
 +
====Mesure du Round Trip Time====
 +
 
 +
La latence, fait référence au RTT (Round Trip Time/Delay) d'une requête c'est à dire le temps que met un signal pour parcourir l'ensemble d'un circuit fermé.
 +
En particulier ça correspond à l'heure à laquelle le paquet doit atteindre la destination. La machine de destination doit répondre à cette requête et cette réponse doit parvenir au demandeur.
 +
 
 +
Chaque réseau a une latence. La quantité totale de latence, que l'on obtient lors de la connexion à un hôte distant donné, peut varier considérablement en fonction des conditions du réseau. C'est alors que on s’intéresse dans cette partie à l'étude de la latence du notre réseau (le temps de transmission d'un paquet à partir de la couche MAC jusqu'au récepteur en fonction de la taille du paquet ou  de la distance émetteur/récepteur).
 +
 
 +
Il faut savoir qu'il y a plusieurs autres facteurs qui peuvent ajouter une latence supplémentaire en plus de la latence de la couche MAC:
 +
 
 +
#'''les délais de routage''': Si les paquets doivent passer par un saut de réseau très encombré, ce délai de buffer peut ajouter une latence considérable.
 +
#'''la retransmission des paquets''' 
 +
#'''retards de propagation du signal dans le matériel qui reçoit, transmet ou répète des paquets'''.
 +
 
 +
 
 +
Afin de calculer la latence du réseau on a procédé  de la manière suivante:
 +
 
 +
# Lors de l'envoi d'un paquet, le client calcule le temps T1 (en milliseconde) et attend la réponse du serveur (temps d'attente = 1 seconde).
 +
# Le serveur reçoit le message et le retransmet au client.
 +
# Lors que le client reçoit la réponse du client il calcule le temps de réception T2 du paquet (en milliseconde). Si la réponse arrive après 1 seconde, on considère que le paquet a été perdu.
 +
# le round-trip time est calculé donc de cette manière: rtt = T2 - T1
 +
 
 +
Les fonctions implémentées, pour le calcul du temps de latence:
 +
 +
'''calculate the time diff between start and end (in ms)'''
 +
 
 +
float delay(uint32_t t1, uint32_t t2)
 +
{
 +
  float d;
 +
  d = (float)(t2 - t1)/1000000;
 +
  return(d);
 +
}
 +
 
 +
'''calculate the min/max/average value from an array'''
 +
 
 +
void rttd(float t[], int size, uint32_t time)
 +
{
 +
  float avg;
 +
  float min = t[0];
 +
  float max = 0.0;
 +
  float sum=0.0;
 +
  int i;
 +
  for(i=0; i< size; i++){
 +
  sum += t[i];
 +
    if(t[i] > max) {max = t[i];}
 +
    if(t[i] < min) {min = t[i];}
 +
    }
 +
    avg = sum/(float)size;
 +
    if(size!=0)printf("Round-trip delay: min/avg/max = %f/%f/%f ms, time = %f s\n",min*1000,avg*1000,max*1000,(float)time/1000000);
 +
  }
 +
 
 +
 
 +
=====Le temps de latence entre 2 et 3 nœuds dans réseau statique=====
 +
 
 +
Afin d'obtenir un meilleur résultat, le rtt a été calculer à partir de la moyenne de l'envoie de 100 paquets à la fois. On calcule aussi le temps minimum et maximum sur le 100 paquets:
 +
 
 +
  # Packets: Size: 1 bytes, Sent = 100, Received = 100, Lost = 0
 +
  # Round-trip delay: min/avg/max = 7.919001/9.907592/12.389999 ms, time = 0.990927 s
 +
 
 +
  # Packets: Size: 32 bytes, Sent = 100, Received = 100, Lost = 0
 +
  # Round-trip delay: min/avg/max = 10.057000/12.173100/14.198999 ms, time = 1.217735 s
 +
 
 +
  # Packets: Size: 1024 bytes, Sent = 100, Received = 99, Lost = 1
 +
  # Round-trip delay: min/avg/max = 130.070007/144.760742/157.856995 ms, time = 14.486991 s
 +
 
 +
  # Packets: Size: 2048 bytes, Sent = 100, Received = 0, Lost = 100
 +
 
 +
D'après le résultat ci-dessus, on constate que le temps de latence augmente selon la taille du message. A partir de 1024 bytes on commence à perdre quelques paquets et à 2048 bytes il n'y en plus des paquets qui sont envoyés.
 +
 
 +
Pour mieux comprendre la latence de ce réseau, on a fait plusieurs mesures et on a trace la courbe du rtt en fonction de la taille du paquet:
 +
 
 +
[[Fichier:Resultat reseau static 1node.png|500px|left|thumb|2 noeuds]][[Fichier:Resultat_reseau_static.png|500px|center|thumb|3 noeuds]]
 +
 
 +
 
 +
 
 +
On compte envoyer des requêtes avec une taille de 32 octets, ayant le message suivant: [cmd,speed,distance], la commande (cmd) a une taille de 8 bytes, la vitesse (speed) 16 octets et la distance que le robot doit parcourir, a une taille de 8 octets. Le temps total qu'un paquet de 32 octets met pour faire le tour d'un réseau avec de 2 nœuds est compris entre 10 et 14 millisecondes; Pour un réseau avec 3 noeuds le temps de latence est le double de celui avec 2, si un rajoute un quatrième noued il va falloir multiplier le temps de basse par trois et ainsi de suite.
 +
 
 +
'''Temps N nœuds = (N-1) x Temps de 2 nœuds'''
 +
 
 +
====Mesure de la latence avec SNTP (one way latency) ====
 +
 
 +
Ayant des mauvais résultats lors du calcul du temps de latence, avec la méthode round trip delay... On a décidé d'implémenter le protocole SNTP afin de synchroniser l'horloge locale d'ordinateurs sur une référence d'heure. Nous avons mis en place la méthode serveur/client, cela marche de la manière suivant:
 +
 
 +
# un nœud « serveur » répond aux demandes d'heure émises par un nœud « client » ;
 +
# les parents sont les serveurs, les enfants sont les clients ;
 +
# en opérant dans le mode « serveur », un nœud annonce son désir de synchroniser ;
 +
# en opérant dans le mode « client », un nœud annonce son désir d’être synchronisé ;
 +
# le mode d'adressage « unicast » est utilisé pour transférer les messages de demande et de réponse
 +
 
 +
=====Description du modèle NTP « client/serveur » implémenté=====
 +
 
 +
# dans un premier temps le serveur envoie un message avec l'heure actuelle (T1)
 +
# ensuite le client fait une demande de synchronisation au serveur
 +
# une fois synchronisé le client calcul l'offset entre les deux horloges (offset)
 +
# enfin le client calcul le temps de réception du message (T2)
 +
 
 +
La latence est calculée de la manière suivante: T2 - T1 + offset
 +
 
 +
 
 +
[[Fichier:Latency.png|center|700px|thumb| 2 nœuds: réseau statique]]
 +
 
 +
Comme nous pouvions le voir, la longueur du paquet a une influence sur le temps de transmission. Globalement, cette évolution est linéaire.
 +
 
 +
==Conclusion==
 +
 
 +
L'application mise en place, est une application basée sur du temps réel grâce au système d'exploitation RIOT. En effet RIOT permet la programmation d'applications en langages C et C++  ainsi que le multithreading et le temps réel. La capacité en temps réel est possible grâce à une interruption de latence très faible (~ 50 cycles d'horloge) et à une programmation basée sur les priorités.
 +
 
 +
Durant ce projet on a put mettre en place deux type de réseau: un réseau statique et l'autre dynamique (avec le protocole RPL). Le temps de latence du réseau statique est presque toujours le même ( vu que le taille du message ne change pas, 32 bytes), sauf que celui augmente lorsque l'on ajoute un nœud dans le réseau. Dans le cas d'un réseau statique la latence varie en fonction du déplacement du robot; par exemple si le robot choisi le nœud racine comme sont parent lors des déplacements la latence sera plus petite contrairement si sont parent était un nœud qui se trouve à un saut du nœud racine.
 +
 
 +
 
 +
Le nœud robot est piloté par des commandes provenant du nœud racine; Afin de s'assurer que la requête est bien arrivée à sa destination, une fois que le nœud racine envoie la commandes, il attend (25 ms max) un retour de la part du robot. S'il ne reçoit aucun retour, un message est affiché disant: <<mode auto>>. Côté robot on attend 5 seconds, s'il ne reçoit rien on passe en mode manu, ce mode dure 15 seconds si aucun message n'est toujours pas arrivé, ensuite il s’arrête.
 +
 
 +
==Bibliographie==
 +
 
 +
http://riot-os.org/files/RIOT-Seminar-2017/RIOT-Spring-Seminar-Song.pdf
 +
 
 +
https://twatteyne.files.wordpress.com/2013/05/watteyne06intersense_pres.pdf
 +
 
 +
https://riot-os.org/api/
 +
 
 +
==Archive Git==
 +
 
 +
https://archives.plil.fr/elopes/PFE15.git
 +
 
 +
==Livrables==
 +
'''Rapport de mi-parcours'''
 +
 
 +
[[Fichier:Rapport_mi_parcours.pdf ]]
 +
 
 +
'''Rapport final'''
 +
 
 +
[[Fichier:Rapport PFE15 LOPES.pdf]]

Version actuelle datée du 21 février 2018 à 13:13

  • Etudiant : Edmur Lopes
  • Encadrants : Alexandre Boé / Xavier Redon / Thomas Vantroys

Cahier des charges

Contexte

L'industrie 4.0 propose d'organiser les moyens de production de façon agile et autonome. Pour cela, on peut envisager de créer des ilots de travail interconnectés. Chaque ilot pourrait être déplacé pour optimiser soit l'utilisation des ressources soit la production. Dans le cas d'ilots identiques, pour faciliter la mise à jour des systèmes et le contrôle des machines, il peut être intéressant de faire la régulation sur un système "serveur". Les ilots deviennent alors les clients et envoient leurs données au serveur qui renvoie par la suite la commande.

Description du projet

Ce projet consiste à évaluer la possibilité de contrôler en temps réel un robot par liaison sans fil. Cela sera possible avec la mise en place d'un réseau sans fil de capteurs temps réel, afin d'échanger des informations entre les nœuds. Ce réseau va devoir être capable d'effectuer le chemin le plus court vers la cible dans le but de diminuer le temps de propagation de l'information, comme montre la figure ci-après:

Architecture matérielle

Objectif du projet

L'objectif est donc la mise en place d'un réseau avec des cartes stm32 équipées d'un module radio at86rf231, plus précisément:

  1. Faire des recherches bibliographiques: temps réel, MAC, RIOT OS...
  2. Prise en main de RIOT OS et de la carte STM32F4
  3. Mettre en Place un réseau non temps réel
  4. Étudier les caractéristiques de ce réseau non temps réel: le temps de latence, des éventuels erreurs lors de l'émission...
  5. Rendre le réseau non temps réel en réseau temps réel
  6. Mise en place d'une commande automatique en cas de défaut sur le réseau

Première semaine (18/09/17 : 24/09/17)

  • Premier Rendez-vous de présentation du projet avec les encadrants
  • Analyse du besoin et élaboration du cahier des charges

Deuxième semaine (25/09/17 : 01/10/17)

  • Élaboration de la page wiki (présentation du projet)
  • Initiation à la recherche bibliographique (RIOT OS, Réseau temps réel, microcontrôleurs ARM (stm32), MAC protocol, RPL, etc.)

Calendrier prévisionnel

Previsionnel.png

Travail réalisé

Récupération du code et installation des outils de compilation

Avant de commencer à programmer une application, il faut tout d'abord cloner le code source de RIOT OS depuis GitHub:

git clone https://github.com/RIOT-OS/RIOT.git RIOT

Il faudra aussi installer les outils nécessaires à la compilation et au débogage de la famille de microcontrôleurs ARM:

sudo apt-get install build-essential g++-multilib gtkterm openocd

Le paquetage g++-multilib est uniquement nécessaire si le système hôte est 64bits.

Installation des compilateurs et ses outils associés:

sudo apt-get install gcc-arm-none-eabi gdb-arm-none-eabi binutils-arm-linux-gnueabi

Prise en main de RIOT OS et STM32F4discovery

RIOT est un système d'exploitation construit autour d'un micro-noyau temps-réel, développé pour les besoins de l'Internet des objets et des réseaux sans fil. Initialement lancé en Europe par INRIA, Freie Universität Berlin, et l'Université de Hambourg en 2013, RIOT est actuellement développé par une large communauté du logiciel libre rassemblant des développeurs du monde entier.

Pour prendre à main RIOT et la carte STM32, On a commencé par réaliser une application basé sur l'exemple "hello_world" de RIOT: cette simple application "gpio_to_serial" est capable d'allumer/éteindre une led dès qu'une interruptions est générée lors qu'on appuie sur le bouton "user" et affiche l'état de la led au terminal:

  # GPIO Callback
  # Message received, LED is ON
  # GPIO Callback
  # Message received, LED is OFF
  # GPIO Callback 
  # Message received, LED is ON
  # GPIO Callback
  # Message received, LED is OFF
  # GPIO Callback
  # Message received, LED is ON
  # GPIO Callback
  # Message received, LED is OFF

Cette application m'a permit de comprendre comment fonctionne le système riot et de passer à la mise en place d'un premier réseau.

Mise en place d'un réseau statique entre 3 nœuds

Maintenant on vais réaliser la mise en place d'un réseau multi-point avec 3 nœuds (2 sauts); Pour que cela soit possible chaque carte ayant un module radio doit avoir son adresse ipv6 global qui va permettre d'échanger des paquets entre elles. On a défini une adresse global du type baad:a555::Hwaddr.

Le réseau statique à 3 nœuds se comporte comme un réseau linéaire avec un nœud central se chargeant uniquement de router les paquets vers la destination:

Static network.png

Pour mettre en place cette structure réseau, RIOT OS dispose des nombreuses fonctions telles quelles:

  • ifconfig: permet configurer l'interface réseau.
  • fibroute: table dynamique qui lie les adresses MAC aux ports
  • pingv6: permet de tester l'accessibilité d'une autre machine à travers un réseau IP en envoyant de paquet ICMPv6
  • udp: permet de démarrer un serveur udp et d'envoyer des paquets via le protocole udp sur un port prédéfini

L'exemple gnrc_networking de RIOT, permet de mettre en place la pile réseau GNRC IPv6/6LoWPAN qui est dédié à l'internet des objets. Cet exemple agit comme un routeur et permet de définir des routes statiques ainsi que d'utiliser RPL. On va donc utiliser cet exemple afin de mettre en place le réseau, il suffira de rajouter le module at86rf231 dans le Makefile.

Le node1/client, enverra des paquets avec des ordres de commande vers le node3/serveur (qui correspond au robot avec des moteurs). Ces informations vont tout d'abord passer par le node2 qui est responsable au routage de ces paquets vers le node2. Le node2 va aussi pouvoir retourner des informations vers le node1, par exemple la vitesse de rotation des roues.

Test, communication réseau

Une fois le réseau mis en place, on a fait des tests afin de voir si les cartes arrivaient à communiquer entre-elles. Les résultats ont étés satisfaisants comme le montre les figures ci-dessous:

ping node1 vers node3


ping node3 vers node1

Après on a éteint node2 et on a essayé de faire un ping à nouveau afin de tester si les paquets ne passaient pas directement du node1 vers node3, sans passer par le deuxième. D'après l'image on voit bien qu'il maintenant impossible de faire un ping:


ping node1 vers node3
Server/Client UDP

Tout d'abord on a démarré un serveur upd au node3:

> udp server start 12345
  #  udp server start 12345
  # Success: started UDP server on port 12345

Ensuite on a envoyé un message ("test") UDP du node1 vers le node3:

 udp send baad:a555::1736 12345 test 
 #  udp send baad:a555::1736 12345 test
 # Success: sent 4 byte(s) to [baad:a555::1736]:12345

Le message a été bien reçu par le node3, cela montre que le réseau a été bien mis en place:

#  PKTDUMP: data received:
# ~~ SNIP  0 - size:   4 byte, type: NETTYPE_UNDEF (0)
# 00000000  74  65  73  74
# ~~ SNIP  1 - size:   8 byte, type: NETTYPE_UDP (4)
#    src-port: 12345  dst-port: 12345
#    length: 12  cksum: 0xc94b
# ~~ SNIP  2 - size:  40 byte, type: NETTYPE_IPV6 (2)
# traffic class: 0x00 (ECN: 0x0, DSCP: 0x00)
# flow label: 0x00000
# length: 12  next header: 17  hop limit: 63
# source address: baad:a555::1702
# destination address: baad:a555::1736
# ~~ SNIP  3 - size:  24 byte, type: NETTYPE_NETIF (-1)
# if_pid: 7  rssi: 21  lqi: 255
# flags: 0x0
# src_l2addr: 10:10:64:32:14:0f:17:32
# dst_l2addr: 10:10:64:2d:14:39:17:36
# ~~ PKT    -  4 snips, total size:  76 byte

Routage dynamique avec le protocole RPL

Les progrès technologiques permettent maintenant d’envisager la connexion des objets du quotidien à l’Internet. Des solutions ouvertes et interopérables doivent cependant être utilisées pour garantir une communication optimum entre ces objets. Le protocole de routage est un élément clé de cet objectif, car il permet pour chaque objet de décider comment joindre un autre objet. Les contraintes s’appliquant aux objets (faible puissance, communications instables) doivent être prises en compte pour le développement de protocole de routages adaptés.

Brève introduction du protocole RPL

Les périphériques réseau exécutant le protocole RPL sont connectés de manière acyclique. Ainsi, un graphe acyclique DODAG (Destination-Oriented Directed Acyclic Graph) est crée comme montre la figure ci-après:

DODAG RPL

Chaque nœud choisit le meilleur chemin pour arriver jusqu'au nœud racine, chaque nœud utilise un objectif function (OF) afin de trouver le mieux chemin pour arriver au nœud racine, cette fonction définie le metric de routage qui va être appliqué.

Le processus de routage commence avec la création d'un DAG, le nœud racine envoie son DODAG à tout les noeuds accessible. A chaque niveau de l'arbre de routage les nœuds font le routage en se basant sur l'OF. Une fois qu'un noeud joint le DODAG, il choisit une racine comme son parent et calcule son rank, ce rank correspond au metric qui indique les coordonnées du nœud dans la hiérarchie du réseau. Les autres nœuds vont répéter ce processus de sélection des parents et de notification des informations DODAG pour de nouveaux appareils possibles. Lorsque ce processus se stabilise, le routage des données peut alors commencer. Le processus crée des routes ascendantes (des nœuds à une racine). Pour construire les routes descendantes, le protocole RPL envoie des messages ICMPv6 telles que:

  1. DAG Information Object (DIO) - transmet des informations qui permettent à un nœud de découvrir une instance RPL, d'apprendre ses paramètres de configuration et de choisir des parents dans le DODAG
  2. DAG Information Solicitation (DIS) - sollicite un DIO à partir d'un nœud RPL
  3. Destination Advertisement Object (DAO) - utilisé pour propager les informations de destination vers le haut le long du DODAG.
Application dans RIOT OS

Le protocole RPL est présent dans RIOT OS. On s'est basé sur le travail de nos collègues de l'année dernier (PFE 7) pour mettre en place ce réseau dynamique. En effet ils ont changé les fichiers de base de l’implémentation du protocole RPL dans RIOT OS afin d'améliorer le choix du parent avec lequel un nœud communique. Le fichier sont les suivant:

 Dans RIOT/sys/net/gnrc/routing/rpl:
    gnrc_rpl.c
    gnrc_rpl_control_messages.c
    of0.c
 Dans RIOT/sys/include/net/gnrc/rpl:
    struct.h
Calcul et utilisation de LQI et RSSI

LQI (Link Quality Indicator) est une métrique de la qualité actuelle du signal reçu. Le LQI donne une estimation de la facilité avec laquelle un signal reçu peut être démodulé en accumulant l'amplitude de l'erreur entre les constellations idéales et le signal reçu sur les 64 symboles immédiatement après le mot de synchronisation. LQI est mieux utilisé en tant que mesure relative de la qualité de la liaison (une valeur faible indique une meilleure liaison qu'une valeur élevée), puisque la valeur dépend du format de modulation.

RSSI (Received Signal Strength Indication) est une indication de force du signal. Il ne se soucie pas de la «qualité» ou de la «correction» du signal. LQI ne se soucie pas de la puissance réelle du signal, mais la qualité du signal est souvent liée à la puissance du signal. En effet, un signal fort est susceptible d'être moins affecté par le bruit et sera donc perçu comme "plus propre" ou plus "correct" par le récepteur.

Il y a quatre à cinq «cas extrêmes» qui peuvent être utilisés pour illustrer comment RSSI et LQI fonctionnent:

  1. Un signal faible en présence de bruit peut donner un RSSI faible et un LQI élevé.
  2. Un signal faible en absence totale de bruit peut donner un RSSI faible et un LQI faible.
  3. Un fort bruit (provenant généralement d'un interféreur) peut donner un RSSI élevé et un IQI élevé.
  4. Un signal fort sans trop de bruit peut donner un RSSI élevé et un faible LQI.
  5. Un signal très fort qui provoque la saturation du récepteur peut donner un RSSI élevé et un LQI élevé.

Notez que RSSI et LQI sont mieux utilisés en tant que mesures relatives puisque les valeurs dépendent du format de modulation.

La fonction qui calcul le rang d'un nœud, en fonction des indicateurs et le RSSI:

//Avec base_rank=256, rssi <= 28 et lqi <=255
add = 256 - (parent->mc.rssi + parent->mc.lqi)/10;
my_rank = base_rank + add;

De cette manière, on se rendre mieux compte de la distance d'un nœud par rapport au DODAG racine diminuant son rang en fonction de ces deux facteurs.

Pour lancer le routage RPL dans sur le cartes il suffit de choisir un nœud comme racine (avec la fonction gnrc_rpl_root_init ) et ajouter les lignes suivant dans le fichier Makefile du projet:

USEMODULE += gnrc_rpl
USEMODULE += auto_init_gnrc_rpl

Une telle solution permet de choisir le parent avec le rang le plus faible et autorise un choix plus objectif du parent:

 #  rpl
 # instance table:	[X]	
 # parent table:	[X]	[ ]	[ ]	
 # 
 # instance [1 | Iface: 7 | mop: 2 | ocp: 0 | mhri: 229 | mri 0]
 # 	dodag [baad:a555::1702 | R: 485 | OP: Router | PIO: on | CL: 0s | TR(I=[8,20], k=10, c=11, TC=4088s)]
 # 		parent [addr: fe80::1210:642c:1432:1702 | rank: 256 | lifetime: 256s]

Implémentation d'un driver sur RIOT OS

Les cartes STM32 n'ont pas la puissance nécessaire pour piloter les deux moteurs DC utilisés sur le robot. Pour cela on utilise un module driver de moteur afin d'accomplir cette tâche.

Le driver TB6612FNG est un driver de moteur à courant continue, qui possède deux entrées IN1 et IN2 permettant de choisir l'un de quatre mode suivant: mode CW ( tourner dans le sens des aiguilles de la montre), mode CCW (tourner dans le sens anti horaire), frein court et mode d'arrêt.

Dans RIOT OS, on trouve plusieurs driver déjà implémenté mais le TB6612FNG n'en fait pas partie. Alors on a mise en place un module qui l'on a appelé robot incluant le driver de moteur + un codeur infrarouge. Le codeur infrarouge va nos permettre, avec la roue codeuse, de donner la distance que le robot va devoir parcourir.

Dans RIOT OS, les drivers de trouver dans les répertoires: RIOT/drivers/ pour la définit des fonction (.c) et RIOT/drivers/include pour le prototypage de fonctions (.h). On a inclut un fichier robotcar.c et robotcar.h, pour l'utiliser, il suffit d'ajouter dans le fichier Makefile la ligne suivante: USEMODULE += robotcar.

Les fonctions implémentées

Sur la première fonction on doit mettre en paramètre les pins sur lesquels le driver/moteur est connecté.

 initialisation
 robot_init(robot_t *dev, pwm_t pwm, int pwm_channel, gpio_t in1, gpio_t in2, gpio_t stby, gpio_t encoder,int id)

 permet de guider le robot en choisissant la direction souhaité
 robot_drive( robot_t *dev, uint16_t speed, int direction)
 aller tout droit
 robot_move_forward(robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)
 aller en arrière
 robot_move_reverse( robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)

 tourner à droite
 robot_spin_right( robot_t *dev1, robot_t *dev2, uint16_t speed,int steps)
 tourner à gauche
 robot_spin_left( robot_t *dev1,  robot_t *dev2, uint16_t speed,int steps)
 arreter le robot
 robot_stop(robot_t *dev1, robot_t *dev2)
 convertir des centimètres en pas
 cm_to_steps(uint8_t cm)

Le robot peut être pilote manuel au automatiquement. A ce qui concerne le pilotage manuel, on a utilisé le shell de RIOT OS et on a créé des lignes de commandes. Par exemple pour aller tout droit il suffit de taper la commande sur le shell côté client: motor move forward 500 50. Ici on a demandé au robot d'aller tout droit avec une vitesse de 500 jusqu'à 50 cm.

Conception d'un nouveau module RF

Les modules radios que l'on utilise maintenant, ne sont pas directement fixés sur les cartes stm32 et on doit à chaque fois faire les câblage lors de tests. Les cartes stm32 n'ont pas aussi un trou permettant de la fixer sur le robot. Alors pour rendre les tâches moins difficiles, on a décidé d'en concevoir des nouveaux.

Commande des composants
Matériel Fournisseur Quantité Prix à l'unité (€) Prix Total (€) URL
SMD balun/filter Mouser Electronics 5 1,39 € 6.95 € http://www.mouser.fr/Search/ProductDetail.aspx?R=2450FB15L0001Evirtualkey58450000virtualkey609-2450FB15L0001E
Condensateur 1uF Mouser Electronics 20 0,085 € 1.7 € https://www.mouser.fr/productdetail/murata-electronics/grm188r61c105ka12j?qs=sGAEpiMZZMs0AnBnWHyRQNchIam%2FLmo3hf6crLvws8Q%3D
Condensateur 12 pF Mouser Electronics 10 0,085 € 0,85 € http://www.mouser.fr/Search/ProductDetail.aspx?R=06035A120JAT2Avirtualkey58110000virtualkey581-06035A120J
Condensateur 22 pF Mouser Electronics 10 0,085 € 0,85 € http://www.mouser.fr/Search/ProductDetail.aspx?R=06035A220JAT2Avirtualkey58110000virtualkey581-06035A220J
Résistance 680 ohms Mouser Electronics 5 0,085 € 0,425 € http://www.mouser.fr/Search/ProductDetail.aspx?R=CRCW0603680RFKEAvirtualkey61300000virtualkey71-CRCW0603-680-E3
AT86RF231-ZF Mouser Electronics 5 2,87 € 14,35 € http://www.mouser.fr/Search/ProductDetail.aspx?R=AT86RF231-ZFvirtualkey55660000virtualkey556-AT86RF231-ZF
Condensateur 2.2pF Mouser Electronics 5 0,247 € 1,235 € http://www.mouser.fr/Search/ProductDetail.aspx?R=C0603C229D5GACTUvirtualkey64600000virtualkey80-C0603C229D5G
Antenne 2.4GHz Mouser Electronics 5 0,536 € 2.68 € https://www.mouser.fr/ProductDetail/Johanson/2450AT18A100E/?qs=%2fha2pyFaduheg09XJzH1azVZtpYax9RgXRvA4o0ekxpMdtXIwMW11g%3d%3d
Oscillateur 16 MHz Conrad 5 0,94 € 4,7 € http://www.conrad.fr/ce/fr/product/1009305/Cristal-de-quartz-EuroQuartz-16000MHz-MT3030-408512pF-CMS-4-16000-MHz-12-pF-32-mm-25-mm-07-mm-1-pcs
CONN HEADR FMALE 50POS .1" DL AU digikey 10 2,03 € 20,3 € https://www.digikey.fr/products/fr?keywords=SFH11-PBPC-D25-ST-BK%20
Réalisation du schematic sous KiCad

On s'est basé, sur la datasheet du composant AT86RF231, pour réaliser le schéma électrique de la carte. On peut y trouver plusieurs notes d'application ainsi qu'un BOM pour la réalisation du module radio. On a choisit de réaliser la carte avec KiCad car, est un logiciel facile à utiliser et gratuit.

Schematic radio.pngConnector stm32.png

Routage de la carte

Le tramsmetteur radio AT86RF231 envoie les données modulées via les pins RFP et RFN. La bande utilisée pour les liaisons Zigbee est à 2,45 GHz ce qui correspond aux hyperfréquences.L'antenne utilisée a une impédance d'entrée de 50 Ohms et il de même pour l’impédance de sortie du balun. Pour adapter ces deux éléments, il faut une ligne d’impédance caractéristique de 50 Ohms.Pour une ligne microstrip, l'impédance caractéristiques dépend fortement de ses dimensions et du matériau isolant. Pour calculer la taille de piste nécessaire, on a utilisé un outil en ligne:

Impendance line.png

Il nous faut donc l’épaisseur t de la piste, l’épaisseur h du diélectrique ainsi que sa permittivité. A Polytech, il est possible de réaliser des cartes avec des pistes d'épaisseur 35 um avec un diélectrique verre-epoxy FR4 d'épaisseur 0,8 mm. Avec ces informations, on trouve une largeur de piste égale à 1,42 mm. Selon la datasheet de l'antenne, il était conseillé d’ajouter un guide d’onde coplanaire constitué de trous afin d'améliorer le transport de l'énergie jusqu'à l'antenne. De plus, l'ajout de vias permet d'atténuer l'effet capacitif des plans de masses situés de part et d'autres du diélectrique. Le rôle du balun est de transformer une impédance symétrique en impédance asymétrique et vice versa. Le balun réalise également une fonction d'adaptation d'impédance entre les ports RFP et RFN et l'antenne. Enfin les condensateurs à l’entrée des ports RFP/RFN sont utilisés pour supprimer la composante continue de l'entrée RF provenant de l'antenne.

Radio pcb.png
Soudure et test du module radio
At86 pfe15 1.jpg
At86rf pfe15.jpg
Problèmes rencontrés

Une fois la soudure du module radio terminé, on est passé au test de ce même; Tout paraissait marcher correctement mais le module ne démarrait pas lorsque le pin CS (chip select) était connecté.

# AT86RF2xx device driver test
# Initializing AT86RF2xx radio at SPI_1

Le résultat avec le CS déconnecté est le suivant:

# AT86RF2xx device driver test
# Initializing AT86RF2xx radio at SPI_1
# Initialization successful - starting the shell now

Ensuite on avait essayé de trouver d'où venait le problème, en mesurant le niveau de tension à chaque pin tout en regardant la note d'application du composant at86rf231. On avait trouvé que sur les deux pins du quartz on devait avoir le même niveau de tension (0.9 Volts), pourtant on avait 0.7 Volts sur un seul pin et 0 volts sur l'autre; cela nous as emmené à une conclusion: le quartz n'oscille pas; Pour vérifier nous avons branché un oscilloscope et c’était vraiment le cas. Alors soit le problème viens du composant at86rf231, soit du quartz.

Mesure du Round Trip Time

La latence, fait référence au RTT (Round Trip Time/Delay) d'une requête c'est à dire le temps que met un signal pour parcourir l'ensemble d'un circuit fermé. En particulier ça correspond à l'heure à laquelle le paquet doit atteindre la destination. La machine de destination doit répondre à cette requête et cette réponse doit parvenir au demandeur.

Chaque réseau a une latence. La quantité totale de latence, que l'on obtient lors de la connexion à un hôte distant donné, peut varier considérablement en fonction des conditions du réseau. C'est alors que on s’intéresse dans cette partie à l'étude de la latence du notre réseau (le temps de transmission d'un paquet à partir de la couche MAC jusqu'au récepteur en fonction de la taille du paquet ou de la distance émetteur/récepteur).

Il faut savoir qu'il y a plusieurs autres facteurs qui peuvent ajouter une latence supplémentaire en plus de la latence de la couche MAC:

  1. les délais de routage: Si les paquets doivent passer par un saut de réseau très encombré, ce délai de buffer peut ajouter une latence considérable.
  2. la retransmission des paquets
  3. retards de propagation du signal dans le matériel qui reçoit, transmet ou répète des paquets.


Afin de calculer la latence du réseau on a procédé de la manière suivante:

  1. Lors de l'envoi d'un paquet, le client calcule le temps T1 (en milliseconde) et attend la réponse du serveur (temps d'attente = 1 seconde).
  2. Le serveur reçoit le message et le retransmet au client.
  3. Lors que le client reçoit la réponse du client il calcule le temps de réception T2 du paquet (en milliseconde). Si la réponse arrive après 1 seconde, on considère que le paquet a été perdu.
  4. le round-trip time est calculé donc de cette manière: rtt = T2 - T1

Les fonctions implémentées, pour le calcul du temps de latence:

calculate the time diff between start and end (in ms)
float delay(uint32_t t1, uint32_t t2)
{
 float d;
 d = (float)(t2 - t1)/1000000;
 return(d); 
}
calculate the min/max/average value from an array
void rttd(float t[], int size, uint32_t time)
{
 float avg;
 float min = t[0];
 float max = 0.0;
 float sum=0.0;
 int i;
 for(i=0; i< size; i++){
  sum += t[i];
   if(t[i] > max) {max = t[i];}
   if(t[i] < min) {min = t[i];}
   }
   avg = sum/(float)size;
   if(size!=0)printf("Round-trip delay: min/avg/max = %f/%f/%f ms, time = %f s\n",min*1000,avg*1000,max*1000,(float)time/1000000);
 }
 
Le temps de latence entre 2 et 3 nœuds dans réseau statique

Afin d'obtenir un meilleur résultat, le rtt a été calculer à partir de la moyenne de l'envoie de 100 paquets à la fois. On calcule aussi le temps minimum et maximum sur le 100 paquets:

 # Packets: Size: 1 bytes, Sent = 100, Received = 100, Lost = 0
 # Round-trip delay: min/avg/max = 7.919001/9.907592/12.389999 ms, time = 0.990927 s
 # Packets: Size: 32 bytes, Sent = 100, Received = 100, Lost = 0
 # Round-trip delay: min/avg/max = 10.057000/12.173100/14.198999 ms, time = 1.217735 s
 # Packets: Size: 1024 bytes, Sent = 100, Received = 99, Lost = 1
 # Round-trip delay: min/avg/max = 130.070007/144.760742/157.856995 ms, time = 14.486991 s
 # Packets: Size: 2048 bytes, Sent = 100, Received = 0, Lost = 100

D'après le résultat ci-dessus, on constate que le temps de latence augmente selon la taille du message. A partir de 1024 bytes on commence à perdre quelques paquets et à 2048 bytes il n'y en plus des paquets qui sont envoyés.

Pour mieux comprendre la latence de ce réseau, on a fait plusieurs mesures et on a trace la courbe du rtt en fonction de la taille du paquet:

2 noeuds
3 noeuds


On compte envoyer des requêtes avec une taille de 32 octets, ayant le message suivant: [cmd,speed,distance], la commande (cmd) a une taille de 8 bytes, la vitesse (speed) 16 octets et la distance que le robot doit parcourir, a une taille de 8 octets. Le temps total qu'un paquet de 32 octets met pour faire le tour d'un réseau avec de 2 nœuds est compris entre 10 et 14 millisecondes; Pour un réseau avec 3 noeuds le temps de latence est le double de celui avec 2, si un rajoute un quatrième noued il va falloir multiplier le temps de basse par trois et ainsi de suite.

Temps N nœuds = (N-1) x Temps de 2 nœuds

Mesure de la latence avec SNTP (one way latency)

Ayant des mauvais résultats lors du calcul du temps de latence, avec la méthode round trip delay... On a décidé d'implémenter le protocole SNTP afin de synchroniser l'horloge locale d'ordinateurs sur une référence d'heure. Nous avons mis en place la méthode serveur/client, cela marche de la manière suivant:

  1. un nœud « serveur » répond aux demandes d'heure émises par un nœud « client » ;
  2. les parents sont les serveurs, les enfants sont les clients ;
  3. en opérant dans le mode « serveur », un nœud annonce son désir de synchroniser ;
  4. en opérant dans le mode « client », un nœud annonce son désir d’être synchronisé ;
  5. le mode d'adressage « unicast » est utilisé pour transférer les messages de demande et de réponse
Description du modèle NTP « client/serveur » implémenté
  1. dans un premier temps le serveur envoie un message avec l'heure actuelle (T1)
  2. ensuite le client fait une demande de synchronisation au serveur
  3. une fois synchronisé le client calcul l'offset entre les deux horloges (offset)
  4. enfin le client calcul le temps de réception du message (T2)

La latence est calculée de la manière suivante: T2 - T1 + offset


2 nœuds: réseau statique

Comme nous pouvions le voir, la longueur du paquet a une influence sur le temps de transmission. Globalement, cette évolution est linéaire.

Conclusion

L'application mise en place, est une application basée sur du temps réel grâce au système d'exploitation RIOT. En effet RIOT permet la programmation d'applications en langages C et C++ ainsi que le multithreading et le temps réel. La capacité en temps réel est possible grâce à une interruption de latence très faible (~ 50 cycles d'horloge) et à une programmation basée sur les priorités.

Durant ce projet on a put mettre en place deux type de réseau: un réseau statique et l'autre dynamique (avec le protocole RPL). Le temps de latence du réseau statique est presque toujours le même ( vu que le taille du message ne change pas, 32 bytes), sauf que celui augmente lorsque l'on ajoute un nœud dans le réseau. Dans le cas d'un réseau statique la latence varie en fonction du déplacement du robot; par exemple si le robot choisi le nœud racine comme sont parent lors des déplacements la latence sera plus petite contrairement si sont parent était un nœud qui se trouve à un saut du nœud racine.


Le nœud robot est piloté par des commandes provenant du nœud racine; Afin de s'assurer que la requête est bien arrivée à sa destination, une fois que le nœud racine envoie la commandes, il attend (25 ms max) un retour de la part du robot. S'il ne reçoit aucun retour, un message est affiché disant: <<mode auto>>. Côté robot on attend 5 seconds, s'il ne reçoit rien on passe en mode manu, ce mode dure 15 seconds si aucun message n'est toujours pas arrivé, ensuite il s’arrête.

Bibliographie

http://riot-os.org/files/RIOT-Seminar-2017/RIOT-Spring-Seminar-Song.pdf

https://twatteyne.files.wordpress.com/2013/05/watteyne06intersense_pres.pdf

https://riot-os.org/api/

Archive Git

https://archives.plil.fr/elopes/PFE15.git

Livrables

Rapport de mi-parcours

Fichier:Rapport mi parcours.pdf

Rapport final

Fichier:Rapport PFE15 LOPES.pdf