Upload
truongtram
View
215
Download
0
Embed Size (px)
Citation preview
ECOLE POLYTECHNIQUE
UNIVERSITAIRE DE
NICE SOPHIA-ANTIPOLIS
Parcours des écoles d'ingénieurs Polytech
Deuxième année
Année scolaire 2015-2016
PROJETS ELECTRONIQUE AVEC ARDUINOTélémesures embarquées dans une fusée
Étudiante : Maéva MANUEL
Encadrants : Fabien FERRERO et Pascal MASSON
3
SOMMAIRE
Chapitre 1 : Introduction et cahier des charges ..................................................................... 4
Chapitre 2 : Communication RF 433 MHz ........................................................................... 5
2.1. Présentation des modules .................................................................................................................................................... 5
2.2. Présentation de la librairie « Virtual Wire » ....................................................................................................................... 5
2.3. Envoi des données d’un capteur ......................................................................................................................................... 5
2.3.1. Envoi d’un simple texte .............................................................................................................................................. 5 2.3.2. Envoi d’un nombre ..................................................................................................................................................... 5 2.3.3. Calibrage de l'antenne ................................................................................................................................................. 6
Chapitre 3 : Les capteurs ....................................................................................................... 7
3.1. Le capteur d’humidité/température DHT11........................................................................................................................ 7
3.2. Le capteur de pression barométrique MPL3115A2 ............................................................................................................ 7
3.2.2. Capteur piezoresistif ................................................................................................................................................... 7 3.2.3. Mise en œuvre du capteur et bus I2C .......................................................................................................................... 8 3.2.4. La libraire MPL3115A2 .............................................................................................................................................. 8
3.3. Module RTC ....................................................................................................................................................................... 8
3.4. Le panneau de LED .......................................................................................................................................................... 10
Chapitre 4 : Mise en œuvre de l’ensemble des éléments .................................................... 11
4.1. Récupération des données des capteurs ............................................................................................................................ 11
4.2. Envoi des données au récepteur RF .................................................................................................................................. 11
4.3. Réception des données ...................................................................................................................................................... 11
4.3. Affichage des informations sur le panneau de LED ......................................................................................................... 11
Chapitre 5 : Conclusions et perspectives ............................................................................. 13
Références ........................................................................................................................... 15
Programme : émission des données ..................................................................................... 17
Programme : réception des données .................................................................................... 23
Programme : affichage des données .................................................................................... 31
4
Chapitre 1 : Introduction et cahier des charges
Ce projet Arduino, dans la continuité du projet « Électronique de guidage d’une FUSEE et mesures embarquées »
qui a débuté en octobre 2015, a pour objectif de développer la communication de la fusée avec la Terre et ainsi de
pouvoir envoyer les données de vol qu'elle récolte grâce à ses multiples capteurs intégrés. Du fait des grandes
distances qui séparent la fusée du sol, nous avons recours à un module RF d'envoi et de réception associés à une
antenne spécialement conçue pour la fusée. D'autre part, nous choisissons d'effectuer des mesures de pression
atmosphérique (module MPL3115), de température et d'humidité (capteur DHT11). Afin de déterminer la position
exacte de la fusée en temps réel, nous utilisons la géolocalisation du GPS (altitude, latitude et longitude) ainsi que
le module d'heure RTC. De ce fait, après le très célèbre décompte des 10 secondes avant le lancement, nous
affichons toutes les données récupérées par la fusée en vol grâce à un panneau de LED prévu à cet effet.
5
Chapitre 2 : Communication RF 433 MHz
2.1. Présentation des modules
Les modules de transmission et réception RF présentés
à la figure (2.1) permettent d’envoyer des informations
sur des distances supérieures à 200 m ce qui est bien
plus élevé que le Bluetooth. Les deux modules sont
réglés sur la même fréquence de 433 MHz et ils ont été
conçus pour être alimentés en 5 V (en réalité entre 3 à
12V) ce qui correspond exactement à la tension
d’alimentation de la carte Arduino. Afin de pouvoir les
faire fonctionner, nous avons soudé des fils, jouant le
rôle d'antenne) d'une longueur minimale de 32 cm.
Les informations sont envoyées sans adresse (tous les
modules de réception reçoivent les mêmes informations
ce qui n’est pas problématique car nous n'utilisons
qu’un récepteur) et sans demande de confirmation (la
liaison ne se fait que dans un sens).
Figure 2.1. modules de transmission et réception RF
433 MHz
L’envoie des données est faite avec une modulation d’amplitude de type ASK (Amplitude Shift Keying).
L’amplitude de la porteuse (sinusoïde de fréquence 433 MHz) est maximale pour l’envoi d’un « 1 » logique et
devient nulle lors de l’envoi d’un « 0 » logique.
A noter également que la fréquence 433 MHz est libre de droit et qu’elle est donc fréquemment utilisée pour les
commandes de volets, de portails, de portes de garage mais aussi les stations météo sans fil, les écoutes bébés...
2.2. Présentation de la librairie « Virtual Wire »
La librairie « VirtualWire » est à télécharger sur le site :
www.airspayce.com/mikem/arduino/VirtualWire/VirtualWire-1.27.zip
et le dossier doit être décompressé dans le répertoire "libraries" du logiciel Arduino.
Cette libraire est d’une utilisation simple et nous donnons ici quelques exemples de fonctions :
- vw_setup(2000) : permet de définir la vitesse de transmission, dans cet exemple de 2000 bits par seconde
- vw_send(message, longueur) : envoie un “message” d'une certaine “longueur”
- vw_wait_tx() : arrête le déroulement du programme jusqu’à ce que le message soit envoyé
2.3. Envoi des données d’un capteur
2.3.1. Envoi d’un simple texte
Pour comprendre le fonctionnement des modules RF, nous avons utilisé le premier exemple de la librairie qui
envoie le texte "hello", défini comme une chaîne de caractère. Le message reçu et affiché sur le port série est « 68
65 6C 6C 6F » car le programme impose d’afficher le message en hexadécimal (Serial.print(buf[i], HEX) où buf[i]
est le message reçu). La lecture en hexadécimale n’étant pas intuitive, nous avons décidé de modifier cette ligne de
code afin d'afficher le texte reçu tel quel sur l’écran : Serial.print((char) buf[i]). Nous avons alors vérifié la bonne
réception du message en éloignant les 2 modules, l’émetteur restant dans la salle 388 de TP et le récepteur se
trouvant au niveau du bâtiment administratif.
2.3.2. Envoi d’un nombre
Pour émuler un capteur, nous avons choisi de brancher un potentiomètre sur une des entrées analogiques de la carte
Arduino émettrice. Le nombre à envoyer doit être converti en une chaîne de caractère car la libraire
6
« WirtualWire » ne supporte que ce type de variables. Cette conversion s'effectue à l'aide de la fonction : sprintf(Y,
"%f", X) où X est le chiffre et Y la chaîne de caractère.
Néanmoins, cette fonction (pourtant utilisée dans de nombreux exemples) n’est pas compilée par l'IDE (Integrated
Development Environment) et il nous a été nécessaire de la remplacer. Nous avons finalement utilisé la fonction :
dtostrf(X,4,2,Y) où 4 est le nombre minimum de chiffres composant le nombre à envoyer, et 2 correspond au
nombre de chiffres après la virgule.
Du côté réception, il a fallu transformer la chaîne de caractères reçue en un float. Pour cela, nous utilisons la
fonction atof : float Y = atof(X) où X est la chaîne de caractères reçue et Y le nombre qui lui correspond.
Lors des essais, nous avons fait varier la tension obtenue avec le potentiomètre, puis nous l’avons affichée sur le
moniteur série et comparée avec le nombre obtenu côté réception.
2.3.3. Calibrage de l'antenne
Afin de calibrer au mieux l'antenne (c.f. figure (2.2)), nous avons eu recours à un analyseur de réseau vectoriel
(VNA, Vector Network Analyser). Cet appareil permet de mesurer le défaut d'adaptation d'impédance entre deux
composants radiofréquences et de ce fait d'optimiser l'intégrité d'un signal. Dès qu'une onde quitte un composant
pour entrer dans un autre, elle se divise en une onde réfléchie et une onde transmise. En mesurant le rapport de
l'énergie réfléchie sur l'énergie émise, qui varie avec la fréquence, le VNA détermine les performances du matériel
sous test. Dans le cas présent, c'est le module RF 433MHz qui assure le rôle du DUT (Dispositif Under Test). Nous
nous intéressons donc au coefficient de réflexion, noté S11 (le premier « 1 » indique le numéro du port de l'onde
réfléchie et le deuxième celui du port du signal incident) dont nous donnons la valeur en fonction de la fréquence à
la figure (2.3). Il est représenté en dB en fonction de la fréquence en Hz.
Tout d'abord, nous avons procédé à l'étalonnage SOLT (Short, Open, Load, Through). Le court-circuit induit un
déphasage de 180° entre les ondes émises et réfléchies ainsi qu'un rapport qui tend vers 0 donc un pic qui tend vers
moins l'infini en dB (réflexion quasi nulle que l'on souhaite approcher). A l'inverse, le circuit ouvert implique un
déphasage proche de 0° et un rapport qui tend vers 1 en linéaire donc 0dB (réflexion totale). Pour une impédance
de sortie de 50Ohms, nous avons mesuré -60dB, soit un million de fois moins d'énergie que celle qui a été envoyée.
Le but est ici de déterminer la fréquence exacte du module RF et de dimensionner l'antenne pour approcher au
mieux cette fréquence sur le VNA (l'énergie réfléchie doit être minimale). Nous avons proportionné l'antenne en
déplaçant le plus grand pic négatif vers la fréquence de 433,8 MHz mesurée préalablement.
Dans un premier temps, nous avons pris une antenne dont la taille est d'une demi-fois la longueur d'onde
cm7010.8,43310.3c 68 (2.1)
Nous avons ensuite enroulé l'antenne autour du corps de la fusée et coupé petit à petit le fils (soudé auparavant sur
un port SMA lui-même relié au port 1 du VNA) jusqu'à décaler vers la droite le pic choisi à 433MHz. Nous avons
également rajouté de la masse autour du connecteur afin d'augmenter la différence de potentiel entre la masse et la
borne plus. A la fin du dimensionnement, nous avons noté un gain de 10dB. En effet, au départ le plus grand pic
se trouvait à 30dB et durant la calibration de l'antenne il est descendu jusqu'à la valeur finale de 40dB.
Figure 2.2. Vue de l’antenne fixée au corps de la fusée Figure 2.3. Vue du VNA et de la mesure de S11
7
Chapitre 3 : Les capteurs
Ce chapitre porte sur les différents capteurs que nous avons placés dans le corps de la fusée.
3.1. Le capteur d’humidité/température DHT11
Le module numérique DHT11 délivre et reçoit un signal
digital sur une entrée/sortie série unique. Ses deux capteurs
analogiques sont une résistance qui détermine le taux
d’humidité et une thermo-résistance de type NTC (Negative
Temperature Coefficient) afin de mesurer la température. La
calibration du module est faite en usine et les paramètres sont
sauvés dans une mémoire OTP (One Time Programming,
comme celle vue en TD de PeiP1 sur les diodes). Le lien
entre l’arduino et les capteurs est assuré par un
microcontrôleur 8 bits. Une communication avec le module
s'effectue sur 40 bits et dure typiquement 4ms. Il coûte
environ 2€ sur eBay.
Figure 3.1. Vue du capteur
d’humidité/température DHT11
Les dimensions du module sans les broches sont de 14 32 8 mm pour une masse de 2 g. Il peut être alimenté
entre 3.5 et 5V. Sa précision et ses caractéristiques de mesures sont :
Humidité de l’air (RH : Relative Humidity) : 20-90 % avec une précision de 4%
Température de l’air : 0-50°C avec une précision de 1°C
La librairie adafruit DHT-sensor-library permet d’utiliser ce module.
3.2. Le capteur de pression barométrique MPL3115A2
3.2.1. Présentation générale
Afin d’évaluer la pression et la température atmosphérique en fonction de
l’altitude durant le vol nous avons recours au capteur MPL3115A2 utilisant
le bus I2C (Inter Integrated Circuit) pour communiquer avec l’arduino. Il
mesure 18mm de longueur, 19mm de largeur et 2mm de profondeur pour
une masse de 1,2g.
Selon la datasheet, il a une gamme de mesure comprise entre 50 et 110kPa
(avec une précision de 1,5Pa) ce qui correspond à une altitude de 10km. Il
donne la température dans la gamme [40 ; + 85 °C] avec une précision de
1 °C. Il coûte environ 12€ sur eBay.
Figure 3.2. Vue de l’altimètre
MPL3115A2
3.2.2. Capteur piezoresistif
Le module MPL311 utilise un capteur MEMS
(MicroElectroMechanical Systems) piezoresistif que l’on
peut observer sur la partie gauche de la figure (3.3).
Des résistances sont intégrées à une membrane posée sur une
cavité et ayant une certaine pression interne. La moindre
pression exercée sur la paroi externe de la membrane induit
une contrainte mécanique sur les résistances qui changent de
valeur. Cette variation permet ainsi de déterminer la pression
qui a été appliquée.
Figure 3.3. Vue du MEMS et du circuit intégré de
l’altimètre MPL3115A2
8
3.2.3. Mise en œuvre du capteur et bus I2C
I2C est un bus de données qui permet de relier un
microprocesseur (ici l’arduino) avec un ou plusieurs
capteurs (dans notre cas le baromètre/thermomètre). Il
nécessite deux fils de communication : SDA (Signal
Data) qui transmet les données et SCL (Signal Clock)
qui transmet un signal d’horloge synchrone.
Sur l’arduino UNO, ces pins correspondent
respectivement aux entrées analogiques A4 et A5 (c.f.
Fig. (3.4)) tandis que sur la MEGA se sont les broches
numériques 20 et 21. Le protocole du bus I2C définit la
succession des différents états possibles sur les lignes
SDA et SCL. Au départ, les deux lignes sont à l’état
haut. Le circuit fait passer la ligne SDA à 0 et le bus
devient occupé. En devenant le maître, le circuit gère le
signal d’horloge et fait passer la ligne SCL à 0.
Figure 3.4. Schéma de câblage de la carte Arduino et
de l’altimètre MPL3115A2
Les échanges de données sur 8 bits peuvent alors commencer sur le principe FIFO (First In First Out). Un bit
d’acquittement ACK doit également être transmis à la ligne SDA pour confirmer que l’esclave s’est bien acquitté
de l’octet qu’il a reçu. Le premier octet représente toujours l’adresse proprement dite de la transmission et son
dernier bit dit "R/W" indique si le maître demande une lecture (0) ou impose une écriture (1) à l’esclave. Toutes ces
étapes sont regroupées sur le chronographe de la figure (3.5).
Figure 3.5. Chronogramme du protocole I2C
3.2.4. La libraire MPL3115A2
L’utilisation de l’altimètre passe par une librairie dédiée à installer dans le logiciel arduino. Voici quelques-unes
des fonctions que nous avons utilisées :
mpl115a2.begin() : initialisation du module de pression
mpl115a2.GetTemperature() : permet d’obtenir la valeur de la température
mpl115a2.getPressure() : permet d’obtenir la valeur de la pression atmosphérique
3.3. Module RTC
A chaque mise sous tension de l’arduino, la carte réinitialise son
module de temps c’est pourquoi nous avons recours à un
module RTC (Real Time Clock) externe permettant de
déterminer des heures absolues. Ce module (c.f. Fig. (3.6))
fournit des informations temporelles en secondes, minutes,
heures, jour, date, mois et année. L’heure est donnée au format
12 ou 24h et il possède une correction automatique des années
bissextiles jusqu’en 2100.
Figure 3.6. Vue du module RTC (Real
Time Clock)
9
Le module de temps contient une puce d’horloge DS1302, une pile bouton CR2032 d’une capacité de 200mAh et
d’une puissance inférieure à 1µW qui permet de sauvegarder l'heure en cas de coupure de courant. Il fonctionne
grâce à un quartz d’une fréquence de 32.768kHz muni lui-même d’une capacité de 6pF. Le circuit doit être
alimenté avec une tension comprise entre 2 et 5.5V et consomme un courant de 300nA. Il mesure 44mm de long
pour 24mm de large. D’autre part, sa plage de fonctionnement s’étend de 40°C à +85°C pour un prix de 6€ sur le
site Hobby Electronic.
Le circuit communique grâce à son unique entrée/sortie (I/O)
série synchrone et possède 31 octets de SRAM (Static Random
Access Memory). Les données peuvent ainsi être transférées
vers et depuis l'horloge ou la RAM à raison de 1 octet à la fois,
ou par rafale de 31 octets. 3 fils sont donc nécessaires pour
échanger avec le DS1302 (cf. Fig.3.7):
CE (RST) contenant une résistance interne de
40kΩ
I/O (DATA) correspondant aux lignes de données
SCLK (Serial Clock) disposant d’une résistance
interne de 40 kΩ
Quartz
CPU
X1 X2
CE
I/O
SCLK
GND
3.3 V
Pile
VCCVCC2
VCC1
DS1302
Figure 3.7. Schéma des connexions du module
RTC
CE donne d'une part accès au registre de décalage, ensemble de bascules synchrones, selon l'adresse ou la
commande passé en paramètre mais aussi le choix de communiquer sur un ou plusieurs octets. Pour entamer le
transfert de données, la ligne CE passe de 0 à 1. SCLK jouant le rôle d’horloge permet de synchroniser le transfert
de données série. Par exemple pour une transmission entre le module RTC et la carte Arduino s'effectuant sur un
octet, l'échange n'a lieu qu'après 8 cycles complets de SCLK. (c. f. Fig (3.8)).
Figure 3.8. Chronogramme du transfert de données
L’implémentation du module d'heure s'effectue au travers de la librairie « DS1032 ». Nous présentons dans ce
paragraphe les fonctions qui nous ont été utiles :
rtc.time() : initialisation du module d'horloge
X.hr : permet d’obtenir l'heure
X.min : permet d’obtenir les minutes
10
X.sec : permet d’obtenir les secondes
X.date : permet d’obtenir la date
X.mon : permet d'obtenir le mois
X.yr : permet d'obtenir l'année
3.4. Le panneau de LED
Figure 3.4.1. Vue du panneau RGB de LED en
fonctionnement
La figure (3.4.1) illustre le panneau utilisé dans ce projet pour l'affichage des informations récoltées par la fusée en
vol. Nous n'avons trouvé qu'une unique librairie fonctionnelle qui permet d'afficher du texte et des géométries
simples comme par exemple des rectangles et des cercles. La superposition de textes sur le panneau implique
d'imposer un écran noir avant de réécrire un autre texte à la même position.
11
Chapitre 4 : Mise en œuvre de l’ensemble des éléments
4.1. Récupération des données des capteurs
Les données stockées dans des variables. En effet, à chaque tour de boucle, l'arduino stocke les données de chaque
capteur dans ces variables du type float (latitude, longitude, altitude, pression, humidité et température) et integer
(date et heure). En raison du nombre important de capteurs et d'entrées/sorties nécessaires, nous avons dû utiliser
une carte Arduino MEGA. Le principal problème rencontré reste néanmoins la synchronisation du GPS avec les
satellites auxquels il doit s’appareiller ainsi que la communication série de la carte qui est de 9600 bits par seconde
et non 4800 comme il est souvent cité dans les exemples pour ce GPS.
4.2. Envoi des données au récepteur RF
A la fin de chaque boucle, la fusée envoie grâce à la carte arduino les données au récepteur. A chaque début d'envoi
le code « 9999 » est envoyé afin d'identifier l'arrivée chronologique des différentes variables. Le module RF envoie
des integer et des float castés en chaînes de caractères.
4.3. Réception des données
La réception des données s'effectue par une deuxième carte arduino MEGA du fait du nombre de variables à traiter
et à stocker dans la mémoire de carte. Initialement, nous avons débuté les tests avec une simple carte arduino UNO
et la réception de 3 variables mais la carte a très vite planté lorsque nous sommes passés à 12 variables. La
condition principale (i.e. « if ») détecte l'arrivée du code « 9999 » ce qui implique le stockage des données avec la
conversion inverse (donc chaîne de caractères vers des float ou des int). Cette étape a été une des plus difficiles car
il a fallu trouver les bonnes fonctions de conversion sachant que certaines étaient proposées mais non compatibles
avec l'IDE. Les données sont affichées sur le moniteur série de l'ordinateur.
4.3. Affichage des informations sur le panneau de LED
Afin de rendre l'affichage un peu plus design et attractif, nous avons fait le choix d'afficher les données sur un
panneau de LED RGB 32*64. Cependant, nous nous sommes très vites aperçus de l'incompatibilité des librairies du
panneau de LED et du module RF. Il a donc fallu utiliser une troisième carte MEGA reliée à la seconde par une
liaison RX/TX. L'envoie des données à ce panneau se fait sur le même principe que celui choisi pour envoyer les
données entre la fusée et la Terre (code « 9999 »). La carte de réception envoie en continu les informations qui ne
sont affichées alternativement par paquets de 3 toutes les 2 secondes. En effet, les données du GPS sont affichées
en premier suivies des données des capteurs de pression, d'humidité et de température.
13
Chapitre 5 : Conclusions et perspectives
Le cahier des charges a donc été respecté avec la modification, entreprise à la première séance, de comprendre et
d'utiliser un module GSM pour communiquer avec un téléphone sur la position de la fusée après atterrissage. Nous
avons axé notre travail dans cette partie du projet sur la liaison RF mais le module GSM s'inclut plus largement
dans le projet fusée qui se poursuivra en département électronique à Sophia.
Toutes les difficultés rencontrées ont été surmontées et/ou contournées et proviennent essentiellement des
problèmes de compatibilité de librairies, de conversion de variables et de librairies elles-mêmes.
Nous envisageons de plus d’intégrer les différents capteurs et modules utilisés dans ce projet au futur projet
ExoMars qui débutera en 3ème année du cycle ingénieur à Sophia en spécialité électronique.
15
Références
Le capteur d’humidité/température DHT11
Datsheet : www.micropik.com/PDF/dht11.pdf
Librairie : github.com/adafruit/DHT-sensor-library
L'antenne
http://www.bde.enseeiht.fr/clubs/ieee/documents/arv.pdf
http://www.ni.com/white-paper/11640/fr/
http://f6crp.pagesperso-orange.fr/ba/minivna.htm
Le capteur de pression barométrique MPL3115A2
Datasheet : cache.freescale.com/files/sensors/doc/data_sheet/MPL115A2.pdf
Librairie : github.com/adafruit/Adafruit_MPL115A2
Capteur pression piézorésistif : www.microsystems.metu.edu.tr/piezops/piezops.html
17
Programme : émission des données
#include <VirtualWire.h> // inclusion de la librairie VirtualWire
//communication RF 433 MHz
#include <Adafruit_MPL115A2.h>//librairie du module de pression atmosphérique
#include <Wire.h>
#include "DHT.h"//librarie du module d'humidité
#include <stdio.h>
#include <DS1302.h>
#include <TinyGPS.h>//librairie du GPS
//fonctions nécessaires à l'utilisation du GPS
TinyGPS gps;
static void smartdelay(unsigned long ms);
//module dhumidité
#define DHTPIN 22//pin de signal
#define DHTTYPE DHT11//instancie le module DHT 11
DHT dht(DHTPIN, DHTTYPE);
//module d'horloge
const int kCePin = 5; // Chip Enable
const int kIoPin = 6; // Input/Output
const int kSclkPin = 7; // Serial Clock
DS1302 rtc(kCePin, kIoPin, kSclkPin);// Create a DS1302 object
Adafruit_MPL115A2 mpl115a2;//capteur de pression
//définition de toutes les variables utilisées pour les mesures
float humidite = 0;
char message_humidite[4];
//taille max de 4 caractères pour la mesure
float pressureKPA = 0;
char message_pressureKPA[4];
float temperatureC = 0;
char message_temperatureC [4];
int heures = 0;
18
char message_heures[4];
int minutes = 0;
char message_minutes[4];
int secondes = 0;
char message_secondes[4];
int jour = 0;
char message_jour[4];
int mois = 0;
char message_mois[4];
int annee = 0;
char message_annee[4];
char *Jsemaine = "HHH";
char *separ = "9999";//séparateur entre chaque salve d'envoi des données
float flat, flon, falt; // latitude, longitude, altitude
char message_flat[10];
char message_flon[10];
char message_falt[10];
unsigned long age; // ne sert que pour la lecture d'une des fonctions du GPS
void setup()
vw_setup(2000); //correspond au nombre de bits par sec pour la communication RF 433 MHz
Serial3.begin(9600); //vitesse de communication du GPS brancher sur le com série n°3
dht.begin();//initialisation du module d'humidité
mpl115a2.begin();//initialisation du module de pression
void loop()
//lecture de différentes mesures et attributions des variables
smartdelay(1000); //attente de la réception de données GPS
gps.f_get_position(&flat, &flon, &age); //lecture latitude, longitude
falt = gps.f_altitude(); // lecture altitude
19
humidite = dht.readHumidity();
temperatureC = mpl115a2.getTemperature();
pressureKPA = mpl115a2.getPressure();
//date et heure
Time X = rtc.time();
heures = X.hr;
minutes = X.min;
secondes = X.sec;
jour = X.date;
mois = X.mon;
annee = X.yr;
// envoi du code "9999" pour la détetcion de l'arrivée des données
vw_send((uint8_t *)separ, strlen(separ));
vw_wait_tx();// attendre jusqu'à ce que le message soit enovyé entièrement
// envoi de la latitude
dtostrf(flat,4,6,message_flat); //largeur mimimale 4, 2 chiffres après la virgule
vw_send((uint8_t *)message_flat, strlen(message_flat));
vw_wait_tx();
// envoi de la longitude
dtostrf(flon,4,6,message_flon); //largeur mimimale 4, 2 chiffres après la virgule
vw_send((uint8_t *)message_flon, strlen(message_flon));
vw_wait_tx();
// envoi de l'altitude
dtostrf(falt,4,6,message_falt); //largeur mimimale 4, 2 chiffres après la virgule
vw_send((uint8_t *)message_falt, strlen(message_falt));
vw_wait_tx();
// envoi du pourcentage d'humidité
dtostrf(humidite,4,2,message_humidite); //largeur mimimale 4, 2 chiffres après la virgule
vw_send((uint8_t *)message_humidite, strlen(message_humidite));
vw_wait_tx();
// envoi de la température
20
dtostrf(temperatureC,4,2,message_temperatureC);
vw_send((uint8_t *)message_temperatureC, strlen(message_temperatureC));
vw_wait_tx();
// envoi de la pression
dtostrf(pressureKPA,4,2,message_pressureKPA);//convertit les float en char
vw_send((uint8_t *)message_pressureKPA, strlen(message_pressureKPA));
vw_wait_tx();
// envoi de l'heure
itoa(heures,message_heures,10);//convertit les int en char
vw_send((uint8_t *)message_heures, strlen(message_heures));
vw_wait_tx();
// envoi des minutes
itoa(minutes,message_minutes,10);
vw_send((uint8_t *)message_minutes, strlen(message_minutes));
vw_wait_tx(); // Wait until the whole message is gone
// envoi des secondes
itoa(secondes,message_secondes,10);
vw_send((uint8_t *)message_secondes, strlen(message_secondes));
vw_wait_tx();
// envoi du jour
itoa(jour,message_jour,10);
//10 signifie que l'on est en base 10 donc en décimal
vw_send((uint8_t *)message_jour, strlen(message_jour));
vw_wait_tx();
// envoi du mois
itoa(mois,message_mois,10);
vw_send((uint8_t *)message_mois, strlen(message_mois));
vw_wait_tx();
// envoi de l'année
itoa(annee,message_annee,10);
vw_send((uint8_t *)message_annee, strlen(message_annee));
vw_wait_tx();
21
delay(2000);
static void smartdelay(unsigned long ms)
unsigned long start = millis();
do
while (Serial3.available())
gps.encode(Serial3.read());
while (millis() - start < ms);
23
Programme : réception des données
#include <VirtualWire.h>
// Detection des données
int separ;
char message[VW_MAX_MESSAGE_LEN];
//données GPS
//latitude, longitude, altitude
float flat=1.11, flon=2.22, falt=3.33;
char message_flat[VW_MAX_MESSAGE_LEN];
char message_flon[VW_MAX_MESSAGE_LEN];
char message_falt[VW_MAX_MESSAGE_LEN];
//VW_MAX_MESSAGE_LEN est de 80 par défaut
//nombre maximum de bytes dans le message
// création des variables relatives aux capteurs
float humidite=4.44;
char message_humidite[VW_MAX_MESSAGE_LEN];
float temperatureC;
char message_temperatureC[VW_MAX_MESSAGE_LEN];
float pressureKPA;
char message_pressureKPA[VW_MAX_MESSAGE_LEN];
int heures=0;
char message_heures[VW_MAX_MESSAGE_LEN];
int minutes=0;
char message_minutes[VW_MAX_MESSAGE_LEN];
int secondes=0;
char message_secondes[VW_MAX_MESSAGE_LEN];
int jour=0;
24
char message_jour[VW_MAX_MESSAGE_LEN];
int mois=0;
char message_mois[VW_MAX_MESSAGE_LEN];
int xm=0;
char message_m[VW_MAX_MESSAGE_LEN];
int annee=0;
char message_annee[VW_MAX_MESSAGE_LEN];
void setup()
Serial.begin(9600);
//initialisation de la vitesse de communication dans le moniteur série numéro 1
Serial2.begin(4800);//communication série numéro 2
Serial.println("debut");
vw_set_ptt_inverted(true);
//par défaut le PTT prend la valeur HIGH
//cette fonction permet de forcer la valeur à LOW
//si on lui passe en paramètre true
vw_setup(2000);
vw_rx_start();//début de la réception
void loop()
vw_wait_rx();
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen))
//If a message is available
//copies up to buflen octets to buf
int i;
for (i = 0; i < buflen; i++)
message[i] = char(buf[i]);
message [buflen] = '\0';
//pour les problèmes de conversion en char
//conversion du char en int
separ= atoi(message);
25
// on teste si le message reçu correspond à l'envoi d'une série de données
if (separ==9999)
vw_wait_rx_max(200);
uint8_t buf_flat[VW_MAX_MESSAGE_LEN];
uint8_t buflen_flat = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_flat, &buflen_flat))
int i1;
for (i = 0; i < buflen_flat; i++)
message_flat[i] = char(buf_flat[i]);
message_flat[buflen_flat] = '\0';
flat = atof(message_flat);
Serial.print("Latitude : ");
Serial.println(message_flat);
// end if latitude
vw_wait_rx_max(200);
uint8_t buf_flon[VW_MAX_MESSAGE_LEN];
uint8_t buflen_flon = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_flon, &buflen_flon))
int i1;
for (i = 0; i < buflen_flon; i++)
message_flon[i] = char(buf_flon[i]);
message_flon[buflen_flon] = '\0';
flon = atof(message_flon);
Serial.print("Longitude : ");
Serial.println(message_flon);
// end if longitude
vw_wait_rx_max(200);
uint8_t buf_falt[VW_MAX_MESSAGE_LEN];
uint8_t buflen_falt = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_falt, &buflen_falt))
int i1;
for (i = 0; i < buflen_falt; i++)
message_falt[i] = char(buf_falt[i]);
26
message_falt[buflen_falt] = '\0';
falt = atof(message_falt);
Serial.print("Altitude : ");
Serial.println(falt);
// end if altitude
vw_wait_rx_max(200);
uint8_t buf_humidite[VW_MAX_MESSAGE_LEN];
uint8_t buflen_humidite = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_humidite, &buflen_humidite))
int i1;
for (i = 0; i < buflen_humidite; i++)
message_humidite[i] = char(buf_humidite[i]);
message_humidite[buflen_humidite] = '\0';
float humidite = atof(message_humidite);
Serial.print("Humidite : ");
Serial.println(humidite);
// end if humidite
vw_wait_rx_max(200);
uint8_t buf_temperatureC[VW_MAX_MESSAGE_LEN];
uint8_t buflen_temperatureC = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_temperatureC, &buflen_temperatureC))
int i;
for (i = 0; i < buflen_temperatureC; i++)
message_temperatureC[i] = char(buf_temperatureC[i]);
message_temperatureC[buflen_temperatureC] = '\0';
float temperatureC = atof(message_temperatureC);
Serial.print("Temperature : ");
Serial.println(temperatureC);
// end if temperature
vw_wait_rx_max(200);
uint8_t buf_pressureKPA[VW_MAX_MESSAGE_LEN];
uint8_t buflen_pressureKPA = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_pressureKPA, &buflen_pressureKPA))
27
int i1;
for (i1 = 0; i1 < buflen_pressureKPA; i1++)
message_pressureKPA[i1] = char(buf_pressureKPA[i1]);
message_pressureKPA[buflen_pressureKPA] = '\0';
float pressureKPA = atof(message_pressureKPA);
Serial.print("Pression : ");
Serial.println(pressureKPA);
// end if pressureKPA
vw_wait_rx_max(200);
uint8_t buf_heures[VW_MAX_MESSAGE_LEN];
uint8_t buflen_heures = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_heures, &buflen_heures))
int i2;
for (i2 = 0; i2 < buflen_heures; i2++)
message_heures[i2] = char(buf_heures[i2]);
message_heures[buflen_heures] = '\0';
heures = atoi(message_heures);
Serial.print("Heure : ");
Serial.print(heures);
Serial.print(":");
// end if heures
vw_wait_rx_max(200);
uint8_t buf_minutes[VW_MAX_MESSAGE_LEN];
uint8_t buflen_minutes = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_minutes, &buflen_minutes))
int i3;
for (i3 = 0; i3 < buflen_minutes; i3++)
message_minutes[i3] = char(buf_minutes[i3]);
message_minutes[buflen_minutes] = '\0';
minutes = atoi(message_minutes);
Serial.print(minutes);
Serial.print(":");
// end if minutes
28
vw_wait_rx_max(200);
uint8_t buf_secondes[VW_MAX_MESSAGE_LEN];
uint8_t buflen_secondes = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_secondes, &buflen_secondes))
int i4;
for (i4 = 0; i4 < buflen_secondes; i4++)
message_secondes[i4] = char(buf_secondes[i4]);
message_secondes[buflen_secondes] = '\0';
secondes = atoi(message_secondes);
Serial.println(secondes);
// end if secondes
vw_wait_rx_max(200);
uint8_t buf_jour[VW_MAX_MESSAGE_LEN];
uint8_t buflen_jour = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_jour, &buflen_jour))
int i5;
for (i5 = 0; i5 < buflen_jour; i5++)
message_jour[i5] = char(buf_jour[i5]);
message_jour[buflen_jour] = '\0';
jour = atoi(message_jour);
Serial.print("Jour : ");
Serial.print(jour);
Serial.print("/");
// end if jour
vw_wait_rx_max(200);
uint8_t buf_mois[VW_MAX_MESSAGE_LEN];
uint8_t buflen_mois = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_mois, &buflen_mois))
int i6;
for (i6 = 0; i6 < buflen_mois; i6++)
message_mois[i6] = char(buf_mois[i6]);
message_mois[buflen_mois] = '\0';
mois = atoi(message_mois);
Serial.print(mois);
29
Serial.print("/");
// end if mois
vw_wait_rx_max(200);
uint8_t buf_annee[VW_MAX_MESSAGE_LEN];
uint8_t buflen_annee = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf_annee, &buflen_annee))
int i7;
for (i7 = 0; i7 < buflen_annee; i7++)
message_annee[i7] = char(buf_annee[i7]);
message_annee[buflen_annee] = '\0';
annee = atoi(message_annee);
Serial.println(annee);
// end if mois
// end if Separ
Serial.println(" ");
//end if message
Serial2.println(separ);
delay(200);
Serial2.println(flat);
delay(200);
Serial2.println(flon);
delay(200);
Serial2.println(falt);
delay(200);
Serial2.println(message_humidite);
delay(200);
Serial2.println(message_temperatureC);
delay(200);
Serial2.println(message_pressureKPA);
delay(1000);
// end loop
31
Programme : affichage des données
#include <Adafruit_GFX.h> // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library
//définition des pins correspondant au panneau de LED
#define OE 9
#define LAT 10
#define CLK 11
#define A A0
#define B A1
#define C A2
#define D A3
//initialisation du panneau de lED
RGBmatrixPanel matrix(A, B, C, D, CLK, LAT, OE, false, 64);
char message[20];
//variable qui va contenir le message du récepteur RF
int separ;
//variable du séparateur
int i=0;
//indice du tableau que l'on lit pour récupérer les données du récepteur
unsigned long temps=0;
//variable qui permet d'attendre un certain temps pour afficher un message
//visible sur le panneau de LED
int vtest=1;
//variable qui permet de différencier la première ou la seconde salve d'affichage des données
//les doonnées GPS pour la première avec vtest=1
//les autres capteurs pour la deuxième avec vtest=2
int ini=0;
//variable qui permet de n'afficher le décompteur qu'une seule fois
int i2=9;//début du décompteur
//création des variables de données
float flat=0.0;//latitude
char message_flat[20];
32
float flon=0.0;//longitude
char message_flon[20];
float falt=0.0;//altitude
char message_falt[20];
float humidite=0.0;//humidité
char message_humidite[20];
float temperature=0.0;//température
char message_temperature[20];
float pression=0.0;//pression
char message_pression[20];
void setup()
matrix.begin(); // initialisation du la matrice de LED
matrix.setTextSize(1); // size 1 == 8 pixels high
matrix.setTextWrap(false);
matrix.setCursor(20, 10); // start at top left, with 8 pixel of spacing
matrix.setTextColor(matrix.Color333(7,7,7));//détermine la couleur d'écriture
matrix.println("SETUP");
Serial2.begin(4800);//initialisation de la vitesse d'écriture sur le port série 2
Serial.begin(9600);
delay(500);
void loop()
if(ini<1)
uint8_t w = 0;
int j=20;
for (i2=9; i2>0; i2--)//boucle du décompteur
for (j=20; j>0; j--) //boucle relative au cercle qui diminue de volume
for (w=0; w<16; w++) //boucle relative au tracé du cercle
matrix.setTextColor(Wheel(w));
matrix.print(i2);//affiche le nombre du décompteur
matrix.setCursor(29,13);
matrix.drawCircle(31,16,j--, matrix.Color333(0, 0, 7));//trace le cercle d'une couleur bleue
delay(30);
matrix.fillScreen(matrix.Color333(0, 0, 0));// fill the screen with black
33
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setTextSize(1);//taille de 8px
matrix.setCursor(25,13);
matrix.print("GO !");//affichage de GO sur le pannel
delay(500);
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setTextSize(2);//grande taille *
matrix.setCursor(15,10);
matrix.print("GO !");
delay(500);
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setTextSize(1);
matrix.setCursor(5,13);
matrix.print("Decollage");//affichage du mot 'Decollage'
matrix.setTextSize(1);
temps=millis();
ini=1;
//fin du décompte pour éviter au prochain passage dans le loop d'afficher de nouveau le décompteur
Serial.println("loop");
if (Serial2.available()>0)
while (Serial2.available()>0)
for (i = 0; i < 20; i++)//tableau initial d'une longeur de 20
message[i] = char(Serial2.read());//lecture des données sur le port série 2
separ= atoi(message);//conversion du message en int
Serial.println(separ);
//---------------------------------------------
if (separ==9999) //si on rencontre le séparateur
delay(200);
if (Serial2.available()>0)
while (Serial2.available()>0)
34
for (i = 0; i < 20; i++)
message_flat[i] = char(Serial2.read());//on ajoute la valeur à la variable de latitude
flat = atof(message_flat);
//end if flat -----------------------------------------------
delay(200);
if (Serial2.available()>0)
while (Serial2.available()>0)
for (i = 0; i < 20; i++)
message_flon[i] = char(Serial2.read());
flon = atof(message_flon);
//end if flon -----------------------------------------------
delay(200);
if (Serial2.available()>0)
while (Serial2.available()>0)
for (i = 0; i < 20; i++)
message_falt[i] = char(Serial2.read());
falt = atof(message_falt);
//end if falt ------------------------------------------------
delay(200);
if (Serial2.available()>0)
while (Serial2.available()>0)
for (i = 0; i < 20; i++)
message_humidite[i] = char(Serial2.read());
humidite = atof(message_humidite);
//end if humidite ---------------------------------------------
delay(200);
if (Serial2.available()>0)
35
while (Serial2.available()>0)
for (i = 0; i < 20; i++)
message_temperature[i] = char(Serial2.read());
temperature = atof(message_temperature);
//end if temperature ------------------------------------------
delay(200);
if (Serial2.available()>0)
while (Serial2.available()>0)
for (i = 0; i < 20; i++)
message_pression[i] = char(Serial2.read());
pression = atof(message_pression);
//end if pression -------------------------------------------
//end if separ
//end if serial2.available()
//affichage des données récupérées sur le terminal
Serial.println(flat);
Serial.println(flon);
Serial.println(falt);
Serial.println(humidite);
Serial.println(temperature);
Serial.println(pression);
delay(100);
if ((millis()>(temps+2000))*(vtest==1))//première salve d'affiche
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setTextColor(matrix.Color333(3,3,3));
matrix.setCursor(0, 0);// start at top left, with 8 pixel of spacing
matrix.println("lat:");//latitude
matrix.setCursor(0, 10);
matrix.println("lon:");//longitude
matrix.setCursor(0, 20);
matrix.println("alt:");//altitude
matrix.setTextColor(matrix.Color333(1,0,5));
36
matrix.setCursor(28, 0);
matrix.println(flat);
matrix.setCursor(28, 10);
matrix.println(flon);
matrix.setCursor(28, 20);
matrix.println(falt);
temps=millis();
vtest=2;//asure de passer à la deuxième salve d'affichage
if ((millis()>(temps+2000))*(vtest==2))//deuxième affichage
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setTextColor(matrix.Color333(3,3,3));
matrix.setCursor(0, 0);// start at top left, with 8 pixel of spacing
matrix.println("hum:");//humidité
matrix.setCursor(0, 10);
matrix.println("tem:");//température
matrix.setCursor(0, 20);
matrix.println("pre:");//pression
matrix.setTextColor(matrix.Color333(1,0,5));
matrix.setCursor(28, 0);
matrix.println(humidite);
matrix.setCursor(28, 10);
matrix.println(temperature);
matrix.setCursor(28, 20);
matrix.println(pression);
temps=millis();
vtest=1;//réaffiche la premère salve de données
// end loop
//fonction qui renvoi un hexadécimal pour tracer un cercle sur le panneau de LED
uint16_t Wheel(byte WheelPos)
if(WheelPos < 8)
return matrix.Color333(7 - WheelPos, WheelPos, 0);
else if(WheelPos < 16)
WheelPos -= 8;
return matrix.Color333(0, 7-WheelPos, WheelPos);