Annexes
Précédent  Utiliser une carte Arduino dans une station météo  

Annexes

Le sketch Arduino


        
                    #include  < SPI.h>//ouvre le port qui gère la carte SD  


/* SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4*/

#include < SD.h>//carte SD


#include "HTU21D.h"//bibliothèques des capteurs sparkfun humidité
#include SFE_BMP180.h// bibliothèques des capteurs sparkfun pression

#include Wire.h//Pour le port I2C

File Myfile;

char fichier_[12];

SFE_BMP180 pressure;//Capteur de pression et de température
HTU21D myHumidity;// capteur d'hygrométrie


long minute_debut;
char commande_mesure;
char message;
int mois_;
int jour_;
int an_;
int heure_=0;
int minute_=0;
int seconde_ = 0;
int anemometre = 2; //Anemometre connecte sur le port 2 
long date_ini_veille;

boolean debut=true;//A la mise sous tension de l'Arduino, debut = true afin que la boucle loop effectue l'initialisation des données enregistrée et que le Xbeene soit pas mis en mode veille
long date_ini,date_depart,date_depart_;
//long date_courante;
boolean Xbee_reveille=true;
//String reponse="";
char status;

long temps;

void setup()
{
  
  pinMode(anemometre, INPUT);
  Serial.begin(9600); //Port Xbee 
  
  pressure.begin();
  delay(10);
  myHumidity.begin();
  delay(100);
  //Réglage en mode veille du Xbee;
  // La borne 9 de l'Arduino est reliée à la borne9 du Xbee
  
  
  date_depart=millis();
  debut=true;
   pinMode(9, OUTPUT);//borne de sortie pour commander la mise ne veille du Xbee nécéssite le réglage de avec XCTU
   digitalWrite(9, LOW);//mode réveillé du XBee
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);//obligatoire pour que la carte sd soit reconnue
  //SD.begin(4);//Sur leonardo ou mega voir https://learn.adafruit.com/adafruit-data-logger-shield/for-the-mega-and-leonardo
  if (SD.begin(4)){//vérification de la présence de la carte SD
    Serial.println("La carte SD est reconnue");
    delay(1000);
    return;
  } 
  else{
    Serial.println("La carte SD n'est pas reconnue");
  }
 



}



void loop(){

  //double T,P,p0;
  if (debut==true){
    initialisation_jour_heure();
    changt_fichier();
    delay(1000);
    if (!SD.exists(fichier_)){ 
      Myfile = SD.open(fichier_, FILE_WRITE);
      Myfile.println("date ; heure; température; pression; hygrométrie;vent :");
      Myfile.close();
      
    }
    else{
      
    }

    
    delay(1000);
    
    date_ini=millis();
    debut =false;
    Serial.write("down");
    delay(100);
    digitalWrite(9,HIGH);
    date_ini_veille=millis();
    Xbee_reveille = false;
  }


  
  if (Serial.available()){//Si le port Xbee recoit une donnée de la part de l'ordinateur par les ondes wifi

    commande_mesure=Serial.read();//Lecture de la valeur sur le port Xbee
    delay(100);
    
    if (commande_mesure==49){//Si la valeur est de 49; valeur 1 en code ASCII envoyé par processing : mesures instantanées
                   
      delay(1000);

      //envoie des quatres valeurs les unes après les autres, cela se traduit par un chaîne de caractère recue par le programme python
      Serial.print(mesure_temperature());//envoie sur le Xbee
      delay(400);//delais technique
      Serial.print(';');//séparation des données 
      delay(10);
      Serial.print(mesure_pression(mesure_temperature()));
      delay(400);
      Serial.print(';');
      delay(10);
      Serial.print(mesure_hygrometrie());
      delay(400);
      Serial.print(';');
      delay(10);
      Serial.print(vitesse_vent());
      delay(400);  
      Serial.print(';');
       delay(10); 
      Serial.print(analogRead(0));//Envoyer surle port Xbee la valeur du niveau de la batterie
      delay(10);
      
      delay(3000);//délais technique
      
      
      initialisation_jour_heure();
      delay(2000);
      date_ini=millis();
       Serial.flush();
      
    }    
    if (commande_mesure==50){//Si la valeur est de 50; valeur 2 en code ASCII envoyé par processinglectures des données du jour en cours
      
   if (SD.exists(fichier_)){ 
        //Serial.print(fichier_);
        Myfile = SD.open(fichier_); 
        while(Myfile.available()){
          Serial.print( char(Myfile.read()));
          
        }
        delay(10);
        Myfile.close();
    }}
    
    if (commande_mesure==51){   // Si la valeur est 3 : valeur 51 en code ASCII: Lecture des données des fichiers non encore lus (_U) de la carte SD ces fichiers sont alors nommés _L
      
      
       delay(100);
        File racine = SD.open("/");
        racine.rewindDirectory();
   while(true) {
     
     File fichier_donnees =  racine.openNextFile();
     char fichier_tmp[12]; 
     if (! fichier_donnees) {
       // no more files
       //Serial.println("**nofiles**");
       //racine.rewindDirectory();
       break;
     }
     
     Serial.println(fichier_donnees.name());
      if (fichier_donnees.name()[6]=='U'){  
         //boolean transfere = false;
         for(int n = 0;n <12;n++){
         fichier_tmp[n]=fichier_donnees.name()[n];      
         }
         fichier_donnees.close();
         //Serial.println(fichier_tmp);
         Myfile = SD.open(fichier_tmp); 
         
         while(Myfile.available()){
            Serial.print( char(Myfile.read()));
          }
         /*transfere=true;
          delay(10);
          if (transfere==true){
          char fichier_tmp_[12];
          for(int n = 0;n 12;n++){
         fichier_tmp_[n]=fichier_tmp[n];      
         }
          fichier_tmp_[6]='L';
          File Myfile_tmp = SD.open(fichier_tmp_,FILE_WRITE); 
          Myfile.seek(0);
          while(Myfile.available()){
          Myfile_tmp.write(Myfile.read());
          
          } 
          Myfile_tmp.close();
          
          }*/
          Myfile.close();
          
          
       }
     else{fichier_donnees.close();}
   }
   //racine.close();
  } 
 }
  
  /**********************************************************************************************************************
  *                                                    MESURES toutes les 60 s- mise en veille                                       *
  ***********************************************************************************************************************/
    double tempe_;
    double pression_;
    float hygro_;
    float vent_;
    if (millis()>=date_ini + 60000){//mesure effectuée environ toutes les minutes
                digitalWrite(9,LOW);//réveil du Xbee
                delay(1000);//délais technique dû au temps de réveil du Xbee
                tempe_ =mesure_temperature();
                delay(400);
                pression_= mesure_pression(tempe_);
                delay(400);
                hygro_=mesure_hygrometrie();
                delay(400);
                vent_=vitesse_vent();
                delay(1100);
                determination_date();//Calcul de la date de la mesure
                
                sauv_donnees(tempe_,pression_,hygro_,vent_);//sauvegarde dans le fichier du jour des dates et valeurs
               
               
                
                date_ini=millis();//initialisation de la date de la mesure en milliseconde
                digitalWrite(9,HIGH);
              }
  if ((millis()=date_ini_veille + 600000)(Xbee_reveille == false)){//réveil du Xbbe toutes les 10 min pendant 1 min pour permettre la communication avec l'ordi
              digitalWrite(9,LOW);
              delay(100);
              Serial.write("up");
              
              Xbee_reveille = true;
  }
  if ((millis()>=date_ini_veille + 690000)(Xbee_reveille == true)){//réveil du Xbbe toutes les 10 min pour permettre la communication avec l'ordi
              Serial.write("down");
              delay(100);
              digitalWrite(9,HIGH);
              date_ini_veille=millis();
              Xbee_reveille = false;
  }
//Serial.flush();
}
  /**********************************************************************************************************************
  *                                                    Diverses fonctions                                       *
  ***********************************************************************************************************************/
double mesure_temperature(){// fontion de mesure de la température codée sur un entier
  double T;
  status = pressure.startTemperature();//la mesure de la température s'effectue sur le module sparkfun BMP201 et utilisation de la bibliothèque de ce module pour lancer la mesure
  if (status != 0)//si le module répond
  { 
    delay(status);//délais imposé par le module

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
  }//lecture de la température
  return T;//renvoie la valeur de T

double mesure_pression(double T){//fonction de mesure de la pression codée sur un entier
  double P;//défintion de la variable pression
  status = pressure.startPressure(3);//demarrage de la mesure de la pression
  if (status != 0)//si le  module répond
  { 
    delay(status);//délais imposé par le module
    status = pressure.getPressure(P,T);//lecture de la pression sur le module
    delay(50);
  }//imposé par le calcul qui suit
  float p0 = pressure.sealevel(P,200);//Pression corrigée de l'altitude de 200 m, changer la veleur selon le lieu
  delay(50);//imposé par le calcul précédent
  return p0;//renvoie la pression corrigée de l'altitude
}
float mesure_hygrometrie(){//fonction de mesure de le l'hygrométrie codée sur un réel
  float humd = myHumidity.readHumidity();  //lecture de la valeur de l'humidité sur le module sparkfun
  return humd; //renvoie la valeur de l'humidité
}

float  vitesse_vent(){//Mesure et Calcul la vitesse du vent : http://www.lextronic.fr/P28025-capteur-anenometre.html
  unsigned long vent= 0;

 vent=pulseIn(anemometre,HIGH,800000);
 //Serial.println(vent);
  //Serial.println(vent2);
  float valeur=0;
  if (vent>0){
  valeur=(70000.0*6.2/vent)*3.6;
//Serial.print("valeur=");
//Serial.println(valeur);
}
  //formule donnée par le constructeur du moulinet
  //Serial.print(valeur);
 
  return valeur;
}


String reponse_Xbee(){//fonction de lecture des donnees recues par le Xbee lors 
  int n=0;
  while(!Serial.available()){
    n++;
    if(n>50000){break;}};
  char byte_recu = Serial.read();//le xbee envoie un succession de charactère
  String reponse_="";
  while (byte_recu!=-1){ //si on lit  -1 sur le port série cela signifie que la communication n'a pas lieu et on répète tant qu'on reçoit des charactère


    if (byte_recu!=-1){//on vérifie de nouveau car la boucle while comporte deux lectures et la deuxième peut être mauvaise
      reponse_=reponse_+byte_recu;
    }//on crée une chaîne de caractère en concaténant les charactères reçus
    byte_recu = Serial.read();//lecture du charactère
    delay(20);
  }  //délais technique
  //Xbee.println(reponse_);
  return reponse_ ; //renvoie de la chaîne réponse
  //Xbee.flush();
}
      
void sauv_donnees(float tempe_,float pression_, float hygro_,float vent_){//Sauvegarde des données dans le fichier de la date courante
    if (SD.exists(fichier_)) {
    Myfile = SD.open(fichier_, FILE_WRITE); 
    
    
    Myfile.print(an_);
    Myfile.print(";");
    Myfile.print(mois_);
    Myfile.print(";");
    Myfile.print(jour_);
    Myfile.print(";");
    Myfile.print(heure_);
    Myfile.print(";");
    Myfile.print(minute_);
    Myfile.print(";");
    Myfile.print(seconde_);
    Myfile.print(";");
    Myfile.print(tempe_);
    Myfile.print(";");
    Myfile.print(pression_);
    Myfile.print(";");
    Myfile.print(hygro_);
    Myfile.print(";");
    Myfile.println(vent_);
    //Myfile.println(":");
    //Myfile.print("\r\n");
    
    delay(10);
          
  
  Myfile.close();}
else {changt_fichier();}
}
void initialisation_jour_heure(){//fonction nécessaire si on ne dispose pas d'un module timing extérieur
  
                  
                  String reponse="";
                  boolean reponse_=false;
                  //int n=0;
                  //Serial.println("initialisation de la date");
                  Serial.flush();//effacement des données sur tampon de réception du port Xbee
                  delay(1000);
                  Serial.print('T');
                  delay(2000);
                  
                  reponse=reponse_Xbee();
                   
                  
                 delay(1000);
              
                  if (reponse!=""){
                  //Serial.println(reponse);
                  //Serial.println("date recue");
                  
                  int repere_1=  reponse.indexOf(';');
                  int repere_2=  reponse.indexOf(';',repere_1+1);
                  //Serial.println(repere_1);
                  int repere_3 = reponse.indexOf(';',repere_2+1);
                  //Serial.println(repere_2);
                  int repere_4 = reponse.indexOf(';',repere_3+1);
                  //Serial.println(repere_3);
                  int repere_5 = reponse.indexOf(';',repere_4+1);
                  //Serial.println(repere_4);
                  if((repere_1!=0)(repere_2!=0)(repere_3!=0)(repere_4!=0)(repere_5!=0)){
                  
                    an_=reponse.substring(0,repere_1).toInt();
                    mois_=reponse.substring(repere_1+1,repere_2).toInt();
                 
                 // Serial.println(mois_ini);
                  jour_=reponse.substring(repere_2+1,repere_3).toInt();
                  // Serial.println(jour_);
                  
                  heure_=reponse.substring(repere_3+1,repere_4).toInt();
                   //Serial.println(heure_);
                  
                  minute_=reponse.substring(repere_4+1,repere_5).toInt();
                   //Serial.println(minute_);
                   
                  seconde_=reponse.substring(repere_5+1).toInt();
                  //Xbee.println(minute_);
                   //changt_fichier();
                   //delay(1000);
                 date_ini=seconde_*1000;}}
                   
                   Serial.flush();
}
void determination_date(){//fonction nécessaire si on ne dispose pas d'un module timing extérieur
    boolean changt_date = false;
    long date_presente = millis();
    long temps_ecoule=date_presente-date_ini+1250;
    temps_ecoule=temps_ecoule/1000;
    if ((seconde_+temps_ecoule)59){seconde_ = seconde_+temps_ecoule;}
    else{seconde_=(temps_ecoule-59);
    if (minute_<59){minute_=minute_+1;}
        else{minute_=0;
        if(heure_<23){heure_=heure_+1;}
             else{heure_=0;
             
             
             
             
                  switch (mois_) {
                  case 1 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 2;}
                              break;
                              case 2 :if (jour_<28){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 3;}
                              break;
                              case 3 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 4;}
                              break;
                              case 4 :if (jour_<30){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 5;}
                              break;
                              case 5 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 6;}
                              break;
                              case 6 :if (jour_<30){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 7;}
                              break;
                              case 7 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 8;}
                              break;
                              case 8 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 9;}
                              break;
                              case 9 :if (jour_<30){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 10;}
                              break;
                              case 10 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 11;}
                              break;
                              case 11 :if (jour_<30){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 12;}
                              break;
                              case 12 :if (jour_<31){jour_=jour_+1;}
                                 else{jour_ = 1; 
                                       mois_= 1;
                                     an_= an_+1;}
                              break;
                 }
              
             
             
           changt_fichier();
         delay(1000);}} 
          
         }
            
          
   
}

void changt_fichier(){
  int n=0;
  String string_mois;
  String string_jour;
  if (mois_<10){string_mois = "0"+ String(mois_);}
  if (mois_>=10){string_mois =  String(mois_);}
  if (jour_<10){string_jour = "0"+ String(jour_);}
  if (jour_>=10){string_jour =  String(jour_);}
  String nom_fichier=string_mois+"-"+string_jour+"-"+"U"+"."+"TXT";
  
  while(n<11){
  fichier_[n]=nom_fichier[n];
  n++;
  
}
//Serial.println("nom du fichier ="+nom_fichier);
if (!SD.exists(fichier_)){  
      Myfile = SD.open(fichier_, FILE_WRITE);//Creation du fichier de sauvegarde
      Myfile.println("date ; heure; temperature; pression; hygrometrie;vent :");//Premiere ligne de la sauvegarde
      Myfile.close();//Fermeture du fichier 
  }
}
]]

Le programme Python complet


 # -*- coding: utf-8 -*-

# Module de lecture/ecriture du port Xbee station météo
from Tkinter import *
from serial import *
import time
import threading
from datetime import datetime,date,timedelta
from time import gmtime, strftime
import platform
from serial.tools import list_ports
import os, io,itertools
import signal
import sys
import pylab
from PIL import Image, ImageTk
import tkMessageBox


if platform.system() == 'Windows':#Détection du système , utilisation du registre windows 
                    import _winreg as winreg
else:
                    import glob
port_Xbee=''

                
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
marche=True            
debut=True
forcage=False        
mise_en_veille_active=True

            
def enumerate_serial_ports():   # fonction listant l'ensemble des ports série(USB) utilisés sur la machine
                                            
                                                
                 #définition du chemin de la clef du registre donnant la lsite des ports séries en activité
                try:
                    key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) #défintion de la clef du registre des ports séries
                except WindowsError:
                    raise Exception
            
                for i in itertools.count():                       #pour l'ensemble des ports série détectés,les lister dans l'ordre croissant 
                    try:
                        val = winreg.EnumValue(key, i)          # valeur des différents ports
                        yield (str(val[1])) #  , str(val[0]))   #La fonction  yield permet de garder la liste des ports classés
                        #print(str(val[i]))
                    
                    except EnvironmentError:
                        print("erreur")
                        break
            
            
            
def detection_port_Xbee():
                global Xbee
                liste_des_ports=enumerate_serial_ports()
                for i in liste_des_ports :#Détetection du port série(USB) sur lequel est branché le module xbee
                    print(i)
                    try :
                       with Serial(port=i, baudrate=9600, timeout=1, writeTimeout=1) as Xbee:
                         if Xbee.isOpen():
                            time.sleep(1)
                            Xbee.write('+++')
                            time.sleep(1.2)
                            ligne = Xbee.readline()
                            if (ligne=='OK'+chr(13)) :
                                port_Xbee=i
                                #return port_Xbee
                                break
                            Xbee.close()
                    except :
                        continue
                                
                Xbee = Serial(port=port_Xbee, baudrate=9600, timeout=1, writeTimeout=1)
                chaine = "Xbee branché sur le port :" +port_Xbee
                B1.config(state=DISABLED)#change l état des boutons 
                B3.config(state=NORMAL)
                B5.config(state=NORMAL)
                text1.set(chaine )  #indication du port utilisé
                detection_creation_fichier_sauvegarde()  #Détecte si le fichier de sauvegarde est présent   
            #
            
            
def Configuration_Xbee() :#Entrée dans le mode configuration du Xbee relié à l'orinateur (pas utilisé)
                
                    while Xbee.isOpen():
                        time.sleep(1)
                        Xbee.write('+++')               #activation du mode config du Xbee
                        time.sleep(1.2)
                        ligne = Xbee.readline()
                        if (ligne=='OK'+chr(13)) :      #Vérification de la réponse du Xbee
                            print(ligne)
                            print( 'mode config')
                            Xbee.write('ATID'+chr(13))  #lecture de n° identification du Xbee
                            time.sleep(1)
                            ligne = Xbee.readline()
                            time.sleep(0.2)
                            print(ligne)
                            
                            
                            
                            
                            
                            Xbee.write('ATCN'+chr(13)) # on quitte le mode config
                            time.sleep(1)
                            ligne = Xbee.readline()
                            time.sleep(0.2)
                            print(ligne)
                            reponse =raw_input("Taper q pour quitter le mode config :")# Demande à l'opérateur si on doit quitter 
                                                                                        
                                                                                    #le mode config la fonction input n'est pas adaptée en python 2 : 
                                                                                    #interprétation du code
                            print reponse
                            if (reponse == 'q'):
                                break
                    print('terminé')
            #Envoie de données de  la carte  Arduino vers l'ordinateur:

def lecture_des_donnees(moment_d_acquisition) :#Commande à l'arduino de lire les données
                if (Xbee.isOpen()) :
                    
                    Xbee.write('1')     #code 1 : indique à l'arduino qu'il faut lire les données
                    b.stop()#arrêt du timer de 10 s pour eviter les conflits de lecture du port série
                    time.sleep(2)#pause de 2s 
    
                    mesure_ = Xbee.readline()#lecture du port série de la ligne envoyé par l'Arduino
                    time.sleep(2)#mise en veille technique
                    mesure=mesure_.split(";")#Sépare les données et les transforme en tableau : le';' est envoyépar l'arduino entre chaque valeur
                    print mesure#écrit la ligne dans la console pour vérification 
                    if (len(mesure)==5):#si il y a 5 éléments dans le tableau la lecture est sans doute bonne
                        
                        
                        temperature=mesure[0] #l'élément 1 du tableau est la tempé
                        #print('Temperature = '+temperature)
                        text_tempe.set( "Tempé =" +temperature[:4] + "°C")
                        
                        pression=mesure[1] #l'élément 2 du tableau est la pression
                        #print('Pression = '+ pression)
                        text_pression.set("Pression = "+pression[:4] + " hPa")
                        
                        hygro = mesure[2]#l'élément 3 du tableau est l'hygrométrie
                        #print('Hygrométrie =' +hygro)
                        text_hygro.set("Hygrométrie = " + hygro[:4]+" % hum")
                        
                        vent=mesure[3]#l'élément 4 du tableau est la vitesse du vent
                        text_vent.set("vent ="+vent[:4]+"km/h")
                        batterie = mesure[4]#l'élément 5 du tableau est la tension aux bornes de la batterie
                        #print('Batterie =' +batterie)
                        
                        y=int(float(batterie)/860*700)#donne un nombre de pixel proportionnel à la tension de charge de la batterie
                        tension=round(float(batterie)/1024.0*16.0,1)#Permet d'obtenir la tension à partir du nombre binaire 
                        texte=str(tension)+ " V"
                        
                        #print(y)
                    
                        text2.set("Mesures : Temperature = " + temperature +"°C ;" +" Pression = " +pression+"hPa ;"+" Hygrométrie = " + hygro + "%"+vent+" km/h")
                        
                        text3.set("Heures des données affichées : "+ str(moment_d_acquisition.hour) +":"+ str(moment_d_acquisition.minute))
                        can1.delete(ALL)#effacemement du canvas de charge de batterie
                        
                        if (tension>=9.0) :
                            poly2=can1.create_polygon(0, 0, y, 0,y,50,0,50, fill='green')#Si la charge de la batterie est bonne on trace un rectangle vert
                            
                        else :
                            poly2=can1.create_polygon(0, 0, y, 0,y,50,0,50, fill='red')#Si la charge de la batterie est insuffisant on trace un rectangle rouge
                               
                        #tracé d'un rectangle de couleur et de longueur proprotionnelle à la tesnion aux bornes de la batterie
                        texte1=can1.create_text(y, 12, text=texte, font="Arial 12 italic", fill="black")
                        texte2=can1.create_text(350, 30, text="charge batterie", font="Arial 16", fill="blue")
                        return [temperature,pression,hygro,vent,batterie]#La fonction de lecture des données renvoie les valeurs
                        Xbee.flushInput()#efface les données du tampon de réception du port série
                        b.start();#redémarrage du timer de 2 s : lecture du port série
                    else :
                        can3.delete(ALL)
                        text2.set("La station météo n'est pas prête")#Si la lecture est mauvaise
                        can2.create_oval(5,5,45,45,fill='red')#le voyant rouge s'allume
                        can3.create_text(200,24, text =' Rouge : station en mode veille')#indique que la station ne répond pas
                        return [0,0,0,0] 
                        Xbee.flushInput()#efface les données du tampon de réception du port série
                        b.start() #redémarrage du timer de 2 s : lecture du port série    
                else :
                    print('Le module Xbee ne répond pas')    
                    return [0,0,0,0]    
                    
                    b.start();#redémarrage du timer de 2 s : lecture du port série
                    
def sauvegarde_donnees(donnees) :#Sauvegarde des données dans un fichier csv
                if os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv') :
                    fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"a")
                    #fichier.write( strftime("%a, %d %b %Y %H:%M", gmtime())+';')
                    for i in range(6) :
                        
                        fichier.write(str(donnees[i]))
                        fichier.write(';')  
                    fichier.write('\n')
                    fichier.close()              
                else :
                    print('Le fichier n''existe pas')
                    donnees=[0,0,0,0]   #pour éviter une erreur d'écriture
                    
                    
def test_date_recuperation():
                     if os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv') :
                        fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"r")
                                           
                        chaine = fichier.read()
                        print chaine
                        fichier.close()
                       
                             
def detection_creation_fichier_sauvegarde():  #Vérification de l'existence d'un fichier de sauvegarde, sinon le créer      
                if (os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv')!=True) :
                    fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"w")
                    fichier.close()  
                
def fermer_programme():
                """Fonction appelée quand vient l'heure de fermer notre programme"""
                print("C'est l'heure de la fermeture !")
                if (Xbee.isOpen()) :
                    Xbee.close()
                if (a) : 
                    a.stop()
                if(b) :    
                    b.stop()
                fenetre_meteo.destroy()
                    
def mise_enveille_Xbee(moment_d_acquisition):
                if (Xbee.isOpen()) :
                    time.sleep(1)
                    Xbee.write('5') # 5 est le code de mise en veille du Xbee station
                    time.sleep(1)
                    Xbee.write(str(moment_d_acquisition.hour))#Donne l'heure à la station 
                    
                    time.sleep(1)
                    Xbee.write(str(moment_d_acquisition.minute))#Donne les minutes à la station
                    time.sleep(1)
            
            
    
    
    
               
def mesures() :
                #fonction appelée par le timer toutes les 60s, la mesure n'est ici effectuée que chaque heure
                    global debut
                    global forcage
                    B2.config(state=DISABLED)#le bouton arret des mesures est désactivé
                    
                  
                    #if( ((moment_d_acquisition.minute%2)==0)and (moment_d_acquisition.second==0)):#toutes les heures (((moment_d_acquisition.minute)==0)and (moment_d_acquisition.second==0)):#chaque heure en réalité
                    moment_d_acquisition = datetime.now()
                    if (moment_d_acquisition.minute>0):#pour que l'acquisition n'ai lieu qu'a l'heure pile
                         global acquisition_effectuee#variable globale indiquant que l'acquisition est effectuée 
                         acquisition_effectuee =False   
                    if (((moment_d_acquisition.minute==0)and (acquisition_effectuee==False))or(debut==True)or(forcage==True)):#démarrage du timer à une heure pleine(((moment_d_acquisition.minute)==0)and (moment_d_acquisition.second==0)):#chaque heure en réalité
                        b.stop()#L'acquisition a lieu lorsque le timer de 2 s est à l'arrêt
                        
                        time.sleep(1.5)#Mise en veille technique.
                        Xbee.flushInput()   #effacement des données entrantes du port   série      
                       
                        debut=False #indique que ce n'est plus la première mesure
                        forcage=False   #indique que l'on de force pas la lecture de la meusre à un moment quelconque
                        acquisition_effectuee=True;
                        donnees=lecture_des_donnees(moment_d_acquisition) #appel de la lecture des données sur l'Arduino distant
                        jour = datetime.now()
                        date_= str(jour.day)+"/"+str(jour.month)+"/"+str(jour.year)#lecture de la date et de l'heure
                        heure_=str(jour.hour)+"h"+str(jour.minute)
                        donnees.insert(0,heure_)
                        donnees.insert(0,date_)
                        print(donnees)
                        sauvegarde_donnees(donnees)#appel de la fonction de sauvgarde des données
                        #mise_enveille_Xbee(moment_d_acquisition)#met en veille le Xbee pour préserver les batteries de la staion météo autonome
                        Xbee.flushInput()
                        b.start()
                    B2.config(state=NORMAL)#le bouton arret des mesures est activé
                     
def scrutation_mise_en_veille() :#fonction applée par le timer de 2 s pour srcuter la mise en veille de la station
                    examen_veille=Xbee.readline()#lecture du port série
                    time.sleep(0.1);
                    
                    print ("Le port Xbee indique : "+examen_veille)
                    if(examen_veille=="up"):#si la station envoie up, elle se réveille
                        can3.delete(ALL)
                        can2.create_oval(5,5,45,45,fill='green')
                        can3.create_text(200,24, text ='Vert : station accessible.')
                        B7.config(text="Desactiver la mise en veille")
                        forcage_mesures()
                        Xbee.flushInput()
                    if(examen_veille=="down"):#si la station envoir down, elle se met en veille
                        can3.delete(ALL)
                        can2.create_oval(5,5,45,45,fill='red')  
                        heure_courante = datetime.now()
                        phrase=' Rouge : station en mode veille à '+str(heure_courante.hour)+' h' +str(heure_courante.minute)+'.'
                        can3.create_text(200,24, text =phrase)
                        Xbee.flushInput()            
                    if (examen_veille=="T"):
                         b.stop()
                         time.sleep(1.0);
                         heure_courante = datetime.now()
                         date_heure = str(heure_courante.year) + ";"+str(heure_courante.month) + ";" + str(heure_courante.day) + ";"+str(heure_courante.hour)+";"+str(heure_courante.minute)+";"+str(heure_courante.second)
                         Xbee.write(date_heure)
                         print(date_heure)
                         time.sleep(1.0)   
                         b.start()
                         Xbee.flushInput()         

class MyTimer: #classe définissant un timer
    def __init__(self, tempo, target, args= [], kwargs={}): 
        self._target = target 
        self._args = args 
        self._kwargs = kwargs 
        self._tempo = tempo 
  
    def _run(self): 
        self._timer = threading.Timer(self._tempo, self._run) 
        self._timer.start() 
        self._target() 
  
    def start(self): 
        self._timer = threading.Timer(self._tempo, self._run) 
        self._timer.start() 
  
    def stop(self): 
        self._timer.cancel() 
        
def lance_mesures() :#lance les mesures
    
    B3.config(state=DISABLED)#le bouton de lancement des mesures est déactivé
    B4.config(state=NORMAL)#
    print('debut des mesures')
    debut=True
    
    #mesures() #une première serie de mesure est prise au début
    moment_d_acquisition = datetime.now()
    while  (moment_d_acquisition.second!=0) :#afin que le démarrage du timer ne prenne effet que lorsque l'heure est de la forme x h y h 00s
                moment_d_acquisition = datetime.now()
                
                
    B6.config(state=NORMAL)   
    a.start() 
    b.start()
    mesures()
         
                             
def arret_mesures() :
    B3.config(state=NORMAL)
    B4.config(state=DISABLED)
    debut=True
    b.stop()
    a.stop() 
    
def forcage_mesures():
    global forcage
    forcage= True
    mesures()
    
    
def recup_mesures_total():
     code_lecture = '3'
     lecture_mesures(code_lecture)
     
def recup_mesures() : 
    code_lecture = '2'
    lecture_mesures(code_lecture)       
                   
def lecture_mesures(code_lecture):#permet la récupération des mesures des 48 h précédentes
     
     b.stop()
     time.sleep(1)
     Xbee.write(code_lecture)
     #Lecture des mesures
     time.sleep(2)
    
     M = Xbee.readlines()  
     
     
     
     #décompose M en autant de lignes qu'il y a d'heures M=M_.split(':')
     print M
                
                                      
     for n in range(0,len(M)-1):
         A = M[n].split(';')
         date_=A[2]+"/"+A[1]+"/"+A[0]
         A[9]=A[9][0:4]
         
         heure_ = A[3]+"h"+A[4]
         mesures_=[date_,heure_,A[6],A[7],A[8],A[9]]   
         print mesures_
         try :
                    sauvegarde_donnees(mesures_) 
         except :
                tkMessageBox.showwarning('Warning','Accés au fichier impossible ! Veuillez le fermer !') 
                b.start()
     
     b.start()
    
                       
def desactive_veille() :#désactive la mise en veille de l'Arduinostation  pour la maintenance
          global mise_en_veille_active
          if (Xbee.isOpen()) :
                    time.sleep(1)
                    Xbee.write('7') #code indiquant qu'il faut sortir ou entrer du mode éco
                    time.sleep(1)
                    
                    if (mise_en_veille_active==True) :#informe que  le mode éco est actif
                        mise_en_veille_active=False   
                        B7.config(text='Activer la mise en veille')                           
                    elif (mise_en_veille_active==False) :#informe que  le mode éco est déactivé
                        mise_en_veille_active=True   
                        B7.config(text='Désactiver la mise en veille')                       
             #######################################################################
             #             Programme principal                                     #
             #######################################################################                                
fenetre_meteo=Tk()#créaction d'une fenêtre graphique
fenetre_meteo.title("Mesures de la station météo")
fenetre_meteo.geometry("800x800")

text1 = StringVar() 
text1.set("Activer la recherche du Xbee")  #initialise le message : il faut lancer la détection du Xbee
text2 = StringVar() 
text2.set("Mesures : ")  #
text3 = StringVar() 
text3.set("Temps : ")
text_tempe = StringVar()
text_tempe.set("°C")
text_pression=StringVar()
text_hygro=StringVar()
text_vent=StringVar()
label_tempe =Label(fenetre_meteo,textvariable=text_tempe,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="red") 
label_tempe.place(x=20,y=400)  #affichage de la température
label_pression =Label(fenetre_meteo,textvariable=text_pression,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="blue") 
label_pression .place(x=20,y=450) #affichage de la pression
label_hygro =Label(fenetre_meteo,textvariable=text_hygro,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="orange") 
label_hygro.place(x=20,y=500) #affichage de l'hygrométrie
label_vent = Label(fenetre_meteo,textvariable=text_vent,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="green") 
label_vent.place(x=20,y=550)#affichage de la vitesse du vent
B1=Button(fenetre_meteo,text="Détection du Xbee",command=detection_port_Xbee,state=NORMAL,width=100)#Bouton d'arrêt du programme
B1.place(x=20,y=10)#bouton de détection du Xbee 
croix=PhotoImage(file='C:/IFE/Météo/documents_contribution/programme python/croix.gif')#image de la croix du bouton de fermeture

B2=Button(fenetre_meteo,image=croix,text='Fermer',command=fermer_programme,state=NORMAL)#Bouton de fermeture du programme
B2.place(x=600,y=700)
L1=Label(fenetre_meteo,textvariable=text1)#Label Texte affichant l'état d erecherche du Xbee

L1.place(x = 160, y=50)
B3=Button(fenetre_meteo,text="Lancer les mesures ",command=lance_mesures,state=DISABLED,width=100)#bouton de lancement des mesures
B3.place(x=20,y=200)#
B4=Button(fenetre_meteo,text="Arrêter les mesures ",command=arret_mesures,state=DISABLED,width=100)#bouton d'arrêt du timer de 1 h
B4.place(x=20,y=250)
B5=Button(fenetre_meteo,text="SD : récuperer les mesures enregistrées",command=recup_mesures,state=NORMAL,width=50)
B5.place(x=100,y=700)#commande la lecture du fichier du jour en cours
B7=Button(fenetre_meteo,text="SD : récuperer les mesures enregistrées les jours précédents",command=recup_mesures_total,state=NORMAL,width=50)
B7.place(x=100,y=650)#commande la lecture de tous les fichiers 
B6=Button(fenetre_meteo,text="Forçage des mesures",command=forcage_mesures,state=DISABLED,width=50)
B6.place(x=100,y=100)#commande manuelle la lecture des mesures 
B7=Button(fenetre_meteo,text="Désactiver la mise en veille",command=desactive_veille,state=NORMAL,width=50)
B7.place(x=400,y=100)# Bouton permettant de désactivier la mise en veille du Xbee Distant
L2=Label(fenetre_meteo,textvariable=text2)
L2.place(x = 20, y=300)#Label d'affichage 
L3=Label(fenetre_meteo,textvariable=text3)
L3.place(x = 20, y=350)

can1 = Canvas(fenetre_meteo,bg='yellow',height=50,width=700)#canvas d'affichage de l'état de la batterie fond
can1.place(x= 20, y = 600)
can2 = Canvas(fenetre_meteo,height=50,width=50)#canvas d'affichage de l'état de la batterie 
can2.place(x=650,y=450)
can3 = Canvas(fenetre_meteo,height=50,width=400)
can3.place(x=400,y=400)

poly2=can1.create_polygon(0, 0, 0, 0,0,50,0,50, fill='red')#canvas d'affichage de l'état de la batterie en rouge si pas assez chargée 
txt0=can1.create_text(350, 30, text="charge batterie", font=("Arial"," 16"), fill="blue")#Texte indiquant l'état de la batterie
texte1=can1.create_text(0, 12, text="0 V" , font=("Arial"," 12"," italic"), fill="black")
a = MyTimer(60, mesures, ["MyTimer"])   #un timer de 1 h   demande  la lecture des données et leur enregistrement

b = MyTimer(2, scrutation_mise_en_veille, ["MyTimer"])#un timer de 2 s scrute le port Xbee 

fenetre_meteo.mainloop()