PAE 2021 Envoi de données
Sources : https://www.signal-drone.com/2020/06/26/informations-codees-transmises-par-le-signalement-electronique/ https://www.ecologie.gouv.fr/sites/default/files/notice_signalement_electronique.pdf
https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000039685188
https://discuss.ardupilot.org/t/open-source-french-drone-identification/56904 (Très utile)
https://github.com/GendarmerieNationale/ReceptionInfoDrone ( code source Gendarmerie pour décoder et afficher une trame beacon.)
https://www.electroniclinic.com/esp32-wroom-32d-pinout-features-and-specifications/
Sommaire
Introduction
Depuis le 27 décembre 2019 un arrêté a été déclaré stipulant les caractéristiques techniques des dispositifs de signalement des aéronefs opérés sans personne à bord. Ces dispositifs utilisent des trame beacon wifi composé de plusieurs informations afin de s’identifier. Parmi ces informations nous retrouvons : la version du protocol, l’identifiant FR, l’identifiant ANSI, la latitude et la longitude de l’appareil, son altitude, latitude et longitude du point de décollage, sa vitesse horizontale, son cap. Dans ce projet nous voulons rajouter une information supplémentaire au sein de cette trame. Cette information est la tension de la batterie de la balise.
source:https://www.signal-drone.com/2020/06/26/informations-codees-transmises-par-le-signalement-electronique/
Ici nous observons un exemple de trame, ainsi que les données obligatoires minimales à transmettre pour être en accord avec la loi drones.
Dans un premier temps nous nous servons d'une carte arduino uno, du module baliz navéol (émetteur) et d'un raspberry pi 3 pour recevoir la trame beacon que nous voulons observer. Après installation du programme de réception de la gendarmerie, trouvable à l'adresse:https://github.com/GendarmerieNationale/ReceptionInfoDrone nous pourrons recevoir, décoder et afficher la trame émise par la baliz navéol.
Mesure de la tension de la batterie
Schéma du montage de la batterie
Les résistances sont choisies avec un pont diviseur de tension. Plus précisément:
(1)
De plus les résistances sont élevées pour débiter un minimum de courant à la batterie. Le rapport entre les résistances (R1/R2) doit être de 1.5.
Sachant que la tension Vmax de la batterie est égale à 8.4V et que la tension max sur le pin de la carte arduino doit être de 3.3V et que le rapport entre ces deux tensions est égale à R2/(R2+R1) d'après le pont diviseur de tension ce rapport de résistance doit être de 0.4.
Nous avons donc R2/(R1+R2) = 0.4 <=> R2 = 2/3 * R1 (1)
De plus nous voulons maximiser les résistances pour débiter un minimum de courant donc fixons donc la résistance R1 à une valeur normalisée élevée de 10M ohm. R1 = 10M ohm (2).
Donc:
(1) R2 = 2/3 * R1
(2) R1 = 10M ohm
nous avons donc R1 = 10M ohm et R2 = 2/3 * 10M ohm soit ~6.67M omh, en normalisant nous pouvons choisir une résistance R2 de 6.8M ohm.
le nouveau rapport R2/(R1+R2) = 6.8/16.8 = 0.405. Ce qui reste cohérent.
Calculs de la mesure
Dans cette partie nous allons détailler comment nous mesurons la tension de la batterie étape essentielle pour pouvoir l'inclure dans la trame que nous voulons modifier. La batterie utilisée sera une Lipo 2S de tension nominale 7.4V et de tension max 8.4V. La carte esp32 contenant notre émetteur va être alimentée en 5V par un régulateur de tension. De plus les pins de cette carte étant ayant des tensions allant de 0 - 3.3V nous adaptons la tension max de notre batterie pour être en accord avec ces valeurs à l'aide d'un pont diviseur de tension. Une fois la tension acquis par le pin, nous allons être capable de la mesurer avec la fonction analogRead(GPIO) Arduino. Le résultat retourné sera une valeur analogique comprise entre 4095 et 0. Avec la courbe ce dessous, nous sommes capable de retrouver la valeur en tension à l'entrée du pin et donc à remonter à la tension de la batterie qui est à transmettre. Plus précisément il suffit de multiplier la valeur analogique lue par 0.000806 (3.3/4095) qui correspond au pas du convertisseur A.N. On obtient donc la valeur en volt de la tension sur le pin 25, que l'on multiplie par 2.545 (inverse du pont diviseur) pour retrouver la tension de la batterie, de plus: 2.545*0.000806=0.00205 donc finalement il nous suffit de multiplier la valeur obtenue à la sortie de la fonction analogRead() par 0.00205 pour obtenir la tension aux bornes de la batterie.
source:https://randomnerdtutorials.com/esp32-adc-analog-read-arduino-ide/
La tension varie beaucoup en entrée (Variation supérieure au quantum du CAN de l'esp32) comme on peut la voir sur la figure suivante qui représente la tension mesurée aux bornes de la batterie, une moyenne est alors effectuée dans le code afin de lisser ces variations.
Le code sera alors le suivant (le code suivant est dans une boucle qui tourne constamment):
int tension_int = analogRead(MESURE_TENSION); // Lecture de la tension sur la pin MESURE_TENSION
tension+= tension_int * 0.0022066;//Conversion de la valeur en tension
compt++;
if(compt == 100){ // Moyenne sur 100 valeurs de la tension
float tension_moy = tension/compt;
compt = 0;
tension = 0;
drone_idfr.set_tension(tension_moy);
}
Émission de la trame Beacon
Premièrement qu'est ce qu'une trame beacon? les trames beacon sont constituées de 3 parties: le 802.11 MAC header, le body et un FCS.
Une trame se compose comme ça:
source:https://ensiwiki.ensimag.fr/index.php?title=Wifi_low_power
La partie qui nous intéresse ici est le body, dans lequel nous voulons ajouter une information.
Modification de la trame
Pour cette partie nous nous sommes servis du programme d'émission déjà fournis par M. Launay et nous avons ajouté une information dans la trame à émettre, l'ensemble du code sera disponible en annexe.
La tension étant un nombre flottant doit être convertie en un tableau d'octets afin d'être transmis. La technique utilisée consiste simplement à appeler la fonction memcpy afin de ne pas modifier l'information en effectuant des casts :
full_frame[start_from + count] = TENSION;
count++;
full_frame[start_from + count] = TLV_LENGTH[TENSION];
count++;
uint8_t tension_uint8[sizeof(float)];
memcpy(tension_uint8, &_tension, sizeof(_tension)); // Recopie du float sous la forme d'un tableau de byte
for (auto i = TLV_LENGTH[TENSION] - 1; i >= 0; i--) {
full_frame[start_from + count] = tension_uint8[i];
count++;
}
Réception de la trame Beacon
Pour ce qui concerne la réception de la trame, plusieurs solutions sont possible, notamment : Solution n°1 : Utiliser une clé Wifi externe connectée sur un système Linux ou Raspberry Pi avec un programme Python. • Solution n°2 Utiliser le logiciel Wireshark sur Linux avec le récepteur Wifi en mode moniteur. • Solution n°3 : Utiliser une autre carte ESP32, puis programmer la carte pour visualiser les trames sur le moniteur série de l’IDE Arduino.
source: Conception d’une balise de signalement électronique. Julien Launay.
Dans un premier temps nous allons essayer la solution numéro 3 à l'aide d'une seconde carte ESP32 programmée en tant que récepteur.
Modification de la réception
Un code de transmission nous était également fourni, il suffisait d'y ajouter la lecture de tension maintenant présente dans notre trame. La réception consiste uniquement à lire les informations transmises à l'émission et à les interpréter, nous avons donc utiliser la même logique qu'a l'émission afin de récupérer notre tension.
uint8_t count = size-1;
int data_value = 0;
uint8_t donnees[4];
float tension;
for(uint16_t i = start; i < len && i < start+size; i++) {
donnees[count] = (data[i]);
count--;
}
memcpy(&tension, donnees, sizeof(tension)); // Recopie du float à partir d'un tableau de byte
trame = trame + String(tension) + "V";
On obtient alors une lecture fonctionnelle des trames beacon émises par la carte esp32 n°1 :
Cependant il est trop compliqué pour un utilisateur qui ne connait pas le système de lire la trame, le code initial fournissait une solution afin de lire la trame sur son téléphone en utilisant le Bluetooth Low Energy mais il est nécessaire d'installer une application sur son telephone afin d'y avoir accès facilement.
Dans ce cas un serveur web nous paraissait pertinent mais l'esp32 de réception utilise déjà sa carte wifi afin de réceptionner les trames, une troisième carte esp32 est donc nécessaire.
Transmission des informations sur un serveur web en série
Cette troisième carte a besoin de recevoir la trame décodée afin de pouvoir l'émettre à l'aide d'un serveur web. La solution retenue est de faire communiquer notre carte de réception et notre 3ème carte en UART à l'aide d'une liaison série. Le schéma de câblage est le suivant :
Le code nécessaire à cette communication est le suivant : Initialisation de la liaison sur les deux cartes (En tête de code):
#define RX 16 #define TX 17 #include <SoftwareSerial.h> SoftwareSerial mySerial(RX,TX)
Dans la fonction setup des deux cartes :
pinMode(RX, INPUT); pinMode(TX, OUTPUT); mySerial.begin(4800);
Quand on souhaite émettre un message il suffit d'appeler la fonction suivante :
mySerial.println(contenuEmission);
La carte qui fait office de serveur web lit les données à l'aide de la fonction readStringUntil :
if(mySerial.available()){
char character;UART_read = "";
while(mySerial.available()){
UART_read = mySerial.readStringUntil('\n');
}
Serial.println(UART_read);
}
La liaison n'est pas parfaite, parfois certains caractère disparaissent ou sont modifiées, nous pensons que ces perturbations sont dus aux câbles ou à des faux contacts.
Mise en place du serveur web
La carte du serveur web reçoit maintenant la trame, il faut alors mettre en place le serveur web afin d'afficher celle ci. Un code de base était déjà fourni par espressif afin d'avoir un serveur web qui a une seule route et affiche Hello Word, ce code a été légèrement modifié afin d'afficher la chaine de caractére récupérée précédemment. Initialisation du serveur web et du point d'accès :
const char* ssid = "test12345678"; const char* password = "12345678"; WebServer server(80);
Dans la fonction setup :
WiFi.begin(ssid, password);
Serial.println("Creation du point d'acces...");
WiFi.softAP(ssid, password);
Serial.print("Adresse IP: ");
Serial.println(WiFi.softAPIP());
Serial.println("");
server.on("/", handleRoot);
server.on("/inline", []() {
server.send(200, "text/plain", "this works as well");
});
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
Dans la fonction loop :
server.handleClient();
La route "/" appelle la fonction "handleRoot", c'est cette fonction qui nous permet d'envoyer une page web avec la trame au client :
void handleRoot() {
server.send(200, "text/plain", UART_read);
}
Le serveur web est maintenant fonctionnel et nous fourni bien une page web avec la trame dedans :

