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:
0:d7a683cf76d9
Child:
3:cb77ea3370e8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Feb 03 20:31:41 2019 +0000
@@ -0,0 +1,1178 @@
+// 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
+        
+    }
+}