mbed-os github

Dependencies:   ADS1015 Faulhaber HTU21D_mod MS5837_potless Sensor_Head_RevB_3 USBDevice_dfu Utilsdfu beep

Fork of ARNSRS_testDFU by POTLESS

Revision:
34:26f6e3dbefb9
Parent:
33:f5d4bae05f16
Child:
35:a209a192f431
diff -r f5d4bae05f16 -r 26f6e3dbefb9 main.cpp
--- a/main.cpp	Sat Feb 24 16:56:19 2018 +0000
+++ b/main.cpp	Mon Mar 05 11:16:18 2018 +0000
@@ -50,7 +50,7 @@
 #define DEBUG(...)
 #endif
 
-       
+
 //PinName pwm, PinName nSleep, PinName fwd, PinName rev, PinName channelA, PinName channelB, int pulsesPerRev, int Rapport, Encoding encoding = X2_ENCODING
 Faulhaber Servo_Poumon("Servo_Poumon", PWM_SERVO_POUMON, nSleep_SERVO_POUMON, FWD_SERVO_POUMON, REV_SERVO_POUMON, Channel_A_SERVO_POUMON, Channel_B_SERVO_POUMON, 16, 207, Faulhaber::X2_ENCODING);
 //Faulhaber Servo_Fuite("Servo_Fuite", PWM_SERVO_FUITE, nSleep_SERVO_FUITE, FWD_SERVO_FUITE, REV_SERVO_FUITE, 1, Channel_A_SERVO_FUITE, Channel_B_SERVO_FUITE, 16, 207, Faulhaber::X2_ENCODING);
@@ -64,8 +64,8 @@
 //Init de la lib ARNSRS;
 SENSOR_HEAD_REV_B sensors;
 
-//pour Param Cozir
-const int sizeParam = 20;
+//pour Param Venant du PV
+const int sizeParam = 30;
 char  param[sizeParam];
 volatile int indexParam = 0;
 bool newParamFlag = false;
@@ -110,15 +110,11 @@
 int Humid;
 
 //Data LOG
+char header[50];
 char to_store[50];
 time_t seconds;
 char Log_File_Name[] = "                           ";
 
-//Thread d'intérogation des capteurs et de positionnement des volets
-Thread thread_Sensors;
-Thread thread_Volets;
-Thread thread_Secu;
-
 //Contrôle des servos
 float Consigne_poumon = 0;
 float volet_poumon_Position = 0;
@@ -188,9 +184,10 @@
     fflush(stdout);
 }
 
-void pressed() {
-  GO = GO + 1;
-  if (GO > 1) NVIC_SystemReset(); 
+void pressed()
+{
+    GO = GO + 1;
+    if (GO > 1) NVIC_SystemReset();
 }
 
 //Passage en mode SECU
@@ -202,7 +199,7 @@
 #endif
     Consigne_poumon = HOME_SERVO_POUMON;
     Consigne_fuite = HOME_SERVO_FUITE;
-    
+
     Volets_Speed = 0.1;
     Volet_DeadBand = 10;
 
@@ -212,9 +209,9 @@
         //if (Servo_Poumon.Pos_OK() == true && Servo_Fuite.Pos_OK() == true) break;
     }
     DEBUG("-------------- Appareil en mode SECU ---------------\r\n");
-    
+
     wait_ms(100);
-    
+
     EN_MODE_SECU = true;
     wait_ms(100);
     int Pos = Servo_Poumon.getPulses();
@@ -229,10 +226,10 @@
 
 //Sequence d'arrêt
 void Stop_Sequence()
-{   
-    Mode_SECU();  
+{
+    Mode_SECU();
     DEBUG("----------------ARRET DE L'APPAREIL--------------------\r\n");
-    
+
     DEBUG("  Deep sleep autorisé : %i\r\n", sleep_manager_can_deep_sleep());
     wait(1.0);
     sleep_manager_sleep_auto();
@@ -242,13 +239,13 @@
 int Power_Test(DigitalIn& pin)
 {
     pin.mode(PullDown);
-    
-    if(!pin){
-         Stop_Sequence();
-         return 0;
-    }else{
-         return 1;
-    }          
+
+    if(!pin) {
+        Stop_Sequence();
+        return 0;
+    } else {
+        return 1;
+    }
 }
 
 //Fonction test de valeur d'entrée analogique
@@ -285,9 +282,10 @@
 }
 
 //Thread d'intérogation des capteurs, positions servo
-void Get_Info_thread()
+void SENSORS_thread()
 {
     while (true) {
+        DEBUG("  SENSORS_thread\r\n");
 
         //CO2 sur Cozir
         co2 = sensors.requestCO2();
@@ -307,17 +305,19 @@
         //Retour position des servos
         volet_poumon_Position = Servo_Poumon.Get_Position();
         //volet_fuite_Position = Servo_Fuite.Get_Position();
-        
+
     }
 }
 
 void GO_TO_thread()
 {
     while (true) {
+        //DEBUG("  GO_TO_Thread\r\n");
+
         //Servo_Poumon.Go_To_Prop(Consigne_poumon);
         //Servo_Poumon.Go_To_PID(Consigne_poumon, Volet_DeadBand);
-        Servo_Poumon.Go_To(Consigne_poumon, Volets_Speed, Volet_DeadBand );
-        
+        Servo_Poumon.Go_To(Consigne_poumon, Volets_Speed, Volet_DeadBand);
+
         //Servo_Fuite.Go_To_Prop(Consigne_fuite);
         //Servo_Fuite.Go_To_PID(Consigne_fuite);
         //Servo_Fuite.Go_To(Consigne_fuite, Volets_Speed, Volet_DeadBand );
@@ -326,7 +326,9 @@
 
 void SECU_thread()
 {
-    while (true) {       
+    while (true) {
+        //DEBUG("  SECU_Thread\r\n");
+
         //Alim USB
         //Vusb = Power_Test(V_USB);
         //VPiles = Power_Test(V_PILES);
@@ -337,19 +339,18 @@
 
 //Callback de l'intérruption des envois de commandes depuis le terminal
 void callbackParam()
-{    
-    while(serialMonit.readable())
-     {
-       if ((indexParam  == sizeParam) || newParamFlag  == true) //éviter la saturation du buffer
+{
+    while(serialMonit.readable()) {
+        if ((indexParam  == sizeParam) || newParamFlag  == true) //éviter la saturation du buffer
             char char_flush = serialMonit.getc();
-        else 
+        else
             param [indexParam ++] = serialMonit.getc();//chargement du buffer dans le message
-       
-       if ((indexParam == sizeParam) || (param[indexParam - 1] == '\n')) {//le message est complet ou nouvelle ligne ou autre si on veut...
-       param[indexParam] = 0;
-       newParamFlag  = true;
-      }
-   }  
+
+        if ((indexParam == sizeParam) || (param[indexParam - 1] == '\n')) {//le message est complet ou nouvelle ligne ou autre si on veut...
+            param[indexParam] = 0;
+            newParamFlag  = true;
+        }
+    }
 }
 
 //Callback de l'intérruption des envois de commandes depuis Android
@@ -371,79 +372,94 @@
 {
 
     char com[sizeParam] = "";
-    float val = 0.0;
+    char numb[] = "";
     
-    sscanf(message,"%s %f",&com , &val);
-        
-    DEBUG("\r\n  Commande = %s       Valeur = %f \r\n\r\n", com, val);
-
+    sscanf(message,"%s %s",&com , &numb);
+    
+    DEBUG("\r\n  Commande = %s       Valeur = %s \r\n\r\n", com, numb);
+    
     if (0 == strcmp(com, "secu")) {
         Mode_SECU();
-    }else if (0 == strcmp(com, "calib_O2")) {
+    } else if (0 == strcmp(com, "ARNSRS_ID")) {
+        UTILS::Store_A_Val(atoi(numb), "ARNSRS_ID");
+    } else if (0 == strcmp(com, "Head_ID")) {
+        //On l'enregistre dans l'eeprom
+        UTILS::write_EEPROM(numb, HEAD_ID);
+    } else if (0 == strcmp(com, "O2_1_ID")) {
+        //On l'enregistre dans l'eeprom
+        UTILS::write_EEPROM(numb, CELL_O2_1_ID);
+    } else if (0 == strcmp(com, "O2_2_ID")) {
+        //On l'enregistre dans l'eeprom
+        UTILS::write_EEPROM(numb, CELL_O2_2_ID);
+    } else if (0 == strcmp(com, "CO2_ID")) {
+        //On l'enregistre dans l'eeprom
+        UTILS::write_EEPROM(numb, CO2_ID);
+    } else if (0 == strcmp(com, "calib_O2")) {
         FLAG_O2 = false;
         wait_ms(100);
-        sensors.Calibrate_O2(true, (int)val);
+        sensors.Calibrate_O2(true, atoi(numb));
         wait_ms(100);
         FLAG_O2 = true;
-    }else if (0 == strcmp(com, "flash_i")) {
+    } else if (0 == strcmp(com, "flash_i")) {
         FLAG_REC = false;
         UTILS::Flash_Infos();
-        FLAG_REC = true;    
-    }else if (0 == strcmp(com, "check")) {
+        FLAG_REC = true;
+    } else if (0 == strcmp(com, "check")) {
         FLAG_REC = false;
         serialMonit.printf("  Calibration_O2.txt = %f\r\n", UTILS::Read_A_Val("Calibration_O2"));
-        serialMonit.printf("  Servo_Poumon.txt   = %d\r\n", (int)UTILS::Read_A_Val("Servo_Poumon")); 
-        //serialMonit.printf("Servo_Fuite.txt    = %d\r\n", (int)UTILS::Read_A_Val("Servo_Fuite"); 
-        FLAG_REC = true; 
-    }else if (0 == strcmp(com, "rec")) {
-        if (FLAG_REC){  
-        FLAG_REC = false;
-        serialMonit.printf("Arrêt du Data Logging."); 
-        }else {
+        serialMonit.printf("  Servo_Poumon.txt   = %d\r\n", (int)UTILS::Read_A_Val("Servo_Poumon"));
+        //serialMonit.printf("Servo_Fuite.txt    = %d\r\n", (int)UTILS::Read_A_Val("Servo_Fuite");
         FLAG_REC = true;
-        serialMonit.printf("Démarrage Data Logging dans %s", Log_File_Name);}          
-    }else if (0 == strcmp(com, "help")) {
+    } else if (0 == strcmp(com, "rec")) {
+        if (FLAG_REC) {
+            FLAG_REC = false;
+            serialMonit.printf("Arrêt du Data Logging.");
+        } else {
+            FLAG_REC = true;
+            serialMonit.printf("Démarrage Data Logging dans %s", Log_File_Name);
+        }
+    } else if (0 == strcmp(com, "help")) {
         FLAG_AFF = false;
-        UTILS::Help();    
-    }else if (0 == strcmp(com, "start")) {
+        UTILS::Help();
+    } else if (0 == strcmp(com, "start")) {
         FLAG_AFF = true;
-    }else if (0 == strcmp(com, "stop")) {
+    } else if (0 == strcmp(com, "stop")) {
         FLAG_AFF = false;
-        UTILS::Help();       
-    }else if (0 == strcmp(com, "clean")) {
+        UTILS::Help();
+    } else if (0 == strcmp(com, "clean")) {
         FLAG_REC = false;
         UTILS::Clean_Flash();
-    }else if (0 == strcmp(com, "dir")) {
+    } else if (0 == strcmp(com, "dir")) {
         FLAG_REC = false;
         UTILS::Dir_Flash();
         FLAG_REC = true;
-    }else if (0 == strcmp(com, "get")) {
-        FLAG_REC = false;        
+    } else if (0 == strcmp(com, "get")) {
+        FLAG_REC = false;
         wait_ms(100);
         char filename[20];
-        sprintf(filename, "LOG_%d.txt", (int)val);
+        sprintf(filename, "LOG_%d.txt", atoi(numb));
         UTILS::Read_Flash_File(filename);
         wait_ms(100);
         FLAG_REC = true;
-    }else if (0 == strcmp(com, "del")) {
+    } else if (0 == strcmp(com, "del")) {
         FLAG_REC = false;
         char filename[20];
-        sprintf(filename, "LOG_%d.txt", (int)val);
+        sprintf(filename, "LOG_%d.txt", atoi(numb));
         UTILS::Delete_Flash_File(filename);
         UTILS::Dir_Flash();
         FLAG_REC = true;
-    }else if (0 == strcmp(com, "file_s")) {
+    } else if (0 == strcmp(com, "file_s")) {
         FLAG_REC = false;
         char filename[20];
-        sprintf(filename, "LOG_%d.txt", (int)val);
+        sprintf(filename, "LOG_%d.txt", atoi(numb));
         UTILS::Get_File_Size(filename);
         FLAG_REC = true;
-    //}else if (0 == strcmp(com, "file_i")) {
-    //    FLAG_REC = false;
-    //    char filename[20];
-    //    sprintf(filename, "LOG_%d.txt", (int)val);
-    //    UTILS::Get_File_Infos_bis(filename);
-    //    FLAG_REC = true;                      
+        //}else if (0 == strcmp(com, "file_i")) {
+        //    FLAG_REC = false;
+        //    char filename[20];
+        //    sprintf(filename, "LOG_%d.txt", (int)valeur_2);
+        //    UTILS::Get_File_Infos_bis(filename);
+        //    FLAG_REC = true;
     } else if (0 == strcmp(com, "calib_p")) {
         Consigne_poumon = 0;
         volet_poumon_Position = 0;
@@ -451,29 +467,23 @@
     } else if (0 == strcmp(com, "calib_f")) {
         Consigne_fuite = 0;
         volet_fuite_Position = 0;
-        //Servo_Fuite.reset();    
+        //Servo_Fuite.reset();
     } else if (0 == strcmp(com, "sleep")) {
         Stop_Sequence();
     } else if (0 == strcmp(com, "time")) {//Depuis terminal MAC taper : " date +%s "
-        set_time(val);
+        set_time(atoi(numb));
     } else if (0 == strcmp(com, "c_pou")) {
-        Consigne_poumon = (float)val;
+        Consigne_poumon = atof(numb);
         DEBUG("  Servo Poumon    = %f\r\n", Consigne_poumon);
     } else if (0 == strcmp(com, "c_fui")) {
-        Consigne_fuite = (float)val;
+        Consigne_fuite = atof(numb);
         DEBUG("  Servo Fuite     =  %f\r\n", Consigne_fuite);
     } else if (0 == strcmp(com, "reset")) {
         NVIC_SystemReset();
-        /////////////////////////////////////////
-        //Pour rajouter une commande
-        //} else if ((char)commande == 'X') {
-        //  attribuer à une VARIABLE = valeur;
-        //  ou une action, avec ou sans valeur
-        /////////////////////////////////////////
     } else {
         sensors.cozirSend(message);
     }
-    
+
     strcpy(param," ");
     indexParam = 0;
     newParamFlag = false;
@@ -538,248 +548,308 @@
     char Time[40];
     strftime(Time, 40, "%a_%d_%m_%Y_%H%M", localtime(&seconds));
     sprintf(Log_File_Name, "%s_LOG.txt", Time);
-    DEBUG("Nouveau fichier LOG = %s \r\n", Log_File_Name);   
-    }
-    
+    DEBUG("Nouveau fichier LOG = %s \r\n", Log_File_Name);
+}
+
 void Create_File_Name_Index()
 {
     //Du nom du fichier par Index
     sprintf(Log_File_Name, "LOG_%d.txt", UTILS::File_Index());
-    DEBUG("  Nouveau fichier LOG = %s \r\n", Log_File_Name);    
-    }
-    
+    DEBUG("  Nouveau fichier LOG = %s \r\n", Log_File_Name);
+}
+
+void Create_File_Header()
+{
+    //On récupère tout...
+    //Les identifiants matériel
+    int ARNSRS_ID = UTILS::Read_A_Val("ARNSRS_ID");
+    int Head_ID = UTILS::read_I_EEPROM(HEAD_ID);
+    int Co2_ID = UTILS::read_I_EEPROM(CO2_ID);
+    int Cell_o2_1_ID = UTILS::read_I_EEPROM(CELL_O2_1_ID);
+    int Cell_o2_2_ID = UTILS::read_I_EEPROM(CELL_O2_2_ID);
+    //Les calibrations O2
+    float calibO2_1 = UTILS::read_F_EEPROM(O2_POINT_1);//Calib dans l'air
+    float calibO2_2 = UTILS::read_F_EEPROM(O2_POINT_2);//Calib dans du 0%, N2 par exemple
+    float calibO2_3 = UTILS::read_F_EEPROM(O2_POINT_3);//Calib dans un gaz donné
+    //Les calibrations CO2
+    int calibCO2_1 = UTILS::read_I_EEPROM(CO2_POINT_1);//Calib dans l'air
+    int calibCO2_2 = UTILS::read_I_EEPROM(CO2_POINT_2);//Calib dans du 0%, N2 par exemple
+    int calibCO2_3 = UTILS::read_I_EEPROM(CO2_POINT_3);//Calib dans un gaz donné
+
+    //Fabrication de la chaine Date / heure
+    seconds = time(NULL);
+    char Time[32];
+    strftime(Time, 32, "%D %I-%M-%S ", localtime(&seconds));
+    //Fabrication de la chaine à enregistrer
+    sprintf(header,"FICHIER %s\r\n> Date : %s\r\n> ARNSRS Id : %d\r\n> Sensor Head Id : %d\r\n> CO2 Id : %d\r\n> Cell O2 Id : %d et %d\r\n> Calib O2 dans l'Air : %f\r\n> Calib O2 dans le N2 : %f\r\n> Calib O2 dans le X : %f\r\n> Calib CO2 dans l'Air : %d\r\n> Calib CO2 dans le N2 : %d\r\n> Calib CO2 dans le X : %d\r\n",
+            Log_File_Name,
+            Time,
+            ARNSRS_ID,
+            Head_ID,
+            Co2_ID,
+            Cell_o2_1_ID,
+            Cell_o2_2_ID,
+            calibO2_1,//Calib dans l'air
+            calibO2_2,//Calib dans du 0%, N2 par exemple
+            calibO2_3,//Calib dans un gaz donné
+            calibCO2_1,//Calib dans l'air
+            calibCO2_2,//Calib dans du 0%, N2 par exemple
+            calibCO2_3//Calib dans un gaz donné
+           );
+
+    DEBUG("  Header du fichier LOG : \r\n\r\n%s\r\n\r\n", header);
+
+    UTILS::Write_Flash_File(header, Log_File_Name);
+}
+
 int main()
 {
-    
-   button.fall(&pressed);
-   
-   int count = 0;
-    
-   while (1) { 
-   
-   if (count == 0) serialMonit.printf("\r\nAppuyez sur le User Button pour commencer...\r\n\r\n");
-   
-   count = 1;
-   
-    if (GO == 1) {
-    
-    wait(1);
-        
-    serialMonit.attach(&callbackParam, Serial::RxIrq);
+
+    button.fall(&pressed);
+
+    int count = 0;
 
-    android.attach(&callbackAndroid, Serial::RxIrq);
+    while (1) {
 
-    //Ci-dessous commande pour formater une nouvelle carte
-    //UTILS::Format_Flash();
+        if (count == 0) serialMonit.printf("\r\nAppuyez sur le User Button pour commencer...\r\n\r\n");
+
+        count = 1;
 
-    //Montage Flash 
-    UTILS::Mount_Flash();
-    
-    //Liste des fichiers sur la Flash
-    UTILS::Dir_Flash();
-    
-    bool calib_O2 = true;
-    bool calib_CO2 = false;
-    
-    /*
-    Par défaut les valeur en cas de calibration sur true sont les suivant
+        if (GO == 1) {
+
+            wait(1);
+
+            serialMonit.attach(&callbackParam, Serial::RxIrq);
 
-       nbCalibO2 = 5
-       Mode = SPOOLING
-       Filtre = DIGI_FILTER32
-       CalibrationCO2 = "CALIB_AIR"
+            android.attach(&callbackAndroid, Serial::RxIrq);
 
-       Parfois la calibration du Cozir coince...faire reset et relancer...
-
-       Pour calibrer avec ces paramètres :
+            //Ci-dessous commande pour formater une nouvelle carte
+            //UTILS::Format_Flash();
 
-       sensors.Sensors_INIT(true, true);
-
-       Pour changer utiliser la syntaxe suivante :
+            //Montage Flash
+            UTILS::Mount_Flash();
 
-       sensors.Sensors_INIT(true, true, true, 5, SPOOLING, DIGI_FILTER32, CALIB_AIR);
-
-    */
-    
-    sensors.Sensors_INIT(calib_O2, calib_CO2);
+            //Liste des fichiers sur la Flash
+            UTILS::Dir_Flash();
 
-    wait(1);
-    
-    Servo_Poumon.Init("Servo_Poumon");
-    //Servo_Fuite.Init("Servo_Fuite");
-     
-    //Création du nouveau fichier LOG par index / par date.
-    Create_File_Name_Index();
-    //Create_File_Name_Date()
-    
-    DEBUG("  Demarrage des threads...\r\n\r\n");
+            if (UTILS::File_Exist("ARNSRS_ID") == false) {
+                UTILS::Store_A_Val(000, "ARNSRS_ID");
+                DEBUG("ARNSRS ID forcée à 000");
+            }
 
-    /*
+            bool calib_O2 = false;
+            bool calib_CO2 = false;
 
-    Pour mémoire, les réglage de priorité des thread
+            /*
+            Par défaut les valeur en cas de calibration sur true sont les suivant
 
-          osPriorityIdle          = -3,          ///< priority: idle (lowest)
-          osPriorityLow           = -2,          ///< priority: low
-          osPriorityBelowNormal   = -1,          ///< priority: below normal
-          osPriorityNormal        =  0,          ///< priority: normal (default)
-          osPriorityAboveNormal   = +1,          ///< priority: above normal
-          osPriorityHigh          = +2,          ///< priority: high
-          osPriorityRealtime      = +3,          ///< priority: realtime (highest)
-          osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority
-    */
+               nbCalibO2 = 5
+               Mode = SPOOLING
+               Filtre = DIGI_FILTER32
+               CalibrationCO2 = "CALIB_AIR"
 
-    thread_Sensors.start(Get_Info_thread);
+               Parfois la calibration du Cozir coince...faire reset et relancer...
 
-    thread_Sensors.set_priority(osPriorityNormal);
-    
-    wait_ms(300);
+               Pour calibrer avec ces paramètres :
 
-    thread_Volets.start(GO_TO_thread);
+               sensors.Sensors_INIT(true, true);
 
-    thread_Volets.set_priority(osPriorityNormal);
-    
-    wait_ms(300);
-    
-    thread_Secu.start(SECU_thread);
+               Pour changer utiliser la syntaxe suivante :
 
-    thread_Secu.set_priority(osPriorityNormal);
-    
-    wait_ms(300);
+               sensors.Sensors_INIT(true, true, true, 5, SPOOLING, DIGI_FILTER32, CALIB_AIR);
 
-#ifdef PID_MODE
-    //Init PID
-    //Entrée PPO2 entre 100 et 1000 mb
-    control_Servo.setInputLimits(Min_Input, Max_Input);
-    //Sortie servo entre 0 et 100 %
-    control_Servo.setOutputLimits(Min_Output, Max_Output);
-    //Mode auto au démarrage
-    control_Servo.setMode(AUTO_MODE);
-    //Consigne à x mb
-    control_Servo.setSetPoint(consigne);
-#endif
-    
-    DEBUG("  Threads démmarés.....\r\n\r\n  Tapez help pour voir la liste des commandes disponibles.\r\n ");
-         
-    while (true) {
-        
-        //Démarrage du Timer mesurant le temps d'éxecution du code
-        REAL_RATE.start();
+            */
+
+            sensors.Sensors_INIT(calib_O2, calib_CO2);
+
+            wait(1);
+
+            Servo_Poumon.Init("Servo_Poumon");
+            //Servo_Fuite.Init("Servo_Fuite");
 
-        if (newParamFlag) {
-            DEBUG("  From PC = %s\r\n", param);
-            Decoding_Message(param);
-        }
+            //Création du nouveau fichier LOG par index / par date.
+            Create_File_Name_Index();
+            //Create_File_Name_Date()
+            //Création et écriture du header du fichier LOG
+            Create_File_Header();
 
-        if (newAndroidFlag) {
-            DEBUG("  From Android = %s\r\n", Android);
-            Decoding_Message_Android(Android);
-        }
+            DEBUG("  Demarrage des threads...\r\n\r\n");
+
+            /*
+
+            Pour mémoire, les réglage de priorité des thread
 
-        //Fabrication de la chaine Date / heure
-        seconds = time(NULL);
-        char Time_buf[32];
-        strftime(Time_buf, 32, "%D %I-%M-%S ", localtime(&seconds));
-        
-#ifdef PID_MODE
-        //Fabrication de la chaine à enregistrer
-        sprintf(to_store,"%s:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f:%d:%.3f:%.3f:%.3f:%d",
-                Time_buf,
-                co2,
-                ppO2,
-                pression,
-                Temp1,
-                Temp2,
-                Humid,
-                CellO2_1,
-                CellO2_2,
-                volet_poumon_Position,
-                volet_fuite_Position,
-                MODE_FLAG,
-                Kc,
-                Ti,
-                Td,
-                (int)consigne
-               );
-#endif
-#ifndef PID_MODE
-        //Fabrication de la chaine à enregistrer sans les variables du PID
-        sprintf(to_store,"%s:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f:%d:%.3f:%.3f:%.3f:%d",
-                Time_buf,
-                co2,
-                ppO2,
-                pression,
-                Temp1,
-                Temp2,
-                Humid,
-                CellO2_1,
-                CellO2_2,
-                volet_poumon_Position,
-                volet_fuite_Position,
-                MODE_FLAG,
-                0.0,
-                0.0,
-                0.0,
-                0
-               );
-#endif
-        char to_slave[50];
-        //Fabrication de la chaine pour l'IHM
-        sprintf(to_slave,"%d:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f\r\n",
-                co2,
-                ppO2,
-                (int)OTU,
-                pression,
-                Temp1,
-                Temp2,
-                Humid,
-                CellO2_1,
-                CellO2_2,
-                volet_poumon_Position,
-                volet_fuite_Position);
-               
-        //Pour Android on ajoute < et > pour décoder l'arrivée du message
-        if (NEED_ANDROID_OUTPUT == 1) {
-            //sprintf(to_android,"<%s>",to_store);
-            ANDROID(to_slave);
-        }
+                  osPriorityIdle          = -3,          ///< priority: idle (lowest)
+                  osPriorityLow           = -2,          ///< priority: low
+                  osPriorityBelowNormal   = -1,          ///< priority: below normal
+                  osPriorityNormal        =  0,          ///< priority: normal (default)
+                  osPriorityAboveNormal   = +1,          ///< priority: above normal
+                  osPriorityHigh          = +2,          ///< priority: high
+                  osPriorityRealtime      = +3,          ///< priority: realtime (highest)
+                  osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority
+            */
+            wait(1); 
+            
+            
+            Thread thread_Volets(osPriorityNormal);
+            
+            thread_Volets.start(callback(GO_TO_thread));
+
+            DEBUG("  Volets thread démarré\r\n\r\n");
 
-        //Calcul des OTU
-        Calcul_OTU();
+            wait(1);
+            
+            Thread thread_Secu(osPriorityNormal);
+
+            thread_Secu.start(callback(SECU_thread));
+
+            DEBUG("  Secu thread démarré\r\n\r\n");
 
-        //Vers le moniteur série
-        if (FLAG_AFF) Affichage();
-        
-        //Enregistrement de la chaine
-        if (FLAG_REC) UTILS::Write_Flash_File(to_store, Log_File_Name);
+            wait(1);
+
+            Thread thread_Head(osPriorityNormal);
+            
+            thread_Head.start(callback(SENSORS_thread));
+
+            DEBUG("  Info thread démarré\r\n\r\n");
+
+            wait(1);
 
 
 #ifdef PID_MODE
-        //Update du PID
-        control_Servo.setProcessValue(ppO2);
-        //Nouvelle sortie servo fuite si on est pas en mode SECU
-        if(!EN_MODE_SECU) Consigne_fuite = control_Servo.compute();
+            //Init PID
+            //Entrée PPO2 entre 100 et 1000 mb
+            control_Servo.setInputLimits(Min_Input, Max_Input);
+            //Sortie servo entre 0 et 100 %
+            control_Servo.setOutputLimits(Min_Output, Max_Output);
+            //Mode auto au démarrage
+            control_Servo.setMode(AUTO_MODE);
+            //Consigne à x mb
+            control_Servo.setSetPoint(consigne);
 #endif
 
-        //Arrêt du Timer mesurant le temps d'éxecution du code
-        REAL_RATE.stop();
-        //Définition de la nouvelle valeur du temps d'échantillonage du PID.
-        RATE = REAL_RATE.read();
-        //Reset du Timer
-        REAL_RATE.reset();
+            DEBUG("  Threads démarrés.....\r\n\r\n  Tapez help pour voir la liste des commandes disponibles.\r\n ");
+
+            while (true) {
+
+                //Démarrage du Timer mesurant le temps d'éxecution du code
+                REAL_RATE.start();
+
+                if (newParamFlag) {
+                    DEBUG("  From PC = %s\r\n", param);
+                    Decoding_Message(param);
+                }
+
+                if (newAndroidFlag) {
+                    DEBUG("  From Android = %s\r\n", Android);
+                    Decoding_Message_Android(Android);
+                }
+
+                //Fabrication de la chaine Date / heure
+                seconds = time(NULL);
+                char Time_buf[32];
+                strftime(Time_buf, 32, "%D %I-%M-%S ", localtime(&seconds));
 
-        //Pour ralentir le code à Ref_Time seconde fixe quelque soit les intéruptions du loop....
-        if (Ref_Time > RATE) {
-            RATE_TRUE = (Ref_Time - RATE) * 1000;
-        } else {
-            RATE_TRUE = 0;
 #ifdef PID_MODE
-            control_Servo.setInterval(RATE);
+                //Fabrication de la chaine à enregistrer
+                sprintf(to_store,"%s:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f:%d:%.3f:%.3f:%.3f:%d",
+                        Time_buf,
+                        co2,
+                        ppO2,
+                        pression,
+                        Temp1,
+                        Temp2,
+                        Humid,
+                        CellO2_1,
+                        CellO2_2,
+                        volet_poumon_Position,
+                        volet_fuite_Position,
+                        MODE_FLAG,
+                        Kc,
+                        Ti,
+                        Td,
+                        (int)consigne
+                       );
+#endif
+#ifndef PID_MODE
+                //Fabrication de la chaine à enregistrer sans les variables du PID
+                sprintf(to_store,"%s:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f:%d:%.3f:%.3f:%.3f:%d",
+                        Time_buf,
+                        co2,
+                        ppO2,
+                        pression,
+                        Temp1,
+                        Temp2,
+                        Humid,
+                        CellO2_1,
+                        CellO2_2,
+                        volet_poumon_Position,
+                        volet_fuite_Position,
+                        MODE_FLAG,
+                        0.0,
+                        0.0,
+                        0.0,
+                        0
+                       );
 #endif
-            DEBUG("Pour ralentir le code, Ref_Time doit être supérieur à %f seconde(s)\r\n\n", RATE);
-        }
+                char to_slave[50];
+                //Fabrication de la chaine pour l'IHM
+                sprintf(to_slave,"%d:%d:%d:%.2f:%.2f:%.2f:%d:%d:%d:%.2f:%.2f\r\n",
+                        co2,
+                        ppO2,
+                        (int)OTU,
+                        pression,
+                        Temp1,
+                        Temp2,
+                        Humid,
+                        CellO2_1,
+                        CellO2_2,
+                        volet_poumon_Position,
+                        volet_fuite_Position);
+
+                //Pour Android on ajoute < et > pour décoder l'arrivée du message
+                if (NEED_ANDROID_OUTPUT == 1) {
+                    //sprintf(to_android,"<%s>",to_store);
+                    ANDROID(to_slave);
+                }
+
+                //Calcul des OTU
+                Calcul_OTU();
+
+                //Vers le moniteur série
+                if (FLAG_AFF) Affichage();
+
+                //Enregistrement de la chaine
+                if (FLAG_REC) UTILS::Write_Flash_File(to_store, Log_File_Name);
+
 
-        wait_ms(RATE_TRUE);
-    }    
-   }
-  }
+#ifdef PID_MODE
+                //Update du PID
+                control_Servo.setProcessValue(ppO2);
+                //Nouvelle sortie servo fuite si on est pas en mode SECU
+                if(!EN_MODE_SECU) Consigne_fuite = control_Servo.compute();
+#endif
+
+                //Arrêt du Timer mesurant le temps d'éxecution du code
+                REAL_RATE.stop();
+                //Définition de la nouvelle valeur du temps d'échantillonage du PID.
+                RATE = REAL_RATE.read();
+                //Reset du Timer
+                REAL_RATE.reset();
+
+                //Pour ralentir le code à Ref_Time seconde fixe quelque soit les intéruptions du loop....
+                if (Ref_Time > RATE) {
+                    RATE_TRUE = (Ref_Time - RATE) * 1000;
+                } else {
+                    RATE_TRUE = 0;
+#ifdef PID_MODE
+                    control_Servo.setInterval(RATE);
+#endif
+                    DEBUG("Pour ralentir le code, Ref_Time doit être supérieur à %f seconde(s)\r\n\n", RATE);
+                }
+
+                wait_ms(RATE_TRUE);
+            }
+        }
+    }
 }