Shared by Polytech Marseille to contribute to the improvement of the mbed community !

Dependencies:   Adafruit_SGP30_mbed mbed GSM X_NUCLEO_IKS01A2 max31865 GroveGPS SDFileSystem DFPlayerMini BME280 DS1820

Revision:
3:cb77ea3370e8
Parent:
0:d7a683cf76d9
--- a/main.cpp	Sun Feb 03 20:52:47 2019 +0000
+++ b/main.cpp	Tue Apr 30 15:00:03 2019 +0000
@@ -1,1178 +1,1122 @@
-// Projet HAB "ST in the sky", Polytech Marseille
-// Programme de la carte mère du HAB, la STM32 Nucleo-L073RZ
-// 20 Janvier 2019
-
-/*  todo :
-- resoudre incompatibilité mbed thermomètre DS18
-- utilisation de l'entrée Reset du module GSM
-- check si le lecteur MP3 est bien actif
-*/
-
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-
-// Activation des différents modules de ce code (via directives de compilation)
-// Permet de désactiver rapidement la compilation de certaines parties du code
-
-// Commentez les lignes pour désactiver les modules/fonctionnalités :
-
-#define SD_COMP 1         // Carte SD
-#define GSM_COMP 1        // module GSM
-#define GPRS_COMP 1       // Données mobiles
-#define SMS_COMP 1       // SMS de données toute les 10 min
-#define GPS_COMP 1        // module GPS
-//#define GPS_DEBUG          // Transmission des données serie GPS sur le moniteur série
-#define XNUCLEO_COMP 1      // shield capteurs XNUCLEO
-#define PT100_COMP 1        // module PT100
-#define CO2_COMP 1          // module CO2
-#define BUZZ_COMP           // Buzzer
-#define UV_COMP 1           // Capteur UV
-#define PHOTORES_COMP 1   // Capteur photoresistance
-#define BOSCH_COMP 1        // module triple capteur Bosch
-#define MP3_COMP 1        // module lecteur MP3
-//#define LORA_COMP 1       // Carte LoRa
-#define O3_COMP 1         // module spi_ozone O3
-//#define DS18_COMP         // Capteur temperature DS18
-
-
-// Assignation des entrées/sorties des différents modules
-
-// DS18 thermomètre
-#define IO_DS18         PC_6
-
-// Carte SD
-#define IO_SD_MOSI      PB_15   // SPI 2
-#define IO_SD_MISO      PB_14
-#define IO_SD_SCK       PB_13
-#define IO_SD_SS        PB_2
-
-// Shield XNUCLEO
-#define IO_XNUC_SDA     PB_9    // I2C 1
-#define IO_XNUC_SCL     PB_8
-
-// GPS
-#define IO_GPS_TX       PC_1    // LPUART 
-#define IO_GPS_RX       PC_0
-
-// GSM/GPRS/2G+/téléphone
-#define IO_GSM_TX       PA_0    // UART 4
-#define IO_GSM_RX       PA_1
-#define IO_GSM_PWR      PC_7
-#define IO_GSM_NET      PA_8
-#define IO_GSM_STAT     PA_9
-#define IO_GSM_RST      PA_7
-
-// Thermomètre PT100 (RTD) MAX31865
-#define IO_PT100_MOSI   PB_15   // SPI 2
-#define IO_PT100_MISO   PB_14
-#define IO_PT100_SCK    PB_13
-#define IO_PT100_SS     PB_1
-
-// Capteur eCO2 TVOC
-#define IO_CO2_SDA      PB_9    // I2C 1
-#define IO_CO2_SCL      PB_8
-
-// Triple capteur Bosch (hum, temp, press)
-#define IO_BOSCH_SDA    PB_9    // I2C 1
-#define IO_BOSCH_SCL    PB_8
-
-// Lecteur MP3 DFPlayer
-#define IO_MP3_TX       PB_6    // UART 1
-#define IO_MP3_RX       PA_10
-
-// LoRa
-#define IO_LORA_TX      PC_12    // UART 5
-#define IO_LORA_RX      PD_2
-
-// Ozone O3
-#define IO_O3_MOSI      PB_15    // SPI 2
-#define IO_O3_MISO      PB_14
-#define IO_O3_SCK       PB_13
-#define IO_O3_SS        PB_12
-
-// Autres
-#define IO_BUZZER       PB_3
-#define IO_UV           PC_2
-#define IO_PHOTORES     PC_3
-#define IO_VBATT        PB_0
-
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-////////////////////////  Début du code  ////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-
-//Autres
-
-#include <stdio.h>
-#include <string>
-#include "mbed.h"
-
-Serial serial_pc(SERIAL_TX, SERIAL_RX, 115200);
-
-#ifdef LORA_COMP    // Debut directive de compilation LoRa
-// todo: liaison UART avec carte LoRa + watchdog carte mère
-Serial lora_serial(IO_LORA_TX, IO_LORA_RX, 9600);
-
-char chaine_lora[50]; //chaine contenant la trame des données des capteurs à envoyer
-#endif  // Fin directive de compilation LoRa
-
-
-#ifdef BUZZ_COMP    // Debut directive de compilation buzzer
-DigitalOut pin_buzzer(IO_BUZZER,0);
-#endif  // Fin directive de compilation buzzer
-
-unsigned int compteur = 0;  //compteur du nombre de fois que la recolte de données à été effectuée depuis le démarrage
-
-// Mesure de la tension de la batterie
-float vbatt = 0.0;  // Tension de la batterie
-AnalogIn pin_vbatt(IO_VBATT);
-
-//chaine contenant la trame des données des capteurs à stocker sur la crate sd et à envoyer par GPRS
-char chaine_data[150];
-
-/////////////////////////////////////////////////////////////////////////
-
-//Tickers
-
-// Ticker executé toute les 5s pour recolter toute les données des capteurs,
-// les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa
-Ticker ticker_hab;          // Object Ticker
-void isr_ticker_hab();      // Routine ISR appellée lors du tick
-void f_ticker_hab();        // Fonction utile appellée à la suite du tick
-bool flag_ticker_hab = 0;   // Flag levé par l'ISR pour appeller la fonction utile
-
-// Ticker executé toute les 30 s pour vérifier l'etat du module GSM
-#ifdef GSM_COMP   // Debut directive de compilation module GSM
-Ticker ticker_check_gsm;        // Object Ticker
-void isr_ticker_check_gsm();    // Routine ISR appellée lors du tick
-void f_ticker_check_gsm();      // Fonction utile appellée à la suite du tick
-bool flag_ticker_check_gsm = 0; // Flag levé par l'ISR pour appeller la fonction utile
-#endif  // Fin directive de compilation module GSM
-
-// Ticker executé toute les 10 min pour vérifier l'etat du module GSM
-#ifdef SMS_COMP  // Debut directive de compilation SMS de données toutes les 10 min
-Ticker ticker_sms_chaine;        // Object Ticker
-void isr_ticker_sms_chaine();    // Routine ISR appellée lors du tick
-void f_ticker_sms_chaine();      // Fonction utile appellée à la suite du tick
-bool flag_ticker_sms_chaine = 0; // Flag levé par l'ISR pour appeller la fonction utile
-#endif  // Fin directive de compilation SMS de données toutes les 10 min
-
-/////////////////////////////////////////////////////////////////////////
-
-// Carte SD
-
-#ifdef SD_COMP   // Debut directive de compilation carte SD
-
-#include "SDFileSystem.h"
-SDFileSystem sd(IO_SD_MOSI, IO_SD_MISO, IO_SD_SCK, IO_SD_SS, "sd"); // MOSI, MISO, SCK, SS
-    
-bool flag_sd_ok = 0;    // Flag mit à '1' après la 1ere initialisation reussie de la carte SD
-
-#endif  // Fin directive de compilation carte SD
-
-/////////////////////////////////////////////////////////////////////////
-
-// Shield capteurs ST X_NUCLEO_IKS01A2
-
-#ifdef XNUCLEO_COMP   // Debut directive de compilation shield capteurs XNUCLEO
-
-#include "XNucleoIKS01A2.h"
-
-// Instantiate the expansion board
-static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(IO_XNUC_SDA, IO_XNUC_SCL);   // SDA, SCL, option(INT1, INT2)
-
-static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
-static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
-static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
-
-#endif  // Fin directive de compilation shield capteurs XNUCLEO
-
-float xnuc_t = 0.0, xnuc_h = 0.0, xnuc_t2 = 0.0, xnuc_p = 0.0;
-int32_t xnuc_acc[3];
-
-/////////////////////////////////////////////////////////////////////////
-
-// Module GPS
-#ifdef GPS_COMP   // Debut directive de compilation module GPS
-
-#include "GroveGPS.h"
-Serial gps_serial(IO_GPS_TX, IO_GPS_RX, 9600); //TX, RX, liaison STM --> GPS
-GroveGPS gps;
-void isr_gps_serial();  // Fonction d'interuption de reception sur le port UART GPS
-char timeUTCBuffer[16], latBuffer[16], lonBuffer[16], altBuffer[16], speedBuffer[16];
-
-#endif  // Fin directive de compilation module GPS
-
-unsigned int timeUTC = 0;
-float lat = 0, lon = 0, alt = 0, speed = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Module GSM
-#ifdef GSM_COMP   // Debut directive de compilation module GSM
-
-// Flag mis à jour par interruption externe sur la LED NET.
-// Passe a true lorsque sa période de clignotement est d'environs 3 s
-bool flag_gsm_net_ok = 1; 
-  
-// Flag a abaisser lors de la 1ere réponse materielle du module GSM
-bool flag_gsm_absent = 1;
-
-// Flag à lever lors de la confirmation de la présence matérielle du module GSM
-// et de son démarrage en cours, et a abaisser lorsque celui ci a également démarrer logiciellement
-bool flag_gsm_starting = 0;
-
-// Compteur calé sur le ticker HAB de période ~5 s, qui compte le temps depuis
-// le dernier reset du module GSM, pour eviter de le reset trop souvent si
-// la connexion est mauvaise.
-unsigned int last_reset_gsm = 0;
-
-DigitalOut gsm_pwr(IO_GSM_PWR);     // Sortie d'allumage du GSM
-// todo sortie RESET du GSM
-InterruptIn gsm_net(IO_GSM_NET);    // Entrée de la LED "NET"
-DigitalIn gsm_status(IO_GSM_STAT);  // Entrée de la LED "STATUS"
-
-#include <GSM.h>
-GSM gsm(IO_GSM_TX, IO_GSM_RX, 9600,"0649980191");  //TX, RX, PWR, NET, STATUS, baudrate, num par defaut
-
-char * url_srv_paul = "http://37.59.60.112/public/HAB/index.php?message=";  // URL du serveur web
-
-#endif  // Fin directive de compilation module GSM
-
-
-/////////////////////////////////////////////////////////////////////////
-
-// Sonde de température PT100 sur ampli MAX31865
-
-#ifdef PT100_COMP   // Debut directive de compilation module PT100
-
-#include "MAX31865.h"
-MAX31865_RTD PT100(MAX31865_RTD::RTD_PT100,IO_PT100_MOSI, IO_PT100_MISO, IO_PT100_SCK, IO_PT100_SS);   // MOSI, MISO, SCK, SS : SPI du MAX311865
-
-#endif  // Fin directive de compilation module PT100
-
-double tempPT100 = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Capteur eCO2/TVOC SGP30
-
-// /!\ Indication :
-// Le module eCO2/TVOC produira pendant ~20 s des resultats invalides pendant son echauffement
-// eCO2=400 et TVOC=0, patientez quelques instants
-// module à allumer 48h à l'avance pour résultats optimums
-
-#ifdef CO2_COMP   // Debut directive de compilation module CO2
-
-#include "Adafruit_SGP30.h"
-
-Adafruit_SGP30 co2(IO_CO2_SDA, IO_CO2_SCL);   // SDA, SCL
-
-#endif  // Fin directive de compilation module CO2
-
-int eco2 = 0;
-int tvoc = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Capteur de temperature (exterieur haut) DS181B20
-
-#ifdef DS18_COMP   // Debut directive de compilation DS181B20
-
-#include "DS1820.h"
-DS1820  ds18(IO_DS18);
-
-#endif  // Fin directive de compilation DS181B20
-
-float tempDS18 = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Capteurs lumière (UV et photoresistance)
-
-//#ifdef UV_COMP   // Debut directive de compilation capteur UV
-AnalogIn pin_UV(IO_UV);
-//#endif  // Fin directive de compilation capteur UV
-
-//#ifdef PHOTORES_COMP   // Debut directive de compilation capteur lumière
-AnalogIn pin_photores(IO_PHOTORES);
-//#endif  // Fin directive de compilation capteur lumière
-
-float uv = 0;
-float photores = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Capteur Bosch BME280 (temperature, pression, humidité exterieure)
-
-#ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-
-#include "BME280.h"
-BME280 bosch(IO_BOSCH_SDA, IO_BOSCH_SCL);    // SDA, SCL
-
-#endif  // Fin directive de compilation Bosch
-
-float bosch_t = 0;
-float bosch_p = 0;
-float bosch_h = 0;
-
-/////////////////////////////////////////////////////////////////////////
-
-// Lecteur MP3 DFPlayer
-
-#ifdef MP3_COMP   // Debut directive de compilation lecteur MP3
-
-#include "DFPlayerMini.h"
-DFPlayerMini mp3(IO_MP3_TX, IO_MP3_RX); //TX, RX
-
-#endif  // Fin directive de compilation MP3
-
-/////////////////////////////////////////////////////////////////////////
-
-// Capteur Ozone O3
-
-// todo
-
-#ifdef O3_COMP   // Debut directive de compilation spi_ozone
-
-SPI spi_ozone(PB_15, PB_14, PB_13); // MOSI,MISO,SCK
-DigitalOut ozone_SS(IO_O3_SS,1);
-
-#endif  // Fin directive de compilation spi_ozone
-
-double ozone = 0;
-
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////  Fonctions annexes  ///////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-
-// Ozone O3
-double lecture_ozone() {
-    
-    uint32_t chiffre=0;
-    uint8_t Buff[4];
-    
-    for(int i=0; i<3;i++) Buff[i] = 0;
-    
-    spi_ozone.format(8,3);
-    spi_ozone.frequency(1000000); 
-    
-    ozone_SS.write(0);  // Selection de l'esclave
-    
-    //spi_ozone.write(0x8F);
-    
-    wait_ms(100);    
-    
-    Buff[0] = spi_ozone.write(0);
-    Buff[1] = spi_ozone.write(0);
-    Buff[2] = spi_ozone.write(0);
-    Buff[3] = spi_ozone.write(0);
-    
-    ozone_SS.write(1);  // Deselection de l'esclave
-    
-    
-    chiffre = ((uint32_t)(Buff[0]) << 24) | ((uint32_t)(Buff[1]) << 16) | ((uint32_t)(Buff[2]) << 8) | (uint32_t)(Buff[3]);
-    chiffre = chiffre >> 7;
-    
-    double resultat = 0.0;    
-    resultat = 100 - (chiffre/41943.040);   // Conversion en %ADC
-
-    return resultat;
-    
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-// Fonctions d'activation et de desactivation de l'interruption UART pour GPS
-
-void irq_gps_off() {
-    // IRQ OFF : desactivation de l'interruption pour le port UART du GPS
-    #ifdef GPS_COMP   // Debut directive de compilation module GPS
-    gps_serial.attach(NULL);
-    #endif  // Fin directive de compilation module GPS
-}
-
-void irq_gps_on() {
-    // IRQ ON : activation de l'interruption pour le port UART du GPS
-    #ifdef GPS_COMP   // Debut directive de compilation module GPS
-    gps_serial.attach(&isr_gps_serial,Serial::RxIrq);
-    #endif  // Fin directive de compilation module GPS
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-// SD
-#ifdef SD_COMP   // Debut directive de compilation carte SD
-
-// Fonction qui ecrit le message dans le fichier passés en arguments sur la carte SD initialisée
-void ecriture_sd(char * fichier, char * message) {
-    
-    // Si la carte SD n'est pas initialisée on quitte
-    if(flag_sd_ok == 0) return;
-    
-    irq_gps_off();   //désactivation de l'interruption UART pour GPS
-    
-    // fichier du type "/sd/data.txt"
-    FILE *fp = fopen(fichier, "a");
-    if(fp == NULL) {
-        serial_pc.printf("ERREUR : carte SD\n");
-    }
-    else {
-        fprintf(fp, message);
-        fprintf(fp, "\n");
-        fclose(fp);
-    }
-    
-    irq_gps_on();   //ré-activation de l'interruption UART pour GPS    
-}
-
-#endif  // Fin directive de compilation carte SD
-
-
-////////////////////////////////////////////////////////////////////////
-
-//Pression - Altitude
-
-double sealevel(double P, double A)
-// Given a pressure P (mb) taken at a specific altitude (meters),
-// return the equivalent pressure (mb) at sea level.
-// This produces pressure readings that can be used for weather measurements.
-{
-  return (P / pow(1 - (A / 44330.0), 5.255));
-}
-
-
-double altitude(double P, double P0)
-// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
-// return altitude (meters) above baseline.
-{
-  return (44330.0 * (1 - pow(P / P0, 1 / 5.255)));
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-// GSM
-
-#ifdef GSM_COMP   // Debut directive de compilation module GSM
-
-void init_GSM(); 
-
-Timer timer_gsm_net;    // Compteur de la période de clignotement de la LED "NET"
-unsigned int last_time_gsm_net = 0;
-
-void isr_net_gsm() {
-    
-    // Arret de toute les sources d'interruptions
-    irq_gps_off();
-    gsm_net.disable_irq();
-    
-    
-    timer_gsm_net.stop();   // Arret du compteur
-    
-    last_time_gsm_net = timer_gsm_net.read_ms();    // Lecture du compteur
-    
-    serial_pc.printf("last_time_gsm_net : %d\n", last_time_gsm_net);
-    
-    // Seulement si la période de clignotement est d'environs 3 s alors le module 
-    // GSM est bien connecté au réseau et est pret a etre utilisé.
-    if(last_time_gsm_net > 2800 && last_time_gsm_net < 3200) {
-        flag_gsm_net_ok = 1;
-        if(flag_gsm_starting == 1) {
-            init_GSM();
-            flag_gsm_starting = 0;
-        }
-    }
-    else flag_gsm_net_ok = 0;
-    
-    timer_gsm_net.reset();  // Remise a zéro et départ à nouveau du compteur
-    timer_gsm_net.start();
-    
-    // Re-allumage des interruptions
-    irq_gps_on();
-    gsm_net.enable_irq();
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-// GSM
-
-void init_GSM() {
-    // Initialise (logiciellement) le module GSM
-    
-    if(gsm_status == 0) return;    // Si module GSM arreté ou absent c'est inutile
-    
-    // Arret de toute les sources d'interruptions
-    irq_gps_off();              // Int sur RX UART
-    gsm_net.disable_irq();      // Int sur LED NET GSM
-    ticker_hab.detach();        // Ticker HAB
-    ticker_check_gsm.detach();  // Ticker check GSM
-
-    serial_pc.printf("****************\nInit GSM : %d\n",gsm.init());
-    serial_pc.printf("Statut SIM : %d\n",gsm.checkSIMStatus());
-    serial_pc.printf("Force signal : %d\n",gsm.checkSignalStrength());
-    serial_pc.printf("Reglage SMS : %d\n",gsm.settingSMS());
-    serial_pc.printf("Test SMS : %d \n****************\n",gsm.sendSMS("+33649980191", "coucou"));
-    
-    flag_gsm_starting = 0;  // Init logiciel effectué
-    
-    // Re-allumage des interruptions
-    irq_gps_on();
-    gsm_net.enable_irq();
-    ticker_hab.attach(&isr_ticker_hab, 5.0);
-    ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0);
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-void gsm_pwr_on() {
-    
-    // Fonction qui allume le module GSM (matériellement) si besoin
-    // Entrée : "bool attendre", specifie si la fonction doit attendre que le
-    // module GSM démarre.
-    
-    
-    if(gsm_status == 0) {
-    
-        // Arret de toute les sources d'interruptions
-        irq_gps_off();              // Int sur RX UART
-        gsm_net.disable_irq();      // Int sur LED NET GSM
-        ticker_hab.detach();        // Ticker HAB
-        ticker_check_gsm.detach();  // Ticker check GSM
-       
-       // Creation et lancement d'un timer de time out du démarrage du module GSM
-       Timer timer_gsm_init;
-       timer_gsm_init.start();
-       
-       gsm_pwr = 1;
-       while(gsm_status == 0) {
-           wait(0.1);
-           
-           if(timer_gsm_init.read() > 5) {
-            
-                serial_pc.printf("ERREUR : module GSM absent\n");
-                flag_gsm_absent = 1;    // Constatation de l'absence du module GSM
-                timer_gsm_net.stop();
-                gsm_pwr = 0;
-                
-                // Re-allumage des interruptions
-                irq_gps_on();
-                gsm_net.enable_irq();
-                ticker_hab.attach(&isr_ticker_hab, 5.0);
-                ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0);
-                return;
-            }
-        }
-       gsm_pwr = 0;
-       timer_gsm_net.stop();
-       
-    }
-    else serial_pc.printf("Module GSM deja allume\n");
-    
-    flag_gsm_absent = 0;    // Constatation de la présence du module GSM
-    
-    // Indication que le module GSM est en train de démarrer materiellement
-    // ou du moins qu'il faudra bientot faire l'init logiciel dès qu'il
-    // sera pret (NET LED avec bonne période de 3s.
-    flag_gsm_starting = 1;  
-    
-    // Re-allumage des interruptions
-    irq_gps_on();
-    gsm_net.enable_irq();
-    ticker_hab.attach(&isr_ticker_hab, 5.0);
-    ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0);
-   
-}
-
-#endif  // Fin directive de compilation module GSM
-
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-///////////////  Tickers, Interruptions, Threads  ///////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-
-//GSM
-#ifdef GSM_COMP   // Debut directive de compilation module GSM
-
-void f_ticker_check_gsm() {
-    // Fonction du ticker de surveillance du module GSM, lancée toute les 30 s
-        
-    // Si module GSM absent, on retourne
-    if(flag_gsm_absent == 1) return;
-        
-    irq_gps_off();   //désactivation de l'interruption UART pour GPS
-    
-    // Si le module GSM est éteint, bé on l'allume
-    if(gsm_status == 0) gsm_pwr_on();
-    
-    // Si module GSM non connecté
-    if(flag_gsm_net_ok == 0) {
-        
-        // Si cela fais plus d'une minute qu'on a démarré alors
-        if(compteur - last_reset_gsm > 15) {
-            serial_pc.printf("/:\\ Reset du module GSM...\n");
-            
-            // todo : appui sur bouton reset du module gsm
-            
-            
-            last_reset_gsm = compteur;            
-        }
-    }
-    
-    
-    // met fin à l'envoi d'un sms, le module reste parfois bloqué dans la
-    // commande d'envoi et ne répond pas "OK" lorsqu'on check power en envoyant "AT"
-    gsm.gprsSerial.putc((char)0x1A); 
-    
-    int stat = gsm.checkSIMStatus();
-    serial_pc.printf("\n-- Check statut SIM : %d --\n", stat);
-    
-    if(stat != 0) {
-        init_GSM();    
-    }
-    
-    irq_gps_on();   //ré-activation de l'interruption UART pour GPS
-       
-
-    flag_ticker_check_gsm = 0;    // Abaissage du flag
-}
-#endif  // Fin directive de compilation module GSM
-
-/////////////////////////////////////////////////////////////////////////
-
-//GPS
-#ifdef GPS_COMP   // Debut directive de compilation module GPS
-
-// Routine d'interruption (ISR) pour la reception sur port UART du GPS
-void isr_gps_serial() {
-    
-    if (gps_serial.readable()) {        
-        #ifdef GPS_DEBUG
-        char c = gps_serial.getc();
-        serial_pc.putc(c);
-        gps.readCharacter(c);
-        #else
-        gps.readCharacter(gps_serial.getc());
-        #endif
-    }
-}
-#endif  // Fin directive de compilation module GPS
-
-////////////////////////////////////////////////////////////////////////
-
-// Ticker executé toute les 10 min pour envoier les données par sms
-#ifdef GSM_COMP   // Debut directive de compilation module GSM
-void f_ticker_sms_chaine() {
-    
-    gsm.sendSMS("+33649980191", chaine_data);
-    
-    flag_ticker_sms_chaine = 0;
-}
-#endif  // Fin directive de compilation module GSM
-
-////////////////////////////////////////////////////////////////////////
-
-/*
-Ticker executé toute les 5 s pour recolter toute les données,
-les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa
-*/
-
-
-void f_ticker_hab() {
-        
-        
-        //DS18 thermomètre pt1 (en 2 parties pour eviter d'attendre)
-        #ifdef DS18_COMP   // Debut directive de compilation DS181B20
-        
-        //todo
-        
-        #endif  // Fin directive de compilation DS181B20
-        
-        
-        
-        // Recuperation donnees capteurs ST X_NUCLEO_IKS01A2
-        #ifdef XNUCLEO_COMP   // Debut directive de compilation shield capteurs XNUCLEO
-        hum_temp->get_temperature(&xnuc_t);
-        hum_temp->get_humidity(&xnuc_h);
-        press_temp->get_temperature(&xnuc_t2);
-        press_temp->get_pressure(&xnuc_p);
-        #endif  // Fin directive de compilation shield capteurs XNUCLEO
-        
-        
-        //PT100
-        #ifdef PT100_COMP   // Debut directive de compilation module PT100
-        PT100.read_all();
-        if(PT100.status() == 0) {
-            tempPT100 = PT100.temperature();
-            //serial_pc.printf(" T = %f degC \r\n",temp);
-        }
-        else {
-            tempPT100 = 0;
-            serial_pc.printf("Registre d'erreur PT100 : %d - ",PT100.status( ));
-            if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) {
-                 serial_pc.printf("ERREUR PT100 seuil haut franchi\n");
-            }
-            else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) {
-                serial_pc.printf("ERREUR PT100 seuil bas franchi\n");
-            }
-            else if(PT100.status() & MAX31865_FAULT_REFIN) {
-                serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n");
-            }
-            else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) {
-                serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
-            }
-            else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) {
-                serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
-            }
-            else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) {
-                serial_pc.printf("ERREUR sur/sous-tension\n");
-            }
-            else serial_pc.printf("ERREUR inconnue\n");
-        }
-        #endif  // Fin directive de compilation module PT100
-        
-        
-        // CO2
-        #ifdef CO2_COMP   // Debut directive de compilation module CO2
-        co2.IAQmeasure();
-        /*serial_pc.printf("TVOC : %d\n", co2.TVOC);
-        serial_pc.printf("eCO2: %d\n", co2.eCO2);*/
-        eco2 = co2.eCO2;
-        tvoc = co2.TVOC;
-        #endif  // Fin directive de compilation module CO2
-        
-        
-        //DS18 thermomètre pt2 (en 2 parties pour eviter d'attendre)
-        #ifdef DS18_COMP   // Debut directive de compilation DS181B20
-        
-        //todo
-        
-        #endif  // Fin directive de compilation DS181B20
-        
-        // Capteurs UV et lumiere
-        #ifdef UV_COMP   // Debut directive de compilation capteur UV
-        uv = pin_UV.read();
-        #endif  // Fin directive de compilation capteur UV
-        #ifdef PHOTORES_COMP   // Debut directive de compilation capteur lumière
-        photores = pin_photores.read();
-        #endif  // Fin directive de compilation capteur lumière
-        
-        
-        // Triple capteur Bosch BME280
-        #ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-        bosch_t = bosch.getTemperature();
-        bosch_p = bosch.getPressure();
-        bosch_h = bosch.getHumidity();
-        //serial_pc.printf("Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity());
-        #endif  // Fin directive de compilation Bosch
-        
-        
-        // Ozone
-        #ifdef O3_COMP   // Debut directive de compilation spi_ozone
-        ozone = lecture_ozone();
-        #endif  // Fin directive de compilation spi_ozone
-        
-        // Mesure tension batterie (tension ref* pont diviseur + chute diode)
-        vbatt = pin_vbatt.read()*3.3*11.07+0.52;
-        
-        // Recuperation données GPS
-        #ifdef GPS_COMP   // Debut directive de compilation module GPS
-        gps.getTimestamp(timeUTCBuffer);
-        gps.getLatitude(latBuffer);
-        gps.getLongitude(lonBuffer);
-        gps.getAltitude(altBuffer);
-        gps.getSpeed(speedBuffer);
-        //printf("UTC: %s\t Latitude: %s\t Longitude: %s\t altitude: %s\t speed: %s\n", timeUTCBuffer, latBuffer, lonBuffer, altBuffer, speedBuffer);
-        // Convertion des chaine en entier et flottant
-        timeUTC = atoi(timeUTCBuffer);
-        lat = (float)atof(latBuffer);
-        lon = (float)atof(lonBuffer);
-        alt = (float)atof(altBuffer);
-        speed = (float)atof(speedBuffer);
-        #endif  // Fin directive de compilation module GPS
-        
-        
-        // mise en forme dans un tableau de caractères
-        sprintf((char*) chaine_data, "%d-%.2f-%d-%f-%f-%.1f-%.1f-%.1f-%.1f-%.3f-%.3f-%.3f-%.1f-%.3f-%.2f-%.2f-%d-%d-%f-%.3f-%.3f", compteur, vbatt, timeUTC, lat, lon, alt, speed, xnuc_t, xnuc_t2, tempPT100, tempDS18, bosch_t, xnuc_h, bosch_h, xnuc_p, bosch_p, eco2, tvoc, ozone, uv*100.0, photores*100.0);
-        
-        
-        // Affichage des données sur port série debug
-        serial_pc.printf("*Compteur : %d\n", compteur);
-        serial_pc.printf("*Tension batterie : %f V\n", vbatt);
-        #ifdef GPS_COMP   // Debut directive de compilation module GPS
-        serial_pc.printf("*Temps UTC : %d\n", timeUTC);
-        serial_pc.printf("*Latitude : %f\n", lat);
-        serial_pc.printf("*Longitude : %f\n", lon);
-        serial_pc.printf("*Altitude : %.2f m\n", alt);
-        serial_pc.printf("*Vitesse : %.2f km/h\n", speed);
-        #endif  // Fin directive de compilation module GPS
-        #ifdef XNUCLEO_COMP   // Debut directive de compilation shield capteurs XNUCLEO
-        serial_pc.printf("*Temperature 1 (XNUCLEO) : %.3f *C\n", xnuc_t);
-        serial_pc.printf("*Temperature 2 (XNUCLEO) : %.3f *C\n", xnuc_t2);
-        #endif  // Fin directive de compilation shield capteurs XNUCLEO
-        #ifdef PT100_COMP   // Debut directive de compilation module PT100
-        serial_pc.printf("*Temperature 3 (PT100) : %.3f *C\n", tempPT100);
-        #endif  // Fin directive de compilation module PT100
-        #ifdef DS18_COMP   // Debut directive de compilation DS181B20
-        serial_pc.printf("*Temperature 4 (DS18) : %.3f *C\n", tempDS18);
-        #endif  // Fin directive de compilation DS181B20
-        #ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-        serial_pc.printf("*Temperature 5 (Bosch) : %.3f *C\n",bosch_t);
-        #endif  // Fin directive de compilation Bosch
-        #ifdef XNUCLEO_COMP   // Debut directive de compilation shield capteurs XNUCLEO
-        serial_pc.printf("*Humidite 1 (XNUCLEO) : %.2f %%\n", xnuc_h);
-        #endif  // Fin directive de compilation shield capteurs XNUCLEO
-        #ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-        serial_pc.printf("*Humidite 2 (Bosch) : %.2f %%\n",bosch_h);
-        #endif  // Fin directive de compilation Bosch
-        #ifdef XNUCLEO_COMP   // Debut directive de compilation shield capteurs XNUCLEO
-        serial_pc.printf("*Pression 1 (XNUCLEO) : %.2f mbar - altitude calculee : %.2f m\n", xnuc_p, altitude(xnuc_p, 1016));
-        #endif  // Fin directive de compilation shield capteurs XNUCLEO
-        #ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-        serial_pc.printf("*Pression 2 (Bosch) : %.2f mbar - altitude calculee : %.2f m\n",bosch_p, altitude(bosch_p, 1016));
-        #endif  // Fin directive de compilation Bosch
-        #ifdef CO2_COMP   // Debut directive de compilation module CO2
-        serial_pc.printf("*eCO2 : %d ppm\n", eco2);
-        serial_pc.printf("*TVOC : %d ppb\n", tvoc);
-        #endif  // Fin directive de compilation module CO2
-        #ifdef UV_COMP   // Debut directive de compilation capteur UV
-        serial_pc.printf("*UV : %.3f %%ADC\n", uv*100.0);
-        #endif  // Fin directive de compilation capteur UV
-        #ifdef PHOTORES_COMP   // Debut directive de compilation capteur lumière
-        serial_pc.printf("*Lum : %.3f %%ADC\n", photores*100.0);
-        #endif  // Fin directive de compilation capteur lumière
-        #ifdef O3_COMP   // Debut directive de compilation spi_ozone
-        serial_pc.printf("*Ozone O3 : %f %%ADC\n", ozone);
-        #endif  // Fin directive de compilation spi_ozone
-        
-        
-        serial_pc.printf(">>  %s\n", chaine_data);
-        
-        
-        // Envoie de la chaine par GPRS au serveur de Paul
-        #ifdef GSM_COMP   // Debut directive de compilation module GSM
-        #ifdef GPRS_COMP   // Debut directive de compilation données mobiles
-        if(flag_gsm_net_ok == 1) gsm.gprs_message(url_srv_paul , chaine_data);
-        #endif  // Fin directive de compilation données mobiles
-        //if(flag_gsm_net_ok == 1) serial_pc.printf("SMS : %d\n",gsm.sendSMS("+33649980191", chaine_data)); // Envoi de la chaine par SMS
-        #endif  // Fin directive de compilation module GSM
-        
-        // Sauvegarde sur carte SD
-        #ifdef SD_COMP   // Debut directive de compilation carte SD
-        ecriture_sd("/sd/data.txt", chaine_data);
-        #endif  // Fin directive de compilation carte SD
-        
-        
-        // Creation de la chaine à envoyer à la carte LoRa
-        #ifdef LORA_COMP    // Debut directive de compilation LoRa
-        sprintf((char*) chaine_lora, "%.2f-%f-%f-%.1f-%.3f", vbatt, lat, lon, alt, tempPT100);
-        serial_pc.printf(">>  %s\n", chaine_lora);
-        #endif  // Fin directive de compilation LoRa
-        
-        serial_pc.printf("************************************************\n");
-        compteur++;
-        
-        flag_ticker_hab = 0;    // Abaissage du flag    
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-// Routines d'interruption appelées au tick des tickers et servant juste à lever un flag
-// Pensez à abaisser le flag dans f_ticker_hab() et f_ticker_gsm() !
-
-void isr_ticker_hab() { flag_ticker_hab = 1; }
-#ifdef GSM_COMP
-void isr_ticker_check_gsm() { flag_ticker_check_gsm = 1; }
-#endif  // Fin directive de compilation module GSM
-#ifdef SMS_COMP
-void isr_ticker_sms_chaine() { flag_ticker_sms_chaine = 1; }
-#endif
-
-/////////////////////////////////////////////////////////////////////////
-
-// LoRa
-
-#ifdef LORA_COMP    // Debut directive de compilation LoRa
-
-void envoi_chaine_lora() {
-    
-    lora_serial.printf("%s\n", chaine_lora);
-    serial_pc.printf("lora!\n");    // debug
-}
-
-void isr_lora_serial() {
-    
-    char c = lora_serial.getc();
-    if(c == 'a') envoi_chaine_lora();
-    #ifdef MP3_COMP   // Debut directive de compilation lecteur MP3
-    elseif(c == 'b') mp3.mp3_play();
-    elseif(c == 'c') mp3.mp3_pause();
-    #endif  // Fin directive de compilation lecteur MP3
-    #ifdef BUZZ_COMP    // Debut directive de compilation buzzer
-    elseif(c == 'd') pin_buzzer.write(1);
-    elseif(c == 'e') pin_buzzer.write(0);
-    #endif  // Fin directive de compilation buzzer
-    
-}
-#endif  // Fin directive de compilation LoRa
-
-
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////  MAIN  ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////
-
-int main() {
-    
-    // Affichage/listage des modules compilés/activés sur port série STLINK
-    serial_pc.printf("--- Programme HAB carte mere ---\n");
-    vbatt = pin_vbatt.read()*3.3*11.07+0.52;    // Tension batterie (tension ref * pont diviseur + chute diode)
-    serial_pc.printf("Tension batterie : %f V\n", vbatt);
-    serial_pc.printf("Modules compiles :\n");
-    
-    
-    //Buzzer, léger bip au démarrage
-    #ifdef BUZZ_COMP
-    serial_pc.printf("- Buzzer\n");
-    pin_buzzer.write(1);
-    wait(0.1);
-    pin_buzzer.write(0);
-    #endif
-    
-    // Shield ST X_NUCLEO_IKS01A2
-    #ifdef XNUCLEO_COMP 
-    hum_temp->enable();
-    press_temp->enable();
-    accelerometer->enable();
-    // lecture des capteurs
-    hum_temp->get_temperature(&xnuc_t);
-    hum_temp->get_humidity(&xnuc_h);
-    press_temp->get_temperature(&xnuc_t2);
-    press_temp->get_pressure(&xnuc_p);
-    serial_pc.printf("- XNUCLEO : %.3f *C, %.3f *C, %.3f mbar, %.2f %%\n",xnuc_t, xnuc_t2, xnuc_p, xnuc_h);
-    
-    accelerometer->get_x_axes(xnuc_acc);
-    serial_pc.printf("  accelerometre :  x = %ld, y = %ld, z = %ld\n", xnuc_acc[0], xnuc_acc[1], xnuc_acc[2]);
-    
-    #endif
-    
-    // GSM
-    #ifdef GSM_COMP
-    serial_pc.printf("- GSM : ");
-    gsm_pwr_on();
-    #endif
-    #ifdef GPRS_COMP
-    serial_pc.printf("- Donnees mobiles\n");
-    #endif
-    
-    #ifdef PT100_COMP
-    serial_pc.printf("- PT100 : ");
-    // Configuration initiale du MAX31865
-    /*
-    1: v_biais : Vbias (tension de polarisation) activée (true) ou non (false)
-    2: conversion_mode : mode de conversion automatique activé (true) ou non (false)
-    3: one_shot : mesure au coup par coup (true) ou en continue (false)
-    4: three_wire : mesure 3 fils activée (true) ou 2/4 fils (false)
-    5: fault_cycle : detection d'erreur (voir datasheet) activée (true) ou non (false)
-    6: fault_clear : acquittement automatique des erreurs activée (true) ou non (false)
-    7: filter_50hz : filtre 50 Hz activé (true) ou non (false)
-    8: low_threshold : seuil d'erreur bas. (0x0000 = 0)
-    9: high_threshold : seuil d'erreur haut. (0x7fff = 32767)
-    */
-    PT100.configure(true, true, false, false, MAX31865_FAULT_DETECTION_NONE, true, true, 0x0000, 0x7fff);
-    PT100.read_all();
-    if(PT100.status() == 0) {
-        serial_pc.printf("%.3f *C\n",PT100.temperature());
-    }
-    else {
-        serial_pc.printf("Registre d'erreur PT100 : %d - ",PT100.status( ));
-        if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) {
-             serial_pc.printf("ERREUR PT100 seuil haut franchi\n");
-        }
-        else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) {
-            serial_pc.printf("ERREUR PT100 seuil bas franchi\n");
-        }
-        else if(PT100.status() & MAX31865_FAULT_REFIN) {
-            serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n");
-        }
-        else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) {
-            serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
-        }
-        else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) {
-            serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
-        }
-        else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) {
-            serial_pc.printf("ERREUR sur/sous-tension\n");
-        }
-        else serial_pc.printf("ERREUR inconnue\n");
-    }
-    #endif
-    
-    // Carte SD, initialisation, et creation d'un fichier de test d'ecriture
-    // /!\ Faire cette étape après l'initialisation du capteur PT100 qui partage le même SPI
-    #ifdef SD_COMP
-    serial_pc.printf("- SD : ");
-    mkdir("/sd/TEST", 0777);
-    FILE *fp = fopen("/sd/TEST/sdtest.txt", "w");
-    if(fp == NULL) {
-        serial_pc.printf("ERREUR, ecriture carte SD\n");
-        // Desactivation de la sauvegarde sur carte SD
-        flag_sd_ok = 0;
-    }
-    else {
-        fprintf(fp, "test ecriture");
-        fclose(fp); 
-        serial_pc.printf("ecriture ok\n");
-        //Activation de la sauvegarde sur carte SD
-        flag_sd_ok = 1;
-    }
-    #endif
-    
-    // CO2
-    #ifdef CO2_COMP
-    co2.begin();
-    co2.IAQmeasure();
-    serial_pc.printf("- CO2 : TVOC = %d, eCO2 = %d\n", co2.TVOC, co2.eCO2);
-    #endif
-    
-    //DS18 thermomètre
-    #ifdef DS18_COMP   // Debut directive de compilation DS181B20
-    
-    if (ds18.begin()) {
-        while (1) {
-            ds18.startConversion();   // start temperature conversion from analog to digital
-            wait(1.0);                  // let DS1820 complete the temperature conversion
-            result = ds18.read(tempDS18); // read temperature from DS1820 and perform cyclic redundancy check (CRC)
-            switch (result) {
-                case 0:                 // no errors -> 'tempDS18' contains the value of measured temperature
-                    serial_pc.printf("temp = %3.1f%cC\r\n", tempDS18, 176);
-                    break;
-                case 1:                 // no sensor present -> 'tempDS18' is not updated
-                    serial_pc.printf("no sensor present\n\r");
-                    break;
-                case 2:                 // CRC error -> 'tempDS18' is not updated
-                    serial_pc.printf("CRC error\r\n");
-            }
-        }
-    }
-    else
-        serial_pc.printf("No DS1820 sensor found!\r\n");
-    
-    #endif  // Fin directive de compilation DS181B20
-    
-    //UV
-    #ifdef UV_COMP
-    serial_pc.printf("- UV : %.3f %%ADC\n",pin_UV.read());
-    #endif
-    
-    //Photoresistance
-    #ifdef PHOTORES_COMP
-    serial_pc.printf("- Photoresistance : %.3f %%ADC\n",pin_photores.read()*100.0);
-    #endif
-    
-    // Triple capteur Bosch BME280
-    #ifdef BOSCH_COMP   // Debut directive de compilation Bosch
-    serial_pc.printf("- Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity());
-    #endif  // Fin directive de compilation Bosch
-    
-    // Lecteur MP3
-    // Creer un fichier 0.mp3 à la racine de la carte SD
-    #ifdef MP3_COMP   // Debut directive de compilation lecteur MP3
-    serial_pc.printf("- MP3\n");
-    mp3.mp3_reset();
-    wait(1);    
-    mp3.mp3_set_EQ(0);
-    wait(0.5);
-    mp3.mp3_set_volume(20);
-    wait(0.5);
-    mp3.mp3_set_device(2);   // 1,2,3,4,5 : USB,SD,AUX,SLEEP,FLASH
-    wait(0.5);
-    mp3.mp3_single_loop(0);
-    wait(0.5);
-    mp3.mp3_play();
-    #endif  // Fin directive de compilation MP3
-    
-    
-    #ifdef LORA_COMP
-    serial_pc.printf("- LoRa\n");
-    #endif
-    #ifdef GPS_COMP
-    serial_pc.printf("- GPS\n");
-    #endif
-    
-    #ifdef O3_COMP
-    serial_pc.printf("- Ozone O3 : %f %%ADC\n", lecture_ozone());    
-    #endif    
-    
-    
-    
-    serial_pc.printf("************************************************\n");
-    
-    //////  Lancement des ticker et des interruptions  ////////
-
-    // GPS
-    // Mise en place de l'interruption pour le port UART du GPS
-    #ifdef GPS_COMP   // Debut directive de compilation module GPS
-    gps_serial.attach(&isr_gps_serial,Serial::RxIrq);
-    #endif  // Fin directive de compilation module GPS
-    
-    
-    // Ticker de creation de la chaine de données toute les 5s
-    ticker_hab.attach(&isr_ticker_hab, 5.0);
-        
-    
-    // GSM
-    #ifdef GSM_COMP   // Debut directive de compilation module GSM
-    if(flag_gsm_absent == 0) {
-        
-        // Interruption sur LED "NET" et compteur de sa période
-        timer_gsm_net.reset();   // Démarrage du compteur de la période de clignotement de la LED "NET"
-        timer_gsm_net.start();   
-        gsm_net.rise(&isr_net_gsm);    // Attachement de l'interruption externe sur la LED "NET"
-       
-        // Ticker de surveillance GSM toute les 30s
-        ticker_check_gsm.attach(&isr_ticker_check_gsm, 30.0);
-        
-        // Ticker d'envoi de données par sms toute les 10 min
-        #ifdef SMS_COMP   // Debut directive de compilation envoi SMS
-        ticker_sms_chaine.attach(&isr_ticker_sms_chaine, 600.0);
-        #endif  // Fin directive de compilation SMS de données toutes les 10 min      
-    }
-    #endif  // Fin directive de compilation module GSM
-    
-    
-    // LoRa
-    // Mise en place de l'interruption pour le port UART LoRa
-    #ifdef LORA_COMP    // Debut directive de compilation LoRa
-    lora_serial.attach(&isr_lora_serial,Serial::RxIrq);
-    #endif  // Fin directive de compilation LoRa
-    
-    ///////////////////  BOUCLE PRINCIPALE  /////////////////
-    
-    while(1) {       
-        
-        // Vérification du flag d'interruption pour la routine de recuperation
-        // des données des capteurs, enregistrement, envoi LoRa, etc.
-        if(flag_ticker_hab == 1) f_ticker_hab();
-        
-        
-        // Vérification du flag d'interruption pour la routine de vérification
-        // de l'état du module
-        #ifdef GSM_COMP   // Debut directive de compilation module GSM
-        if(flag_ticker_check_gsm == 1) f_ticker_check_gsm();
-        #endif  // Fin directive de compilation module GSM
-        
-        // Vérification du flag d'interruption pour la routine d'envoi de SMS
-        // de donnée toute les 10 min
-        #ifdef GPS_COMP   // Debut directive de compilation module GPS
-        #ifdef SMS_COMP  // Debut directive de compilation SMS de données toutes les 10 min
-        if(flag_ticker_sms_chaine == 1) f_ticker_sms_chaine();
-        #endif  // Fin directive de compilation SMS de données toutes les 10 min
-        #endif  // Fin directive de compilation module GSM
-        
-    }
-}
+/////////////////////////////////////////////////////////////////////////
+// AMU - Aix-Marseille Université
+// Polytech Marseille - Microelectronique & Telecommunications (MT)
+// Projet MT5A "STM32 In the Sky - HAB", 2018-2019
+// Enseignants : C.Dufaza & H. Aziza
+// Etudiants : ...
+/////////////////////////////////////////////////////////////////////////
+// Version avril 2019, C.Dufaza
+/*  todo :
+- resoudre incompatibilité mbed thermomètre DS18
+- utilisation de l'entrée Reset du module GSM
+- check si le lecteur MP3 est bien actif
+*/
+
+/////////////////////////////////////////////////////////////////////////
+//// ... Includes
+
+// Activation des différents modules de ce code (via directives de compilation)
+#include "define_myMODULES.h"
+// Assignation des entrées/sorties des différents modules
+#include "define_myIO.h"
+// Include usuels ...
+#include <stdio.h>
+#include <string>
+#include "mbed.h"
+
+/////////////////////////////////////////////////////////////////////////
+//// Main code
+/////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////
+//// Variables globales ...
+
+// Compteur du nombre de recolte de données depuis le démarrage
+unsigned int hab_frame_counter = 1;
+// Mesure de la tension de la batterie
+float vbatt = 0.0;
+AnalogIn pin_vbatt(IO_VBATT);
+// Trame des données des capteurs à stocker sur la carte sd et au GPRS
+char sd_gprs_data[SD_GPRS_DATA_SIZE];
+// GPS variables
+unsigned int timeUTC = 0;
+float lat = 0, lon = 0, alt = 0, speed = 0;
+// Xnucleo variables
+float xnuc_t = 0.0, xnuc_h = 0.0, xnuc_t2 = 0.0, xnuc_p = 0.0;
+int32_t xnuc_acc[3];
+// PT100 variables
+double tempPT100 = 0;
+// SGP30 variables
+int eco2 = 0, tvoc = 0;
+// Temperature DS18 variable
+float tempDS18 = 0;
+// UV & Photo variables
+float uv = 0, photores = 0;
+// BME280 variables (temperature, pression, humidité exterieure)
+float bosch_t = 0, bosch_p = 0, bosch_h = 0;
+// Ozone variable
+double ozone = 0;
+
+/////////////////////////////////////////////////////////////////////////
+//// Tickers d'interruption
+
+// Ticker executé toute les xx s pour recolter toute les données des capteurs,
+// les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa
+#ifdef HAB_FUNCTION   // Debut directive de compilation module HAB
+  Ticker ticker_hab;          // Object Ticker
+  void isr_ticker_hab();      // Routine ISR appellée lors du tick
+  void f_ticker_hab();        // Fonction utile appellée à la suite du tick
+  bool flag_ticker_hab = 0;   // Flag levé par l'ISR pour appeller la fonction utile
+#endif  // Fin directive de compilation module HAB
+
+// Ticker executé toute les xx s pour vérifier l'etat du module GSM
+#ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+  Ticker ticker_check_gsm;        // Object Ticker
+  void isr_ticker_check_gsm();    // Routine ISR appellée lors du tick
+  void f_ticker_check_gsm();      // Fonction utile appellée à la suite du tick
+  bool flag_ticker_check_gsm = 0; // Flag levé par l'ISR pour appeller la fonction utile
+#endif  // Fin directive de compilation module GSM
+
+// Ticker executé toute les 10 min pour vérifier l'etat du module GPRS SMS
+#ifdef SMS_FUNCTION  // Debut directive de compilation SMS de données toutes les 10 min
+  Ticker ticker_sms_data;        // Object Ticker
+  void isr_ticker_sms_data();    // Routine ISR appellée lors du tick
+  void f_ticker_sms_data();      // Fonction utile appellée à la suite du tick
+  bool flag_ticker_sms_data = 0; // Flag levé par l'ISR pour appeller la fonction utile
+#endif  // Fin directive de compilation SMS de données toutes les 10 min
+
+/////////////////////////////////////////////////////////////////////////
+// UART PC Debug
+#ifdef DEBUG_SERIAL_PC // ACtivation de la liaison UART PC pour Debug
+  Serial serial_pc(SERIAL_TX, SERIAL_RX, DEBUG_SERIAL_PC_BAUDRATE);
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// Buzzer digital Out pin
+#ifdef BUZZ_FUNCTION    // Debut directive de compilation buzzer
+  DigitalOut pin_buzzer(IO_BUZZER,0);
+#endif  // Fin directive de compilation buzzer
+
+/////////////////////////////////////////////////////////////////////////
+// Carte SD
+#ifdef SD_FUNCTION   // Debut directive de compilation carte SD
+  #include "SDFileSystem.h"
+  // MOSI, MISO, SCK, SS
+  SDFileSystem sd(IO_SD_MOSI, IO_SD_MISO, IO_SD_SCK, IO_SD_CS, SD_FUNCTION_SDNAME);
+  // flag_sd_ok = 1 après la 1ere initialisation reussie de la carte SD
+  bool flag_sd_ok = 0;
+#endif  // Fin directive de compilation carte SD
+
+/////////////////////////////////////////////////////////////////////////
+// Lecteur MP3 DFPlayer
+#ifdef MP3_FUNCTION   // Debut directive de compilation lecteur MP3
+  #include "DFPlayerMini.h"
+  DFPlayerMini mp3(IO_MP3_TX, IO_MP3_RX); //TX, RX
+#endif  // Fin directive de compilation MP3
+
+/////////////////////////////////////////////////////////////////////////
+// Module GSM
+#ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+  #include <GSM.h>    // GSM Library
+  // Flag mis à jour par interruption externe sur la LED NET.
+  // Passe a true lorsque sa période de clignotement est d'environ 3s
+  bool flag_gsm_network_ok = 0; 
+  // Flag a abaisser lors de la 1ere réponse materielle du module GSM
+  bool flag_gsm_absent = 1;
+  // Flag à lever lors de la confirmation de la présence matérielle du module GSM
+  // et de son démarrage en cours, et à abaisser lorsque celui ci a également démarrer logiciellement
+  bool flag_gsm_starting = 0;
+  // Compteur calé sur le ticker HAB de période ~5 s, qui compte le temps depuis
+  // le dernier reset du module GSM, pour eviter un reset trop fréquent si la connexion est mauvaise.
+  unsigned int last_reset_gsm = 0;
+  // GSM I/O PinInOut
+  DigitalOut gsm_pwr(IO_GSM_PWR);     // Sortie d'allumage du GSM
+  // todo sortie RESET du GSM
+  InterruptIn gsm_net(IO_GSM_NET);    // Entrée de la LED "NET"
+  DigitalIn gsm_status(IO_GSM_STAT);  // Entrée de la LED "STATUS"
+  //TX, RX, PWR, NET, STATUS, baudrate, num par defaut
+  GSM gsm(IO_GSM_TX, IO_GSM_RX, GSM_BAUDRATE, GSM_SIM_NUMBER);
+  // URL du serveur web
+  char * url_srv_polytech = POLYTECH_SERVER;
+#endif  // Fin directive de compilation module GSM
+
+/////////////////////////////////////////////////////////////////////////
+// Module GPS
+#ifdef GPS_FUNCTION   // Debut directive de compilation module GPS
+  #include "GroveGPS.h"
+  //TX, RX, liaison STM --> GPS
+  Serial gps_serial(IO_GPS_TX, IO_GPS_RX, GPS_BAUDRATE); 
+  GroveGPS gps;
+  void isr_gps_serial(); // Fonction d'interuption de reception sur le port UART GPS
+  char timeUTCBuffer[16], latBuffer[16], lonBuffer[16], altBuffer[16], speedBuffer[16];
+#endif  // Fin directive de compilation module GPS
+
+/////////////////////////////////////////////////////////////////////////
+// Shield capteurs ST X_NUCLEO_IKS01A2
+#ifdef XNUCLEO_FUNCTION   // Debut directive de compilation shield capteurs XNUCLEO
+  #include "XNucleoIKS01A2.h"
+  // Instantiate the expansion board: SDA, SCL, option(INT1, INT2)
+  static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(IO_XNUC_SDA, IO_XNUC_SCL);
+  static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
+  static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
+  static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
+#endif  // Fin directive de compilation shield capteurs XNUCLEO
+
+/////////////////////////////////////////////////////////////////////////
+// Sonde de température PT100 sur ampli MAX31865
+#ifdef PT100_FUNCTION   // Debut directive de compilation module PT100
+  #include "MAX31865.h"
+  // MOSI, MISO, SCK, SS : SPI du MAX311865
+  MAX31865_RTD PT100(MAX31865_RTD::RTD_PT100,IO_PT100_MOSI, IO_PT100_MISO, IO_PT100_SCK, IO_PT100_CS);
+#endif  // Fin directive de compilation module PT100
+
+/////////////////////////////////////////////////////////////////////////
+// Capteur de temperature (exterieur haut) DS181B20
+#ifdef DS18_FUNCTION   // Debut directive de compilation DS181B20
+  #include "DS1820.h"
+  DS1820  ds18(IO_DS18);
+#endif  // Fin directive de compilation DS181B20
+
+/////////////////////////////////////////////////////////////////////////
+// Capteurs lumière (UV et photoresistance)
+#ifdef UV_FUNCTION   // Debut directive de compilation capteur UV
+  AnalogIn pin_UV(IO_UV);
+#endif  // Fin directive de compilation capteur UV
+#ifdef PHOTORES_FUNCTION   // Debut directive de compilation capteur lumière
+  AnalogIn pin_photores(IO_PHOTORES);
+#endif  // Fin directive de compilation capteur lumière
+
+/////////////////////////////////////////////////////////////////////////
+// Capteur Bosch BME280 (temperature, pression, humidité exterieure)
+#ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+  #include "BME280.h"
+  BME280 bosch(IO_BOSCH_SDA, IO_BOSCH_SCL);    // SDA, SCL
+#endif  // Fin directive de compilation Bosch
+
+/////////////////////////////////////////////////////////////////////////
+// Capteur eCO2/TVOC SGP30, voir note :
+// Le module eCO2/TVOC produira pendant ~20 s des resultats invalides
+// eCO2=400 et TVOC=0, patientez quelques instants
+// module à allumer 48h à l'avance pour résultats optimums
+#ifdef CO2_FUNCTION   // Debut directive de compilation module CO2
+  #include "Adafruit_SGP30.h"
+  Adafruit_SGP30 co2(IO_CO2_SDA, IO_CO2_SCL);   // SDA, SCL
+#endif  // Fin directive de compilation module CO2
+
+/////////////////////////////////////////////////////////////////////////
+// Capteur Ozone O3
+// ... todo
+#ifdef O3_FUNCTION   // Debut directive de compilation spi_ozone
+  SPI spi_ozone(PB_15, PB_14, PB_13); // MOSI, MISO, SCK
+  DigitalOut ozone_SS(IO_O3_CS,1);
+#endif  // Fin directive de compilation spi_ozone
+
+/////////////////////////////////////////////////////////////////////////
+// LORA Module
+#ifdef LORA_FUNCTION    // Debut directive de compilation LoRa
+  // todo: liaison UART avec carte LoRa + watchdog carte mère
+  Serial lora_serial(IO_LORA_TX, IO_LORA_RX, LORA_FUNCTION_BAUDRATE);
+  // Chaine de char contenant la trame des données des capteurs à envoyer
+  char lora_data_tx[LORA_FUNCTION_DATASIZE]; 
+#endif  // Fin directive de compilation LoRa
+
+/////////////////////////////////////////////////////////////////////////
+//// Fonctions annexes
+
+////////////////////////////////////////////////////////////////////////
+// Pression - Altitude
+double sealevel(double P, double A)
+// Given a pressure P (mb) taken at a specific altitude (meters),
+// return the equivalent pressure (mb) at sea level.
+// This produces pressure readings that can be used for weather measurements.
+{ return (P / pow(1 - (A / 44330.0), 5.255));
+}
+
+double altitude(double P, double P0)
+// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
+// return altitude (meters) above baseline.
+{ return (44330.0 * (1 - pow(P / P0, 1 / 5.255)));
+}
+
+// Initialise l'interruption GPS ... pré-déclaration
+void irq_gps_on(); 
+void irq_gps_off(); 
+
+// Permet de gérer les modes On-Off des Interruption & Tickers
+void all_irq_on_off(int gps_on_off, int gsm_on_off, int ticker_hab_on_off, int ticker_gsm_on_off) {
+  // Interruption GPS On ou Off
+  if(gps_on_off == 1) { irq_gps_on();  }
+  if(gps_on_off == 0) { irq_gps_off(); }
+  // Module GSM Enable ou Disable
+  if(gsm_on_off == 1) { gsm_net.enable_irq();  }
+  if(gsm_on_off == 0) { gsm_net.disable_irq(); }
+  // Ticker HAB Attach ou Detach
+  if(ticker_hab_on_off == 1) { ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME); }
+  if(ticker_hab_on_off == 0) { ticker_hab.detach(); }
+  // Ticker GSM Attach ou Detach
+  if(ticker_gsm_on_off == 1) { ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME); }
+  if(ticker_gsm_on_off == 0) { ticker_check_gsm.detach(); }
+}
+  
+/////////////////////////////////////////////////////////////////////////
+// SD
+#ifdef SD_FUNCTION   // Debut directive de compilation carte SD
+
+// Fonction qui ecrit le message dans le fichier passés en arguments sur la carte SD initialisée
+void ecriture_sd(char * fichier, char * message) {
+  // Si la carte SD n'est pas initialisée on quitte
+  if(flag_sd_ok == 0) return;
+  // On désactive l'interruption UART pour GPS
+  all_irq_on_off(0, 2, 2, 2); // irq_gps_off(); 
+  // Fichier en mode a - append ... du type "/sd/data.txt"
+  FILE *fp = fopen(fichier, "a");
+  if(fp == NULL) { // Erreur d'ouverture du fichier
+    #ifdef DEBUG_SERIAL_PC 
+      serial_pc.printf("<<<< ERREUR >>>> carte SD, ouverture fichier impossible\n");
+    #endif
+  }
+  else { // Fichier correctement ouvert en mode append, écriture puis fermeture
+      fprintf(fp, message); fprintf(fp, "\n");
+      fclose(fp);
+  }
+  // Ré-activation de l'interruption UART pour GPS
+    all_irq_on_off(1, 2, 2, 2); // irq_gps_on(); 
+}
+
+#endif  // Fin directive de compilation carte SD
+
+/////////////////////////////////////////////////////////////////////////
+// GSM
+#ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+
+// Initialise le GSM ... pré-déclaration
+void init_GSM(); 
+
+// Variables GSM
+Timer timer_gsm_network; // Compteur de la période de clignotement de la LED "NET"
+unsigned int last_time_gsm_network = 0;
+
+void isr_network_gsm() {
+  // Arret de toute les sources d'interruptions
+   all_irq_on_off(0, 0, 2, 2);
+  //irq_gps_off();            // Interruption GPS off
+  //gsm_net.disable_irq();    // Disable interrupt GSM
+     
+  timer_gsm_network.stop(); // Arret du timer GSM
+  last_time_gsm_network = timer_gsm_network.read_ms(); // Lecture du timer GSM
+  #ifdef DEBUG_SERIAL_PC
+    //debug_if(DEBUG_SERIAL_PC, "Timer GSM Network (ms) : %d\n", last_time_gsm_network);
+    //serial_pc.printf("Timer GSM Network (ms) : %d\n", last_time_gsm_network);
+  #endif
+  // Seulement si la période de clignotement est d'environs 3s alors le module 
+  // GSM est bien connecté au réseau et est pret a etre utilisé.
+  if(last_time_gsm_network > 2800 && last_time_gsm_network < 3200) {
+     #ifdef DEBUG_SERIAL_PC
+       //serial_pc.printf("> Timer GSM Network (ms) : %d\n", last_time_gsm_network);
+     #endif
+     flag_gsm_network_ok = 1; // le GSM est ok
+     if(flag_gsm_starting == 1) { // est-il tjs en démarrage ?
+        init_GSM();
+        flag_gsm_starting = 0;
+  }  }
+  else flag_gsm_network_ok = 0; // le GSM n'est pas ok
+    
+  timer_gsm_network.reset();  // Raz et nouveau départ du timer GSM
+  timer_gsm_network.start();
+    
+  // On autorise de nouveau les interruptions GPS et GSM
+  all_irq_on_off(1, 1, 2, 2);
+  //irq_gps_on();
+  //gsm_net.enable_irq();
+}
+
+// On initialise le GSM
+void init_GSM() {
+  // Initialise (logiciellement) le module GSM
+  if(gsm_status == 0) return;    // Si module GSM arreté ou absent c'est inutile
+   
+  // Arret de toute les sources d'interruptions
+  all_irq_on_off(0, 0, 0, 0);
+  //irq_gps_off();              // Int sur RX UART
+  //gsm_net.disable_irq();      // Int sur LED NET GSM
+  //ticker_hab.detach();        // Ticker HAB
+  //ticker_check_gsm.detach();  // Ticker check GSM
+    
+  #ifdef DEBUG_SERIAL_PC
+    serial_pc.printf(">>> GSM Initialisation <<<\n");
+    serial_pc.printf(" Init GSM : %d\n",gsm.init());
+    serial_pc.printf(" Statut SIM : %d\n",gsm.checkSIMStatus());
+    serial_pc.printf(" Force signal : %d\n",gsm.checkSignalStrength());
+    serial_pc.printf(" Reglage SMS : %d\n",gsm.settingSMS());
+    //serial_pc.printf(" Test SMS : %d\n",gsm.sendSMS(GSM_SEND_NUMBER, GSM_SEND_SMS_HELLO));
+  #endif
+  
+  // On considere le GSM initialisé et n'est donc plus en phase de démarrage
+  flag_gsm_starting = 0;
+    
+  // On autorise de nouveau les interruptions GPS et GSM, ticker HAB
+  all_irq_on_off(1, 1, 1, 1);
+  //irq_gps_on();
+  //gsm_net.enable_irq();
+  //ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME);
+  //ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME);
+}
+
+// Fonction qui allume le module GSM (matériellement)
+void gsm_pwr_on() {
+  // Entrée : "bool attendre", specifie si la fonction doit attendre que le
+  // module GSM démarre.
+  if(gsm_status == 0) {
+    // Arret de toute les sources d'interruptions
+    all_irq_on_off(0, 0, 0, 0);
+
+    // Creation et lancement d'un timer de time out du démarrage du module GSM
+    Timer timer_gsm_init;
+    timer_gsm_init.start();
+
+    // On considere que le GSM est sous-tension, on verifiera ...     
+    gsm_pwr = 1;
+
+    while(gsm_status == 0) {
+      wait(0.5);
+      if(timer_gsm_init.read() > 5) { // Si après 5s ... ?
+        #ifdef DEBUG_SERIAL_PC
+          serial_pc.printf("<<<< ERREUR >>>> module GSM absent\n");
+        #endif
+        flag_gsm_absent = 1;      // Constatation de l'absence du module GSM
+        timer_gsm_network.stop(); // Arrêt du timer GSM
+        gsm_pwr = 0;              // le GSM n'est donc pas sous tension                
+        // On autorise de nouveau les interruptions GPS et GSM, ticker HAB
+        all_irq_on_off(1, 1, 1, 1);
+        return;
+      }
+    }
+    gsm_pwr = 0;
+    timer_gsm_network.stop(); 
+  }
+  else     
+    #ifdef DEBUG_SERIAL_PC 
+      serial_pc.printf("Module GSM deja allume ");
+    #endif
+    // Constatation de la présence du module GSM
+    flag_gsm_absent = 0;  
+    // Indication que le module GSM est en train de démarrer materiellement
+    // ou du moins qu'il faudra bientot faire l'init logiciel dès qu'il
+    // sera pret (NET LED avec bonne période de 3s.
+    flag_gsm_starting = 1;  
+    
+    // On autorise de nouveau les interruptions GPS et GSM, ticker HAB
+    all_irq_on_off(1, 1, 1, 1);
+
+}
+
+#endif  // Fin directive de compilation module GSM
+
+/////////////////////////////////////////////////////////////////////////
+// Ozone O3
+#ifdef O3_FUNCTION   // Debut directive de compilation spi_ozone
+
+double lecture_ozone() {
+  // Variables
+  double resultat = 0.0;    
+  uint32_t chiffre=0;
+  uint8_t Buff[4];
+  for(int i=0; i<3;i++) Buff[i] = 0;
+  
+  // Paramètres Ozone
+  spi_ozone.format(8,3);
+  spi_ozone.frequency(1000000); 
+  ozone_SS.write(0);  // Selection de l'esclave
+  //spi_ozone.write(0x8F);
+  wait_ms(100);      
+  Buff[0] = spi_ozone.write(0);
+  Buff[1] = spi_ozone.write(0);
+  Buff[2] = spi_ozone.write(0);
+  Buff[3] = spi_ozone.write(0);
+  ozone_SS.write(1);  // Deselection de l'esclave
+    
+  chiffre = ((uint32_t)(Buff[0]) << 24) | ((uint32_t)(Buff[1]) << 16) | ((uint32_t)(Buff[2]) << 8) | (uint32_t)(Buff[3]);
+  chiffre = chiffre >> 7;
+  resultat = 100 - (chiffre/41943.040);   // Conversion en %ADC
+  return resultat;    
+}
+
+#endif  // Fin directive de compilation spi_ozone
+
+/////////////////////////////////////////////////////////////////////////
+//// Tickers, Interruptions, Threads
+
+/////////////////////////////////////////////////////////////////////////
+// GSM
+#ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+
+void f_ticker_check_gsm() {
+  // Fonction du ticker de surveillance du module GSM, lancée toute les .. s
+        
+  // Si module GSM absent, on retourne
+  if(flag_gsm_absent == 1) return;
+        
+  // Arret de toute les sources d'interruptions
+  all_irq_on_off(0, 2, 2, 2);
+    
+  // Si le module GSM est éteint, on l'allume
+  if(gsm_status == 0) gsm_pwr_on();
+    
+  // Si module GSM non connecté
+  if(flag_gsm_network_ok == 0) {      
+    // Si cela fait plus de 15 trames que l'on a démarré alors
+    if(hab_frame_counter - last_reset_gsm > 15) {
+      #ifdef DEBUG_SERIAL_PC 
+        serial_pc.printf("\n Reset du module GSM ...");
+      #endif
+      // todo : appui sur bouton reset du module gsm          
+      last_reset_gsm = hab_frame_counter;      
+  } }
+     
+  // met fin à l'envoi d'un sms, le module reste parfois bloqué dans la
+  // commande d'envoi et ne répond pas "OK" lorsqu'on check power en envoyant "AT"
+  gsm.gprsSerial.putc((char)0x1A); 
+    
+  int sim_status = gsm.checkSIMStatus();
+  #ifdef DEBUG_SERIAL_PC 
+    serial_pc.printf("\n>>> Check statut SIM : %d\n", sim_status);
+  #endif
+  if(sim_status != 0) { init_GSM(); } // Il est nécessaire d'initialiser de nouveau le GSM
+        
+  // On autorise de nouveau les interruptions GPS et GSM, ticker HAB
+  all_irq_on_off(1, 2, 2, 2);
+  // Flag ticker GSM inactif
+  flag_ticker_check_gsm = 0;
+}
+
+#endif  // Fin directive de compilation module GSM
+
+/////////////////////////////////////////////////////////////////////////
+// GPS
+#ifdef GPS_FUNCTION   // Debut directive de compilation module GPS
+/////////////////////////////////////////////////////////////////////////
+
+// GPS = fonctions d'activation et de desactivation de l'interruption UART
+void irq_gps_off() {
+  // IRQ OFF : desactivation de l'interruption pour le port UART du GPS
+  gps_serial.attach(NULL);
+}
+void irq_gps_on() {
+  // IRQ ON : activation de l'interruption pour le port UART du GPS
+  gps_serial.attach(&isr_gps_serial,Serial::RxIrq);
+}
+
+// Routine d'interruption (ISR) pour la reception sur port UART du GPS
+void isr_gps_serial() { 
+  if(gps_serial.readable()) {        
+    #ifdef GPS_DEBUG
+      char c = gps_serial.getc();
+      serial_pc.putc(c);
+      gps.readCharacter(c);
+    #else
+      gps.readCharacter(gps_serial.getc());
+    #endif
+  }
+}
+
+#endif  // Fin directive de compilation module GPS
+
+////////////////////////////////////////////////////////////////////////
+// SMS (GSM)
+// Ticker executé toute les xx sec pour envoi des données par sms
+#ifdef SMS_FUNCTION   // Debut directive de compilation module SMS
+
+void f_ticker_sms_data() {
+  if(flag_gsm_network_ok == 1) {
+    #ifdef DEBUG_SERIAL_PC 
+      serial_pc.printf(">>>>>> Send HAB data to SMS\n");
+    #endif
+    // Portable personnel de Dufaza
+    gsm.sendSMS(GSM_SEND_NUMBER, sd_gprs_data);
+    // Le SMS a ete envoyé ...
+    flag_ticker_sms_data = 0;
+} }
+
+#endif  // Fin directive de compilation module SMS
+
+////////////////////////////////////////////////////////////////////////
+// HAB
+// Ticker executé toute les 5 s pour recolter toute les données,
+// les enregistrer sur la carte SD et les envoyer en UART à la carte LoRa
+#ifdef HAB_FUNCTION   // Debut directive de compilation module HAB
+
+void f_ticker_hab() {        
+  //DS18 thermomètre pt1 (en 2 parties pour eviter d'attendre)
+  #ifdef DS18_FUNCTION   // Debut directive de compilation DS181B20    
+    // todo 
+  #endif  // Fin directive de compilation DS181B20
+         
+  // Recuperation donnees capteurs ST X_NUCLEO_IKS01A2
+  #ifdef XNUCLEO_FUNCTION   // Debut directive de compilation shield capteurs XNUCLEO
+    hum_temp->get_temperature(&xnuc_t);
+    hum_temp->get_humidity(&xnuc_h);
+    press_temp->get_temperature(&xnuc_t2);
+    press_temp->get_pressure(&xnuc_p);
+  #endif  // Fin directive de compilation shield capteurs XNUCLEO
+      
+  //PT100
+  #ifdef PT100_FUNCTION   // Debut directive de compilation module PT100
+    PT100.read_all();
+    if(PT100.status() == 0) {
+       tempPT100 = PT100.temperature();
+       #ifdef DEBUG_SERIAL_PC 
+         //serial_pc.printf(">>>>>> Temp PT100 = %f degC \r\n",tempPT100);
+       #endif
+    }
+    else {
+       tempPT100 = 0;
+       #ifdef DEBUG_SERIAL_PC 
+          serial_pc.printf("<<< ERREUR >>> Registre d'erreur PT100 : %d - ",PT100.status( ));
+          if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) {
+               serial_pc.printf("ERREUR PT100 seuil haut franchi\n");
+          }
+          else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) {
+               serial_pc.printf("ERREUR PT100 seuil bas franchi\n");
+          }
+          else if(PT100.status() & MAX31865_FAULT_REFIN) {
+               serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n");
+          }
+          else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) {
+               serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
+          }
+          else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) {
+               serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
+          }
+          else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) {
+               serial_pc.printf("ERREUR sur/sous-tension\n");
+          }
+          else serial_pc.printf("ERREUR inconnue\n");
+       #endif
+       }
+  #endif  // Fin directive de compilation module PT100
+                
+  // CO2
+  #ifdef CO2_FUNCTION   // Debut directive de compilation module CO2
+    co2.IAQmeasure();
+    #ifdef DEBUG_SERIAL_PC 
+      /*serial_pc.printf("TVOC : %d\n", co2.TVOC);
+      serial_pc.printf("eCO2: %d\n", co2.eCO2);*/
+    #endif
+    eco2 = co2.eCO2;
+    tvoc = co2.TVOC;
+  #endif  // Fin directive de compilation module CO2
+              
+  //DS18 thermomètre pt2 (en 2 parties pour eviter d'attendre)
+  #ifdef DS18_FUNCTION   // Debut directive de compilation DS181B20      
+    // todo 
+  #endif  // Fin directive de compilation DS181B20
+        
+  // Capteurs UV et lumiere
+  #ifdef UV_FUNCTION   // Debut directive de compilation capteur UV
+    uv = pin_UV.read();
+  #endif  // Fin directive de compilation capteur UV
+  #ifdef PHOTORES_FUNCTION   // Debut directive de compilation capteur lumière
+     photores = pin_photores.read();
+  #endif  // Fin directive de compilation capteur lumière
+                
+  // Triple capteur Bosch BME280
+  #ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+     bosch_t = bosch.getTemperature();
+     //bosch_p = bosch.getPressure();
+     bosch_p = 900.0 ;
+
+     bosch_h = bosch.getHumidity();
+     #ifdef DEBUG_SERIAL_PC 
+       //serial_pc.printf("-> Bosch : %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity());
+     #endif
+  #endif  // Fin directive de compilation Bosch
+              
+  // Ozone
+  #ifdef O3_FUNCTION   // Debut directive de compilation spi_ozone
+    ozone = lecture_ozone();
+  #endif  // Fin directive de compilation spi_ozone
+        
+  // Mesure tension batterie (tension ref* pont diviseur + chute diode)
+  vbatt = ((double) pin_vbatt.read())*3.3*11.07+0.52;
+        
+  // Recuperation données GPS
+  #ifdef GPS_FUNCTION   // Debut directive de compilation module GPS
+    gps.getTimestamp(timeUTCBuffer);
+    gps.getLatitude(latBuffer);
+    gps.getLongitude(lonBuffer);
+    gps.getAltitude(altBuffer);
+    gps.getSpeed(speedBuffer);
+    //printf("UTC: %s\t Latitude: %s\t Longitude: %s\t altitude: %s\t speed: %s\n", timeUTCBuffer, latBuffer, lonBuffer, altBuffer, speedBuffer);
+    // Convertion des chaine en entier et flottant
+    timeUTC = atoi(timeUTCBuffer);
+    lat = (float)atof(latBuffer);
+    lon = (float)atof(lonBuffer);
+    alt = (float)atof(altBuffer);
+    speed = (float)atof(speedBuffer);
+  #endif  // Fin directive de compilation module GPS
+              
+  // Mise en forme dans un tableau de caractères
+  sprintf((char*) sd_gprs_data, "%d-%.2f-%d-%f-%f-%.1f-%.1f-%.1f-%.1f-%.3f-%.3f-%.3f-%.1f-%.3f-%.2f-%.2f-%d-%d-%f-%.3f-%.3f", 
+          hab_frame_counter, vbatt, timeUTC, lat, lon, alt, speed, 
+          xnuc_t, xnuc_t2, tempPT100, tempDS18, bosch_t, xnuc_h, bosch_h, xnuc_p, bosch_p, eco2, tvoc, ozone, (double)uv*100.0, (double)photores*100.0);
+        
+  #ifdef DEBUG_SERIAL_PC   
+    // Affichage des données sur port série debug
+    serial_pc.printf("\n>>> HAB Frame Counter : %d\n", hab_frame_counter);
+    serial_pc.printf("> Tension batterie : %f V\n", vbatt);
+    #ifdef GPS_FUNCTION   // Debut directive de compilation module GPS
+      serial_pc.printf("> Temps UTC : %d\n", timeUTC);
+      serial_pc.printf("> Latitude : %f\n", lat);
+      serial_pc.printf("> Longitude : %f\n", lon);
+      serial_pc.printf("> Altitude : %.2f m\n", alt);
+      serial_pc.printf("> Vitesse : %.2f km/h\n", speed);
+    #endif  // Fin directive de compilation module GPS
+      
+    #ifdef XNUCLEO_FUNCTION   // Debut directive de compilation shield capteurs XNUCLEO
+      serial_pc.printf("> Temperature 1 (XNUCLEO) : %.3f *C\n", xnuc_t);
+      serial_pc.printf("> Temperature 2 (XNUCLEO) : %.3f *C\n", xnuc_t2);
+    #endif  // Fin directive de compilation shield capteurs XNUCLEO
+  
+    #ifdef PT100_FUNCTION   // Debut directive de compilation module PT100
+      serial_pc.printf("> Temperature 3 (PT100) : %.3f *C\n", tempPT100);
+    #endif  // Fin directive de compilation module PT100
+  
+    #ifdef DS18_FUNCTION   // Debut directive de compilation DS181B20
+      serial_pc.printf("> Temperature 4 (DS18) : %.3f *C\n", tempDS18);
+    #endif  // Fin directive de compilation DS181B20
+  
+    #ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+      serial_pc.printf("> Temperature 5 (Bosch) : %.3f *C\n",bosch_t);
+    #endif  // Fin directive de compilation Bosch
+  
+    #ifdef XNUCLEO_FUNCTION   // Debut directive de compilation shield capteurs XNUCLEO
+      serial_pc.printf("> Humidite 1 (XNUCLEO) : %.2f %%\n", xnuc_h);
+    #endif  // Fin directive de compilation shield capteurs XNUCLEO
+  
+    #ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+      serial_pc.printf("> Humidite 2 (Bosch) : %.2f %%\n",bosch_h);
+    #endif  // Fin directive de compilation Bosch
+  
+    #ifdef XNUCLEO_FUNCTION   // Debut directive de compilation shield capteurs XNUCLEO
+      serial_pc.printf("> Pression 1 (XNUCLEO) : %.2f mbar - altitude calculee : %.2f m\n", xnuc_p, altitude(xnuc_p, BASE_PRESSURE));
+    #endif  // Fin directive de compilation shield capteurs XNUCLEO
+  
+    #ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+        serial_pc.printf("> Pression 2 (Bosch) : %.2f mbar - altitude calculee : %.2f m\n",bosch_p, altitude(bosch_p, BASE_PRESSURE));
+    #endif  // Fin directive de compilation Bosch
+  
+    #ifdef CO2_FUNCTION   // Debut directive de compilation module CO2
+      serial_pc.printf("> eCO2 : %d ppm\n", eco2);
+      serial_pc.printf("> TVOC : %d ppb\n", tvoc);
+    #endif  // Fin directive de compilation module CO2
+  
+    #ifdef UV_FUNCTION   // Debut directive de compilation capteur UV
+      serial_pc.printf("> UV : %.3f %%ADC\n", (double)uv*100.0);
+    #endif  // Fin directive de compilation capteur UV
+  
+    #ifdef PHOTORES_FUNCTION   // Debut directive de compilation capteur lumière
+      serial_pc.printf("> Lum : %.3f %%ADC\n", (double)photores*100.0);
+    #endif  // Fin directive de compilation capteur lumière
+  
+    #ifdef O3_FUNCTION   // Debut directive de compilation spi_ozone
+      serial_pc.printf("> Ozone O3 : %f %%ADC\n", ozone);
+    #endif  // Fin directive de compilation spi_ozone
+           
+    serial_pc.printf("%s\n", sd_gprs_data);
+  #endif
+        
+  // Envoi de la chaine par GPRS au Polytech Server
+  #ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+    #ifdef GPRS_FUNCTION   // Debut directive de compilation données mobiles
+      if(flag_gsm_network_ok == 1) {
+        #ifdef DEBUG_SERIAL_PC 
+          serial_pc.printf(">>>>>> Send HAB data to Polytech Server\n");
+        #endif
+        gsm.gprs_message(url_srv_polytech , sd_gprs_data);
+      }
+    #endif  // Fin directive de compilation données mobiles
+    /*if(flag_gsm_network_ok == 1) {
+         #ifdef DEBUG_SERIAL_PC   
+           serial_pc.printf("SMS : %d\n",gsm.sendSMS("+33676040268", sd_gprs_data)); // Envoi de la chaine par SMS
+         #endif
+    */
+  #endif  // Fin directive de compilation module GSM
+        
+  // Sauvegarde sur carte SD
+  #ifdef SD_FUNCTION   // Debut directive de compilation carte SD
+     ecriture_sd(SD_FUNCTION_FILENAME, sd_gprs_data);
+  #endif  // Fin directive de compilation carte SD
+              
+  // Creation de la chaine à envoyer à la carte LoRa
+  #ifdef LORA_FUNCTION    // Debut directive de compilation LoRa
+    sprintf((char*) lora_data_tx, "%.2f-%f-%f-%.1f-%.3f", vbatt, lat, lon, alt, tempPT100);
+    #ifdef DEBUG_SERIAL_PC   
+      serial_pc.printf("%s\n", lora_data_tx);
+    #endif
+  #endif  // Fin directive de compilation LoRa
+        
+  #ifdef DEBUG_SERIAL_PC   
+    //serial_pc.printf("------------------------------------------------\n");
+    serial_pc.printf("\n");
+  #endif
+
+  // Increment du numéro de la trame transmise
+  hab_frame_counter++;
+  // Flag ticker HAB inactif
+  flag_ticker_hab = 0;    
+}
+
+#endif  // Fin directive de compilation module HAB
+
+/////////////////////////////////////////////////////////////////////////
+// Routines d'interruption appelées au tick des tickers et servant juste à lever un flag
+// Pensez à abaisser le flag dans f_ticker_hab() et f_ticker_gsm() !
+#ifdef HAB_FUNCTION
+  void isr_ticker_hab() { flag_ticker_hab = 1; }
+#endif
+
+#ifdef GSM_FUNCTION
+  void isr_ticker_check_gsm() { flag_ticker_check_gsm = 1; }
+#endif
+
+#ifdef SMS_FUNCTION
+  void isr_ticker_sms_data() { flag_ticker_sms_data = 1; }
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// LoRa
+#ifdef LORA_FUNCTION    // Debut directive de compilation LoRa
+
+void envoi_lora_data_tx() { 
+  lora_serial.printf("%s\n", lora_data_tx);
+  #ifdef DEBUG_SERIAL_PC   
+    serial_pc.printf("lora!\n");    // debug
+  #endif
+}
+
+void isr_lora_serial() {  
+  char c = lora_serial.getc();
+  if(c == 'a') envoi_lora_data_tx();
+  #ifdef MP3_FUNCTION   // Debut directive de compilation lecteur MP3
+    elseif(c == 'b') mp3.mp3_play();
+    elseif(c == 'c') mp3.mp3_pause();
+  #endif  // Fin directive de compilation lecteur MP3
+  #ifdef BUZZ_FUNCTION    // Debut directive de compilation buzzer
+    elseif(c == 'd') pin_buzzer.write(1);
+    elseif(c == 'e') pin_buzzer.write(0);
+  #endif  // Fin directive de compilation buzzer  
+}
+
+#endif  // Fin directive de compilation LoRa
+
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////  MAIN  ////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+int main() {
+    
+  // Affichage/listage des modules compilés/activés sur port série STLINK
+  #ifdef DEBUG_SERIAL_PC
+    serial_pc.printf("\n\n-----------------------------------------------------------------------------------\n");
+    serial_pc.printf("--- AMU Aix-Marseille Universit\xE9 - Polytech Marseille MT - STM32 in the Sky HAB ---\n");
+    vbatt = ((double)pin_vbatt.read())*3.3*11.07+0.52;    // Tension batterie (tension ref * pont diviseur + chute diode)
+    serial_pc.printf("- Tension batterie = %f V\n", vbatt);
+    serial_pc.printf("- Liste des Fonctionalit\xE9s & Capteurs op\xE9rationnels ...\n");
+  #endif
+    
+  //Buzzer, léger bip au démarrage
+  #ifdef BUZZ_FUNCTION
+    #ifdef DEBUG_SERIAL_PC   
+      serial_pc.printf("-> Buzzer ON ... ");
+    #endif
+    for(int i=1; i<BUZZ_FUNCTION_DURATION; i++) // #périodes de 1,5kHz
+    { // 333us x 2 = 1,5k Hz
+      pin_buzzer.write(1); wait_us(BUZZ_FUNCTION_HZ);
+      pin_buzzer.write(0); wait_us(BUZZ_FUNCTION_HZ);
+    };
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("OFF\n");
+    #endif
+  #endif
+    
+  // Shield ST X_NUCLEO_IKS01A2
+  #ifdef XNUCLEO_FUNCTION 
+    // Hum, Temp, Press, Temp, Accelero enable
+    hum_temp->enable();
+    press_temp->enable();
+    accelerometer->enable();
+    // Lecture des capteurs
+    hum_temp->get_temperature(&xnuc_t);
+    hum_temp->get_humidity(&xnuc_h);
+    press_temp->get_temperature(&xnuc_t2);
+    press_temp->get_pressure(&xnuc_p);
+    accelerometer->get_x_axes(xnuc_acc);
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> XNucleo = %.3f \xB0 C, %.3f \xB0 C, %.3f mbar, %.2f %%, ",xnuc_t, xnuc_t2, xnuc_p, xnuc_h);  
+      serial_pc.printf("Acc x = %ld, y = %ld, z = %ld\n", xnuc_acc[0], xnuc_acc[1], xnuc_acc[2]);
+    #endif
+  #endif
+    
+  // GSM
+  #ifdef GSM_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> GSM ON ");
+    #endif
+    gsm_pwr_on();
+  #endif
+
+  // GPRS SMS
+  #ifdef GPRS_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("& GPRS ON\n");
+    #endif
+  #endif
+    
+  #ifdef PT100_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> PT100 = ");
+    #endif
+    // Configuration initiale du MAX31865
+    /*
+    1: v_biais : Vbias (tension de polarisation) activée (true) ou non (false)
+    2: conversion_mode : mode de conversion automatique activé (true) ou non (false)
+    3: one_shot : mesure au coup par coup (true) ou en continue (false)
+    4: three_wire : mesure 3 fils activée (true) ou 2/4 fils (false)
+    5: fault_cycle : detection d'erreur (voir datasheet) activée (true) ou non (false)
+    6: fault_clear : acquittement automatique des erreurs activée (true) ou non (false)
+    7: filter_50hz : filtre 50 Hz activé (true) ou non (false)
+    8: low_threshold : seuil d'erreur bas. (0x0000 = 0)
+    9: high_threshold : seuil d'erreur haut. (0x7fff = 32767)
+    */
+    PT100.configure(true, true, false, false, MAX31865_FAULT_DETECTION_NONE, true, true, 0x0000, 0x7fff);
+    PT100.read_all();
+    #ifdef DEBUG_SERIAL_PC       
+    if(PT100.status() == 0) {
+        //serial_pc.printf("PT100 OK Temp = %.3f *C\n",PT100.temperature());
+        serial_pc.printf("PT100 OK\n");
+    }
+    else {
+        serial_pc.printf("\n!!! Registre d'erreur PT100 = %d - ",PT100.status( ));
+        if(PT100.status() & MAX31865_FAULT_HIGH_THRESHOLD) {
+             serial_pc.printf("ERREUR PT100 seuil haut franchi\n");
+        }
+        else if(PT100.status() & MAX31865_FAULT_LOW_THRESHOLD) {
+            serial_pc.printf("ERREUR PT100 seuil bas franchi\n");
+        }
+        else if(PT100.status() & MAX31865_FAULT_REFIN) {
+            serial_pc.printf("ERREUR REFIN- > 0,85 x V_BIAS\n");
+        }
+        else if(PT100.status( ) & MAX31865_FAULT_REFIN_FORCE) {
+            serial_pc.printf("ERREUR REFIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
+        }
+        else if(PT100.status( ) & MAX31865_FAULT_RTDIN_FORCE ) {
+            serial_pc.printf("ERREUR RTDIN- < 0,85 x V_BIAS, FORCE- ouvert\n");
+        }
+        else if(PT100.status( ) & MAX31865_FAULT_VOLTAGE) {
+            serial_pc.printf("ERREUR sur/sous-tension\n");
+        }
+        else serial_pc.printf("ERREUR inconnue\n");
+      }
+    #endif
+  #endif
+    
+  // Carte SD, initialisation, et creation d'un fichier de test d'ecriture
+  // /!\ Faire cette étape après l'initialisation du capteur PT100 qui partage le même SPI
+  #ifdef SD_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> SD = ");
+    #endif
+    //mkdir("/sd/TEST", 0777);
+    FILE *fp = fopen(SD_FUNCTION_TESTFILENAME, "w");
+    if(fp == NULL) {
+        #ifdef DEBUG_SERIAL_PC       
+          serial_pc.printf("ERREUR - Ecriture carte SD\n");
+        #endif
+        // Desactivation de la sauvegarde sur carte SD
+        flag_sd_ok = 0;
+    }
+    else {
+        fprintf(fp, "AMU - Polytech Marseille - HAB STM32 in the Sky - Test ecriture SD");
+        fclose(fp); 
+        #ifdef DEBUG_SERIAL_PC       
+          serial_pc.printf("Ecriture carte SD - ok\n");
+        #endif
+        //Activation de la sauvegarde sur carte SD
+        flag_sd_ok = 1;
+    }
+  #endif
+    
+  // CO2
+  #ifdef CO2_FUNCTION
+    co2.begin();
+    co2.IAQmeasure();
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> CO2 = TVOC = %d, eCO2 = %d\n", co2.TVOC, co2.eCO2);
+    #endif
+  #endif
+    
+  //DS18 thermomètre
+  #ifdef DS18_FUNCTION   // Debut directive de compilation DS181B20
+    
+    if (ds18.begin()) {
+        while (1) {
+            ds18.startConversion();   // start temperature conversion from analog to digital
+            wait(1.0);                  // let DS1820 complete the temperature conversion
+            result = ds18.read(tempDS18); // read temperature from DS1820 and perform cyclic redundancy check (CRC)
+            switch (result) {
+                case 0:                 // no errors -> 'tempDS18' contains the value of measured temperature
+                    #ifdef DEBUG_SERIAL_PC       
+                      serial_pc.printf("temp = %3.1f%cC\r\n", tempDS18, 176);
+                    #endif
+                    break;
+                case 1:                 // no sensor present -> 'tempDS18' is not updated
+                    #ifdef DEBUG_SERIAL_PC       
+                      serial_pc.printf("no sensor present\n\r");
+                    #endif
+                    break;
+                case 2:                 // CRC error -> 'tempDS18' is not updated
+                    #ifdef DEBUG_SERIAL_PC       
+                      serial_pc.printf("CRC error\r\n");
+                    #endif
+            }
+        }
+    }
+    else
+        #ifdef DEBUG_SERIAL_PC       
+          serial_pc.printf("No DS1820 sensor found!\r\n");
+        #endif
+    
+  #endif  // Fin directive de compilation DS181B20
+    
+  //UV
+  #ifdef UV_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> UV = %.3f %%ADC\n",pin_UV.read());
+    #endif
+  #endif
+    
+  //Photoresistance
+  #ifdef PHOTORES_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> Photoresistance = %.3f %%ADC\n",(double)pin_photores.read()*100.0);
+    #endif
+  #endif
+    
+  // Triple capteur Bosch BME280
+  #ifdef BOSCH_FUNCTION   // Debut directive de compilation Bosch
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> Bosch = %.2f *C, %.2f mbar, %.2f %%\n", bosch.getTemperature(), bosch.getPressure(), bosch.getHumidity());
+    #endif
+  #endif  // Fin directive de compilation Bosch
+    
+  // Lecteur MP3
+  // Creer un fichier 0.mp3 à la racine de la carte SD
+  #ifdef MP3_FUNCTION   // Debut directive de compilation lecteur MP3
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> MP3 ON\n");
+    #endif
+    mp3.mp3_reset();
+    wait(1);    
+    mp3.mp3_set_EQ(0);
+    wait(0.5);
+    mp3.mp3_set_volume(20);
+    wait(0.5);
+    mp3.mp3_set_device(2);   // 1,2,3,4,5 : USB,SD,AUX,SLEEP,FLASH
+    wait(0.5);
+    mp3.mp3_single_loop(0);
+    //mp3.mp3_single_play(0) ; 
+    wait(0.5);
+    //serial_pc.printf("We are in the MP3 func !!!!!\n\r");
+    mp3.mp3_play();
+  #endif  // Fin directive de compilation MP3
+      
+  #ifdef LORA_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> LoRa ON\n");
+    #endif
+  #endif
+
+  #ifdef GPS_FUNCTION
+    #ifdef DEBUG_SERIAL_PC 
+      serial_pc.printf("-> GPS ON\n");
+    #endif
+  #endif
+    
+  #ifdef O3_FUNCTION
+    #ifdef DEBUG_SERIAL_PC       
+      serial_pc.printf("-> Ozone O3 = %f %%ADC\n", lecture_ozone());
+    #endif  
+  #endif    
+
+  #ifdef DEBUG_SERIAL_PC       
+    serial_pc.printf("\n");
+  #endif
+      
+  //////  Lancement des ticker et des interruptions  ////////
+
+  // GPS
+  // Mise en place de l'interruption pour le port UART du GPS
+  #ifdef GPS_FUNCTION   // Debut directive de compilation module GPS
+    gps_serial.attach(&isr_gps_serial,Serial::RxIrq);
+  #endif  // Fin directive de compilation module GPS
+      
+  // Ticker de creation de la chaine de données toute les 5s
+  ticker_hab.attach(&isr_ticker_hab, TICKER_HAB_TIME);
+
+  // GSM
+  #ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+    if(flag_gsm_absent == 0) {
+        
+        // Interruption sur LED "NET" et compteur de sa période
+        timer_gsm_network.reset();   // Démarrage du compteur de la période de clignotement de la LED "NET"
+        timer_gsm_network.start();   
+        gsm_net.rise(&isr_network_gsm);    // Attachement de l'interruption externe sur la LED "NET"
+       
+        // Ticker de surveillance GSM toute les xx sec
+        ticker_check_gsm.attach(&isr_ticker_check_gsm, TICKER_CHECK_GSM_TIME);
+        
+        // Ticker d'envoi de données par sms toute les xx sec
+        #ifdef SMS_FUNCTION   // Debut directive de compilation envoi SMS
+          ticker_sms_data.attach(&isr_ticker_sms_data, TICKER_SMS_DATA_TIME);
+        #endif  // Fin directive de compilation SMS de données toutes les xx sec      
+    }
+  #endif  // Fin directive de compilation module GSM
+      
+  // LoRa
+  // Mise en place de l'interruption pour le port UART LoRa
+  #ifdef LORA_FUNCTION    // Debut directive de compilation LoRa
+    lora_serial.attach(&isr_lora_serial,Serial::RxIrq);
+  #endif  // Fin directive de compilation LoRa
+    
+  ///////////////////  BOUCLE PRINCIPALE  /////////////////  
+  while(1) {       
+        
+    // Vérification du flag d'interruption pour la routine de recuperation
+    // des données des capteurs, enregistrement, envoi LoRa, etc.
+    #ifdef HAB_FUNCTION
+      if(flag_ticker_hab == 1) f_ticker_hab();
+    #endif
+    
+    // Vérification du flag d'interruption pour la routine de vérification
+    // de l'état du module
+    #ifdef GSM_FUNCTION   // Debut directive de compilation module GSM
+      if(flag_ticker_check_gsm == 1)  
+      {  if ( (altitude(xnuc_p, BASE_PRESSURE) < GSM_START_ALTITUDE ) || (altitude(bosch_p, BASE_PRESSURE) < GSM_START_ALTITUDE) )
+        { 
+            #ifdef DEBUG_SERIAL_PC       
+            serial_pc.printf("> Pression 1 (XNUCLEO) : %.2f mbar - altitude GSM : %.2f m\n", xnuc_p, altitude(xnuc_p, BASE_PRESSURE));
+            serial_pc.printf("> Pression 1 (BOSCH) : %.2f mbar - altitude GSM : %.2f m\n", bosch_p, altitude(bosch_p, BASE_PRESSURE));
+            #endif
+            f_ticker_check_gsm();
+        }
+      }
+    #endif  // Fin directive de compilation module GSM
+        
+    // Vérification du flag d'interruption pour la routine d'envoi de SMS
+    // de donnée toute les 10 min
+    #ifdef SMS_FUNCTION  // Debut directive de compilation SMS de données toutes les 10 min
+        if(flag_ticker_sms_data == 1)  f_ticker_sms_data();
+    #endif  // Fin directive de compilation SMS de données toutes les 10 min           
+    }
+}